[Feature] add GA346 baseline version
Change-Id: Ic62933698569507dcf98240cdf5d9931ae34348f
diff --git a/src/devtools/datool/.gitignore b/src/devtools/datool/.gitignore
new file mode 100644
index 0000000..0d20b64
--- /dev/null
+++ b/src/devtools/datool/.gitignore
@@ -0,0 +1 @@
+*.pyc
diff --git a/src/devtools/datool/README b/src/devtools/datool/README
new file mode 100644
index 0000000..960be87
--- /dev/null
+++ b/src/devtools/datool/README
@@ -0,0 +1,78 @@
+== fbtool introduction ==
+ fbtool.py is a tool program running at host pc.
+ It will send preloader and lk to platform via usb in order to support fastboot command.
+
+
+1 environment preparation
+ 1.1 Need to install Python 2.7 or Python 3 (or higher version) firstly
+ 1.2 Local pySerial library is preferred.
+ If there is no pySerial folder or fail to import local pySerial,
+ fbtool.py will find pySerial library in the host PC.
+ In this case, please ensure host PC has installed pySerial library (2.6 or higher version):
+ - Download pySerial from https://pypi.python.org/pypi/pyserial . e.g. pyserial-3.2.1.tar.gz
+ Exceptionally, please install *pySerial 3.0.1* (https://pypi.python.org/pypi/pyserial/3.0.1) on Windows XP.
+ - Unzip and execute 'python setup.py install' to install it
+
+3 usage
+ fbtool.py [options]
+ Options:
+ -h, --help show this help message and exit
+ -f FILE, --file=FILE read config file, default config file: dl_addr.ini
+ -d, --debug enable debug log
+ -m, --meid get meid
+
+ auth_file: ${PROJECT}/fbtool-da/auth_sv5.auth
+ preloader: ${PROJECT}/fbtool-da/fbtool-da-pl.bin
+ lk: ${PROJECT}/fbtool-da/fbtool-da-lk.bin
+
+3.1 usage with normal chip
+ command : command: python fbtool.py (or python fbtool.py -f config.ini)
+
+ Add preloader file path and preloader load address to dl_addr.ini or config.ini "da1_path" key and "da1_addr" key
+ Add preloader load address to dl_addr.ini or config.ini 'da1_addr' key
+ Add lk file path and lk load address to dl_addr.ini or config.ini "da2_path" key and "da2_addr" key
+
+ preloader support the following files:
+ ${PROJECT}/fbtool-da/fbtool-da-pl.bin
+ ${OUT}/.../bin/preloader_${PROJECT}_NO_GFH.bin
+ ${OUT}/.../preloader_${PROJECT}.bin
+ ${OUT}/.../preloader.img
+ We recommend to use pre-built binary fbtool-da-pl.bin in case customer disable the download support of preloader.
+
+ lk support only ${PROJECT}/fbtool-da/fbtool-da-lk.bin
+ fbtool-da-lk.bin is generated by ./tool/gen-dalk-from-lk.py
+ usage: python ./tool/gen-dalk-from-lk.py ${CHIP_ID} ${OUT}/.../lk-no-mtk-header.bin fbtool-da-lk.bin
+
+3.2 usage with secure chip (enable DAA)
+ command: python fbtool.py (or python fbtool.py -f config.ini)
+ Add authorization file path to dl_addr.ini or config.ini "auth_path" key
+
+ Generate an auth_file which contains the corresponding public key of private-key.pem (private-key.pem is used to sign preloader)
+ (just like SP Flash tool).
+
+ Sign preloader with ./tool/signfile-for-brom.sh
+ usage: signfile-for-brom.sh private-key.pem fbtool-da-pl.bin
+ private-key.pem is generated from openssl command.
+ run the script and it will output a file : fbtool-da-pl.bin.sign.
+ (fbtool-da-pl.bin is a pre-built preloader_${PROJECT}_NO_GFH.bin.
+ DO NOT use preloader.bin or preloader.img to generate the sign file.)
+
+ With DAA enabled, the fbtool will automatically use *.sign as the signature of pl & lk.
+ Thus, we have to
+ put fbtool-da-pl.bin and fbtool-da-pl.bin.sign in the same folder.
+ put fbtool-da-lk.bin and fbtool-da-lk.bin.sign in the same folder.
+
+3.3 usage with secure preloader (enable preloader secure DA verify)
+ Sign lk with ./tool/signfile-for-pl.sh
+
+ usage: signfile-for-pl.sh private-key.pem fbtool-da-lk.bin
+ the private-key.pem is generated from openssl rsa-1024.
+ and the fbtool-da-lk.bin.sign is generated.
+
+3.4 usage with single lk
+ command: python fbtool.py (or python fbtool.py -f config.ini)
+ Just add single lk path and load address to dl_addr.ini or config.ini "da1_path" key and "da1_addr" key
+
+3.5 send certificate file
+ command: python fbtool.py (or python fbtool.py -f config.ini)
+ Just add certificate file path to dl_addr.ini or config.ini "cert_path" key
diff --git a/src/devtools/datool/fbtool.py b/src/devtools/datool/fbtool.py
new file mode 100644
index 0000000..bbcf36e
--- /dev/null
+++ b/src/devtools/datool/fbtool.py
@@ -0,0 +1,549 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*
+try:
+ import pyserial as serial
+ import pyserial.tools.list_ports as ser_tools
+except ImportError:
+ import serial
+ import serial.tools.list_ports as ser_tools
+import sys, time, struct, logging
+from optparse import OptionParser
+try:
+ # python2
+ import ConfigParser as configparser
+except ImportError:
+ # python3
+ import configparser
+
+class Fbtool:
+ def __init__(self, config_file, meid=False):
+ self.TGT_CFG_SBC_EN = 0x00000001
+ self.TGT_CFG_SLA_EN = 0x00000002
+ self.TGT_CFG_DAA_EN = 0x00000004
+ self.E_ERROR = 0x1000
+ self.__ser = None
+ self.__connect_type = 'UNKNOWN'
+ self.__meid = meid
+ cfg = configparser.ConfigParser()
+ cfg.read(config_file)
+ self.__da1_path = cfg.get('DA1', 'da1_path')
+ self.__da1_addr = int(cfg.get('DA1', 'da1_addr'), 16)
+ self.__da1_jump_64 = int(cfg.get('DA1', 'da1_jump_64'), 16)
+ self.__da2_path = cfg.get('DA2', 'da2_path')
+ self.__da2_addr = int(cfg.get('DA2', 'da2_addr'), 16)
+ self.__auth_path = cfg.get('Auth', 'auth_path')
+ self.__cert_path = cfg.get('Cert', 'cert_path')
+ self.__fall_thru_to_fb = int(cfg.get('FALL_THRU_TO_FB', 'fall_thru_to_fb'))
+ logging.debug('da1_path: %s' %(self.__da1_path))
+ logging.debug('da1_addr: 0x%x' %(self.__da1_addr))
+ logging.debug('da1_jump_64: 0x%x' %(self.__da1_jump_64))
+ logging.debug('da2_path: %s' %(self.__da2_path))
+ logging.debug('ad2_addr: 0x%x' %(self.__da2_addr))
+ logging.debug('auth_path: %s' %(self.__auth_path))
+ logging.debug('cert_path: %s' %(self.__cert_path))
+
+ def __del__(self):
+ # compatible with pySerial 2.6.
+ # isOpen() is deprecated since version 3.0, 3.0 uses is_open
+ if self.__ser and self.__ser.isOpen():
+ self.__ser.close()
+
+ def __match_usb_br(self, vid, pid):
+ if vid == 0x0e8d and pid == 0x0003:
+ self.__connect_type = 'BROM'
+ return True
+ return False
+
+ def __match_usb_bl(self, vid, pid):
+ if ((vid == 0x0e8d and pid == 0x2000) or (vid == 0x0e8d and pid == 0x3000)):
+ self.__connect_type = 'BOOTLOADER'
+ return True
+ return False
+
+ def __match_usb_auto(self, vid, pid):
+ if self.__match_usb_br(vid, pid):
+ return True
+ if self.__match_usb_bl(vid, pid):
+ return True
+ return False
+
+ def __open_usb_device(self, match_usb_func, comport, vid, pid):
+ if match_usb_func(vid, pid):
+ time.sleep(0.1)
+ try:
+ self.__ser = serial.Serial(comport, 115200)
+ except serial.SerialException as e:
+ logging.debug('%s, retry...' %(str(e)))
+ else:
+ logging.info('Got %s' %(comport))
+ return True
+ return False
+
+ def __find_usb_device(self, match_usb_func):
+ while True:
+ ports = ser_tools.comports()
+ if serial.VERSION < '3':
+ ports_list = list(ports)
+ for port in ports_list:
+ if 'USB' in port[2]:
+ if sys.platform.startswith('win'):
+ idx = port[2].index('VID_')+4
+ vid = int(port[2][idx : idx + 4], 16)
+ idx = port[2].index('PID_')+4
+ pid = int(port[2][idx : idx + 4], 16)
+ elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
+ idx = port[2].index('VID:PID=') + 8
+ vid = int(port[2][idx : idx + 4], 16)
+ pid = int(port[2][idx + 5 : idx + 13], 16)
+ elif sys.platform.startswith('darwin'):
+ raise EnvironmentError('Unsupport macOS')
+ else:
+ raise EnvironmentError('Unsupported platform')
+ if self.__open_usb_device(match_usb_func, port[0], vid, pid):
+ return
+ else:
+ for port in ports:
+ if self.__open_usb_device(match_usb_func, port.device, port.vid, port.pid):
+ return
+
+ def __read8(self):
+ data = struct.unpack('!B', self.__ser.read())[0]
+ logging.debug("RECV 0x%X" %data)
+ return data
+
+ def __read16(self):
+ data = struct.unpack('!H', self.__ser.read(2))[0]
+ logging.debug("RECV 0x%X" %data)
+ return data
+
+ def __read32(self):
+ data = struct.unpack('!I', self.__ser.read(4))[0]
+ logging.debug("RECV 0x%X" %data)
+ return data
+
+ def __write8(self, data, echo):
+ logging.debug("SEND 0x%X" %data)
+ self.__ser.write(struct.pack('!B', data))
+ if echo:
+ val = struct.unpack('!B', self.__ser.read())[0]
+ logging.debug("RECV 0x%X" %val)
+ return val == data
+ return True
+
+ def __write16(self, data, echo):
+ logging.debug("SEND 0x%X" %data)
+ self.__ser.write(struct.pack('!H', data))
+ if echo:
+ val = struct.unpack('!H', self.__ser.read(2))[0]
+ logging.debug("RECV 0x%X" %val)
+ return val == data
+ return True
+
+ def __write32(self, data, echo):
+ logging.debug("SEND 0x%X" %data)
+ self.__ser.write(struct.pack('!I', data))
+ if echo:
+ val = struct.unpack('!I', self.__ser.read(4))[0]
+ logging.debug("RECV 0x%X" %val)
+ return val == data
+ return True
+
+ def __start_cmd(self):
+ cmd = (0xa0, 0x0a, 0x50, 0x05)
+ echo_cmd = (0x5f, 0xf5, 0xaf, 0xfa)
+
+ i = 0
+ while (i < len(cmd)):
+ self.__write8(cmd[i], False)
+ if self.__read8() != echo_cmd[i]:
+ i = 0
+ self.__ser.flushInput()
+ else:
+ i = i + 1
+ time.sleep(0.1)
+ # self.__ser.flush()
+ self.__ser.flushInput()
+ self.__ser.flushOutput()
+ if self.__connect_type == 'BROM':
+ logging.info('Connect brom')
+ elif self.__connect_type == 'BOOTLOADER':
+ logging.info('Connect bootloader')
+
+ def __load_binary(self, path):
+ logging.info("Loading file: %s" %path)
+ with open(path, 'rb') as f:
+ return f.read()
+
+ def __checksum(self, data, length):
+ checksum = 0
+ for i in range(0, length, 2):
+ checksum ^= struct.unpack('<H', data[i:i+2])[0]
+ checksum &= 0xFFFF
+ return checksum
+
+ def __get_target_config(self):
+ if not self.__write8(0xd8, True):
+ return -1, None
+ cfg = self.__read32()
+ status = self.__read16()
+
+ if status >= self.E_ERROR:
+ return status, None
+ return 0, cfg
+
+ def __send_auth(self, cfg):
+ if self.TGT_CFG_DAA_EN & cfg == 0:
+ return 0
+ else:
+ if self.TGT_CFG_SBC_EN & cfg == 0:
+ logging.error('daa=1, sbc=0')
+ return -2
+ if self.__auth_path == '':
+ logging.error('no auth file')
+ return -3
+ auth = self.__load_binary(self.__auth_path)
+ auth_len = len(auth)
+ logging.debug("auth file size: 0x%x" %(auth_len))
+
+ if not self.__write8(0xe2, True):
+ return -4
+ if not self.__write32(len(auth), True):
+ return -5
+
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ self.__ser.write(auth)
+
+ # compare checksum
+ if self.__read16() != self.__checksum(auth, auth_len):
+ return -6
+
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ return 0
+
+ def __strip_pl_hdr(self, pl, pl_len):
+ # EMMC_HEADER_V1
+ identifier, ver, dev_rw_unit = struct.unpack('12s2I', pl[:20])
+ # GFH_FILE_INFO_V1
+ gfh = pl[:56]
+ gfh_offset = 0
+
+ if identifier.strip(b'\0') == b'EMMC_BOOT' and ver == 1:
+ logging.debug('emmc_hdr: identifier:%s, ver:0x%08x, dev_rw_unit:0x%08x' %(identifier, ver, dev_rw_unit))
+ # BR_Layout_v1 size: 40
+ if dev_rw_unit + 40 > pl_len:
+ logging.error('EMMC HDR error. dev_rw_unit=0x%x, brlyt_size=0x%x, pl_len=0x%x'
+ %(dev_rw_unit, brlyt_size, pl_len))
+ return False, None, None
+
+ brlyt_identifier, brlyt_ver = struct.unpack('8sI', pl[dev_rw_unit:dev_rw_unit + 12])
+ logging.debug('brlyt_identifier: %s, brlyt_ver=0x%x' %(brlyt_identifier, brlyt_ver))
+ if brlyt_identifier.strip(b'\0') != b'BRLYT' or brlyt_ver != 1:
+ logging.error('BRLYT error. ver=0x%x, identifier=%s' %(brlyt_ver, brlyt_identifier))
+ return False, None, None
+ # BL_Descriptor
+ bl_begin_dev_addr = struct.unpack('I', pl[dev_rw_unit + 28 : dev_rw_unit + 32])[0]
+ if bl_begin_dev_addr + 56 > pl_len:
+ logging.error('BRLYT error. bl_begin_dev_addr=0x%x' %bl_begin_dev_addr)
+ return False, None, None
+ # GFH_FILE_INFO_v1
+ gfh = pl[bl_begin_dev_addr:bl_begin_dev_addr + 56]
+ gfh_offset = bl_begin_dev_addr
+
+ gfh_struct =struct.unpack('I2H12sIH2B7I', gfh)
+
+ gfh_magic_ver = gfh_struct[0]
+ gfh_type = gfh_struct[2]
+ gfh_identifier = gfh_struct[3]
+ gfh_file_len = gfh_struct[9]
+ gfh_jump_offset = gfh_struct[13]
+ gfh_sig_len = gfh_struct[12]
+ if (gfh_magic_ver & 0x00FFFFFF) == 0x004D4D4D and gfh_type == 0 and gfh_identifier.strip(b'\0') == b'FILE_INFO':
+ if gfh_file_len < gfh_jump_offset + gfh_sig_len:
+ logging.error('GFH error. pl_len=0x%x, file_len=0x%x, jump_offset=0x%x, sig_len=0x%x'
+ %(pl_len, gfh_file_len, gfh_jump_offset, gfh_sig_len))
+ return False, None, None
+ logging.debug('gfh: magic_ver: 0x%08x' %gfh_struct[0])
+ logging.debug('gfh: size: 0x%04x' %gfh_struct[1])
+ logging.debug('gfh: type: 0x%04x' %gfh_struct[2])
+ logging.debug('gfh: identifier: %s' %gfh_struct[3])
+ logging.debug('gfh: file_ver: 0x%08x' %gfh_struct[4])
+ logging.debug('gfh: file_type: 0x%04x' %gfh_struct[5])
+ logging.debug('gfh: flash_dev: 0x%02x' %gfh_struct[6])
+ logging.debug('gfh: sig_type: 0x%02x' %gfh_struct[7])
+ logging.debug('gfh: load_addr: 0x%08x' %gfh_struct[8])
+ logging.debug('gfh: file_len: 0x%08x' %gfh_struct[9])
+ logging.debug('gfh: max_size: 0x%08x' %gfh_struct[10])
+ logging.debug('gfh: content_offset: 0x%08x' %gfh_struct[11])
+ logging.debug('gfh: sig_len: 0x%08x' %gfh_struct[12])
+ logging.debug('gfh: jump_offset: 0x%08x' %gfh_struct[13])
+ logging.debug('gfh: attr: 0x%08x' %gfh_struct[14])
+ strip_pl_len = gfh_file_len - gfh_jump_offset - gfh_sig_len
+ start = gfh_offset + gfh_jump_offset
+ strip_pl = pl[start:start + strip_pl_len]
+ return (True, strip_pl, strip_pl_len)
+ else:
+ return (True, pl, pl_len)
+
+ def __send_da(self, addr, da, da_len, sig, sig_len):
+ if not self.__write8(0xd7, True):
+ return -1
+ if not self.__write32(addr, True):
+ return -2
+ logging.debug('len: 0x%x' %(da_len + sig_len))
+ if not self.__write32(da_len + sig_len, True):
+ return -3
+ if not self.__write32(sig_len, True):
+ return -4
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+
+ if da_len > 0:
+ logging.debug("Send DA")
+ self.__ser.write(da)
+ if sig_len > 0:
+ logging.debug("Send SIG")
+ self.__ser.write(sig)
+
+ logging.debug('Calc checksum')
+ checksum = self.__checksum(da, da_len) ^ self.__checksum(sig, sig_len)
+ data = self.__read16()
+ logging.debug('checksum: 0x%x - 0x%x' %(checksum, data))
+ if data != checksum:
+ return -5
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+
+ return 0
+
+ def __jump_da(self, addr):
+ if not self.__write8(0xd5, True):
+ return -1
+ if not self.__write32(addr, True):
+ return -2
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ return 0
+
+ def __jump_da_ex(self, addr):
+ if not self.__write8(0xde, True):
+ return -1
+ if not self.__write32(addr, True):
+ return -2
+ if not self.__write8(0x1, True):
+ return -3
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ if not self.__write8(0x64, True):
+ return -4
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ return 0
+
+ def __get_meid(self):
+ if not self.__write8(0xe1, True):
+ return -1
+ len = self.__read32()
+ logging.debug('meid len: 0x%x' %len)
+ data = struct.unpack('!'+str(len)+'B', self.__ser.read(len))
+ meid_str = lambda s: ''.join(map(lambda c: '%02x' %c, s))
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ logging.info(meid_str(data));
+ return 0
+
+ def __send_cert(self, data, len):
+ if not self.__write8(0xe0, True):
+ return -1
+ if not self.__write32(len, True):
+ return -2
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ self.__ser.write(data)
+ checksum = self.__checksum(data, len)
+ data = self.__read16()
+ if checksum != data:
+ logging.error("checksum: 0x%x - 0x%x" %(checksum, data))
+ return -3
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ return 0
+
+ def __reboot_platform(self):
+ if not self.__write8(0xd4, True):
+ return -1
+ if not self.__write32(0x10007000, True):
+ return -2
+ if not self.__write32(0x1, True):
+ return -3
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ if not self.__write32(0x22000004, True):
+ return -4
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ if not self.__write8(0xd4, True):
+ return -5
+ if not self.__write32(0x10007014, True):
+ return -6
+ if not self.__write32(0x1, True):
+ return -7
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ if not self.__write32(0x1209, True):
+ return -8
+ return 0
+
+ def __fall_through_to_fastboot(self):
+ if not self.__write8(0xd9, True):
+ return -1
+ status = self.__read16()
+ if status >= self.E_ERROR:
+ return status
+ return 0
+
+ def start(self):
+ self.__find_usb_device(self.__match_usb_auto)
+ self.__start_cmd()
+
+ # get meid
+ if self.__meid:
+ status = self.__get_meid()
+ if status != 0:
+ logging.error('get meid (%d)' %status)
+ return -1
+ return 0
+
+ # send cert
+ if self.__cert_path != '':
+ cert = self.__load_binary(self.__cert_path)
+ cert_len = len(cert)
+ logging.debug('cert_len: 0x%x' %cert_len)
+ status = self.__send_cert(cert, cert_len)
+ if status != 0:
+ logging.error('send cert (%d)' %status)
+ return -1
+ logging.info('Reboot...')
+ status = self.__reboot_platform()
+ if status != 0:
+ logging.error('reboot platform (%d)' %status)
+ return -1
+ return 0
+
+ if self.__connect_type == 'BROM':
+ status, cfg = self.__get_target_config()
+ if status != 0:
+ logging.error('get target config (%s)' %status)
+ return -1
+ logging.debug('cfg=0x%x' %cfg)
+
+ status = self.__send_auth(cfg)
+ if status != 0:
+ logging.error('send auth (%d)' %status)
+ return -1
+
+ da1 = self.__load_binary(self.__da1_path)
+ da1_len = len(da1)
+ logging.debug('da1 length: 0x%x' %da1_len)
+ status, strip_pl, strip_pl_len = self.__strip_pl_hdr(da1, da1_len)
+ if not status:
+ logging.error('strip pl hdr')
+ return -1
+
+ sig_da1 = None
+ sig_da1_len = 0
+ if self.TGT_CFG_DAA_EN & cfg:
+ sig_da1 = self.__load_binary(self.__da1_path + '.sign')
+ sig_da1_len = len(sig_da1)
+
+ logging.debug('strip_pl_len: 0x%x' %strip_pl_len)
+ logging.info('Send %s' %self.__da1_path)
+ status = self.__send_da(self.__da1_addr, strip_pl, strip_pl_len, sig_da1, sig_da1_len)
+ if status != 0:
+ logging.error('send da1 (%d)' %status)
+ return -1
+ logging.info('Jump da')
+ if self.__da1_jump_64 == 0:
+ status = self.__jump_da(self.__da1_addr)
+ else:
+ status = self.__jump_da_ex(self.__da1_addr)
+ if status != 0:
+ logging.error('jump da1 (%d)' %status)
+ return -1
+
+ self.__ser.close()
+ if self.__da2_path == '':
+ return 0
+
+ # handshake to bootloader
+ self.__find_usb_device(self.__match_usb_bl)
+ self.__start_cmd()
+
+ if self.__fall_thru_to_fb == 1:
+ logging.info("fall through to fastboot")
+ status = self.__fall_through_to_fastboot()
+ self.__ser.close()
+ if status != 0:
+ logging.error("fall through to fastboot failed(%d)" %(status))
+ return -1
+ else:
+ return 0
+
+ # load da2 (lk)
+ da2 = self.__load_binary(self.__da2_path)
+ da2_len = len(da2)
+ sig_da2 = self.__load_binary(self.__da2_path + '.sign')
+ sig_da2_len = len(sig_da2)
+ logging.info('Send %s' %self.__da2_path)
+ status = self.__send_da(self.__da2_addr, da2, da2_len, sig_da2, sig_da2_len)
+ if status != 0:
+ logging.error('send da2 (%d)' %status)
+ return -1
+ logging.info('Jump da2')
+ status = self.__jump_da(self.__da2_addr)
+ if status != 0:
+ logging.error('jump da2 (%d)' %status)
+ return -1
+
+ self.__ser.close()
+ return 0
+
+
+if __name__ == '__main__':
+ parser = OptionParser()
+ parser.add_option('-f', '--file', dest='configfile', help='read config file',
+ metavar='FILE', default='dl_addr.ini')
+ parser.add_option('-d', '--debug', action='store_true', dest='debuglog',
+ default=False, help='enable debug log')
+ parser.add_option('-m', '--meid', action='store_true', dest='meid',
+ default=False, help='get meid')
+ options, args = parser.parse_args()
+ config_file = options.configfile
+ meid = options.meid
+ debug = options.debuglog
+ if debug:
+ logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s] %(levelname)s: %(message)s')
+ else:
+ logging.basicConfig(level=logging.INFO, format='[%(asctime)s] %(levelname)s: %(message)s')
+
+ logging.info('pySerial version: (%s)' %serial.VERSION)
+ if serial.VERSION < '2.6':
+ logging.error('pySerial version(%s) is lower than 2.6, please upgrade!' %serial.VERSION)
+ logging.info('Use config file: %s' %(config_file))
+ logging.info('Waiting to connect platform...')
+ fbtool = Fbtool(config_file, meid)
+ fbtool.start()
diff --git a/src/devtools/datool/oe-logs b/src/devtools/datool/oe-logs
new file mode 120000
index 0000000..8e650f6
--- /dev/null
+++ b/src/devtools/datool/oe-logs
@@ -0,0 +1 @@
+/home/xj/GA376/MP1_GA/build/tmp/work/aarch64-poky-linux/fbtool/1.0-r0/temp
\ No newline at end of file
diff --git a/src/devtools/datool/oe-workdir b/src/devtools/datool/oe-workdir
new file mode 120000
index 0000000..5e5a9d3
--- /dev/null
+++ b/src/devtools/datool/oe-workdir
@@ -0,0 +1 @@
+/home/xj/GA376/MP1_GA/build/tmp/work/aarch64-poky-linux/fbtool/1.0-r0
\ No newline at end of file
diff --git a/src/devtools/datool/pyserial/__init__.py b/src/devtools/datool/pyserial/__init__.py
new file mode 100644
index 0000000..a5d1233
--- /dev/null
+++ b/src/devtools/datool/pyserial/__init__.py
@@ -0,0 +1,86 @@
+#!/usr/bin/env python
+#
+# This is a wrapper module for different platform implementations
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2001-2016 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import importlib
+import sys
+
+from pyserial.serialutil import *
+#~ SerialBase, SerialException, to_bytes, iterbytes
+
+VERSION = '3.0.1'
+
+if sys.platform == 'cli':
+ from serial.serialcli import Serial
+else:
+ import os
+ # chose an implementation, depending on os
+ if os.name == 'nt': # sys.platform == 'win32':
+ from pyserial.serialwin32 import Serial
+ elif os.name == 'posix':
+ from pyserial.serialposix import Serial, PosixPollSerial, VTIMESerial # noqa
+ elif os.name == 'java':
+ from pyserial.serialjava import Serial
+ else:
+ raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
+
+
+protocol_handler_packages = [
+ 'pyserial.urlhandler',
+]
+
+
+def serial_for_url(url, *args, **kwargs):
+ """\
+ Get an instance of the Serial class, depending on port/url. The port is not
+ opened when the keyword parameter 'do_not_open' is true, by default it
+ is. All other parameters are directly passed to the __init__ method when
+ the port is instantiated.
+
+ The list of package names that is searched for protocol handlers is kept in
+ ``protocol_handler_packages``.
+
+ e.g. we want to support a URL ``foobar://``. A module
+ ``my_handlers.protocol_foobar`` is provided by the user. Then
+ ``protocol_handler_packages.append("my_handlers")`` would extend the search
+ path so that ``serial_for_url("foobar://"))`` would work.
+ """
+ # check and remove extra parameter to not confuse the Serial class
+ do_open = not kwargs.pop('do_not_open', False)
+ # the default is to use the native implementation
+ klass = Serial
+ try:
+ url_lowercase = url.lower()
+ except AttributeError:
+ # it's not a string, use default
+ pass
+ else:
+ # if it is an URL, try to import the handler module from the list of possible packages
+ if '://' in url_lowercase:
+ protocol = url_lowercase.split('://', 1)[0]
+ module_name = '.protocol_%s' % (protocol,)
+ for package_name in protocol_handler_packages:
+ try:
+ package = importlib.import_module(package_name)
+ handler_module = importlib.import_module(module_name, package_name)
+ except ImportError:
+ continue
+ else:
+ if hasattr(handler_module, 'serial_class_for_url'):
+ url, klass = handler_module.serial_class_for_url(url)
+ else:
+ klass = handler_module.Serial
+ break
+ else:
+ raise ValueError('invalid URL, protocol %r not known' % (protocol,))
+ # instantiate and open when desired
+ instance = klass(None, *args, **kwargs)
+ instance.port = url
+ if do_open:
+ instance.open()
+ return instance
diff --git a/src/devtools/datool/pyserial/serialcli.py b/src/devtools/datool/pyserial/serialcli.py
new file mode 100644
index 0000000..c79cd7b
--- /dev/null
+++ b/src/devtools/datool/pyserial/serialcli.py
@@ -0,0 +1,270 @@
+#! python
+#
+# Backend for .NET/Mono (IronPython), .NET >= 2
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2008-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import clr
+import System
+import System.IO.Ports
+from pyserial.serialutil import *
+
+
+#~ def device(portnum):
+ #~ """Turn a port number into a device name"""
+ #~ return System.IO.Ports.SerialPort.GetPortNames()[portnum]
+
+
+# must invoke function with byte array, make a helper to convert strings
+# to byte arrays
+sab = System.Array[System.Byte]
+def as_byte_array(string):
+ return sab([ord(x) for x in string]) # XXX will require adaption when run with a 3.x compatible IronPython
+
+class Serial(SerialBase):
+ """Serial port implementation for .NET/Mono."""
+
+ BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200)
+
+ def open(self):
+ """\
+ Open port with current settings. This may throw a SerialException
+ if the port cannot be opened.
+ """
+ if self._port is None:
+ raise SerialException("Port must be configured before it can be used.")
+ if self.is_open:
+ raise SerialException("Port is already open.")
+ try:
+ self._port_handle = System.IO.Ports.SerialPort(self.portstr)
+ except Exception as msg:
+ self._port_handle = None
+ raise SerialException("could not open port %s: %s" % (self.portstr, msg))
+
+ self._reconfigurePort()
+ self._port_handle.Open()
+ self.is_open = True
+ if not self._dsrdtr:
+ self._update_dtr_state()
+ if not self._rtscts:
+ self._update_rts_state()
+ self.reset_input_buffer()
+
+ def _reconfigurePort(self):
+ """Set communication parameters on opened port."""
+ if not self._port_handle:
+ raise SerialException("Can only operate on a valid port handle")
+
+ #~ self._port_handle.ReceivedBytesThreshold = 1
+
+ if self._timeout is None:
+ self._port_handle.ReadTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
+ else:
+ self._port_handle.ReadTimeout = int(self._timeout*1000)
+
+ # if self._timeout != 0 and self._interCharTimeout is not None:
+ # timeouts = (int(self._interCharTimeout * 1000),) + timeouts[1:]
+
+ if self._write_timeout is None:
+ self._port_handle.WriteTimeout = System.IO.Ports.SerialPort.InfiniteTimeout
+ else:
+ self._port_handle.WriteTimeout = int(self._write_timeout*1000)
+
+
+ # Setup the connection info.
+ try:
+ self._port_handle.BaudRate = self._baudrate
+ except IOError as e:
+ # catch errors from illegal baudrate settings
+ raise ValueError(str(e))
+
+ if self._bytesize == FIVEBITS:
+ self._port_handle.DataBits = 5
+ elif self._bytesize == SIXBITS:
+ self._port_handle.DataBits = 6
+ elif self._bytesize == SEVENBITS:
+ self._port_handle.DataBits = 7
+ elif self._bytesize == EIGHTBITS:
+ self._port_handle.DataBits = 8
+ else:
+ raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
+
+ if self._parity == PARITY_NONE:
+ self._port_handle.Parity = getattr(System.IO.Ports.Parity, 'None') # reserved keyword in Py3k
+ elif self._parity == PARITY_EVEN:
+ self._port_handle.Parity = System.IO.Ports.Parity.Even
+ elif self._parity == PARITY_ODD:
+ self._port_handle.Parity = System.IO.Ports.Parity.Odd
+ elif self._parity == PARITY_MARK:
+ self._port_handle.Parity = System.IO.Ports.Parity.Mark
+ elif self._parity == PARITY_SPACE:
+ self._port_handle.Parity = System.IO.Ports.Parity.Space
+ else:
+ raise ValueError("Unsupported parity mode: %r" % self._parity)
+
+ if self._stopbits == STOPBITS_ONE:
+ self._port_handle.StopBits = System.IO.Ports.StopBits.One
+ elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
+ self._port_handle.StopBits = System.IO.Ports.StopBits.OnePointFive
+ elif self._stopbits == STOPBITS_TWO:
+ self._port_handle.StopBits = System.IO.Ports.StopBits.Two
+ else:
+ raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
+
+ if self._rtscts and self._xonxoff:
+ self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSendXOnXOff
+ elif self._rtscts:
+ self._port_handle.Handshake = System.IO.Ports.Handshake.RequestToSend
+ elif self._xonxoff:
+ self._port_handle.Handshake = System.IO.Ports.Handshake.XOnXOff
+ else:
+ self._port_handle.Handshake = getattr(System.IO.Ports.Handshake, 'None') # reserved keyword in Py3k
+
+ #~ def __del__(self):
+ #~ self.close()
+
+ def close(self):
+ """Close port"""
+ if self.is_open:
+ if self._port_handle:
+ try:
+ self._port_handle.Close()
+ except System.IO.Ports.InvalidOperationException:
+ # ignore errors. can happen for unplugged USB serial devices
+ pass
+ self._port_handle = None
+ self.is_open = False
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ @property
+ def in_waiting(self):
+ """Return the number of characters currently in the input buffer."""
+ if not self._port_handle:
+ raise portNotOpenError
+ return self._port_handle.BytesToRead
+
+ def read(self, size=1):
+ """\
+ Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read.
+ """
+ if not self._port_handle:
+ raise portNotOpenError
+ # must use single byte reads as this is the only way to read
+ # without applying encodings
+ data = bytearray()
+ while size:
+ try:
+ data.append(self._port_handle.ReadByte())
+ except System.TimeoutException as e:
+ break
+ else:
+ size -= 1
+ return bytes(data)
+
+ def write(self, data):
+ """Output the given string over the serial port."""
+ if not self._port_handle:
+ raise portNotOpenError
+ #~ if not isinstance(data, (bytes, bytearray)):
+ #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
+ try:
+ # must call overloaded method with byte array argument
+ # as this is the only one not applying encodings
+ self._port_handle.Write(as_byte_array(data), 0, len(data))
+ except System.TimeoutException as e:
+ raise writeTimeoutError
+ return len(data)
+
+ def reset_input_buffer(self):
+ """Clear input buffer, discarding all that is in the buffer."""
+ if not self._port_handle:
+ raise portNotOpenError
+ self._port_handle.DiscardInBuffer()
+
+ def reset_output_buffer(self):
+ """\
+ Clear output buffer, aborting the current output and
+ discarding all that is in the buffer.
+ """
+ if not self._port_handle:
+ raise portNotOpenError
+ self._port_handle.DiscardOutBuffer()
+
+ def _update_break_state(self):
+ """
+ Set break: Controls TXD. When active, to transmitting is possible.
+ """
+ if not self._port_handle:
+ raise portNotOpenError
+ self._port_handle.BreakState = bool(self._break_state)
+
+ def _update_rts_state(self):
+ """Set terminal status line: Request To Send"""
+ if not self._port_handle:
+ raise portNotOpenError
+ self._port_handle.RtsEnable = bool(self._rts_state)
+
+ def _update_dtr_state(self):
+ """Set terminal status line: Data Terminal Ready"""
+ if not self._port_handle:
+ raise portNotOpenError
+ self._port_handle.DtrEnable = bool(self._dtr_state)
+
+ @property
+ def cts(self):
+ """Read terminal status line: Clear To Send"""
+ if not self._port_handle:
+ raise portNotOpenError
+ return self._port_handle.CtsHolding
+
+ @property
+ def dsr(self):
+ """Read terminal status line: Data Set Ready"""
+ if not self._port_handle:
+ raise portNotOpenError
+ return self._port_handle.DsrHolding
+
+ @property
+ def ri(self):
+ """Read terminal status line: Ring Indicator"""
+ if not self._port_handle:
+ raise portNotOpenError
+ #~ return self._port_handle.XXX
+ return False #XXX an error would be better
+
+ @property
+ def cd(self):
+ """Read terminal status line: Carrier Detect"""
+ if not self._port_handle:
+ raise portNotOpenError
+ return self._port_handle.CDHolding
+
+ # - - platform specific - - - -
+ # none
+
+
+# Nur Testfunktion!!
+if __name__ == '__main__':
+ import sys
+
+ s = Serial(0)
+ sys.stdio.write('%s\n' % s)
+
+ s = Serial()
+ sys.stdio.write('%s\n' % s)
+
+
+ s.baudrate = 19200
+ s.databits = 7
+ s.close()
+ s.port = 0
+ s.open()
+ sys.stdio.write('%s\n' % s)
+
diff --git a/src/devtools/datool/pyserial/serialjava.py b/src/devtools/datool/pyserial/serialjava.py
new file mode 100644
index 0000000..dae8b5d
--- /dev/null
+++ b/src/devtools/datool/pyserial/serialjava.py
@@ -0,0 +1,270 @@
+#!jython
+#
+# Backend Jython with JavaComm
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2002-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+from pyserial.serialutil import *
+
+
+def my_import(name):
+ mod = __import__(name)
+ components = name.split('.')
+ for comp in components[1:]:
+ mod = getattr(mod, comp)
+ return mod
+
+
+def detect_java_comm(names):
+ """try given list of modules and return that imports"""
+ for name in names:
+ try:
+ mod = my_import(name)
+ mod.SerialPort
+ return mod
+ except (ImportError, AttributeError):
+ pass
+ raise ImportError("No Java Communications API implementation found")
+
+
+# Java Communications API implementations
+# http://mho.republika.pl/java/comm/
+
+comm = detect_java_comm([
+ 'javax.comm', # Sun/IBM
+ 'gnu.io', # RXTX
+])
+
+
+def device(portnumber):
+ """Turn a port number into a device name"""
+ enum = comm.CommPortIdentifier.getPortIdentifiers()
+ ports = []
+ while enum.hasMoreElements():
+ el = enum.nextElement()
+ if el.getPortType() == comm.CommPortIdentifier.PORT_SERIAL:
+ ports.append(el)
+ return ports[portnumber].getName()
+
+
+class Serial(SerialBase):
+ """\
+ Serial port class, implemented with Java Communications API and
+ thus usable with jython and the appropriate java extension.
+ """
+
+ def open(self):
+ """\
+ Open port with current settings. This may throw a SerialException
+ if the port cannot be opened.
+ """
+ if self._port is None:
+ raise SerialException("Port must be configured before it can be used.")
+ if self.is_open:
+ raise SerialException("Port is already open.")
+ if type(self._port) == type(''): # strings are taken directly
+ portId = comm.CommPortIdentifier.getPortIdentifier(self._port)
+ else:
+ portId = comm.CommPortIdentifier.getPortIdentifier(device(self._port)) # numbers are transformed to a comport id obj
+ try:
+ self.sPort = portId.open("python serial module", 10)
+ except Exception as msg:
+ self.sPort = None
+ raise SerialException("Could not open port: %s" % msg)
+ self._reconfigurePort()
+ self._instream = self.sPort.getInputStream()
+ self._outstream = self.sPort.getOutputStream()
+ self.is_open = True
+
+ def _reconfigurePort(self):
+ """Set communication parameters on opened port."""
+ if not self.sPort:
+ raise SerialException("Can only operate on a valid port handle")
+
+ self.sPort.enableReceiveTimeout(30)
+ if self._bytesize == FIVEBITS:
+ jdatabits = comm.SerialPort.DATABITS_5
+ elif self._bytesize == SIXBITS:
+ jdatabits = comm.SerialPort.DATABITS_6
+ elif self._bytesize == SEVENBITS:
+ jdatabits = comm.SerialPort.DATABITS_7
+ elif self._bytesize == EIGHTBITS:
+ jdatabits = comm.SerialPort.DATABITS_8
+ else:
+ raise ValueError("unsupported bytesize: %r" % self._bytesize)
+
+ if self._stopbits == STOPBITS_ONE:
+ jstopbits = comm.SerialPort.STOPBITS_1
+ elif self._stopbits == STOPBITS_ONE_POINT_FIVE:
+ jstopbits = comm.SerialPort.STOPBITS_1_5
+ elif self._stopbits == STOPBITS_TWO:
+ jstopbits = comm.SerialPort.STOPBITS_2
+ else:
+ raise ValueError("unsupported number of stopbits: %r" % self._stopbits)
+
+ if self._parity == PARITY_NONE:
+ jparity = comm.SerialPort.PARITY_NONE
+ elif self._parity == PARITY_EVEN:
+ jparity = comm.SerialPort.PARITY_EVEN
+ elif self._parity == PARITY_ODD:
+ jparity = comm.SerialPort.PARITY_ODD
+ elif self._parity == PARITY_MARK:
+ jparity = comm.SerialPort.PARITY_MARK
+ elif self._parity == PARITY_SPACE:
+ jparity = comm.SerialPort.PARITY_SPACE
+ else:
+ raise ValueError("unsupported parity type: %r" % self._parity)
+
+ jflowin = jflowout = 0
+ if self._rtscts:
+ jflowin |= comm.SerialPort.FLOWCONTROL_RTSCTS_IN
+ jflowout |= comm.SerialPort.FLOWCONTROL_RTSCTS_OUT
+ if self._xonxoff:
+ jflowin |= comm.SerialPort.FLOWCONTROL_XONXOFF_IN
+ jflowout |= comm.SerialPort.FLOWCONTROL_XONXOFF_OUT
+
+ self.sPort.setSerialPortParams(self._baudrate, jdatabits, jstopbits, jparity)
+ self.sPort.setFlowControlMode(jflowin | jflowout)
+
+ if self._timeout >= 0:
+ self.sPort.enableReceiveTimeout(int(self._timeout*1000))
+ else:
+ self.sPort.disableReceiveTimeout()
+
+ def close(self):
+ """Close port"""
+ if self.is_open:
+ if self.sPort:
+ self._instream.close()
+ self._outstream.close()
+ self.sPort.close()
+ self.sPort = None
+ self.is_open = False
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ @property
+ def in_waiting(self):
+ """Return the number of characters currently in the input buffer."""
+ if not self.sPort:
+ raise portNotOpenError
+ return self._instream.available()
+
+ def read(self, size=1):
+ """\
+ Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read.
+ """
+ if not self.sPort:
+ raise portNotOpenError
+ read = bytearray()
+ if size > 0:
+ while len(read) < size:
+ x = self._instream.read()
+ if x == -1:
+ if self.timeout >= 0:
+ break
+ else:
+ read.append(x)
+ return bytes(read)
+
+ def write(self, data):
+ """Output the given string over the serial port."""
+ if not self.sPort:
+ raise portNotOpenError
+ if not isinstance(data, (bytes, bytearray)):
+ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
+ self._outstream.write(data)
+ return len(data)
+
+ def reset_input_buffer(self):
+ """Clear input buffer, discarding all that is in the buffer."""
+ if not self.sPort:
+ raise portNotOpenError
+ self._instream.skip(self._instream.available())
+
+ def reset_output_buffer(self):
+ """\
+ Clear output buffer, aborting the current output and
+ discarding all that is in the buffer.
+ """
+ if not self.sPort:
+ raise portNotOpenError
+ self._outstream.flush()
+
+ def send_break(self, duration=0.25):
+ """Send break condition. Timed, returns to idle state after given duration."""
+ if not self.sPort:
+ raise portNotOpenError
+ self.sPort.sendBreak(duration*1000.0)
+
+ def _update_break_state(self):
+ """Set break: Controls TXD. When active, to transmitting is possible."""
+ if self.fd is None:
+ raise portNotOpenError
+ raise SerialException("The _update_break_state function is not implemented in java.")
+
+ def _update_rts_state(self):
+ """Set terminal status line: Request To Send"""
+ if not self.sPort:
+ raise portNotOpenError
+ self.sPort.setRTS(self._rts_state)
+
+ def _update_dtr_state(self):
+ """Set terminal status line: Data Terminal Ready"""
+ if not self.sPort:
+ raise portNotOpenError
+ self.sPort.setDTR(self._dtr_state)
+
+ @property
+ def cts(self):
+ """Read terminal status line: Clear To Send"""
+ if not self.sPort:
+ raise portNotOpenError
+ self.sPort.isCTS()
+
+ @property
+ def dsr(self):
+ """Read terminal status line: Data Set Ready"""
+ if not self.sPort:
+ raise portNotOpenError
+ self.sPort.isDSR()
+
+ @property
+ def ri(self):
+ """Read terminal status line: Ring Indicator"""
+ if not self.sPort:
+ raise portNotOpenError
+ self.sPort.isRI()
+
+ @property
+ def cd(self):
+ """Read terminal status line: Carrier Detect"""
+ if not self.sPort:
+ raise portNotOpenError
+ self.sPort.isCD()
+
+
+if __name__ == '__main__':
+ s = Serial(0,
+ baudrate=19200, # baudrate
+ bytesize=EIGHTBITS, # number of databits
+ parity=PARITY_EVEN, # enable parity checking
+ stopbits=STOPBITS_ONE, # number of stopbits
+ timeout=3, # set a timeout value, None for waiting forever
+ xonxoff=0, # enable software flow control
+ rtscts=0, # enable RTS/CTS flow control
+ )
+ s.setRTS(1)
+ s.setDTR(1)
+ s.reset_input_buffer()
+ s.reset_output_buffer()
+ s.write('hello')
+ sys.stdio.write('%r\n' % s.read(5))
+ sys.stdio.write('%s\n' % s.in_waiting())
+ del s
+
diff --git a/src/devtools/datool/pyserial/serialposix.py b/src/devtools/datool/pyserial/serialposix.py
new file mode 100644
index 0000000..0e26e78
--- /dev/null
+++ b/src/devtools/datool/pyserial/serialposix.py
@@ -0,0 +1,798 @@
+#!/usr/bin/env python
+#
+# backend for serial IO for POSIX compatible systems, like Linux, OSX
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# parts based on code from Grant B. Edwards <grante@visi.com>:
+# ftp://ftp.visi.com/users/grante/python/PosixSerial.py
+#
+# references: http://www.easysw.com/~mike/serial/serial.html
+
+import errno
+import fcntl
+import os
+import select
+import struct
+import sys
+import termios
+import time
+
+import pyserial as serial
+from pyserial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError
+
+
+class PlatformSpecificBase(object):
+ BAUDRATE_CONSTANTS = {}
+
+ def number_to_device(self, port_number):
+ sys.stderr.write("""\
+don't know how to number ttys on this system.
+! Use an explicit path (eg /dev/ttyS1) or send this information to
+! the author of this module:
+
+sys.platform = %r
+os.name = %r
+serialposix.py version = %s
+
+also add the device name of the serial port and where the
+counting starts for the first serial port.
+e.g. 'first serial port: /dev/ttyS0'
+and with a bit luck you can get this module running...
+""" % (sys.platform, os.name, serial.VERSION))
+ raise NotImplementedError('no number-to-device mapping defined on this platform')
+
+ def _set_special_baudrate(self, baudrate):
+ raise NotImplementedError('non-standard baudrates are not supported on this platform')
+
+ def _set_rs485_mode(self, rs485_settings):
+ raise NotImplementedError('RS485 not supported on this platform')
+
+# try to detect the OS so that a device can be selected...
+# this code block should supply a device() and set_special_baudrate() function
+# for the platform
+plat = sys.platform.lower()
+
+if plat[:5] == 'linux': # Linux (confirmed)
+ import array
+
+ # baudrate ioctls
+ TCGETS2 = 0x802C542A
+ TCSETS2 = 0x402C542B
+ BOTHER = 0o010000
+
+ # RS485 ioctls
+ TIOCGRS485 = 0x542E
+ TIOCSRS485 = 0x542F
+ SER_RS485_ENABLED = 0b00000001
+ SER_RS485_RTS_ON_SEND = 0b00000010
+ SER_RS485_RTS_AFTER_SEND = 0b00000100
+ SER_RS485_RX_DURING_TX = 0b00010000
+
+ class PlatformSpecific(PlatformSpecificBase):
+ BAUDRATE_CONSTANTS = {
+ 0: 0o000000, # hang up
+ 50: 0o000001,
+ 75: 0o000002,
+ 110: 0o000003,
+ 134: 0o000004,
+ 150: 0o000005,
+ 200: 0o000006,
+ 300: 0o000007,
+ 600: 0o000010,
+ 1200: 0o000011,
+ 1800: 0o000012,
+ 2400: 0o000013,
+ 4800: 0o000014,
+ 9600: 0o000015,
+ 19200: 0o000016,
+ 38400: 0o000017,
+ 57600: 0o010001,
+ 115200: 0o010002,
+ 230400: 0o010003,
+ 460800: 0o010004,
+ 500000: 0o010005,
+ 576000: 0o010006,
+ 921600: 0o010007,
+ 1000000: 0o010010,
+ 1152000: 0o010011,
+ 1500000: 0o010012,
+ 2000000: 0o010013,
+ 2500000: 0o010014,
+ 3000000: 0o010015,
+ 3500000: 0o010016,
+ 4000000: 0o010017
+ }
+
+ def number_to_device(self, port_number):
+ return '/dev/ttyS%d' % (port_number,)
+
+ def _set_special_baudrate(self, baudrate):
+ # right size is 44 on x86_64, allow for some growth
+ buf = array.array('i', [0] * 64)
+ try:
+ # get serial_struct
+ fcntl.ioctl(self.fd, TCGETS2, buf)
+ # set custom speed
+ buf[2] &= ~termios.CBAUD
+ buf[2] |= BOTHER
+ buf[9] = buf[10] = baudrate
+
+ # set serial_struct
+ fcntl.ioctl(self.fd, TCSETS2, buf)
+ except IOError as e:
+ raise ValueError('Failed to set custom baud rate (%s): %s' % (baudrate, e))
+
+ def _set_rs485_mode(self, rs485_settings):
+ buf = array.array('i', [0] * 8) # flags, delaytx, delayrx, padding
+ try:
+ fcntl.ioctl(self.fd, TIOCGRS485, buf)
+ if rs485_settings is not None:
+ if rs485_settings.loopback:
+ buf[0] |= SER_RS485_RX_DURING_TX
+ else:
+ buf[0] &= ~SER_RS485_RX_DURING_TX
+ if rs485_settings.rts_level_for_tx:
+ buf[0] |= SER_RS485_RTS_ON_SEND
+ else:
+ buf[0] &= ~SER_RS485_RTS_ON_SEND
+ if rs485_settings.rts_level_for_rx:
+ buf[0] |= SER_RS485_RTS_AFTER_SEND
+ else:
+ buf[0] &= ~SER_RS485_RTS_AFTER_SEND
+ buf[1] = int(rs485_settings.delay_rts_before_send * 1000)
+ buf[2] = int(rs485_settings.delay_rts_after_send * 1000)
+ else:
+ buf[0] = 0 # clear SER_RS485_ENABLED
+ fcntl.ioctl(self.fd, TIOCSRS485, buf)
+ except IOError as e:
+ raise ValueError('Failed to set RS485 mode: %s' % (e,))
+
+
+elif plat == 'cygwin': # cygwin/win32 (confirmed)
+
+ class PlatformSpecific(PlatformSpecificBase):
+ BAUDRATE_CONSTANTS = {
+ 128000: 0x01003,
+ 256000: 0x01005,
+ 500000: 0x01007,
+ 576000: 0x01008,
+ 921600: 0x01009,
+ 1000000: 0x0100a,
+ 1152000: 0x0100b,
+ 1500000: 0x0100c,
+ 2000000: 0x0100d,
+ 2500000: 0x0100e,
+ 3000000: 0x0100f
+ }
+
+ def number_to_device(self, port_number):
+ return '/dev/com%d' % (port_number + 1,)
+
+
+elif plat[:7] == 'openbsd': # OpenBSD
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/cua%02d' % (port_number,)
+
+elif plat[:3] == 'bsd' or plat[:7] == 'freebsd':
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/cuad%d' % (port_number,)
+
+elif plat[:6] == 'darwin': # OS X
+ import array
+ IOSSIOSPEED = 0x80045402 # _IOW('T', 2, speed_t)
+
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/cuad%d' % (port_number,)
+
+ osx_version = os.uname()[2].split('.')
+ # Tiger or above can support arbitrary serial speeds
+ if int(osx_version[0]) >= 8:
+ def _set_special_baudrate(self, baudrate):
+ # use IOKit-specific call to set up high speeds
+ buf = array.array('i', [baudrate])
+ fcntl.ioctl(self.fd, IOSSIOSPEED, buf, 1)
+
+
+elif plat[:6] == 'netbsd': # NetBSD 1.6 testing by Erk
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/dty%02d' % (port_number,)
+
+elif plat[:4] == 'irix': # IRIX (partially tested)
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/ttyf%d' % (port_number + 1,) # XXX different device names depending on flow control
+
+elif plat[:2] == 'hp': # HP-UX (not tested)
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/tty%dp0' % (port_number + 1,)
+
+elif plat[:5] == 'sunos': # Solaris/SunOS (confirmed)
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/tty%c' % (ord('a') + port_number,)
+
+elif plat[:3] == 'aix': # AIX
+ class PlatformSpecific(PlatformSpecificBase):
+ def number_to_device(self, port_number):
+ return '/dev/tty%d' % (port_number,)
+
+else:
+ class PlatformSpecific(PlatformSpecificBase):
+ pass
+
+# whats up with "aix", "beos", ....
+# they should work, just need to know the device names.
+
+
+# load some constants for later use.
+# try to use values from termios, use defaults from linux otherwise
+TIOCMGET = getattr(termios, 'TIOCMGET', 0x5415)
+TIOCMBIS = getattr(termios, 'TIOCMBIS', 0x5416)
+TIOCMBIC = getattr(termios, 'TIOCMBIC', 0x5417)
+TIOCMSET = getattr(termios, 'TIOCMSET', 0x5418)
+
+# TIOCM_LE = getattr(termios, 'TIOCM_LE', 0x001)
+TIOCM_DTR = getattr(termios, 'TIOCM_DTR', 0x002)
+TIOCM_RTS = getattr(termios, 'TIOCM_RTS', 0x004)
+# TIOCM_ST = getattr(termios, 'TIOCM_ST', 0x008)
+# TIOCM_SR = getattr(termios, 'TIOCM_SR', 0x010)
+
+TIOCM_CTS = getattr(termios, 'TIOCM_CTS', 0x020)
+TIOCM_CAR = getattr(termios, 'TIOCM_CAR', 0x040)
+TIOCM_RNG = getattr(termios, 'TIOCM_RNG', 0x080)
+TIOCM_DSR = getattr(termios, 'TIOCM_DSR', 0x100)
+TIOCM_CD = getattr(termios, 'TIOCM_CD', TIOCM_CAR)
+TIOCM_RI = getattr(termios, 'TIOCM_RI', TIOCM_RNG)
+# TIOCM_OUT1 = getattr(termios, 'TIOCM_OUT1', 0x2000)
+# TIOCM_OUT2 = getattr(termios, 'TIOCM_OUT2', 0x4000)
+if hasattr(termios, 'TIOCINQ'):
+ TIOCINQ = termios.TIOCINQ
+else:
+ TIOCINQ = getattr(termios, 'FIONREAD', 0x541B)
+TIOCOUTQ = getattr(termios, 'TIOCOUTQ', 0x5411)
+
+TIOCM_zero_str = struct.pack('I', 0)
+TIOCM_RTS_str = struct.pack('I', TIOCM_RTS)
+TIOCM_DTR_str = struct.pack('I', TIOCM_DTR)
+
+TIOCSBRK = getattr(termios, 'TIOCSBRK', 0x5427)
+TIOCCBRK = getattr(termios, 'TIOCCBRK', 0x5428)
+
+CMSPAR = 0o10000000000 # Use "stick" (mark/space) parity
+
+
+class Serial(SerialBase, PlatformSpecific):
+ """\
+ Serial port class POSIX implementation. Serial port configuration is
+ done with termios and fcntl. Runs on Linux and many other Un*x like
+ systems.
+ """
+
+ def open(self):
+ """\
+ Open port with current settings. This may throw a SerialException
+ if the port cannot be opened."""
+ if self._port is None:
+ raise SerialException("Port must be configured before it can be used.")
+ if self.is_open:
+ raise SerialException("Port is already open.")
+ self.fd = None
+ # open
+ try:
+ self.fd = os.open(self.portstr, os.O_RDWR | os.O_NOCTTY | os.O_NONBLOCK)
+ except OSError as msg:
+ self.fd = None
+ raise SerialException(msg.errno, "could not open port %s: %s" % (self._port, msg))
+ #~ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # set blocking
+
+ try:
+ self._reconfigure_port(force_update=True)
+ except:
+ try:
+ os.close(self.fd)
+ except:
+ # ignore any exception when closing the port
+ # also to keep original exception that happened when setting up
+ pass
+ self.fd = None
+ raise
+ else:
+ self.is_open = True
+ if not self._dsrdtr:
+ self._update_dtr_state()
+ if not self._rtscts:
+ self._update_rts_state()
+ self.reset_input_buffer()
+
+ def _reconfigure_port(self, force_update=False):
+ """Set communication parameters on opened port."""
+ if self.fd is None:
+ raise SerialException("Can only operate on a valid file descriptor")
+ custom_baud = None
+
+ vmin = vtime = 0 # timeout is done via select
+ if self._inter_byte_timeout is not None:
+ vmin = 1
+ vtime = int(self._inter_byte_timeout * 10)
+ try:
+ orig_attr = termios.tcgetattr(self.fd)
+ iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
+ except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
+ raise SerialException("Could not configure port: %s" % msg)
+ # set up raw mode / no echo / binary
+ cflag |= (termios.CLOCAL | termios.CREAD)
+ lflag &= ~(termios.ICANON | termios.ECHO | termios.ECHOE |
+ termios.ECHOK | termios.ECHONL |
+ termios.ISIG | termios.IEXTEN) # |termios.ECHOPRT
+ for flag in ('ECHOCTL', 'ECHOKE'): # netbsd workaround for Erk
+ if hasattr(termios, flag):
+ lflag &= ~getattr(termios, flag)
+
+ oflag &= ~(termios.OPOST | termios.ONLCR | termios.OCRNL)
+ iflag &= ~(termios.INLCR | termios.IGNCR | termios.ICRNL | termios.IGNBRK)
+ if hasattr(termios, 'IUCLC'):
+ iflag &= ~termios.IUCLC
+ if hasattr(termios, 'PARMRK'):
+ iflag &= ~termios.PARMRK
+
+ # setup baud rate
+ try:
+ ispeed = ospeed = getattr(termios, 'B%s' % (self._baudrate))
+ except AttributeError:
+ try:
+ ispeed = ospeed = self.BAUDRATE_CONSTANTS[self._baudrate]
+ except KeyError:
+ #~ raise ValueError('Invalid baud rate: %r' % self._baudrate)
+ # may need custom baud rate, it isn't in our list.
+ ispeed = ospeed = getattr(termios, 'B38400')
+ try:
+ custom_baud = int(self._baudrate) # store for later
+ except ValueError:
+ raise ValueError('Invalid baud rate: %r' % self._baudrate)
+ else:
+ if custom_baud < 0:
+ raise ValueError('Invalid baud rate: %r' % self._baudrate)
+
+ # setup char len
+ cflag &= ~termios.CSIZE
+ if self._bytesize == 8:
+ cflag |= termios.CS8
+ elif self._bytesize == 7:
+ cflag |= termios.CS7
+ elif self._bytesize == 6:
+ cflag |= termios.CS6
+ elif self._bytesize == 5:
+ cflag |= termios.CS5
+ else:
+ raise ValueError('Invalid char len: %r' % self._bytesize)
+ # setup stop bits
+ if self._stopbits == serial.STOPBITS_ONE:
+ cflag &= ~(termios.CSTOPB)
+ elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
+ cflag |= (termios.CSTOPB) # XXX same as TWO.. there is no POSIX support for 1.5
+ elif self._stopbits == serial.STOPBITS_TWO:
+ cflag |= (termios.CSTOPB)
+ else:
+ raise ValueError('Invalid stop bit specification: %r' % self._stopbits)
+ # setup parity
+ iflag &= ~(termios.INPCK | termios.ISTRIP)
+ if self._parity == serial.PARITY_NONE:
+ cflag &= ~(termios.PARENB | termios.PARODD)
+ elif self._parity == serial.PARITY_EVEN:
+ cflag &= ~(termios.PARODD)
+ cflag |= (termios.PARENB)
+ elif self._parity == serial.PARITY_ODD:
+ cflag |= (termios.PARENB | termios.PARODD)
+ elif self._parity == serial.PARITY_MARK and plat[:5] == 'linux':
+ cflag |= (termios.PARENB | CMSPAR | termios.PARODD)
+ elif self._parity == serial.PARITY_SPACE and plat[:5] == 'linux':
+ cflag |= (termios.PARENB | CMSPAR)
+ cflag &= ~(termios.PARODD)
+ else:
+ raise ValueError('Invalid parity: %r' % self._parity)
+ # setup flow control
+ # xonxoff
+ if hasattr(termios, 'IXANY'):
+ if self._xonxoff:
+ iflag |= (termios.IXON | termios.IXOFF) # |termios.IXANY)
+ else:
+ iflag &= ~(termios.IXON | termios.IXOFF | termios.IXANY)
+ else:
+ if self._xonxoff:
+ iflag |= (termios.IXON | termios.IXOFF)
+ else:
+ iflag &= ~(termios.IXON | termios.IXOFF)
+ # rtscts
+ if hasattr(termios, 'CRTSCTS'):
+ if self._rtscts:
+ cflag |= (termios.CRTSCTS)
+ else:
+ cflag &= ~(termios.CRTSCTS)
+ elif hasattr(termios, 'CNEW_RTSCTS'): # try it with alternate constant name
+ if self._rtscts:
+ cflag |= (termios.CNEW_RTSCTS)
+ else:
+ cflag &= ~(termios.CNEW_RTSCTS)
+ # XXX should there be a warning if setting up rtscts (and xonxoff etc) fails??
+
+ # buffer
+ # vmin "minimal number of characters to be read. 0 for non blocking"
+ if vmin < 0 or vmin > 255:
+ raise ValueError('Invalid vmin: %r ' % vmin)
+ cc[termios.VMIN] = vmin
+ # vtime
+ if vtime < 0 or vtime > 255:
+ raise ValueError('Invalid vtime: %r' % vtime)
+ cc[termios.VTIME] = vtime
+ # activate settings
+ if force_update or [iflag, oflag, cflag, lflag, ispeed, ospeed, cc] != orig_attr:
+ termios.tcsetattr(
+ self.fd,
+ termios.TCSANOW,
+ [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
+
+ # apply custom baud rate, if any
+ if custom_baud is not None:
+ self._set_special_baudrate(custom_baud)
+
+ if self._rs485_mode is not None:
+ self._set_rs485_mode(self._rs485_mode)
+
+ def close(self):
+ """Close port"""
+ if self.is_open:
+ if self.fd is not None:
+ os.close(self.fd)
+ self.fd = None
+ self.is_open = False
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ @property
+ def in_waiting(self):
+ """Return the number of bytes currently in the input buffer."""
+ #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
+ s = fcntl.ioctl(self.fd, TIOCINQ, TIOCM_zero_str)
+ return struct.unpack('I', s)[0]
+
+ # select based implementation, proved to work on many systems
+ def read(self, size=1):
+ """\
+ Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read.
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ read = bytearray()
+ timeout = self._timeout
+ while len(read) < size:
+ try:
+ start_time = time.time()
+ ready, _, _ = select.select([self.fd], [], [], timeout)
+ # If select was used with a timeout, and the timeout occurs, it
+ # returns with empty lists -> thus abort read operation.
+ # For timeout == 0 (non-blocking operation) also abort when
+ # there is nothing to read.
+ if not ready:
+ break # timeout
+ buf = os.read(self.fd, size - len(read))
+ # read should always return some data as select reported it was
+ # ready to read when we get to this point.
+ if not buf:
+ # Disconnected devices, at least on Linux, show the
+ # behavior that they are always ready to read immediately
+ # but reading returns nothing.
+ raise SerialException('device reports readiness to read but returned no data (device disconnected or multiple access on port?)')
+ read.extend(buf)
+ if timeout is not None:
+ timeout -= time.time() - start_time
+ if timeout <= 0:
+ break
+ except OSError as e:
+ # this is for Python 3.x where select.error is a subclass of
+ # OSError ignore EAGAIN errors. all other errors are shown
+ if e.errno != errno.EAGAIN:
+ raise SerialException('read failed: %s' % (e,))
+ except select.error as e:
+ # this is for Python 2.x
+ # ignore EAGAIN errors. all other errors are shown
+ # see also http://www.python.org/dev/peps/pep-3151/#select
+ if e[0] != errno.EAGAIN:
+ raise SerialException('read failed: %s' % (e,))
+ return bytes(read)
+
+ def write(self, data):
+ """Output the given byte string over the serial port."""
+ if not self.is_open:
+ raise portNotOpenError
+ d = to_bytes(data)
+ tx_len = len(d)
+ if self._write_timeout is not None and self._write_timeout > 0:
+ timeout = time.time() + self._write_timeout
+ else:
+ timeout = None
+ while tx_len > 0:
+ try:
+ n = os.write(self.fd, d)
+ if timeout:
+ # when timeout is set, use select to wait for being ready
+ # with the time left as timeout
+ timeleft = timeout - time.time()
+ if timeleft < 0:
+ raise writeTimeoutError
+ _, ready, _ = select.select([], [self.fd], [], timeleft)
+ if not ready:
+ raise writeTimeoutError
+ else:
+ # wait for write operation
+ _, ready, _ = select.select([], [self.fd], [], None)
+ if not ready:
+ raise SerialException('write failed (select)')
+ d = d[n:]
+ tx_len -= n
+ except SerialException:
+ raise
+ except OSError as v:
+ if v.errno != errno.EAGAIN:
+ raise SerialException('write failed: %s' % (v,))
+ # still calculate and check timeout
+ if timeout and timeout - time.time() < 0:
+ raise writeTimeoutError
+ return len(data)
+
+ def flush(self):
+ """\
+ Flush of file like objects. In this case, wait until all data
+ is written.
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ termios.tcdrain(self.fd)
+
+ def reset_input_buffer(self):
+ """Clear input buffer, discarding all that is in the buffer."""
+ if not self.is_open:
+ raise portNotOpenError
+ termios.tcflush(self.fd, termios.TCIFLUSH)
+
+ def reset_output_buffer(self):
+ """\
+ Clear output buffer, aborting the current output and discarding all
+ that is in the buffer.
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ termios.tcflush(self.fd, termios.TCOFLUSH)
+
+ def send_break(self, duration=0.25):
+ """\
+ Send break condition. Timed, returns to idle state after given
+ duration.
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ termios.tcsendbreak(self.fd, int(duration / 0.25))
+
+ def _update_break_state(self):
+ """\
+ Set break: Controls TXD. When active, no transmitting is possible.
+ """
+ if self._break_state:
+ fcntl.ioctl(self.fd, TIOCSBRK)
+ else:
+ fcntl.ioctl(self.fd, TIOCCBRK)
+
+ def _update_rts_state(self):
+ """Set terminal status line: Request To Send"""
+ if self._rts_state:
+ fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_RTS_str)
+ else:
+ fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_RTS_str)
+
+ def _update_dtr_state(self):
+ """Set terminal status line: Data Terminal Ready"""
+ if self._dtr_state:
+ fcntl.ioctl(self.fd, TIOCMBIS, TIOCM_DTR_str)
+ else:
+ fcntl.ioctl(self.fd, TIOCMBIC, TIOCM_DTR_str)
+
+ @property
+ def cts(self):
+ """Read terminal status line: Clear To Send"""
+ if not self.is_open:
+ raise portNotOpenError
+ s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
+ return struct.unpack('I', s)[0] & TIOCM_CTS != 0
+
+ @property
+ def dsr(self):
+ """Read terminal status line: Data Set Ready"""
+ if not self.is_open:
+ raise portNotOpenError
+ s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
+ return struct.unpack('I', s)[0] & TIOCM_DSR != 0
+
+ @property
+ def ri(self):
+ """Read terminal status line: Ring Indicator"""
+ if not self.is_open:
+ raise portNotOpenError
+ s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
+ return struct.unpack('I', s)[0] & TIOCM_RI != 0
+
+ @property
+ def cd(self):
+ """Read terminal status line: Carrier Detect"""
+ if not self.is_open:
+ raise portNotOpenError
+ s = fcntl.ioctl(self.fd, TIOCMGET, TIOCM_zero_str)
+ return struct.unpack('I', s)[0] & TIOCM_CD != 0
+
+ # - - platform specific - - - -
+
+ @property
+ def out_waiting(self):
+ """Return the number of bytes currently in the output buffer."""
+ #~ s = fcntl.ioctl(self.fd, termios.FIONREAD, TIOCM_zero_str)
+ s = fcntl.ioctl(self.fd, TIOCOUTQ, TIOCM_zero_str)
+ return struct.unpack('I', s)[0]
+
+ def nonblocking(self):
+ """internal - not portable!"""
+ if not self.is_open:
+ raise portNotOpenError
+ fcntl.fcntl(self.fd, fcntl.F_SETFL, os.O_NONBLOCK)
+
+ def fileno(self):
+ """\
+ For easier use of the serial port instance with select.
+ WARNING: this function is not portable to different platforms!
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ return self.fd
+
+ def set_input_flow_control(self, enable=True):
+ """\
+ Manually control flow - when software flow control is enabled.
+ This will send XON (true) or XOFF (false) to the other device.
+ WARNING: this function is not portable to different platforms!
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ if enable:
+ termios.tcflow(self.fd, termios.TCION)
+ else:
+ termios.tcflow(self.fd, termios.TCIOFF)
+
+ def set_output_flow_control(self, enable=True):
+ """\
+ Manually control flow of outgoing data - when hardware or software flow
+ control is enabled.
+ WARNING: this function is not portable to different platforms!
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ if enable:
+ termios.tcflow(self.fd, termios.TCOON)
+ else:
+ termios.tcflow(self.fd, termios.TCOOFF)
+
+
+class PosixPollSerial(Serial):
+ """\
+ Poll based read implementation. Not all systems support poll properly.
+ However this one has better handling of errors, such as a device
+ disconnecting while it's in use (e.g. USB-serial unplugged).
+ """
+
+ def read(self, size=1):
+ """\
+ Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read.
+ """
+ if self.fd is None:
+ raise portNotOpenError
+ read = bytearray()
+ poll = select.poll()
+ poll.register(self.fd, select.POLLIN | select.POLLERR | select.POLLHUP | select.POLLNVAL)
+ if size > 0:
+ while len(read) < size:
+ # print "\tread(): size",size, "have", len(read) #debug
+ # wait until device becomes ready to read (or something fails)
+ for fd, event in poll.poll(self._timeout * 1000):
+ if event & (select.POLLERR | select.POLLHUP | select.POLLNVAL):
+ raise SerialException('device reports error (poll)')
+ # we don't care if it is select.POLLIN or timeout, that's
+ # handled below
+ buf = os.read(self.fd, size - len(read))
+ read.extend(buf)
+ if ((self._timeout is not None and self._timeout >= 0) or
+ (self._inter_byte_timeout is not None and self._inter_byte_timeout > 0)) and not buf:
+ break # early abort on timeout
+ return bytes(read)
+
+
+class VTIMESerial(Serial):
+ """\
+ Implement timeout using vtime of tty device instead of using select.
+ This means that no inter character timeout can be specified and that
+ the error handling is degraded.
+
+ Overall timeout is disabled when inter-character timeout is used.
+ """
+
+ def _reconfigure_port(self, force_update=True):
+ """Set communication parameters on opened port."""
+ super(VTIMESerial, self)._reconfigure_port()
+ fcntl.fcntl(self.fd, fcntl.F_SETFL, 0) # clear O_NONBLOCK
+
+ if self._inter_byte_timeout is not None:
+ vmin = 1
+ vtime = int(self._inter_byte_timeout * 10)
+ else:
+ vmin = 0
+ vtime = int(self._timeout * 10)
+ try:
+ orig_attr = termios.tcgetattr(self.fd)
+ iflag, oflag, cflag, lflag, ispeed, ospeed, cc = orig_attr
+ except termios.error as msg: # if a port is nonexistent but has a /dev file, it'll fail here
+ raise serial.SerialException("Could not configure port: %s" % msg)
+
+ if vtime < 0 or vtime > 255:
+ raise ValueError('Invalid vtime: %r' % vtime)
+ cc[termios.VTIME] = vtime
+ cc[termios.VMIN] = vmin
+
+ termios.tcsetattr(
+ self.fd,
+ termios.TCSANOW,
+ [iflag, oflag, cflag, lflag, ispeed, ospeed, cc])
+
+
+ def read(self, size=1):
+ """\
+ Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read.
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ read = bytearray()
+ while len(read) < size:
+ buf = os.read(self.fd, size - len(read))
+ if not buf:
+ break
+ read.extend(buf)
+ return bytes(read)
+
+
+if __name__ == '__main__':
+ s = Serial(0,
+ baudrate=19200, # baud rate
+ bytesize=serial.EIGHTBITS, # number of data bits
+ parity=serial.PARITY_EVEN, # enable parity checking
+ stopbits=serial.STOPBITS_ONE, # number of stop bits
+ timeout=3, # set a timeout value, None for waiting forever
+ xonxoff=0, # enable software flow control
+ rtscts=0, # enable RTS/CTS flow control
+ )
+ s.rts = True
+ s.dtr = True
+ s.reset_input_buffer()
+ s.reset_output_buffer()
+ s.write('hello')
+ sys.stdout.write('%r\n' % s.read(5))
+ sys.stdout.write('%s\n' % s.inWaiting())
+ del s
diff --git a/src/devtools/datool/pyserial/serialutil.py b/src/devtools/datool/pyserial/serialutil.py
new file mode 100644
index 0000000..6f31efe
--- /dev/null
+++ b/src/devtools/datool/pyserial/serialutil.py
@@ -0,0 +1,635 @@
+#! python
+#
+# Base class and support functions used by various backends.
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import io
+import time
+
+# ``memoryview`` was introduced in Python 2.7 and ``bytes(some_memoryview)``
+# isn't returning the contents (very unfortunate). Therefore we need special
+# cases and test for it. Ensure that there is a ``memoryview`` object for older
+# Python versions. This is easier than making every test dependent on its
+# existence.
+try:
+ memoryview
+except (NameError, AttributeError):
+ # implementation does not matter as we do not realy use it.
+ # it just must not inherit from something else we might care for.
+ class memoryview(object):
+ pass
+
+try:
+ unicode
+except (NameError, AttributeError):
+ unicode = str # for Python 3
+
+
+# "for byte in data" fails for python3 as it returns ints instead of bytes
+def iterbytes(b):
+ """Iterate over bytes, returning bytes instead of ints (python3)"""
+ if isinstance(b, memoryview):
+ b = b.tobytes()
+ x = 0
+ while True:
+ a = b[x:x + 1]
+ x += 1
+ if a:
+ yield a
+ else:
+ break
+
+
+# all Python versions prior 3.x convert ``str([17])`` to '[17]' instead of '\x11'
+# so a simple ``bytes(sequence)`` doesn't work for all versions
+def to_bytes(seq):
+ """convert a sequence to a bytes type"""
+ if isinstance(seq, bytes):
+ return seq
+ elif isinstance(seq, bytearray):
+ return bytes(seq)
+ elif isinstance(seq, memoryview):
+ return seq.tobytes()
+ elif isinstance(seq, unicode):
+ raise TypeError('unicode strings are not supported, please encode to bytes: %r' % (seq,))
+ else:
+ b = bytearray()
+ for item in seq:
+ # this one handles int and bytes in Python 2.7
+ # add conversion in case of Python 3.x
+ if isinstance(item, bytes):
+ item = ord(item)
+ b.append(item)
+ return bytes(b)
+
+# create control bytes
+XON = to_bytes([17])
+XOFF = to_bytes([19])
+
+CR = to_bytes([13])
+LF = to_bytes([10])
+
+
+PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE = 'N', 'E', 'O', 'M', 'S'
+STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO = (1, 1.5, 2)
+FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS = (5, 6, 7, 8)
+
+PARITY_NAMES = {
+ PARITY_NONE: 'None',
+ PARITY_EVEN: 'Even',
+ PARITY_ODD: 'Odd',
+ PARITY_MARK: 'Mark',
+ PARITY_SPACE: 'Space',
+}
+
+
+class SerialException(IOError):
+ """Base class for serial port related exceptions."""
+
+
+class SerialTimeoutException(SerialException):
+ """Write timeouts give an exception"""
+
+
+writeTimeoutError = SerialTimeoutException('Write timeout')
+portNotOpenError = SerialException('Attempting to use a port that is not open')
+
+
+class SerialBase(io.RawIOBase):
+ """\
+ Serial port base class. Provides __init__ function and properties to
+ get/set port settings.
+ """
+
+ # default values, may be overridden in subclasses that do not support all values
+ BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200, 230400, 460800, 500000,
+ 576000, 921600, 1000000, 1152000, 1500000, 2000000, 2500000,
+ 3000000, 3500000, 4000000)
+ BYTESIZES = (FIVEBITS, SIXBITS, SEVENBITS, EIGHTBITS)
+ PARITIES = (PARITY_NONE, PARITY_EVEN, PARITY_ODD, PARITY_MARK, PARITY_SPACE)
+ STOPBITS = (STOPBITS_ONE, STOPBITS_ONE_POINT_FIVE, STOPBITS_TWO)
+
+ def __init__(self,
+ port=None, # number of device, numbering starts at
+ # zero. if everything fails, the user
+ # can specify a device string, note
+ # that this isn't portable anymore
+ # port will be opened if one is specified
+ baudrate=9600, # baud rate
+ bytesize=EIGHTBITS, # number of data bits
+ parity=PARITY_NONE, # enable parity checking
+ stopbits=STOPBITS_ONE, # number of stop bits
+ timeout=None, # set a timeout value, None to wait forever
+ xonxoff=False, # enable software flow control
+ rtscts=False, # enable RTS/CTS flow control
+ write_timeout=None, # set a timeout for writes
+ dsrdtr=False, # None: use rtscts setting, dsrdtr override if True or False
+ inter_byte_timeout=None, # Inter-character timeout, None to disable
+ **kwargs
+ ):
+ """\
+ Initialize comm port object. If a port is given, then the port will be
+ opened immediately. Otherwise a Serial port object in closed state
+ is returned.
+ """
+
+ self.is_open = False
+ # correct values are assigned below through properties
+ self._port = None
+ self._baudrate = None
+ self._bytesize = None
+ self._parity = None
+ self._stopbits = None
+ self._timeout = None
+ self._write_timeout = None
+ self._xonxoff = None
+ self._rtscts = None
+ self._dsrdtr = None
+ self._inter_byte_timeout = None
+ self._rs485_mode = None # disabled by default
+ self._rts_state = True
+ self._dtr_state = True
+ self._break_state = False
+
+ # assign values using get/set methods using the properties feature
+ self.port = port
+ self.baudrate = baudrate
+ self.bytesize = bytesize
+ self.parity = parity
+ self.stopbits = stopbits
+ self.timeout = timeout
+ self.write_timeout = write_timeout
+ self.xonxoff = xonxoff
+ self.rtscts = rtscts
+ self.dsrdtr = dsrdtr
+ self.inter_byte_timeout = inter_byte_timeout
+ # watch for backward compatible kwargs
+ if 'writeTimeout' in kwargs:
+ self.write_timeout = kwargs.pop('writeTimeout')
+ if 'interCharTimeout' in kwargs:
+ self.inter_byte_timeout = kwargs.pop('interCharTimeout')
+ if kwargs:
+ raise ValueError('unexpected keyword arguments: %r' % (kwargs,))
+
+ if port is not None:
+ self.open()
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ # to be implemented by subclasses:
+ # def open(self):
+ # def close(self):
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ @property
+ def port(self):
+ """\
+ Get the current port setting. The value that was passed on init or using
+ setPort() is passed back. See also the attribute portstr which contains
+ the name of the port as a string.
+ """
+ return self._port
+
+ @port.setter
+ def port(self, port):
+ """\
+ Change the port. The attribute portstr is set to a string that
+ contains the name of the port.
+ """
+
+ was_open = self.is_open
+ if was_open:
+ self.close()
+ self.portstr = port
+ self._port = port
+ self.name = self.portstr
+ if was_open:
+ self.open()
+
+
+ @property
+ def baudrate(self):
+ """Get the current baud rate setting."""
+ return self._baudrate
+
+ @baudrate.setter
+ def baudrate(self, baudrate):
+ """\
+ Change baud rate. It raises a ValueError if the port is open and the
+ baud rate is not possible. If the port is closed, then the value is
+ accepted and the exception is raised when the port is opened.
+ """
+ try:
+ b = int(baudrate)
+ except TypeError:
+ raise ValueError("Not a valid baudrate: %r" % (baudrate,))
+ else:
+ if b <= 0:
+ raise ValueError("Not a valid baudrate: %r" % (baudrate,))
+ self._baudrate = b
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def bytesize(self):
+ """Get the current byte size setting."""
+ return self._bytesize
+
+ @bytesize.setter
+ def bytesize(self, bytesize):
+ """Change byte size."""
+ if bytesize not in self.BYTESIZES:
+ raise ValueError("Not a valid byte size: %r" % (bytesize,))
+ self._bytesize = bytesize
+ if self.is_open:
+ self._reconfigure_port()
+
+
+
+ @property
+ def parity(self):
+ """Get the current parity setting."""
+ return self._parity
+
+ @parity.setter
+ def parity(self, parity):
+ """Change parity setting."""
+ if parity not in self.PARITIES:
+ raise ValueError("Not a valid parity: %r" % (parity,))
+ self._parity = parity
+ if self.is_open:
+ self._reconfigure_port()
+
+
+
+ @property
+ def stopbits(self):
+ """Get the current stop bits setting."""
+ return self._stopbits
+
+ @stopbits.setter
+ def stopbits(self, stopbits):
+ """Change stop bits size."""
+ if stopbits not in self.STOPBITS:
+ raise ValueError("Not a valid stop bit size: %r" % (stopbits,))
+ self._stopbits = stopbits
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def timeout(self):
+ """Get the current timeout setting."""
+ return self._timeout
+
+ @timeout.setter
+ def timeout(self, timeout):
+ """Change timeout setting."""
+ if timeout is not None:
+ try:
+ timeout + 1 # test if it's a number, will throw a TypeError if not...
+ except TypeError:
+ raise ValueError("Not a valid timeout: %r" % (timeout,))
+ if timeout < 0:
+ raise ValueError("Not a valid timeout: %r" % (timeout,))
+ self._timeout = timeout
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def write_timeout(self):
+ """Get the current timeout setting."""
+ return self._write_timeout
+
+ @write_timeout.setter
+ def write_timeout(self, timeout):
+ """Change timeout setting."""
+ if timeout is not None:
+ if timeout < 0:
+ raise ValueError("Not a valid timeout: %r" % (timeout,))
+ try:
+ timeout + 1 # test if it's a number, will throw a TypeError if not...
+ except TypeError:
+ raise ValueError("Not a valid timeout: %r" % timeout)
+
+ self._write_timeout = timeout
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def inter_byte_timeout(self):
+ """Get the current inter-character timeout setting."""
+ return self._inter_byte_timeout
+
+ @inter_byte_timeout.setter
+ def inter_byte_timeout(self, ic_timeout):
+ """Change inter-byte timeout setting."""
+ if ic_timeout is not None:
+ if ic_timeout < 0:
+ raise ValueError("Not a valid timeout: %r" % ic_timeout)
+ try:
+ ic_timeout + 1 # test if it's a number, will throw a TypeError if not...
+ except TypeError:
+ raise ValueError("Not a valid timeout: %r" % ic_timeout)
+
+ self._inter_byte_timeout = ic_timeout
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def xonxoff(self):
+ """Get the current XON/XOFF setting."""
+ return self._xonxoff
+
+ @xonxoff.setter
+ def xonxoff(self, xonxoff):
+ """Change XON/XOFF setting."""
+ self._xonxoff = xonxoff
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def rtscts(self):
+ """Get the current RTS/CTS flow control setting."""
+ return self._rtscts
+
+ @rtscts.setter
+ def rtscts(self, rtscts):
+ """Change RTS/CTS flow control setting."""
+ self._rtscts = rtscts
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def dsrdtr(self):
+ """Get the current DSR/DTR flow control setting."""
+ return self._dsrdtr
+
+ @dsrdtr.setter
+ def dsrdtr(self, dsrdtr=None):
+ """Change DsrDtr flow control setting."""
+ if dsrdtr is None:
+ # if not set, keep backwards compatibility and follow rtscts setting
+ self._dsrdtr = self._rtscts
+ else:
+ # if defined independently, follow its value
+ self._dsrdtr = dsrdtr
+ if self.is_open:
+ self._reconfigure_port()
+
+
+ @property
+ def rts(self):
+ return self._rts_state
+
+ @rts.setter
+ def rts(self, value):
+ self._rts_state = value
+ if self.is_open:
+ self._update_rts_state()
+
+ @property
+ def dtr(self):
+ return self._dtr_state
+
+ @dtr.setter
+ def dtr(self, value):
+ self._dtr_state = value
+ if self.is_open:
+ self._update_dtr_state()
+
+ @property
+ def break_condition(self):
+ return self._break_state
+
+ @break_condition.setter
+ def break_condition(self, value):
+ self._break_state = value
+ if self.is_open:
+ self._update_break_state()
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+ # functions useful for RS-485 adapters
+
+ @property
+ def rs485_mode(self):
+ """\
+ Enable RS485 mode and apply new settings, set to None to disable.
+ See serial.rs485.RS485Settings for more info about the value.
+ """
+ return self._rs485_mode
+
+ @rs485_mode.setter
+ def rs485_mode(self, rs485_settings):
+ self._rs485_mode = rs485_settings
+ if self.is_open:
+ self._reconfigure_port()
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ _SAVED_SETTINGS = ('baudrate', 'bytesize', 'parity', 'stopbits', 'xonxoff',
+ 'dsrdtr', 'rtscts', 'timeout', 'write_timeout',
+ 'inter_byte_timeout')
+
+ def get_settings(self):
+ """\
+ Get current port settings as a dictionary. For use with
+ apply_settings().
+ """
+ return dict([(key, getattr(self, '_' + key)) for key in self._SAVED_SETTINGS])
+
+ def apply_settings(self, d):
+ """\
+ Apply stored settings from a dictionary returned from
+ get_settings(). It's allowed to delete keys from the dictionary. These
+ values will simply left unchanged.
+ """
+ for key in self._SAVED_SETTINGS:
+ if key in d and d[key] != getattr(self, '_' + key): # check against internal "_" value
+ setattr(self, key, d[key]) # set non "_" value to use properties write function
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ def __repr__(self):
+ """String representation of the current port settings and its state."""
+ return "%s<id=0x%x, open=%s>(port=%r, baudrate=%r, bytesize=%r, parity=%r, stopbits=%r, timeout=%r, xonxoff=%r, rtscts=%r, dsrdtr=%r)" % (
+ self.__class__.__name__,
+ id(self),
+ self.is_open,
+ self.portstr,
+ self.baudrate,
+ self.bytesize,
+ self.parity,
+ self.stopbits,
+ self.timeout,
+ self.xonxoff,
+ self.rtscts,
+ self.dsrdtr,
+ )
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+ # compatibility with io library
+
+ def readable(self):
+ return True
+
+ def writable(self):
+ return True
+
+ def seekable(self):
+ return False
+
+ def readinto(self, b):
+ data = self.read(len(b))
+ n = len(data)
+ try:
+ b[:n] = data
+ except TypeError as err:
+ import array
+ if not isinstance(b, array.array):
+ raise err
+ b[:n] = array.array('b', data)
+ return n
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+ # context manager
+
+ def __enter__(self):
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.close()
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ def send_break(self, duration=0.25):
+ """\
+ Send break condition. Timed, returns to idle state after given
+ duration.
+ """
+ if not self.is_open:
+ raise portNotOpenError
+ self.break_condition = True
+ time.sleep(duration)
+ self.break_condition = False
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+ # backwards compatibility / deprecated functions
+
+ def flushInput(self):
+ self.reset_input_buffer()
+
+ def flushOutput(self):
+ self.reset_output_buffer()
+
+ def inWaiting(self):
+ return self.in_waiting
+
+ def sendBreak(self, duration=0.25):
+ self.send_break(duration)
+
+ def setRTS(self, value=1):
+ self.rts = value
+
+ def setDTR(self, value=1):
+ self.dtr = value
+
+ def getCTS(self):
+ return self.cts
+
+ def getDSR(self):
+ return self.dsr
+
+ def getRI(self):
+ return self.ri
+
+ def getCD(self):
+ return self.cd
+
+ @property
+ def writeTimeout(self):
+ return self.write_timeout
+
+ @writeTimeout.setter
+ def writeTimeout(self, timeout):
+ self.write_timeout = timeout
+
+ @property
+ def interCharTimeout(self):
+ return self.inter_byte_timeout
+
+ @interCharTimeout.setter
+ def interCharTimeout(self, interCharTimeout):
+ self.inter_byte_timeout = interCharTimeout
+
+ def getSettingsDict(self):
+ return self.get_settings()
+
+ def applySettingsDict(self, d):
+ self.apply_settings(d)
+
+ def isOpen(self):
+ return self.is_open
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+ # additional functionality
+
+ def read_all(self):
+ """\
+ Read all bytes currently available in the buffer of the OS.
+ """
+ return self.read(self.in_waiting)
+
+ def read_until(self, terminator=LF, size=None):
+ """\
+ Read until a termination sequence is found ('\n' by default), the size
+ is exceeded or until timeout occurs.
+ """
+ lenterm = len(terminator)
+ line = bytearray()
+ while True:
+ c = self.read(1)
+ if c:
+ line += c
+ if line[-lenterm:] == terminator:
+ break
+ if size is not None and len(line) >= size:
+ break
+ else:
+ break
+ return bytes(line)
+
+ def iread_until(self, *args, **kwargs):
+ """\
+ Read lines, implemented as generator. It will raise StopIteration on
+ timeout (empty read).
+ """
+ while True:
+ line = self.read_until(*args, **kwargs)
+ if not line:
+ break
+ yield line
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - -
+if __name__ == '__main__':
+ import sys
+ s = SerialBase()
+ sys.stdout.write('port name: %s\n' % s.name)
+ sys.stdout.write('baud rates: %s\n' % s.BAUDRATES)
+ sys.stdout.write('byte sizes: %s\n' % s.BYTESIZES)
+ sys.stdout.write('parities: %s\n' % s.PARITIES)
+ sys.stdout.write('stop bits: %s\n' % s.STOPBITS)
+ sys.stdout.write('%s\n' % s)
diff --git a/src/devtools/datool/pyserial/serialwin32.py b/src/devtools/datool/pyserial/serialwin32.py
new file mode 100644
index 0000000..309264e
--- /dev/null
+++ b/src/devtools/datool/pyserial/serialwin32.py
@@ -0,0 +1,443 @@
+#! python
+#
+# backend for Windows ("win32" incl. 32/64 bit support)
+#
+# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# SPDX-License-Identifier: BSD-3-Clause
+#
+# Initial patch to use ctypes by Giovanni Bajo <rasky@develer.com>
+
+import ctypes
+import time
+from pyserial import win32
+
+import pyserial as serial
+from pyserial.serialutil import SerialBase, SerialException, to_bytes, portNotOpenError, writeTimeoutError
+
+
+class Serial(SerialBase):
+ """Serial port implementation for Win32 based on ctypes."""
+
+ BAUDRATES = (50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
+ 9600, 19200, 38400, 57600, 115200)
+
+ def __init__(self, *args, **kwargs):
+ super(SerialBase, self).__init__()
+ self._port_handle = None
+ self._overlapped_read = None
+ self._overlapped_write = None
+ SerialBase.__init__(self, *args, **kwargs)
+
+ def open(self):
+ """\
+ Open port with current settings. This may throw a SerialException
+ if the port cannot be opened.
+ """
+ if self._port is None:
+ raise SerialException("Port must be configured before it can be used.")
+ if self.is_open:
+ raise SerialException("Port is already open.")
+ # the "\\.\COMx" format is required for devices other than COM1-COM8
+ # not all versions of windows seem to support this properly
+ # so that the first few ports are used with the DOS device name
+ port = self.name
+ try:
+ if port.upper().startswith('COM') and int(port[3:]) > 8:
+ port = '\\\\.\\' + port
+ except ValueError:
+ # for like COMnotanumber
+ pass
+ self._port_handle = win32.CreateFile(
+ port,
+ win32.GENERIC_READ | win32.GENERIC_WRITE,
+ 0, # exclusive access
+ None, # no security
+ win32.OPEN_EXISTING,
+ win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
+ 0)
+ if self._port_handle == win32.INVALID_HANDLE_VALUE:
+ self._port_handle = None # 'cause __del__ is called anyway
+ raise SerialException("could not open port %r: %r" % (self.portstr, ctypes.WinError()))
+
+ try:
+ self._overlapped_read = win32.OVERLAPPED()
+ self._overlapped_read.hEvent = win32.CreateEvent(None, 1, 0, None)
+ self._overlapped_write = win32.OVERLAPPED()
+ #~ self._overlapped_write.hEvent = win32.CreateEvent(None, 1, 0, None)
+ self._overlapped_write.hEvent = win32.CreateEvent(None, 0, 0, None)
+
+ # Setup a 4k buffer
+ win32.SetupComm(self._port_handle, 4096, 4096)
+
+ # Save original timeout values:
+ self._orgTimeouts = win32.COMMTIMEOUTS()
+ win32.GetCommTimeouts(self._port_handle, ctypes.byref(self._orgTimeouts))
+
+ self._reconfigure_port()
+
+ # Clear buffers:
+ # Remove anything that was there
+ win32.PurgeComm(
+ self._port_handle,
+ win32.PURGE_TXCLEAR | win32.PURGE_TXABORT |
+ win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
+ except:
+ try:
+ self._close()
+ except:
+ # ignore any exception when closing the port
+ # also to keep original exception that happened when setting up
+ pass
+ self._port_handle = None
+ raise
+ else:
+ self.is_open = True
+
+ def _reconfigure_port(self):
+ """Set communication parameters on opened port."""
+ if not self._port_handle:
+ raise SerialException("Can only operate on a valid port handle")
+
+ # Set Windows timeout values
+ # timeouts is a tuple with the following items:
+ # (ReadIntervalTimeout,ReadTotalTimeoutMultiplier,
+ # ReadTotalTimeoutConstant,WriteTotalTimeoutMultiplier,
+ # WriteTotalTimeoutConstant)
+ timeouts = win32.COMMTIMEOUTS()
+ if self._timeout is None:
+ pass # default of all zeros is OK
+ elif self._timeout == 0:
+ timeouts.ReadIntervalTimeout = win32.MAXDWORD
+ else:
+ timeouts.ReadTotalTimeoutConstant = max(int(self._timeout * 1000), 1)
+ if self._timeout != 0 and self._inter_byte_timeout is not None:
+ timeouts.ReadIntervalTimeout = max(int(self._inter_byte_timeout * 1000), 1)
+
+ if self._write_timeout is None:
+ pass
+ elif self._write_timeout == 0:
+ timeouts.WriteTotalTimeoutConstant = win32.MAXDWORD
+ else:
+ timeouts.WriteTotalTimeoutConstant = max(int(self._write_timeout * 1000), 1)
+ win32.SetCommTimeouts(self._port_handle, ctypes.byref(timeouts))
+
+ win32.SetCommMask(self._port_handle, win32.EV_ERR)
+
+ # Setup the connection info.
+ # Get state and modify it:
+ comDCB = win32.DCB()
+ win32.GetCommState(self._port_handle, ctypes.byref(comDCB))
+ comDCB.BaudRate = self._baudrate
+
+ if self._bytesize == serial.FIVEBITS:
+ comDCB.ByteSize = 5
+ elif self._bytesize == serial.SIXBITS:
+ comDCB.ByteSize = 6
+ elif self._bytesize == serial.SEVENBITS:
+ comDCB.ByteSize = 7
+ elif self._bytesize == serial.EIGHTBITS:
+ comDCB.ByteSize = 8
+ else:
+ raise ValueError("Unsupported number of data bits: %r" % self._bytesize)
+
+ if self._parity == serial.PARITY_NONE:
+ comDCB.Parity = win32.NOPARITY
+ comDCB.fParity = 0 # Disable Parity Check
+ elif self._parity == serial.PARITY_EVEN:
+ comDCB.Parity = win32.EVENPARITY
+ comDCB.fParity = 1 # Enable Parity Check
+ elif self._parity == serial.PARITY_ODD:
+ comDCB.Parity = win32.ODDPARITY
+ comDCB.fParity = 1 # Enable Parity Check
+ elif self._parity == serial.PARITY_MARK:
+ comDCB.Parity = win32.MARKPARITY
+ comDCB.fParity = 1 # Enable Parity Check
+ elif self._parity == serial.PARITY_SPACE:
+ comDCB.Parity = win32.SPACEPARITY
+ comDCB.fParity = 1 # Enable Parity Check
+ else:
+ raise ValueError("Unsupported parity mode: %r" % self._parity)
+
+ if self._stopbits == serial.STOPBITS_ONE:
+ comDCB.StopBits = win32.ONESTOPBIT
+ elif self._stopbits == serial.STOPBITS_ONE_POINT_FIVE:
+ comDCB.StopBits = win32.ONE5STOPBITS
+ elif self._stopbits == serial.STOPBITS_TWO:
+ comDCB.StopBits = win32.TWOSTOPBITS
+ else:
+ raise ValueError("Unsupported number of stop bits: %r" % self._stopbits)
+
+ comDCB.fBinary = 1 # Enable Binary Transmission
+ # Char. w/ Parity-Err are replaced with 0xff (if fErrorChar is set to TRUE)
+ if self._rs485_mode is None:
+ if self._rtscts:
+ comDCB.fRtsControl = win32.RTS_CONTROL_HANDSHAKE
+ else:
+ comDCB.fRtsControl = win32.RTS_CONTROL_ENABLE if self._rts_state else win32.RTS_CONTROL_DISABLE
+ comDCB.fOutxCtsFlow = self._rtscts
+ else:
+ # checks for unsupported settings
+ # XXX verify if platform really does not have a setting for those
+ if not self._rs485_mode.rts_level_for_tx:
+ raise ValueError(
+ 'Unsupported value for RS485Settings.rts_level_for_tx: %r' % (
+ self._rs485_mode.rts_level_for_tx,))
+ if self._rs485_mode.rts_level_for_rx:
+ raise ValueError(
+ 'Unsupported value for RS485Settings.rts_level_for_rx: %r' % (
+ self._rs485_mode.rts_level_for_rx,))
+ if self._rs485_mode.delay_before_tx is not None:
+ raise ValueError(
+ 'Unsupported value for RS485Settings.delay_before_tx: %r' % (
+ self._rs485_mode.delay_before_tx,))
+ if self._rs485_mode.delay_before_rx is not None:
+ raise ValueError(
+ 'Unsupported value for RS485Settings.delay_before_rx: %r' % (
+ self._rs485_mode.delay_before_rx,))
+ if self._rs485_mode.loopback:
+ raise ValueError(
+ 'Unsupported value for RS485Settings.loopback: %r' % (
+ self._rs485_mode.loopback,))
+ comDCB.fRtsControl = win32.RTS_CONTROL_TOGGLE
+ comDCB.fOutxCtsFlow = 0
+
+ if self._dsrdtr:
+ comDCB.fDtrControl = win32.DTR_CONTROL_HANDSHAKE
+ else:
+ comDCB.fDtrControl = win32.DTR_CONTROL_ENABLE if self._dtr_state else win32.DTR_CONTROL_DISABLE
+ comDCB.fOutxDsrFlow = self._dsrdtr
+ comDCB.fOutX = self._xonxoff
+ comDCB.fInX = self._xonxoff
+ comDCB.fNull = 0
+ comDCB.fErrorChar = 0
+ comDCB.fAbortOnError = 0
+ comDCB.XonChar = serial.XON
+ comDCB.XoffChar = serial.XOFF
+
+ if not win32.SetCommState(self._port_handle, ctypes.byref(comDCB)):
+ raise SerialException("Cannot configure port, something went wrong. Original message: %r" % ctypes.WinError())
+
+ #~ def __del__(self):
+ #~ self.close()
+
+ def _close(self):
+ """internal close port helper"""
+ if self._port_handle:
+ # Restore original timeout values:
+ win32.SetCommTimeouts(self._port_handle, self._orgTimeouts)
+ # Close COM-Port:
+ win32.CloseHandle(self._port_handle)
+ if self._overlapped_read is not None:
+ win32.CloseHandle(self._overlapped_read.hEvent)
+ self._overlapped_read = None
+ if self._overlapped_write is not None:
+ win32.CloseHandle(self._overlapped_write.hEvent)
+ self._overlapped_write = None
+ self._port_handle = None
+
+ def close(self):
+ """Close port"""
+ if self.is_open:
+ self._close()
+ self.is_open = False
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+
+ @property
+ def in_waiting(self):
+ """Return the number of bytes currently in the input buffer."""
+ flags = win32.DWORD()
+ comstat = win32.COMSTAT()
+ if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
+ raise SerialException('call to ClearCommError failed')
+ return comstat.cbInQue
+
+ def read(self, size=1):
+ """\
+ Read size bytes from the serial port. If a timeout is set it may
+ return less characters as requested. With no timeout it will block
+ until the requested number of bytes is read."""
+ if not self._port_handle:
+ raise portNotOpenError
+ if size > 0:
+ win32.ResetEvent(self._overlapped_read.hEvent)
+ flags = win32.DWORD()
+ comstat = win32.COMSTAT()
+ if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
+ raise SerialException('call to ClearCommError failed')
+ if self.timeout == 0:
+ n = min(comstat.cbInQue, size)
+ if n > 0:
+ buf = ctypes.create_string_buffer(n)
+ rc = win32.DWORD()
+ read_ok = win32.ReadFile(self._port_handle, buf, n, ctypes.byref(rc), ctypes.byref(self._overlapped_read))
+ if not read_ok and win32.GetLastError() not in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
+ raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
+ win32.GetOverlappedResult(self._port_handle, ctypes.byref(self._overlapped_read), ctypes.byref(rc), True)
+ read = buf.raw[:rc.value]
+ else:
+ read = bytes()
+ else:
+ buf = ctypes.create_string_buffer(size)
+ rc = win32.DWORD()
+ read_ok = win32.ReadFile(self._port_handle, buf, size, ctypes.byref(rc), ctypes.byref(self._overlapped_read))
+ if not read_ok and win32.GetLastError() not in (win32.ERROR_SUCCESS, win32.ERROR_IO_PENDING):
+ raise SerialException("ReadFile failed (%r)" % ctypes.WinError())
+ win32.GetOverlappedResult(self._port_handle, ctypes.byref(self._overlapped_read), ctypes.byref(rc), True)
+ read = buf.raw[:rc.value]
+ else:
+ read = bytes()
+ return bytes(read)
+
+ def write(self, data):
+ """Output the given byte string over the serial port."""
+ if not self._port_handle:
+ raise portNotOpenError
+ #~ if not isinstance(data, (bytes, bytearray)):
+ #~ raise TypeError('expected %s or bytearray, got %s' % (bytes, type(data)))
+ # convert data (needed in case of memoryview instance: Py 3.1 io lib), ctypes doesn't like memoryview
+ data = to_bytes(data)
+ if data:
+ #~ win32event.ResetEvent(self._overlapped_write.hEvent)
+ n = win32.DWORD()
+ err = win32.WriteFile(self._port_handle, data, len(data), ctypes.byref(n), self._overlapped_write)
+ if not err and win32.GetLastError() != win32.ERROR_IO_PENDING:
+ raise SerialException("WriteFile failed (%r)" % ctypes.WinError())
+ if self._write_timeout != 0: # if blocking (None) or w/ write timeout (>0)
+ # Wait for the write to complete.
+ #~ win32.WaitForSingleObject(self._overlapped_write.hEvent, win32.INFINITE)
+ err = win32.GetOverlappedResult(self._port_handle, self._overlapped_write, ctypes.byref(n), True)
+ if n.value != len(data):
+ raise writeTimeoutError
+ return n.value
+ else:
+ return 0
+
+ def flush(self):
+ """\
+ Flush of file like objects. In this case, wait until all data
+ is written.
+ """
+ while self.out_waiting:
+ time.sleep(0.05)
+ # XXX could also use WaitCommEvent with mask EV_TXEMPTY, but it would
+ # require overlapped IO and its also only possible to set a single mask
+ # on the port---
+
+ def reset_input_buffer(self):
+ """Clear input buffer, discarding all that is in the buffer."""
+ if not self._port_handle:
+ raise portNotOpenError
+ win32.PurgeComm(self._port_handle, win32.PURGE_RXCLEAR | win32.PURGE_RXABORT)
+
+ def reset_output_buffer(self):
+ """\
+ Clear output buffer, aborting the current output and discarding all
+ that is in the buffer.
+ """
+ if not self._port_handle:
+ raise portNotOpenError
+ win32.PurgeComm(self._port_handle, win32.PURGE_TXCLEAR | win32.PURGE_TXABORT)
+
+ def _update_break_state(self):
+ """Set break: Controls TXD. When active, to transmitting is possible."""
+ if not self._port_handle:
+ raise portNotOpenError
+ if self._break_state:
+ win32.SetCommBreak(self._port_handle)
+ else:
+ win32.ClearCommBreak(self._port_handle)
+
+ def _update_rts_state(self):
+ """Set terminal status line: Request To Send"""
+ if self._rts_state:
+ win32.EscapeCommFunction(self._port_handle, win32.SETRTS)
+ else:
+ win32.EscapeCommFunction(self._port_handle, win32.CLRRTS)
+
+ def _update_dtr_state(self):
+ """Set terminal status line: Data Terminal Ready"""
+ if self._dtr_state:
+ win32.EscapeCommFunction(self._port_handle, win32.SETDTR)
+ else:
+ win32.EscapeCommFunction(self._port_handle, win32.CLRDTR)
+
+ def _GetCommModemStatus(self):
+ if not self._port_handle:
+ raise portNotOpenError
+ stat = win32.DWORD()
+ win32.GetCommModemStatus(self._port_handle, ctypes.byref(stat))
+ return stat.value
+
+ @property
+ def cts(self):
+ """Read terminal status line: Clear To Send"""
+ return win32.MS_CTS_ON & self._GetCommModemStatus() != 0
+
+ @property
+ def dsr(self):
+ """Read terminal status line: Data Set Ready"""
+ return win32.MS_DSR_ON & self._GetCommModemStatus() != 0
+
+ @property
+ def ri(self):
+ """Read terminal status line: Ring Indicator"""
+ return win32.MS_RING_ON & self._GetCommModemStatus() != 0
+
+ @property
+ def cd(self):
+ """Read terminal status line: Carrier Detect"""
+ return win32.MS_RLSD_ON & self._GetCommModemStatus() != 0
+
+ # - - platform specific - - - -
+
+ def set_buffer_size(self, rx_size=4096, tx_size=None):
+ """\
+ Recommend a buffer size to the driver (device driver can ignore this
+ value). Must be called before the port is opended.
+ """
+ if tx_size is None:
+ tx_size = rx_size
+ win32.SetupComm(self._port_handle, rx_size, tx_size)
+
+ def set_output_flow_control(self, enable=True):
+ """\
+ Manually control flow - when software flow control is enabled.
+ This will do the same as if XON (true) or XOFF (false) are received
+ from the other device and control the transmission accordingly.
+ WARNING: this function is not portable to different platforms!
+ """
+ if not self._port_handle:
+ raise portNotOpenError
+ if enable:
+ win32.EscapeCommFunction(self._port_handle, win32.SETXON)
+ else:
+ win32.EscapeCommFunction(self._port_handle, win32.SETXOFF)
+
+ @property
+ def out_waiting(self):
+ """Return how many bytes the in the outgoing buffer"""
+ flags = win32.DWORD()
+ comstat = win32.COMSTAT()
+ if not win32.ClearCommError(self._port_handle, ctypes.byref(flags), ctypes.byref(comstat)):
+ raise SerialException('call to ClearCommError failed')
+ return comstat.cbOutQue
+
+
+# Nur Testfunktion!!
+if __name__ == '__main__':
+ import sys
+ s = Serial(0)
+ sys.stdout.write("%s\n" % s)
+
+ s = Serial()
+ sys.stdout.write("%s\n" % s)
+
+ s.baudrate = 19200
+ s.databits = 7
+ s.close()
+ s.port = 0
+ s.open()
+ sys.stdout.write("%s\n" % s)
diff --git a/src/devtools/datool/pyserial/tools/__init__.py b/src/devtools/datool/pyserial/tools/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/__init__.py
diff --git a/src/devtools/datool/pyserial/tools/hexlify_codec.py b/src/devtools/datool/pyserial/tools/hexlify_codec.py
new file mode 100644
index 0000000..3200701
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/hexlify_codec.py
@@ -0,0 +1,98 @@
+#! python
+#
+# This is a codec to create and decode hexdumps with spaces between characters. used by miniterm.
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2011 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+"""\
+Python 'hex' Codec - 2-digit hex with spaces content transfer encoding.
+"""
+
+import codecs
+import pyserial as serial
+
+HEXDIGITS = '0123456789ABCDEF'
+
+### Codec APIs
+
+
+def hex_encode(input, errors='strict'):
+ return (serial.to_bytes([int(h, 16) for h in input.split()]), len(input))
+
+
+def hex_decode(input, errors='strict'):
+ return (''.join('{:02X} '.format(b) for b in input), len(input))
+
+
+class Codec(codecs.Codec):
+ def encode(self, input, errors='strict'):
+ return serial.to_bytes([int(h, 16) for h in input.split()])
+
+ def decode(self, input, errors='strict'):
+ return ''.join('{:02X} '.format(b) for b in input)
+
+
+class IncrementalEncoder(codecs.IncrementalEncoder):
+
+ def __init__(self, errors='strict'):
+ self.errors = errors
+ self.state = 0
+
+ def reset(self):
+ self.state = 0
+
+ def getstate(self):
+ return self.state
+
+ def setstate(self, state):
+ self.state = state
+
+ def encode(self, input, final=False):
+ state = self.state
+ encoded = []
+ for c in input.upper():
+ if c in HEXDIGITS:
+ z = HEXDIGITS.index(c)
+ if state:
+ encoded.append(z + (state & 0xf0))
+ state = 0
+ else:
+ state = 0x100 + (z << 4)
+ elif c == ' ': # allow spaces to separate values
+ if state and self.errors == 'strict':
+ raise UnicodeError('odd number of hex digits')
+ state = 0
+ else:
+ if self.errors == 'strict':
+ raise UnicodeError('non-hex digit found: %r' % c)
+ self.state = state
+ return serial.to_bytes(encoded)
+
+
+class IncrementalDecoder(codecs.IncrementalDecoder):
+ def decode(self, input, final=False):
+ return ''.join('{:02X} '.format(b) for b in input)
+
+
+class StreamWriter(Codec, codecs.StreamWriter):
+ pass
+
+
+class StreamReader(Codec, codecs.StreamReader):
+ pass
+
+
+### encodings module API
+def getregentry():
+ return codecs.CodecInfo(
+ name='hexlify',
+ encode=hex_encode,
+ decode=hex_decode,
+ incrementalencoder=IncrementalEncoder,
+ incrementaldecoder=IncrementalDecoder,
+ streamwriter=StreamWriter,
+ streamreader=StreamReader,
+ _is_text_encoding=True,
+ )
diff --git a/src/devtools/datool/pyserial/tools/list_ports.py b/src/devtools/datool/pyserial/tools/list_ports.py
new file mode 100644
index 0000000..d174f2a
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/list_ports.py
@@ -0,0 +1,103 @@
+#!/usr/bin/env python
+#
+# Serial port enumeration. Console tool and backend selection.
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2011-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+"""\
+This module will provide a function called comports that returns an
+iterable (generator or list) that will enumerate available com ports. Note that
+on some systems non-existent ports may be listed.
+
+Additionally a grep function is supplied that can be used to search for ports
+based on their descriptions or hardware ID.
+"""
+
+import sys
+import os
+import re
+
+# chose an implementation, depending on os
+#~ if sys.platform == 'cli':
+#~ else:
+if os.name == 'nt': # sys.platform == 'win32':
+ from pyserial.tools.list_ports_windows import comports
+elif os.name == 'posix':
+ from pyserial.tools.list_ports_posix import comports
+#~ elif os.name == 'java':
+else:
+ raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+def grep(regexp):
+ """\
+ Search for ports using a regular expression. Port name, description and
+ hardware ID are searched. The function returns an iterable that returns the
+ same tuples as comport() would do.
+ """
+ r = re.compile(regexp, re.I)
+ for info in comports():
+ port, desc, hwid = info
+ if r.search(port) or r.search(desc) or r.search(hwid):
+ yield info
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+def main():
+ import argparse
+
+ parser = argparse.ArgumentParser(description='Serial port enumeration')
+
+ parser.add_argument(
+ 'regexp',
+ nargs='?',
+ help='only show ports that match this regex')
+
+ parser.add_argument(
+ '-v', '--verbose',
+ action='store_true',
+ help='show more messages')
+
+ parser.add_argument(
+ '-q', '--quiet',
+ action='store_true',
+ help='suppress all messages')
+
+ parser.add_argument(
+ '-n',
+ type=int,
+ help='only output the N-th entry')
+
+ args = parser.parse_args()
+
+ hits = 0
+ # get iteraror w/ or w/o filter
+ if args.regexp:
+ if not args.quiet:
+ sys.stderr.write("Filtered list with regexp: %r\n" % (args.regexp,))
+ iterator = sorted(grep(args.regexp))
+ else:
+ iterator = sorted(comports())
+ # list them
+ for n, (port, desc, hwid) in enumerate(iterator, 1):
+ if args.n is None or args.n == n:
+ sys.stdout.write("{:20}\n".format(port))
+ if args.verbose:
+ sys.stdout.write(" desc: {}\n".format(desc))
+ sys.stdout.write(" hwid: {}\n".format(hwid))
+ hits += 1
+ if not args.quiet:
+ if hits:
+ sys.stderr.write("{} ports found\n".format(hits))
+ else:
+ sys.stderr.write("no ports found\n")
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# test
+if __name__ == '__main__':
+ main()
diff --git a/src/devtools/datool/pyserial/tools/list_ports_common.py b/src/devtools/datool/pyserial/tools/list_ports_common.py
new file mode 100644
index 0000000..640b2a1
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/list_ports_common.py
@@ -0,0 +1,90 @@
+#!/usr/bin/env python
+#
+# This is a helper module for the various platform dependent list_port
+# implementations.
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+import re
+
+
+def numsplit(text):
+ """\
+ Convert string into a list of texts and numbers in order to support a
+ natural sorting.
+ """
+ result = []
+ for group in re.split(r'(\d+)', text):
+ if group:
+ try:
+ group = int(group)
+ except ValueError:
+ pass
+ result.append(group)
+ return result
+
+
+class ListPortInfo(object):
+ """Info collection base class for serial ports"""
+
+ def __init__(self, device=None):
+ self.device = device
+ self.name = None
+ self.description = 'n/a'
+ self.hwid = 'n/a'
+ # USB specific data
+ self.vid = None
+ self.pid = None
+ self.serial_number = None
+ self.location = None
+ self.manufacturer = None
+ self.product = None
+ self.interface = None
+
+ def usb_description(self):
+ if self.interface is not None:
+ return '{} - {}'.format(self.product, self.interface)
+ elif self.product is not None:
+ return self.product
+ else:
+ return self.name
+
+ def usb_info(self):
+ return 'USB VID:PID={:04X}:{:04X}{}{}'.format(
+ self.vid,
+ self.pid,
+ ' SER={}'.format(self.serial_number) if self.serial_number is not None else '',
+ ' LOCATION={}'.format(self.location) if self.location is not None else '',
+ )
+
+ def apply_usb_info(self):
+ """update description and hwid from USB data"""
+ self.description = self.usb_description()
+ self.hwid = self.usb_info()
+
+ def __eq__(self, other):
+ return self.device == other.device
+
+ def __lt__(self, other):
+ return numsplit(self.device) < numsplit(other.device)
+
+ def __str__(self):
+ return '{} - {}'.format(self.device, self.description)
+
+ def __getitem__(self, index):
+ """Item access: backwards compatible -> (port, desc, hwid)"""
+ if index == 0:
+ return self.device
+ elif index == 1:
+ return self.description
+ elif index == 2:
+ return self.hwid
+ else:
+ raise IndexError('{} > 2'.format(index))
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# test
+if __name__ == '__main__':
+ print(ListPortInfo('dummy'))
diff --git a/src/devtools/datool/pyserial/tools/list_ports_linux.py b/src/devtools/datool/pyserial/tools/list_ports_linux.py
new file mode 100644
index 0000000..1969695
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/list_ports_linux.py
@@ -0,0 +1,84 @@
+#!/usr/bin/env python
+#
+# This is a module that gathers a list of serial ports including details on
+# GNU/Linux systems.
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2011-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import glob
+import os
+from pyserial.tools import list_ports_common
+
+
+class SysFS(list_ports_common.ListPortInfo):
+ """Wrapper for easy sysfs access and device info"""
+
+ def __init__(self, device):
+ super(SysFS, self).__init__(device)
+ self.name = os.path.basename(device)
+ self.usb_device_path = None
+ if os.path.exists('/sys/class/tty/%s/device' % (self.name,)):
+ self.device_path = os.path.realpath('/sys/class/tty/%s/device' % (self.name,))
+ self.subsystem = os.path.basename(os.path.realpath(os.path.join(self.device_path, 'subsystem')))
+ else:
+ self.device_path = None
+ self.subsystem = None
+ # check device type
+ if self.subsystem == 'usb-serial':
+ self.usb_device_path = os.path.dirname(os.path.dirname(self.device_path))
+ elif self.subsystem == 'usb':
+ self.usb_device_path = os.path.dirname(self.device_path)
+ else:
+ self.usb_device_path = None
+ # fill-in info for USB devices
+ if self.usb_device_path is not None:
+ self.vid = int(self.read_line(self.usb_device_path, 'idVendor'), 16)
+ self.pid = int(self.read_line(self.usb_device_path, 'idProduct'), 16)
+ self.serial_number = self.read_line(self.usb_device_path, 'serial')
+ self.location = os.path.basename(self.usb_device_path)
+ self.manufacturer = self.read_line(self.usb_device_path, 'manufacturer')
+ self.product = self.read_line(self.usb_device_path, 'product')
+ self.interface = self.read_line(self.device_path, 'interface')
+
+ if self.subsystem in ('usb', 'usb-serial'):
+ self.apply_usb_info()
+ #~ elif self.subsystem in ('pnp', 'amba'): # PCI based devices, raspi
+ elif self.subsystem == 'pnp': # PCI based devices
+ self.description = self.name
+ self.hwid = self.read_line(self.device_path, 'id')
+ elif self.subsystem == 'amba': # raspi
+ self.description = self.name
+ self.hwid = os.path.basename(self.device_path)
+
+ def read_line(self, *args):
+ """\
+ Helper function to read a single line from a file.
+ One or more parameters are allowed, they are joined with os.path.join.
+ Returns None on errors..
+ """
+ try:
+ with open(os.path.join(*args)) as f:
+ line = f.readline().strip()
+ return line
+ except IOError:
+ return None
+
+
+def comports():
+ devices = glob.glob('/dev/ttyS*') # built-in serial ports
+ devices.extend(glob.glob('/dev/ttyUSB*')) # usb-serial with own driver
+ devices.extend(glob.glob('/dev/ttyACM*')) # usb-serial with CDC-ACM profile
+ devices.extend(glob.glob('/dev/ttyAMA*')) # ARM internal port (raspi)
+ devices.extend(glob.glob('/dev/rfcomm*')) # BT serial devices
+ return [info
+ for info in [SysFS(d) for d in devices]
+ if info.subsystem != "platform"] # hide non-present internal serial ports
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# test
+if __name__ == '__main__':
+ for port, desc, hwid in sorted(comports()):
+ print("%s: %s [%s]" % (port, desc, hwid))
diff --git a/src/devtools/datool/pyserial/tools/list_ports_osx.py b/src/devtools/datool/pyserial/tools/list_ports_osx.py
new file mode 100644
index 0000000..543b3c7
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/list_ports_osx.py
@@ -0,0 +1,259 @@
+#!/usr/bin/env python
+#
+# This is a module that gathers a list of serial ports including details on OSX
+#
+# code originally from https://github.com/makerbot/pyserial/tree/master/serial/tools
+# with contributions from cibomahto, dgs3, FarMcKon, tedbrandston
+# and modifications by cliechti, hoihu, hardkrash
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2013-2015
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+
+# List all of the callout devices in OS/X by querying IOKit.
+
+# See the following for a reference of how to do this:
+# http://developer.apple.com/library/mac/#documentation/DeviceDrivers/Conceptual/WorkingWSerial/WWSerial_SerialDevs/SerialDevices.html#//apple_ref/doc/uid/TP30000384-CIHGEAFD
+
+# More help from darwin_hid.py
+
+# Also see the 'IORegistryExplorer' for an idea of what we are actually searching
+
+import ctypes
+from ctypes import util
+
+from pyserial.tools import list_ports_common
+
+iokit = ctypes.cdll.LoadLibrary(ctypes.util.find_library('IOKit'))
+cf = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreFoundation'))
+
+kIOMasterPortDefault = ctypes.c_void_p.in_dll(iokit, "kIOMasterPortDefault")
+kCFAllocatorDefault = ctypes.c_void_p.in_dll(cf, "kCFAllocatorDefault")
+
+kCFStringEncodingMacRoman = 0
+
+iokit.IOServiceMatching.restype = ctypes.c_void_p
+
+iokit.IOServiceGetMatchingServices.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
+iokit.IOServiceGetMatchingServices.restype = ctypes.c_void_p
+
+iokit.IORegistryEntryGetParentEntry.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
+
+iokit.IORegistryEntryCreateCFProperty.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_uint32]
+iokit.IORegistryEntryCreateCFProperty.restype = ctypes.c_void_p
+
+iokit.IORegistryEntryGetPath.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
+iokit.IORegistryEntryGetPath.restype = ctypes.c_void_p
+
+iokit.IORegistryEntryGetName.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
+iokit.IORegistryEntryGetName.restype = ctypes.c_void_p
+
+iokit.IOObjectGetClass.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
+iokit.IOObjectGetClass.restype = ctypes.c_void_p
+
+iokit.IOObjectRelease.argtypes = [ctypes.c_void_p]
+
+
+cf.CFStringCreateWithCString.argtypes = [ctypes.c_void_p, ctypes.c_char_p, ctypes.c_int32]
+cf.CFStringCreateWithCString.restype = ctypes.c_void_p
+
+cf.CFStringGetCStringPtr.argtypes = [ctypes.c_void_p, ctypes.c_uint32]
+cf.CFStringGetCStringPtr.restype = ctypes.c_char_p
+
+cf.CFNumberGetValue.argtypes = [ctypes.c_void_p, ctypes.c_uint32, ctypes.c_void_p]
+cf.CFNumberGetValue.restype = ctypes.c_void_p
+
+# void CFRelease ( CFTypeRef cf );
+cf.CFRelease.argtypes = [ctypes.c_void_p]
+cf.CFRelease.restype = None
+
+# CFNumber type defines
+kCFNumberSInt8Type = 1
+kCFNumberSInt16Type = 2
+kCFNumberSInt32Type = 3
+kCFNumberSInt64Type = 4
+
+
+def get_string_property(device_type, property):
+ """
+ Search the given device for the specified string property
+
+ @param device_type Type of Device
+ @param property String to search for
+ @return Python string containing the value, or None if not found.
+ """
+ key = cf.CFStringCreateWithCString(
+ kCFAllocatorDefault,
+ property.encode("mac_roman"),
+ kCFStringEncodingMacRoman)
+
+ CFContainer = iokit.IORegistryEntryCreateCFProperty(
+ device_type,
+ key,
+ kCFAllocatorDefault,
+ 0)
+ output = None
+
+ if CFContainer:
+ output = cf.CFStringGetCStringPtr(CFContainer, 0)
+ if output is not None:
+ output = output.decode('mac_roman')
+ cf.CFRelease(CFContainer)
+ return output
+
+
+def get_int_property(device_type, property, cf_number_type):
+ """
+ Search the given device for the specified string property
+
+ @param device_type Device to search
+ @param property String to search for
+ @param cf_number_type CFType number
+
+ @return Python string containing the value, or None if not found.
+ """
+ key = cf.CFStringCreateWithCString(
+ kCFAllocatorDefault,
+ property.encode("mac_roman"),
+ kCFStringEncodingMacRoman)
+
+ CFContainer = iokit.IORegistryEntryCreateCFProperty(
+ device_type,
+ key,
+ kCFAllocatorDefault,
+ 0)
+
+ if CFContainer:
+ if (cf_number_type == kCFNumberSInt32Type):
+ number = ctypes.c_uint32()
+ elif (cf_number_type == kCFNumberSInt16Type):
+ number = ctypes.c_uint16()
+ cf.CFNumberGetValue(CFContainer, cf_number_type, ctypes.byref(number))
+ cf.CFRelease(CFContainer)
+ return number.value
+ return None
+
+
+def IORegistryEntryGetName(device):
+ pathname = ctypes.create_string_buffer(100) # TODO: Is this ok?
+ iokit.IOObjectGetClass(device, ctypes.byref(pathname))
+ return pathname.value
+
+
+def GetParentDeviceByType(device, parent_type):
+ """ Find the first parent of a device that implements the parent_type
+ @param IOService Service to inspect
+ @return Pointer to the parent type, or None if it was not found.
+ """
+ # First, try to walk up the IOService tree to find a parent of this device that is a IOUSBDevice.
+ parent_type = parent_type.encode('mac_roman')
+ while IORegistryEntryGetName(device) != parent_type:
+ parent = ctypes.c_void_p()
+ response = iokit.IORegistryEntryGetParentEntry(
+ device,
+ "IOService".encode("mac_roman"),
+ ctypes.byref(parent))
+ # If we weren't able to find a parent for the device, we're done.
+ if response != 0:
+ return None
+ device = parent
+ return device
+
+
+def GetIOServicesByType(service_type):
+ """
+ returns iterator over specified service_type
+ """
+ serial_port_iterator = ctypes.c_void_p()
+
+ iokit.IOServiceGetMatchingServices(
+ kIOMasterPortDefault,
+ iokit.IOServiceMatching(service_type.encode('mac_roman')),
+ ctypes.byref(serial_port_iterator))
+
+ services = []
+ while iokit.IOIteratorIsValid(serial_port_iterator):
+ service = iokit.IOIteratorNext(serial_port_iterator)
+ if not service:
+ break
+ services.append(service)
+ iokit.IOObjectRelease(serial_port_iterator)
+ return services
+
+
+def location_to_string(locationID):
+ """
+ helper to calculate port and bus number from locationID
+ """
+ loc = ['{}-'.format(locationID >> 24)]
+ while locationID & 0xf00000:
+ if len(loc) > 1:
+ loc.append('.')
+ loc.append('{}'.format((locationID >> 20) & 0xf))
+ locationID <<= 4
+ return ''.join(loc)
+
+
+class SuitableSerialInterface(object):
+ pass
+
+
+def scan_interfaces():
+ """
+ helper function to scan USB interfaces
+ returns a list of SuitableSerialInterface objects with name and id attributes
+ """
+ interfaces = []
+ for service in GetIOServicesByType('IOSerialBSDClient'):
+ device = get_string_property(service, "IOCalloutDevice")
+ if device:
+ usb_device = GetParentDeviceByType(service, "IOUSBInterface")
+ if usb_device:
+ name = get_string_property(usb_device, "USB Interface Name") or None
+ locationID = get_int_property(usb_device, "locationID", kCFNumberSInt32Type) or ''
+ i = SuitableSerialInterface()
+ i.id = locationID
+ i.name = name
+ interfaces.append(i)
+ return interfaces
+
+
+def search_for_locationID_in_interfaces(serial_interfaces, locationID):
+ for interface in serial_interfaces:
+ if (interface.id == locationID):
+ return interface.name
+ return None
+
+
+def comports():
+ # Scan for all iokit serial ports
+ services = GetIOServicesByType('IOSerialBSDClient')
+ ports = []
+ serial_interfaces = scan_interfaces()
+ for service in services:
+ # First, add the callout device file.
+ device = get_string_property(service, "IOCalloutDevice")
+ if device:
+ info = list_ports_common.ListPortInfo(device)
+ # If the serial port is implemented by IOUSBDevice
+ usb_device = GetParentDeviceByType(service, "IOUSBDevice")
+ if usb_device:
+ # fetch some useful informations from properties
+ info.vid = get_int_property(usb_device, "idVendor", kCFNumberSInt16Type)
+ info.pid = get_int_property(usb_device, "idProduct", kCFNumberSInt16Type)
+ info.serial_number = get_string_property(usb_device, "USB Serial Number")
+ info.product = get_string_property(usb_device, "USB Product Name") or 'n/a'
+ info.manufacturer = get_string_property(usb_device, "USB Vendor Name")
+ locationID = get_int_property(usb_device, "locationID", kCFNumberSInt32Type)
+ info.location = location_to_string(locationID)
+ info.interface = search_for_locationID_in_interfaces(serial_interfaces, locationID)
+ info.apply_usb_info()
+ ports.append(info)
+ return ports
+
+# test
+if __name__ == '__main__':
+ for port, desc, hwid in sorted(comports()):
+ print("%s: %s [%s]" % (port, desc, hwid))
diff --git a/src/devtools/datool/pyserial/tools/list_ports_posix.py b/src/devtools/datool/pyserial/tools/list_ports_posix.py
new file mode 100644
index 0000000..ecb2334
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/list_ports_posix.py
@@ -0,0 +1,102 @@
+#!/usr/bin/env python
+#
+# This is a module that gathers a list of serial ports on POSIXy systems.
+# For some specific implementations, see also list_ports_linux, list_ports_osx
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2011-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+"""\
+The ``comports`` function is expected to return an iterable that yields tuples
+of 3 strings: port name, human readable description and a hardware ID.
+
+As currently no method is known to get the second two strings easily, they are
+currently just identical to the port name.
+"""
+
+import glob
+import sys
+import os
+from pyserial.tools import list_ports_common
+
+# try to detect the OS so that a device can be selected...
+plat = sys.platform.lower()
+
+if plat[:5] == 'linux': # Linux (confirmed) # noqa
+ from pyserial.tools.list_ports_linux import comports
+
+elif plat[:6] == 'darwin': # OS X (confirmed)
+ from pyserial.tools.list_ports_osx import comports
+
+elif plat == 'cygwin': # cygwin/win32
+ # cygwin accepts /dev/com* in many contexts
+ # (such as 'open' call, explicit 'ls'), but 'glob.glob'
+ # and bare 'ls' do not; so use /dev/ttyS* instead
+ def comports():
+ devices = glob.glob('/dev/ttyS*')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+elif plat[:7] == 'openbsd': # OpenBSD
+ def comports():
+ devices = glob.glob('/dev/cua*')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+elif plat[:3] == 'bsd' or plat[:7] == 'freebsd':
+
+ def comports():
+ devices = glob.glob('/dev/cua*[!.init][!.lock]')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+elif plat[:6] == 'netbsd': # NetBSD
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/dty*')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+elif plat[:4] == 'irix': # IRIX
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/ttyf*')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+elif plat[:2] == 'hp': # HP-UX (not tested)
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/tty*p0')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+elif plat[:5] == 'sunos': # Solaris/SunOS
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/tty*c')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+elif plat[:3] == 'aix': # AIX
+ def comports():
+ """scan for available ports. return a list of device names."""
+ devices = glob.glob('/dev/tty*')
+ return [list_ports_common.ListPortInfo(d) for d in devices]
+
+else:
+ # platform detection has failed...
+ import pyserial as serial
+ sys.stderr.write("""\
+don't know how to enumerate ttys on this system.
+! I you know how the serial ports are named send this information to
+! the author of this module:
+
+sys.platform = %r
+os.name = %r
+pySerial version = %s
+
+also add the naming scheme of the serial ports and with a bit luck you can get
+this module running...
+""" % (sys.platform, os.name, serial.VERSION))
+ raise ImportError("Sorry: no implementation for your platform ('%s') available" % (os.name,))
+
+# test
+if __name__ == '__main__':
+ for port, desc, hwid in sorted(comports()):
+ print("%s: %s [%s]" % (port, desc, hwid))
diff --git a/src/devtools/datool/pyserial/tools/list_ports_windows.py b/src/devtools/datool/pyserial/tools/list_ports_windows.py
new file mode 100644
index 0000000..e234fc2
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/list_ports_windows.py
@@ -0,0 +1,294 @@
+#! python
+#
+# Enumerate serial ports on Windows including a human readable description
+# and hardware information.
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2001-2016 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import re
+import ctypes
+from ctypes.wintypes import BOOL
+from ctypes.wintypes import HWND
+from ctypes.wintypes import DWORD
+from ctypes.wintypes import WORD
+from ctypes.wintypes import LONG
+from ctypes.wintypes import ULONG
+from ctypes.wintypes import LPCSTR
+from ctypes.wintypes import HKEY
+from ctypes.wintypes import BYTE
+import pyserial as serial
+from pyserial.win32 import ULONG_PTR
+from pyserial.tools import list_ports_common
+
+
+def ValidHandle(value, func, arguments):
+ if value == 0:
+ raise ctypes.WinError()
+ return value
+
+NULL = 0
+HDEVINFO = ctypes.c_void_p
+PCTSTR = ctypes.c_char_p
+PTSTR = ctypes.c_void_p
+CHAR = ctypes.c_char
+LPDWORD = PDWORD = ctypes.POINTER(DWORD)
+#~ LPBYTE = PBYTE = ctypes.POINTER(BYTE)
+LPBYTE = PBYTE = ctypes.c_void_p # XXX avoids error about types
+
+ACCESS_MASK = DWORD
+REGSAM = ACCESS_MASK
+
+
+def byte_buffer(length):
+ """Get a buffer for a string"""
+ return (BYTE*length)()
+
+
+def string(buffer):
+ s = []
+ for c in buffer:
+ if c == 0:
+ break
+ s.append(chr(c & 0xff)) # "& 0xff": hack to convert signed to unsigned
+ return ''.join(s)
+
+
+class GUID(ctypes.Structure):
+ _fields_ = [
+ ('Data1', DWORD),
+ ('Data2', WORD),
+ ('Data3', WORD),
+ ('Data4', BYTE*8),
+ ]
+
+ def __str__(self):
+ return "{%08x-%04x-%04x-%s-%s}" % (
+ self.Data1,
+ self.Data2,
+ self.Data3,
+ ''.join(["%02x" % d for d in self.Data4[:2]]),
+ ''.join(["%02x" % d for d in self.Data4[2:]]),
+ )
+
+
+class SP_DEVINFO_DATA(ctypes.Structure):
+ _fields_ = [
+ ('cbSize', DWORD),
+ ('ClassGuid', GUID),
+ ('DevInst', DWORD),
+ ('Reserved', ULONG_PTR),
+ ]
+
+ def __str__(self):
+ return "ClassGuid:%s DevInst:%s" % (self.ClassGuid, self.DevInst)
+
+PSP_DEVINFO_DATA = ctypes.POINTER(SP_DEVINFO_DATA)
+
+PSP_DEVICE_INTERFACE_DETAIL_DATA = ctypes.c_void_p
+
+setupapi = ctypes.windll.LoadLibrary("setupapi")
+SetupDiDestroyDeviceInfoList = setupapi.SetupDiDestroyDeviceInfoList
+SetupDiDestroyDeviceInfoList.argtypes = [HDEVINFO]
+SetupDiDestroyDeviceInfoList.restype = BOOL
+
+SetupDiClassGuidsFromName = setupapi.SetupDiClassGuidsFromNameA
+SetupDiClassGuidsFromName.argtypes = [PCTSTR, ctypes.POINTER(GUID), DWORD, PDWORD]
+SetupDiClassGuidsFromName.restype = BOOL
+
+SetupDiEnumDeviceInfo = setupapi.SetupDiEnumDeviceInfo
+SetupDiEnumDeviceInfo.argtypes = [HDEVINFO, DWORD, PSP_DEVINFO_DATA]
+SetupDiEnumDeviceInfo.restype = BOOL
+
+SetupDiGetClassDevs = setupapi.SetupDiGetClassDevsA
+SetupDiGetClassDevs.argtypes = [ctypes.POINTER(GUID), PCTSTR, HWND, DWORD]
+SetupDiGetClassDevs.restype = HDEVINFO
+SetupDiGetClassDevs.errcheck = ValidHandle
+
+SetupDiGetDeviceRegistryProperty = setupapi.SetupDiGetDeviceRegistryPropertyA
+SetupDiGetDeviceRegistryProperty.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD]
+SetupDiGetDeviceRegistryProperty.restype = BOOL
+
+SetupDiGetDeviceInstanceId = setupapi.SetupDiGetDeviceInstanceIdA
+SetupDiGetDeviceInstanceId.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, PTSTR, DWORD, PDWORD]
+SetupDiGetDeviceInstanceId.restype = BOOL
+
+SetupDiOpenDevRegKey = setupapi.SetupDiOpenDevRegKey
+SetupDiOpenDevRegKey.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, DWORD, DWORD, REGSAM]
+SetupDiOpenDevRegKey.restype = HKEY
+
+advapi32 = ctypes.windll.LoadLibrary("Advapi32")
+RegCloseKey = advapi32.RegCloseKey
+RegCloseKey.argtypes = [HKEY]
+RegCloseKey.restype = LONG
+
+RegQueryValueEx = advapi32.RegQueryValueExA
+RegQueryValueEx.argtypes = [HKEY, LPCSTR, LPDWORD, LPDWORD, LPBYTE, LPDWORD]
+RegQueryValueEx.restype = LONG
+
+
+DIGCF_PRESENT = 2
+DIGCF_DEVICEINTERFACE = 16
+INVALID_HANDLE_VALUE = 0
+ERROR_INSUFFICIENT_BUFFER = 122
+SPDRP_HARDWAREID = 1
+SPDRP_FRIENDLYNAME = 12
+SPDRP_LOCATION_PATHS = 35
+DICS_FLAG_GLOBAL = 1
+DIREG_DEV = 0x00000001
+KEY_READ = 0x20019
+
+# workaround for compatibility between Python 2.x and 3.x
+Ports = serial.to_bytes([80, 111, 114, 116, 115]) # "Ports"
+PortName = serial.to_bytes([80, 111, 114, 116, 78, 97, 109, 101]) # "PortName"
+
+
+def comports():
+ GUIDs = (GUID*8)() # so far only seen one used, so hope 8 are enough...
+ guids_size = DWORD()
+ if not SetupDiClassGuidsFromName(
+ Ports,
+ GUIDs,
+ ctypes.sizeof(GUIDs),
+ ctypes.byref(guids_size)):
+ raise ctypes.WinError()
+
+ # repeat for all possible GUIDs
+ for index in range(guids_size.value):
+ g_hdi = SetupDiGetClassDevs(
+ ctypes.byref(GUIDs[index]),
+ None,
+ NULL,
+ DIGCF_PRESENT) # was DIGCF_PRESENT|DIGCF_DEVICEINTERFACE which misses CDC ports
+
+ devinfo = SP_DEVINFO_DATA()
+ devinfo.cbSize = ctypes.sizeof(devinfo)
+ index = 0
+ while SetupDiEnumDeviceInfo(g_hdi, index, ctypes.byref(devinfo)):
+ index += 1
+
+ # get the real com port name
+ hkey = SetupDiOpenDevRegKey(
+ g_hdi,
+ ctypes.byref(devinfo),
+ DICS_FLAG_GLOBAL,
+ 0,
+ DIREG_DEV, # DIREG_DRV for SW info
+ KEY_READ)
+ port_name_buffer = byte_buffer(250)
+ port_name_length = ULONG(ctypes.sizeof(port_name_buffer))
+ RegQueryValueEx(
+ hkey,
+ PortName,
+ None,
+ None,
+ ctypes.byref(port_name_buffer),
+ ctypes.byref(port_name_length))
+ RegCloseKey(hkey)
+
+ # unfortunately does this method also include parallel ports.
+ # we could check for names starting with COM or just exclude LPT
+ # and hope that other "unknown" names are serial ports...
+ if string(port_name_buffer).startswith('LPT'):
+ continue
+
+ # hardware ID
+ szHardwareID = byte_buffer(250)
+ # try to get ID that includes serial number
+ if not SetupDiGetDeviceInstanceId(
+ g_hdi,
+ ctypes.byref(devinfo),
+ ctypes.byref(szHardwareID),
+ ctypes.sizeof(szHardwareID) - 1,
+ None):
+ # fall back to more generic hardware ID if that would fail
+ if not SetupDiGetDeviceRegistryProperty(
+ g_hdi,
+ ctypes.byref(devinfo),
+ SPDRP_HARDWAREID,
+ None,
+ ctypes.byref(szHardwareID),
+ ctypes.sizeof(szHardwareID) - 1,
+ None):
+ # Ignore ERROR_INSUFFICIENT_BUFFER
+ if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
+ raise ctypes.WinError()
+ # stringify
+ szHardwareID_str = string(szHardwareID)
+
+ info = list_ports_common.ListPortInfo(string(port_name_buffer))
+
+ # in case of USB, make a more readable string, similar to that form
+ # that we also generate on other platforms
+ if szHardwareID_str.startswith('USB'):
+ m = re.search(r'VID_([0-9a-f]{4})&PID_([0-9a-f]{4})(\\(\w+))?', szHardwareID_str, re.I)
+ if m:
+ info.vid = int(m.group(1), 16)
+ info.pid = int(m.group(2), 16)
+ if m.group(4):
+ info.serial_number = m.group(4)
+ # calculate a location string
+ loc_path_str = byte_buffer(250)
+ if SetupDiGetDeviceRegistryProperty(
+ g_hdi,
+ ctypes.byref(devinfo),
+ SPDRP_LOCATION_PATHS,
+ None,
+ ctypes.byref(loc_path_str),
+ ctypes.sizeof(loc_path_str) - 1,
+ None):
+ #~ print (string(loc_path_str))
+ m = re.finditer(r'USBROOT\((\w+)\)|#USB\((\w+)\)', string(loc_path_str))
+ location = []
+ for g in m:
+ if g.group(1):
+ location.append('%d' % (int(g.group(1)) + 1))
+ else:
+ if len(location) > 1:
+ location.append('.')
+ else:
+ location.append('-')
+ location.append(g.group(2))
+ if location:
+ info.location = ''.join(location)
+ info.hwid = info.usb_info()
+ elif szHardwareID_str.startswith('FTDIBUS'):
+ m = re.search(r'VID_([0-9a-f]{4})\+PID_([0-9a-f]{4})(\+(\w+))?', szHardwareID_str, re.I)
+ if m:
+ info.vid = int(m.group(1), 16)
+ info.pid = int(m.group(2), 16)
+ if m.group(4):
+ info.serial_number = m.group(4)
+ # USB location is hidden by FDTI driver :(
+ info.hwid = info.usb_info()
+ else:
+ info.hwid = szHardwareID_str
+
+ # friendly name
+ szFriendlyName = byte_buffer(250)
+ if SetupDiGetDeviceRegistryProperty(
+ g_hdi,
+ ctypes.byref(devinfo),
+ SPDRP_FRIENDLYNAME,
+ #~ SPDRP_DEVICEDESC,
+ None,
+ ctypes.byref(szFriendlyName),
+ ctypes.sizeof(szFriendlyName) - 1,
+ None):
+ info.description = string(szFriendlyName)
+ #~ else:
+ # Ignore ERROR_INSUFFICIENT_BUFFER
+ #~ if ctypes.GetLastError() != ERROR_INSUFFICIENT_BUFFER:
+ #~ raise IOError("failed to get details for %s (%s)" % (devinfo, szHardwareID.value))
+ # ignore errors and still include the port in the list, friendly name will be same as port name
+ yield info
+ SetupDiDestroyDeviceInfoList(g_hdi)
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# test
+if __name__ == '__main__':
+ for port, desc, hwid in sorted(comports()):
+ print("%s: %s [%s]" % (port, desc, hwid))
diff --git a/src/devtools/datool/pyserial/tools/miniterm.py b/src/devtools/datool/pyserial/tools/miniterm.py
new file mode 100644
index 0000000..186ac10
--- /dev/null
+++ b/src/devtools/datool/pyserial/tools/miniterm.py
@@ -0,0 +1,878 @@
+#!/usr/bin/env python
+#
+# Very simple serial terminal
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C)2002-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+import codecs
+import os
+import sys
+import threading
+
+import pyserial as serial
+from pyserial.tools.list_ports import comports
+from pyserial.tools import hexlify_codec
+
+codecs.register(lambda c: hexlify_codec.getregentry() if c == 'hexlify' else None)
+
+try:
+ raw_input
+except NameError:
+ raw_input = input # in python3 it's "raw"
+ unichr = chr
+
+
+def key_description(character):
+ """generate a readable description for a key"""
+ ascii_code = ord(character)
+ if ascii_code < 32:
+ return 'Ctrl+%c' % (ord('@') + ascii_code)
+ else:
+ return repr(character)
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+class ConsoleBase(object):
+ def __init__(self):
+ if sys.version_info >= (3, 0):
+ self.byte_output = sys.stdout.buffer
+ else:
+ self.byte_output = sys.stdout
+ self.output = sys.stdout
+
+ def setup(self):
+ pass
+
+ def cleanup(self):
+ pass
+
+ def getkey(self):
+ return None
+
+ def write_bytes(self, s):
+ self.byte_output.write(s)
+ self.byte_output.flush()
+
+ def write(self, s):
+ self.output.write(s)
+ self.output.flush()
+
+ # - - - - - - - - - - - - - - - - - - - - - - - -
+ # context manager:
+ # switch terminal temporary to normal mode (e.g. to get user input)
+
+ def __enter__(self):
+ self.cleanup()
+ return self
+
+ def __exit__(self, *args, **kwargs):
+ self.setup()
+
+
+if os.name == 'nt':
+ import msvcrt
+ import ctypes
+
+ class Out(object):
+ def __init__(self, fd):
+ self.fd = fd
+
+ def flush(self):
+ pass
+
+ def write(self, s):
+ os.write(self.fd, s)
+
+ class Console(ConsoleBase):
+ def __init__(self):
+ super(Console, self).__init__()
+ self._saved_ocp = ctypes.windll.kernel32.GetConsoleOutputCP()
+ self._saved_icp = ctypes.windll.kernel32.GetConsoleCP()
+ ctypes.windll.kernel32.SetConsoleOutputCP(65001)
+ ctypes.windll.kernel32.SetConsoleCP(65001)
+ self.output = codecs.getwriter('UTF-8')(Out(sys.stdout.fileno()), 'replace')
+ # the change of the code page is not propagated to Python, manually fix it
+ sys.stderr = codecs.getwriter('UTF-8')(Out(sys.stderr.fileno()), 'replace')
+ sys.stdout = self.output
+ self.output.encoding = 'UTF-8' # needed for input
+
+ def __del__(self):
+ ctypes.windll.kernel32.SetConsoleOutputCP(self._saved_ocp)
+ ctypes.windll.kernel32.SetConsoleCP(self._saved_icp)
+
+ def getkey(self):
+ while True:
+ z = msvcrt.getwch()
+ if z == unichr(13):
+ return unichr(10)
+ elif z in (unichr(0), unichr(0x0e)): # functions keys, ignore
+ msvcrt.getwch()
+ else:
+ return z
+
+elif os.name == 'posix':
+ import atexit
+ import termios
+
+ class Console(ConsoleBase):
+ def __init__(self):
+ super(Console, self).__init__()
+ self.fd = sys.stdin.fileno()
+ self.old = termios.tcgetattr(self.fd)
+ atexit.register(self.cleanup)
+ if sys.version_info < (3, 0):
+ self.enc_stdin = codecs.getreader(sys.stdin.encoding)(sys.stdin)
+ else:
+ self.enc_stdin = sys.stdin
+
+ def setup(self):
+ new = termios.tcgetattr(self.fd)
+ new[3] = new[3] & ~termios.ICANON & ~termios.ECHO & ~termios.ISIG
+ new[6][termios.VMIN] = 1
+ new[6][termios.VTIME] = 0
+ termios.tcsetattr(self.fd, termios.TCSANOW, new)
+
+ def getkey(self):
+ c = self.enc_stdin.read(1)
+ if c == unichr(0x7f):
+ c = unichr(8) # map the BS key (which yields DEL) to backspace
+ return c
+
+ def cleanup(self):
+ termios.tcsetattr(self.fd, termios.TCSAFLUSH, self.old)
+
+else:
+ raise NotImplementedError("Sorry no implementation for your platform (%s) available." % sys.platform)
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+class Transform(object):
+ """do-nothing: forward all data unchanged"""
+ def rx(self, text):
+ """text received from serial port"""
+ return text
+
+ def tx(self, text):
+ """text to be sent to serial port"""
+ return text
+
+ def echo(self, text):
+ """text to be sent but displayed on console"""
+ return text
+
+
+class CRLF(Transform):
+ """ENTER sends CR+LF"""
+
+ def tx(self, text):
+ return text.replace('\n', '\r\n')
+
+
+class CR(Transform):
+ """ENTER sends CR"""
+
+ def rx(self, text):
+ return text.replace('\r', '\n')
+
+ def tx(self, text):
+ return text.replace('\n', '\r')
+
+
+class LF(Transform):
+ """ENTER sends LF"""
+
+
+class NoTerminal(Transform):
+ """remove typical terminal control codes from input"""
+
+ REPLACEMENT_MAP = dict((x, 0x2400 + x) for x in range(32) if unichr(x) not in '\r\n\b\t')
+ REPLACEMENT_MAP.update({
+ 0x7F: 0x2421, # DEL
+ 0x9B: 0x2425, # CSI
+ })
+
+ def rx(self, text):
+ return text.translate(self.REPLACEMENT_MAP)
+
+ echo = rx
+
+
+class NoControls(NoTerminal):
+ """Remove all control codes, incl. CR+LF"""
+
+ REPLACEMENT_MAP = dict((x, 0x2400 + x) for x in range(32))
+ REPLACEMENT_MAP.update({
+ 32: 0x2423, # visual space
+ 0x7F: 0x2421, # DEL
+ 0x9B: 0x2425, # CSI
+ })
+
+
+class Printable(Transform):
+ """Show decimal code for all non-ASCII characters and replace most control codes"""
+
+ def rx(self, text):
+ r = []
+ for t in text:
+ if ' ' <= t < '\x7f' or t in '\r\n\b\t':
+ r.append(t)
+ elif t < ' ':
+ r.append(unichr(0x2400 + ord(t)))
+ else:
+ r.extend(unichr(0x2080 + ord(d) - 48) for d in '{:d}'.format(ord(t)))
+ r.append(' ')
+ return ''.join(r)
+
+ echo = rx
+
+
+class Colorize(Transform):
+ """Apply different colors for received and echo"""
+
+ def __init__(self):
+ # XXX make it configurable, use colorama?
+ self.input_color = '\x1b[37m'
+ self.echo_color = '\x1b[31m'
+
+ def rx(self, text):
+ return self.input_color + text
+
+ def echo(self, text):
+ return self.echo_color + text
+
+
+class DebugIO(Transform):
+ """Print what is sent and received"""
+
+ def rx(self, text):
+ sys.stderr.write(' [RX:{}] '.format(repr(text)))
+ sys.stderr.flush()
+ return text
+
+ def tx(self, text):
+ sys.stderr.write(' [TX:{}] '.format(repr(text)))
+ sys.stderr.flush()
+ return text
+
+
+# other ideas:
+# - add date/time for each newline
+# - insert newline after: a) timeout b) packet end character
+
+EOL_TRANSFORMATIONS = {
+ 'crlf': CRLF,
+ 'cr': CR,
+ 'lf': LF,
+ }
+
+TRANSFORMATIONS = {
+ 'direct': Transform, # no transformation
+ 'default': NoTerminal,
+ 'nocontrol': NoControls,
+ 'printable': Printable,
+ 'colorize': Colorize,
+ 'debug': DebugIO,
+ }
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+def ask_for_port():
+ """\
+ Show a list of ports and ask the user for a choice. To make selection
+ easier on systems with long device names, also allow the input of an
+ index.
+ """
+ sys.stderr.write('\n--- Available ports:\n')
+ ports = []
+ for n, (port, desc, hwid) in enumerate(sorted(comports()), 1):
+ #~ sys.stderr.write('--- %-20s %s [%s]\n' % (port, desc, hwid))
+ sys.stderr.write('--- {:2}: {:20} {}\n'.format(n, port, desc))
+ ports.append(port)
+ while True:
+ port = raw_input('--- Enter port index or full name: ')
+ try:
+ index = int(port) - 1
+ if not 0 <= index < len(ports):
+ sys.stderr.write('--- Invalid index!\n')
+ continue
+ except ValueError:
+ pass
+ else:
+ port = ports[index]
+ return port
+
+
+class Miniterm(object):
+ """\
+ Terminal application. Copy data from serial port to console and vice versa.
+ Handle special keys from the console to show menu etc.
+ """
+
+ def __init__(self, serial_instance, echo=False, eol='crlf', filters=()):
+ self.console = Console()
+ self.serial = serial_instance
+ self.echo = echo
+ self.raw = False
+ self.input_encoding = 'UTF-8'
+ self.output_encoding = 'UTF-8'
+ self.eol = eol
+ self.filters = filters
+ self.update_transformations()
+ self.exit_character = 0x1d # GS/CTRL+]
+ self.menu_character = 0x14 # Menu: CTRL+T
+
+ def _start_reader(self):
+ """Start reader thread"""
+ self._reader_alive = True
+ # start serial->console thread
+ self.receiver_thread = threading.Thread(target=self.reader, name='rx')
+ self.receiver_thread.daemon = True
+ self.receiver_thread.start()
+
+ def _stop_reader(self):
+ """Stop reader thread only, wait for clean exit of thread"""
+ self._reader_alive = False
+ self.receiver_thread.join()
+
+ def start(self):
+ self.alive = True
+ self._start_reader()
+ # enter console->serial loop
+ self.transmitter_thread = threading.Thread(target=self.writer, name='tx')
+ self.transmitter_thread.daemon = True
+ self.transmitter_thread.start()
+ self.console.setup()
+
+ def stop(self):
+ self.alive = False
+
+ def join(self, transmit_only=False):
+ self.transmitter_thread.join()
+ if not transmit_only:
+ self.receiver_thread.join()
+
+ def update_transformations(self):
+ transformations = [EOL_TRANSFORMATIONS[self.eol]] + [TRANSFORMATIONS[f] for f in self.filters]
+ self.tx_transformations = [t() for t in transformations]
+ self.rx_transformations = list(reversed(self.tx_transformations))
+
+ def set_rx_encoding(self, encoding, errors='replace'):
+ self.input_encoding = encoding
+ self.rx_decoder = codecs.getincrementaldecoder(encoding)(errors)
+
+ def set_tx_encoding(self, encoding, errors='replace'):
+ self.output_encoding = encoding
+ self.tx_encoder = codecs.getincrementalencoder(encoding)(errors)
+
+ def dump_port_settings(self):
+ sys.stderr.write("\n--- Settings: {p.name} {p.baudrate},{p.bytesize},{p.parity},{p.stopbits}\n".format(
+ p=self.serial))
+ sys.stderr.write('--- RTS: {:8} DTR: {:8} BREAK: {:8}\n'.format(
+ ('active' if self.serial.rts else 'inactive'),
+ ('active' if self.serial.dtr else 'inactive'),
+ ('active' if self.serial.break_condition else 'inactive')))
+ try:
+ sys.stderr.write('--- CTS: {:8} DSR: {:8} RI: {:8} CD: {:8}\n'.format(
+ ('active' if self.serial.cts else 'inactive'),
+ ('active' if self.serial.dsr else 'inactive'),
+ ('active' if self.serial.ri else 'inactive'),
+ ('active' if self.serial.cd else 'inactive')))
+ except serial.SerialException:
+ # on RFC 2217 ports, it can happen if no modem state notification was
+ # yet received. ignore this error.
+ pass
+ sys.stderr.write('--- software flow control: {}\n'.format('active' if self.serial.xonxoff else 'inactive'))
+ sys.stderr.write('--- hardware flow control: {}\n'.format('active' if self.serial.rtscts else 'inactive'))
+ #~ sys.stderr.write('--- data escaping: %s linefeed: %s\n' % (
+ #~ REPR_MODES[self.repr_mode],
+ #~ LF_MODES[self.convert_outgoing]))
+ sys.stderr.write('--- serial input encoding: {}\n'.format(self.input_encoding))
+ sys.stderr.write('--- serial output encoding: {}\n'.format(self.output_encoding))
+ sys.stderr.write('--- EOL: {}\n'.format(self.eol.upper()))
+ sys.stderr.write('--- filters: {}\n'.format(' '.join(self.filters)))
+
+ def reader(self):
+ """loop and copy serial->console"""
+ try:
+ while self.alive and self._reader_alive:
+ # read all that is there or wait for one byte
+ data = self.serial.read(self.serial.in_waiting or 1)
+ if data:
+ if self.raw:
+ self.console.write_bytes(data)
+ else:
+ text = self.rx_decoder.decode(data)
+ for transformation in self.rx_transformations:
+ text = transformation.rx(text)
+ self.console.write(text)
+ except serial.SerialException:
+ self.alive = False
+ # XXX would be nice if the writer could be interrupted at this
+ # point... to exit completely
+ raise
+
+ def writer(self):
+ """\
+ Loop and copy console->serial until self.exit_character character is
+ found. When self.menu_character is found, interpret the next key
+ locally.
+ """
+ menu_active = False
+ try:
+ while self.alive:
+ try:
+ c = self.console.getkey()
+ except KeyboardInterrupt:
+ c = '\x03'
+ if menu_active:
+ self.handle_menu_key(c)
+ menu_active = False
+ elif c == self.menu_character:
+ menu_active = True # next char will be for menu
+ elif c == self.exit_character:
+ self.stop() # exit app
+ break
+ else:
+ #~ if self.raw:
+ text = c
+ for transformation in self.tx_transformations:
+ text = transformation.tx(text)
+ self.serial.write(self.tx_encoder.encode(text))
+ if self.echo:
+ echo_text = c
+ for transformation in self.tx_transformations:
+ echo_text = transformation.echo(echo_text)
+ self.console.write(echo_text)
+ except:
+ self.alive = False
+ raise
+
+ def handle_menu_key(self, c):
+ """Implement a simple menu / settings"""
+ if c == self.menu_character or c == self.exit_character:
+ # Menu/exit character again -> send itself
+ self.serial.write(self.tx_encoder.encode(c))
+ if self.echo:
+ self.console.write(c)
+ elif c == '\x15': # CTRL+U -> upload file
+ sys.stderr.write('\n--- File to upload: ')
+ sys.stderr.flush()
+ with self.console:
+ filename = sys.stdin.readline().rstrip('\r\n')
+ if filename:
+ try:
+ with open(filename, 'rb') as f:
+ sys.stderr.write('--- Sending file {} ---\n'.format(filename))
+ while True:
+ block = f.read(1024)
+ if not block:
+ break
+ self.serial.write(block)
+ # Wait for output buffer to drain.
+ self.serial.flush()
+ sys.stderr.write('.') # Progress indicator.
+ sys.stderr.write('\n--- File {} sent ---\n'.format(filename))
+ except IOError as e:
+ sys.stderr.write('--- ERROR opening file {}: {} ---\n'.format(filename, e))
+ elif c in '\x08hH?': # CTRL+H, h, H, ? -> Show help
+ sys.stderr.write(self.get_help_text())
+ elif c == '\x12': # CTRL+R -> Toggle RTS
+ self.serial.rts = not self.serial.rts
+ sys.stderr.write('--- RTS {} ---\n'.format('active' if self.serial.rts else 'inactive'))
+ elif c == '\x04': # CTRL+D -> Toggle DTR
+ self.serial.dtr = not self.serial.dtr
+ sys.stderr.write('--- DTR {} ---\n'.format('active' if self.serial.dtr else 'inactive'))
+ elif c == '\x02': # CTRL+B -> toggle BREAK condition
+ self.serial.break_condition = not self.serial.break_condition
+ sys.stderr.write('--- BREAK {} ---\n'.format('active' if self.serial.break_condition else 'inactive'))
+ elif c == '\x05': # CTRL+E -> toggle local echo
+ self.echo = not self.echo
+ sys.stderr.write('--- local echo {} ---\n'.format('active' if self.echo else 'inactive'))
+ elif c == '\x06': # CTRL+F -> edit filters
+ sys.stderr.write('\n--- Available Filters:\n')
+ sys.stderr.write('\n'.join(
+ '--- {:<10} = {.__doc__}'.format(k, v)
+ for k, v in sorted(TRANSFORMATIONS.items())))
+ sys.stderr.write('\n--- Enter new filter name(s) [{}]: '.format(' '.join(self.filters)))
+ with self.console:
+ new_filters = sys.stdin.readline().lower().split()
+ if new_filters:
+ for f in new_filters:
+ if f not in TRANSFORMATIONS:
+ sys.stderr.write('--- unknown filter: {}'.format(repr(f)))
+ break
+ else:
+ self.filters = new_filters
+ self.update_transformations()
+ sys.stderr.write('--- filters: {}\n'.format(' '.join(self.filters)))
+ elif c == '\x0c': # CTRL+L -> EOL mode
+ modes = list(EOL_TRANSFORMATIONS) # keys
+ eol = modes.index(self.eol) + 1
+ if eol >= len(modes):
+ eol = 0
+ self.eol = modes[eol]
+ sys.stderr.write('--- EOL: {} ---\n'.format(self.eol.upper()))
+ self.update_transformations()
+ elif c == '\x01': # CTRL+A -> set encoding
+ sys.stderr.write('\n--- Enter new encoding name [{}]: '.format(self.input_encoding))
+ with self.console:
+ new_encoding = sys.stdin.readline().strip()
+ if new_encoding:
+ try:
+ codecs.lookup(new_encoding)
+ except LookupError:
+ sys.stderr.write('--- invalid encoding name: {}\n'.format(new_encoding))
+ else:
+ self.set_rx_encoding(new_encoding)
+ self.set_tx_encoding(new_encoding)
+ sys.stderr.write('--- serial input encoding: {}\n'.format(self.input_encoding))
+ sys.stderr.write('--- serial output encoding: {}\n'.format(self.output_encoding))
+ elif c == '\x09': # CTRL+I -> info
+ self.dump_port_settings()
+ #~ elif c == '\x01': # CTRL+A -> cycle escape mode
+ #~ elif c == '\x0c': # CTRL+L -> cycle linefeed mode
+ elif c in 'pP': # P -> change port
+ with self.console:
+ try:
+ port = ask_for_port()
+ except KeyboardInterrupt:
+ port = None
+ if port and port != self.serial.port:
+ # reader thread needs to be shut down
+ self._stop_reader()
+ # save settings
+ settings = self.serial.getSettingsDict()
+ try:
+ new_serial = serial.serial_for_url(port, do_not_open=True)
+ # restore settings and open
+ new_serial.applySettingsDict(settings)
+ new_serial.rts = self.serial.rts
+ new_serial.dtr = self.serial.dtr
+ new_serial.open()
+ new_serial.break_condition = self.serial.break_condition
+ except Exception as e:
+ sys.stderr.write('--- ERROR opening new port: {} ---\n'.format(e))
+ new_serial.close()
+ else:
+ self.serial.close()
+ self.serial = new_serial
+ sys.stderr.write('--- Port changed to: {} ---\n'.format(self.serial.port))
+ # and restart the reader thread
+ self._start_reader()
+ elif c in 'bB': # B -> change baudrate
+ sys.stderr.write('\n--- Baudrate: ')
+ sys.stderr.flush()
+ with self.console:
+ backup = self.serial.baudrate
+ try:
+ self.serial.baudrate = int(sys.stdin.readline().strip())
+ except ValueError as e:
+ sys.stderr.write('--- ERROR setting baudrate: %s ---\n'.format(e))
+ self.serial.baudrate = backup
+ else:
+ self.dump_port_settings()
+ elif c == '8': # 8 -> change to 8 bits
+ self.serial.bytesize = serial.EIGHTBITS
+ self.dump_port_settings()
+ elif c == '7': # 7 -> change to 8 bits
+ self.serial.bytesize = serial.SEVENBITS
+ self.dump_port_settings()
+ elif c in 'eE': # E -> change to even parity
+ self.serial.parity = serial.PARITY_EVEN
+ self.dump_port_settings()
+ elif c in 'oO': # O -> change to odd parity
+ self.serial.parity = serial.PARITY_ODD
+ self.dump_port_settings()
+ elif c in 'mM': # M -> change to mark parity
+ self.serial.parity = serial.PARITY_MARK
+ self.dump_port_settings()
+ elif c in 'sS': # S -> change to space parity
+ self.serial.parity = serial.PARITY_SPACE
+ self.dump_port_settings()
+ elif c in 'nN': # N -> change to no parity
+ self.serial.parity = serial.PARITY_NONE
+ self.dump_port_settings()
+ elif c == '1': # 1 -> change to 1 stop bits
+ self.serial.stopbits = serial.STOPBITS_ONE
+ self.dump_port_settings()
+ elif c == '2': # 2 -> change to 2 stop bits
+ self.serial.stopbits = serial.STOPBITS_TWO
+ self.dump_port_settings()
+ elif c == '3': # 3 -> change to 1.5 stop bits
+ self.serial.stopbits = serial.STOPBITS_ONE_POINT_FIVE
+ self.dump_port_settings()
+ elif c in 'xX': # X -> change software flow control
+ self.serial.xonxoff = (c == 'X')
+ self.dump_port_settings()
+ elif c in 'rR': # R -> change hardware flow control
+ self.serial.rtscts = (c == 'R')
+ self.dump_port_settings()
+ else:
+ sys.stderr.write('--- unknown menu character {} --\n'.format(key_description(c)))
+
+ def get_help_text(self):
+ # help text, starts with blank line!
+ return """
+--- pySerial ({version}) - miniterm - help
+---
+--- {exit:8} Exit program
+--- {menu:8} Menu escape key, followed by:
+--- Menu keys:
+--- {menu:7} Send the menu character itself to remote
+--- {exit:7} Send the exit character itself to remote
+--- {info:7} Show info
+--- {upload:7} Upload file (prompt will be shown)
+--- {repr:7} encoding
+--- {filter:7} edit filters
+--- Toggles:
+--- {rts:7} RTS {dtr:7} DTR {brk:7} BREAK
+--- {echo:7} echo {eol:7} EOL
+---
+--- Port settings ({menu} followed by the following):
+--- p change port
+--- 7 8 set data bits
+--- N E O S M change parity (None, Even, Odd, Space, Mark)
+--- 1 2 3 set stop bits (1, 2, 1.5)
+--- b change baud rate
+--- x X disable/enable software flow control
+--- r R disable/enable hardware flow control
+""".format(
+ version=getattr(serial, 'VERSION', 'unknown version'),
+ exit=key_description(self.exit_character),
+ menu=key_description(self.menu_character),
+ rts=key_description('\x12'),
+ dtr=key_description('\x04'),
+ brk=key_description('\x02'),
+ echo=key_description('\x05'),
+ info=key_description('\x09'),
+ upload=key_description('\x15'),
+ repr=key_description('\x01'),
+ filter=key_description('\x06'),
+ eol=key_description('\x0c'),
+ )
+
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+# default args can be used to override when calling main() from an other script
+# e.g to create a miniterm-my-device.py
+def main(default_port=None, default_baudrate=9600, default_rts=None, default_dtr=None):
+ import argparse
+
+ parser = argparse.ArgumentParser(
+ description="Miniterm - A simple terminal program for the serial port.")
+
+ parser.add_argument(
+ "port",
+ nargs='?',
+ help="serial port name ('-' to show port list)",
+ default=default_port)
+
+ parser.add_argument(
+ "baudrate",
+ nargs='?',
+ type=int,
+ help="set baud rate, default: %(default)s",
+ default=default_baudrate)
+
+ group = parser.add_argument_group("port settings")
+
+ group.add_argument(
+ "--parity",
+ choices=['N', 'E', 'O', 'S', 'M'],
+ type=lambda c: c.upper(),
+ help="set parity, one of {N E O S M}, default: N",
+ default='N')
+
+ group.add_argument(
+ "--rtscts",
+ action="store_true",
+ help="enable RTS/CTS flow control (default off)",
+ default=False)
+
+ group.add_argument(
+ "--xonxoff",
+ action="store_true",
+ help="enable software flow control (default off)",
+ default=False)
+
+ group.add_argument(
+ "--rts",
+ type=int,
+ help="set initial RTS line state (possible values: 0, 1)",
+ default=default_rts)
+
+ group.add_argument(
+ "--dtr",
+ type=int,
+ help="set initial DTR line state (possible values: 0, 1)",
+ default=default_dtr)
+
+ group.add_argument(
+ "--ask",
+ action="store_true",
+ help="ask again for port when open fails",
+ default=False)
+
+ group = parser.add_argument_group("data handling")
+
+ group.add_argument(
+ "-e", "--echo",
+ action="store_true",
+ help="enable local echo (default off)",
+ default=False)
+
+ group.add_argument(
+ "--encoding",
+ dest="serial_port_encoding",
+ metavar="CODEC",
+ help="set the encoding for the serial port (e.g. hexlify, Latin1, UTF-8), default: %(default)s",
+ default='UTF-8')
+
+ group.add_argument(
+ "-f", "--filter",
+ action="append",
+ metavar="NAME",
+ help="add text transformation",
+ default=[])
+
+ group.add_argument(
+ "--eol",
+ choices=['CR', 'LF', 'CRLF'],
+ type=lambda c: c.upper(),
+ help="end of line mode",
+ default='CRLF')
+
+ group.add_argument(
+ "--raw",
+ action="store_true",
+ help="Do no apply any encodings/transformations",
+ default=False)
+
+ group = parser.add_argument_group("hotkeys")
+
+ group.add_argument(
+ "--exit-char",
+ type=int,
+ metavar='NUM',
+ help="Unicode of special character that is used to exit the application, default: %(default)s",
+ default=0x1d # GS/CTRL+]
+ )
+
+ group.add_argument(
+ "--menu-char",
+ type=int,
+ metavar='NUM',
+ help="Unicode code of special character that is used to control miniterm (menu), default: %(default)s",
+ default=0x14 # Menu: CTRL+T
+ )
+
+ group = parser.add_argument_group("diagnostics")
+
+ group.add_argument(
+ "-q", "--quiet",
+ action="store_true",
+ help="suppress non-error messages",
+ default=False)
+
+ group.add_argument(
+ "--develop",
+ action="store_true",
+ help="show Python traceback on error",
+ default=False)
+
+ args = parser.parse_args()
+
+ if args.menu_char == args.exit_char:
+ parser.error('--exit-char can not be the same as --menu-char')
+
+ if args.filter:
+ if 'help' in args.filter:
+ sys.stderr.write('Available filters:\n')
+ sys.stderr.write('\n'.join(
+ '{:<10} = {.__doc__}'.format(k, v)
+ for k, v in sorted(TRANSFORMATIONS.items())))
+ sys.stderr.write('\n')
+ sys.exit(1)
+ filters = args.filter
+ else:
+ filters = ['default']
+
+ while True:
+ # no port given on command line -> ask user now
+ if args.port is None or args.port == '-':
+ try:
+ args.port = ask_for_port()
+ except KeyboardInterrupt:
+ sys.stderr.write('\n')
+ parser.error('user aborted and port is not given')
+ else:
+ if not args.port:
+ parser.error('port is not given')
+ try:
+ serial_instance = serial.serial_for_url(
+ args.port,
+ args.baudrate,
+ parity=args.parity,
+ rtscts=args.rtscts,
+ xonxoff=args.xonxoff,
+ timeout=1,
+ do_not_open=True)
+
+ if args.dtr is not None:
+ if not args.quiet:
+ sys.stderr.write('--- forcing DTR {}\n'.format('active' if args.dtr else 'inactive'))
+ serial_instance.dtr = args.dtr
+ if args.rts is not None:
+ if not args.quiet:
+ sys.stderr.write('--- forcing RTS {}\n'.format('active' if args.rts else 'inactive'))
+ serial_instance.rts = args.rts
+
+ serial_instance.open()
+ except serial.SerialException as e:
+ sys.stderr.write('could not open port {}: {}\n'.format(repr(args.port), e))
+ if args.develop:
+ raise
+ if not args.ask:
+ sys.exit(1)
+ else:
+ args.port = '-'
+ else:
+ break
+
+ miniterm = Miniterm(
+ serial_instance,
+ echo=args.echo,
+ eol=args.eol.lower(),
+ filters=filters)
+ miniterm.exit_character = unichr(args.exit_char)
+ miniterm.menu_character = unichr(args.menu_char)
+ miniterm.raw = args.raw
+ miniterm.set_rx_encoding(args.serial_port_encoding)
+ miniterm.set_tx_encoding(args.serial_port_encoding)
+
+ if not args.quiet:
+ sys.stderr.write('--- Miniterm on {p.name} {p.baudrate},{p.bytesize},{p.parity},{p.stopbits} ---\n'.format(
+ p=miniterm.serial))
+ sys.stderr.write('--- Quit: {} | Menu: {} | Help: {} followed by {} ---\n'.format(
+ key_description(miniterm.exit_character),
+ key_description(miniterm.menu_character),
+ key_description(miniterm.menu_character),
+ key_description('\x08'),
+ ))
+
+ miniterm.start()
+ try:
+ miniterm.join(True)
+ except KeyboardInterrupt:
+ pass
+ if not args.quiet:
+ sys.stderr.write("\n--- exit ---\n")
+ miniterm.join()
+
+# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+if __name__ == '__main__':
+ main()
diff --git a/src/devtools/datool/pyserial/win32.py b/src/devtools/datool/pyserial/win32.py
new file mode 100644
index 0000000..cca6195
--- /dev/null
+++ b/src/devtools/datool/pyserial/win32.py
@@ -0,0 +1,343 @@
+#! python
+#
+# Constants and types for use with Windows API, used by serialwin32.py
+#
+# This file is part of pySerial. https://github.com/pyserial/pyserial
+# (C) 2001-2015 Chris Liechti <cliechti@gmx.net>
+#
+# SPDX-License-Identifier: BSD-3-Clause
+
+from ctypes import *
+from ctypes.wintypes import HANDLE
+from ctypes.wintypes import BOOL
+from ctypes.wintypes import LPCWSTR
+from ctypes.wintypes import DWORD
+from ctypes.wintypes import WORD
+from ctypes.wintypes import BYTE
+_stdcall_libraries = {}
+_stdcall_libraries['kernel32'] = WinDLL('kernel32')
+
+INVALID_HANDLE_VALUE = HANDLE(-1).value
+
+
+# some details of the windows API differ between 32 and 64 bit systems..
+def is_64bit():
+ """Returns true when running on a 64 bit system"""
+ return sizeof(c_ulong) != sizeof(c_void_p)
+
+# ULONG_PTR is a an ordinary number, not a pointer and contrary to the name it
+# is either 32 or 64 bits, depending on the type of windows...
+# so test if this a 32 bit windows...
+if is_64bit():
+ # assume 64 bits
+ ULONG_PTR = c_int64
+else:
+ # 32 bits
+ ULONG_PTR = c_ulong
+
+
+class _SECURITY_ATTRIBUTES(Structure):
+ pass
+LPSECURITY_ATTRIBUTES = POINTER(_SECURITY_ATTRIBUTES)
+
+
+try:
+ CreateEventW = _stdcall_libraries['kernel32'].CreateEventW
+except AttributeError:
+ # Fallback to non wide char version for old OS...
+ from ctypes.wintypes import LPCSTR
+ CreateEventA = _stdcall_libraries['kernel32'].CreateEventA
+ CreateEventA.restype = HANDLE
+ CreateEventA.argtypes = [LPSECURITY_ATTRIBUTES, BOOL, BOOL, LPCSTR]
+ CreateEvent = CreateEventA
+
+ CreateFileA = _stdcall_libraries['kernel32'].CreateFileA
+ CreateFileA.restype = HANDLE
+ CreateFileA.argtypes = [LPCSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE]
+ CreateFile = CreateFileA
+else:
+ CreateEventW.restype = HANDLE
+ CreateEventW.argtypes = [LPSECURITY_ATTRIBUTES, BOOL, BOOL, LPCWSTR]
+ CreateEvent = CreateEventW # alias
+
+ CreateFileW = _stdcall_libraries['kernel32'].CreateFileW
+ CreateFileW.restype = HANDLE
+ CreateFileW.argtypes = [LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE]
+ CreateFile = CreateFileW # alias
+
+
+class _OVERLAPPED(Structure):
+ pass
+
+OVERLAPPED = _OVERLAPPED
+
+
+class _COMSTAT(Structure):
+ pass
+
+COMSTAT = _COMSTAT
+
+
+class _DCB(Structure):
+ pass
+
+DCB = _DCB
+
+
+class _COMMTIMEOUTS(Structure):
+ pass
+
+COMMTIMEOUTS = _COMMTIMEOUTS
+
+GetLastError = _stdcall_libraries['kernel32'].GetLastError
+GetLastError.restype = DWORD
+GetLastError.argtypes = []
+
+LPOVERLAPPED = POINTER(_OVERLAPPED)
+LPDWORD = POINTER(DWORD)
+
+GetOverlappedResult = _stdcall_libraries['kernel32'].GetOverlappedResult
+GetOverlappedResult.restype = BOOL
+GetOverlappedResult.argtypes = [HANDLE, LPOVERLAPPED, LPDWORD, BOOL]
+
+ResetEvent = _stdcall_libraries['kernel32'].ResetEvent
+ResetEvent.restype = BOOL
+ResetEvent.argtypes = [HANDLE]
+
+LPCVOID = c_void_p
+
+WriteFile = _stdcall_libraries['kernel32'].WriteFile
+WriteFile.restype = BOOL
+WriteFile.argtypes = [HANDLE, LPCVOID, DWORD, LPDWORD, LPOVERLAPPED]
+
+LPVOID = c_void_p
+
+ReadFile = _stdcall_libraries['kernel32'].ReadFile
+ReadFile.restype = BOOL
+ReadFile.argtypes = [HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED]
+
+CloseHandle = _stdcall_libraries['kernel32'].CloseHandle
+CloseHandle.restype = BOOL
+CloseHandle.argtypes = [HANDLE]
+
+ClearCommBreak = _stdcall_libraries['kernel32'].ClearCommBreak
+ClearCommBreak.restype = BOOL
+ClearCommBreak.argtypes = [HANDLE]
+
+LPCOMSTAT = POINTER(_COMSTAT)
+
+ClearCommError = _stdcall_libraries['kernel32'].ClearCommError
+ClearCommError.restype = BOOL
+ClearCommError.argtypes = [HANDLE, LPDWORD, LPCOMSTAT]
+
+SetupComm = _stdcall_libraries['kernel32'].SetupComm
+SetupComm.restype = BOOL
+SetupComm.argtypes = [HANDLE, DWORD, DWORD]
+
+EscapeCommFunction = _stdcall_libraries['kernel32'].EscapeCommFunction
+EscapeCommFunction.restype = BOOL
+EscapeCommFunction.argtypes = [HANDLE, DWORD]
+
+GetCommModemStatus = _stdcall_libraries['kernel32'].GetCommModemStatus
+GetCommModemStatus.restype = BOOL
+GetCommModemStatus.argtypes = [HANDLE, LPDWORD]
+
+LPDCB = POINTER(_DCB)
+
+GetCommState = _stdcall_libraries['kernel32'].GetCommState
+GetCommState.restype = BOOL
+GetCommState.argtypes = [HANDLE, LPDCB]
+
+LPCOMMTIMEOUTS = POINTER(_COMMTIMEOUTS)
+
+GetCommTimeouts = _stdcall_libraries['kernel32'].GetCommTimeouts
+GetCommTimeouts.restype = BOOL
+GetCommTimeouts.argtypes = [HANDLE, LPCOMMTIMEOUTS]
+
+PurgeComm = _stdcall_libraries['kernel32'].PurgeComm
+PurgeComm.restype = BOOL
+PurgeComm.argtypes = [HANDLE, DWORD]
+
+SetCommBreak = _stdcall_libraries['kernel32'].SetCommBreak
+SetCommBreak.restype = BOOL
+SetCommBreak.argtypes = [HANDLE]
+
+SetCommMask = _stdcall_libraries['kernel32'].SetCommMask
+SetCommMask.restype = BOOL
+SetCommMask.argtypes = [HANDLE, DWORD]
+
+SetCommState = _stdcall_libraries['kernel32'].SetCommState
+SetCommState.restype = BOOL
+SetCommState.argtypes = [HANDLE, LPDCB]
+
+SetCommTimeouts = _stdcall_libraries['kernel32'].SetCommTimeouts
+SetCommTimeouts.restype = BOOL
+SetCommTimeouts.argtypes = [HANDLE, LPCOMMTIMEOUTS]
+
+WaitForSingleObject = _stdcall_libraries['kernel32'].WaitForSingleObject
+WaitForSingleObject.restype = DWORD
+WaitForSingleObject.argtypes = [HANDLE, DWORD]
+
+ONESTOPBIT = 0 # Variable c_int
+TWOSTOPBITS = 2 # Variable c_int
+ONE5STOPBITS = 1
+
+NOPARITY = 0 # Variable c_int
+ODDPARITY = 1 # Variable c_int
+EVENPARITY = 2 # Variable c_int
+MARKPARITY = 3
+SPACEPARITY = 4
+
+RTS_CONTROL_HANDSHAKE = 2 # Variable c_int
+RTS_CONTROL_DISABLE = 0 # Variable c_int
+RTS_CONTROL_ENABLE = 1 # Variable c_int
+RTS_CONTROL_TOGGLE = 3 # Variable c_int
+SETRTS = 3
+CLRRTS = 4
+
+DTR_CONTROL_HANDSHAKE = 2 # Variable c_int
+DTR_CONTROL_DISABLE = 0 # Variable c_int
+DTR_CONTROL_ENABLE = 1 # Variable c_int
+SETDTR = 5
+CLRDTR = 6
+
+MS_DSR_ON = 32 # Variable c_ulong
+EV_RING = 256 # Variable c_int
+EV_PERR = 512 # Variable c_int
+EV_ERR = 128 # Variable c_int
+SETXOFF = 1 # Variable c_int
+EV_RXCHAR = 1 # Variable c_int
+GENERIC_WRITE = 1073741824 # Variable c_long
+PURGE_TXCLEAR = 4 # Variable c_int
+FILE_FLAG_OVERLAPPED = 1073741824 # Variable c_int
+EV_DSR = 16 # Variable c_int
+MAXDWORD = 4294967295 # Variable c_uint
+EV_RLSD = 32 # Variable c_int
+ERROR_SUCCESS = 0
+ERROR_IO_PENDING = 997 # Variable c_long
+MS_CTS_ON = 16 # Variable c_ulong
+EV_EVENT1 = 2048 # Variable c_int
+EV_RX80FULL = 1024 # Variable c_int
+PURGE_RXABORT = 2 # Variable c_int
+FILE_ATTRIBUTE_NORMAL = 128 # Variable c_int
+PURGE_TXABORT = 1 # Variable c_int
+SETXON = 2 # Variable c_int
+OPEN_EXISTING = 3 # Variable c_int
+MS_RING_ON = 64 # Variable c_ulong
+EV_TXEMPTY = 4 # Variable c_int
+EV_RXFLAG = 2 # Variable c_int
+MS_RLSD_ON = 128 # Variable c_ulong
+GENERIC_READ = 2147483648 # Variable c_ulong
+EV_EVENT2 = 4096 # Variable c_int
+EV_CTS = 8 # Variable c_int
+EV_BREAK = 64 # Variable c_int
+PURGE_RXCLEAR = 8 # Variable c_int
+INFINITE = 0xFFFFFFFF
+
+
+class N11_OVERLAPPED4DOLLAR_48E(Union):
+ pass
+
+
+class N11_OVERLAPPED4DOLLAR_484DOLLAR_49E(Structure):
+ pass
+
+
+N11_OVERLAPPED4DOLLAR_484DOLLAR_49E._fields_ = [
+ ('Offset', DWORD),
+ ('OffsetHigh', DWORD),
+]
+
+PVOID = c_void_p
+
+N11_OVERLAPPED4DOLLAR_48E._anonymous_ = ['_0']
+N11_OVERLAPPED4DOLLAR_48E._fields_ = [
+ ('_0', N11_OVERLAPPED4DOLLAR_484DOLLAR_49E),
+ ('Pointer', PVOID),
+]
+_OVERLAPPED._anonymous_ = ['_0']
+_OVERLAPPED._fields_ = [
+ ('Internal', ULONG_PTR),
+ ('InternalHigh', ULONG_PTR),
+ ('_0', N11_OVERLAPPED4DOLLAR_48E),
+ ('hEvent', HANDLE),
+]
+_SECURITY_ATTRIBUTES._fields_ = [
+ ('nLength', DWORD),
+ ('lpSecurityDescriptor', LPVOID),
+ ('bInheritHandle', BOOL),
+]
+_COMSTAT._fields_ = [
+ ('fCtsHold', DWORD, 1),
+ ('fDsrHold', DWORD, 1),
+ ('fRlsdHold', DWORD, 1),
+ ('fXoffHold', DWORD, 1),
+ ('fXoffSent', DWORD, 1),
+ ('fEof', DWORD, 1),
+ ('fTxim', DWORD, 1),
+ ('fReserved', DWORD, 25),
+ ('cbInQue', DWORD),
+ ('cbOutQue', DWORD),
+]
+_DCB._fields_ = [
+ ('DCBlength', DWORD),
+ ('BaudRate', DWORD),
+ ('fBinary', DWORD, 1),
+ ('fParity', DWORD, 1),
+ ('fOutxCtsFlow', DWORD, 1),
+ ('fOutxDsrFlow', DWORD, 1),
+ ('fDtrControl', DWORD, 2),
+ ('fDsrSensitivity', DWORD, 1),
+ ('fTXContinueOnXoff', DWORD, 1),
+ ('fOutX', DWORD, 1),
+ ('fInX', DWORD, 1),
+ ('fErrorChar', DWORD, 1),
+ ('fNull', DWORD, 1),
+ ('fRtsControl', DWORD, 2),
+ ('fAbortOnError', DWORD, 1),
+ ('fDummy2', DWORD, 17),
+ ('wReserved', WORD),
+ ('XonLim', WORD),
+ ('XoffLim', WORD),
+ ('ByteSize', BYTE),
+ ('Parity', BYTE),
+ ('StopBits', BYTE),
+ ('XonChar', c_char),
+ ('XoffChar', c_char),
+ ('ErrorChar', c_char),
+ ('EofChar', c_char),
+ ('EvtChar', c_char),
+ ('wReserved1', WORD),
+]
+_COMMTIMEOUTS._fields_ = [
+ ('ReadIntervalTimeout', DWORD),
+ ('ReadTotalTimeoutMultiplier', DWORD),
+ ('ReadTotalTimeoutConstant', DWORD),
+ ('WriteTotalTimeoutMultiplier', DWORD),
+ ('WriteTotalTimeoutConstant', DWORD),
+]
+__all__ = ['GetLastError', 'MS_CTS_ON', 'FILE_ATTRIBUTE_NORMAL',
+ 'DTR_CONTROL_ENABLE', '_COMSTAT', 'MS_RLSD_ON',
+ 'GetOverlappedResult', 'SETXON', 'PURGE_TXABORT',
+ 'PurgeComm', 'N11_OVERLAPPED4DOLLAR_48E', 'EV_RING',
+ 'ONESTOPBIT', 'SETXOFF', 'PURGE_RXABORT', 'GetCommState',
+ 'RTS_CONTROL_ENABLE', '_DCB', 'CreateEvent',
+ '_COMMTIMEOUTS', '_SECURITY_ATTRIBUTES', 'EV_DSR',
+ 'EV_PERR', 'EV_RXFLAG', 'OPEN_EXISTING', 'DCB',
+ 'FILE_FLAG_OVERLAPPED', 'EV_CTS', 'SetupComm',
+ 'LPOVERLAPPED', 'EV_TXEMPTY', 'ClearCommBreak',
+ 'LPSECURITY_ATTRIBUTES', 'SetCommBreak', 'SetCommTimeouts',
+ 'COMMTIMEOUTS', 'ODDPARITY', 'EV_RLSD',
+ 'GetCommModemStatus', 'EV_EVENT2', 'PURGE_TXCLEAR',
+ 'EV_BREAK', 'EVENPARITY', 'LPCVOID', 'COMSTAT', 'ReadFile',
+ 'PVOID', '_OVERLAPPED', 'WriteFile', 'GetCommTimeouts',
+ 'ResetEvent', 'EV_RXCHAR', 'LPCOMSTAT', 'ClearCommError',
+ 'ERROR_IO_PENDING', 'EscapeCommFunction', 'GENERIC_READ',
+ 'RTS_CONTROL_HANDSHAKE', 'OVERLAPPED',
+ 'DTR_CONTROL_HANDSHAKE', 'PURGE_RXCLEAR', 'GENERIC_WRITE',
+ 'LPDCB', 'CreateEventW', 'SetCommMask', 'EV_EVENT1',
+ 'SetCommState', 'LPVOID', 'CreateFileW', 'LPDWORD',
+ 'EV_RX80FULL', 'TWOSTOPBITS', 'LPCOMMTIMEOUTS', 'MAXDWORD',
+ 'MS_DSR_ON', 'MS_RING_ON',
+ 'N11_OVERLAPPED4DOLLAR_484DOLLAR_49E', 'EV_ERR',
+ 'ULONG_PTR', 'CreateFile', 'NOPARITY', 'CloseHandle']
diff --git a/src/devtools/datool/tool/gen-dalk-from-lk.py b/src/devtools/datool/tool/gen-dalk-from-lk.py
new file mode 100755
index 0000000..52dffa9
--- /dev/null
+++ b/src/devtools/datool/tool/gen-dalk-from-lk.py
@@ -0,0 +1,197 @@
+#!/usr/bin/env python
+
+#
+# Copyright (C) 2015 MediaTek Inc. All rights reserved.
+# Tristan Shieh <tristan.shieh@mediatek.com>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+import os
+import struct
+import sys
+
+def read(path):
+ with open(path, "rb") as f:
+ return f.read()
+
+def write(path, data):
+ with open(path, "wb") as f:
+ f.write(data)
+
+def padding(data, size, pattern = '\0'):
+ return data + pattern * (size - len(data))
+
+LK_MEM_ADDRs = {'8135': 0x81e00000,
+ '8127': 0x81e00000,
+ '6595': 0x41e00000,
+ '8172': 0x41e00000,
+ '8173': 0x41e00000,
+ '7623': 0x81e00000,
+ '8163': 0x41e00000}
+
+BOOTARG_OFFSET = 0x80
+
+boot_args = {
+ '8135': struct.pack("26I",
+ 0x504c504c, 0x00000063, 0x00000000, 0x11009000,
+ 0x000e1000, 0x00500a01, 0x00000001, 0x34000000,
+ 0x10240d40, 0x02101010, 0x000a8200, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000231, 0x00000000,
+ 0x00000000, 0x00000000, 0x822041c1, 0x51200655,
+ 0x92124805, 0x18420000, 0x3a00a284, 0xc0444890,
+ 0x1980a991, 0x04000099),
+
+ '8127': struct.pack("27I",
+ 0x504C504C, 0x00000063, 0x00000000, 0x11002000,
+ 0x000E1000, 0x00000301, 0x00000001, 0x37C00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000003,
+ 0x00000000, 0x00000000, 0x00002116, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xAFB50204, 0x00000000,
+ 0x00000000, 0x00000000, 0x00008127),
+
+ '6595': struct.pack("26I",
+ 0x504c504c, 0x00000063, 0x00000000, 0x11002000,
+ 0x000e1000, 0xEBFE0101, 0x00000001, 0x80000000,
+ 0x00000000, 0xE59304C0, 0xE3500000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000231, 0x00000000,
+ 0x00000000, 0x00000000, 0x822041c1, 0x51200655,
+ 0x92124805, 0x18420000, 0x40079a84, 0xE1A09000,
+ 0x00000000, 0x00000000),
+
+ '8172': struct.pack("102I",
+ 0x504C504C, 0x00000063, 0x00000000, 0x11002000,
+ 0x000E1000, 0x00000301, 0x00000001, 0x76C00000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0xB6C00000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000A2B,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x42079A84,
+ 0x00000000, 0x00000000, 0x00000000, 0x002198C0,
+ 0x00000000, 0x00000000, 0x00000007, 0x00000005,
+ 0x0012FB00, 0x00000500, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0xB6C00000, 0x00000000,
+ 0x09400000, 0x00000000),
+
+ '8173': struct.pack("44I",
+ 0x504C504C, 0x00000063, 0x00000000, 0x11002000,
+ 0x000E1000, 0x00000301, 0x00000001, 0x7F800000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000001,
+ 0x00000000, 0x00000000, 0x000014E7, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x40079A84, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x001997C0, 0x00000000,
+ 0x00000007, 0x00000005, 0x0012C000, 0x00004000,
+ 0xBF800000, 0x00000000, 0x00800000, 0x00000000),
+
+ '7623': struct.pack("27I",
+ 0x504C504C, 0x00000063, 0x00000000, 0x11004000,
+ 0x000E1000, 0xFFFC4201, 0x00000001, 0x3FE00000,
+ 0xDFF4FFBF, 0xFE7FFFFF, 0xDFEFFFFF, 0x00000000,
+ 0x00000000, 0x00000000, 0x000011FD, 0xFFFDB7FE,
+ 0xF1FF2FFF, 0xFFFFFFAF, 0xFFF29FFF, 0xBF7BDE7F,
+ 0x3FFD997F, 0xFFEFFFBF, 0xAFB50204, 0xFECF3FFF,
+ 0x00000000, 0x00000000, 0x00008590),
+
+ '8163': struct.pack("88I",
+ 0x504C504C, 0x00000063, 0x00000000, 0x11002000,
+ 0x000E1000, 0xFFFF0301, 0x00000001, 0x3FC00000,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0x00000001, 0x00000000, 0x40000000, 0x00000000,
+ 0x3FC00000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF,
+ 0x40000000, 0x00000000, 0x40000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000,
+ 0x7FC00000, 0x00000000, 0x00400000, 0x00000000,
+ 0x00000000, 0x00000000, 0x00000000, 0x0000E4DC,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
+ 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x42058A04,
+ 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00178980,
+ 0x11003000, 0x00000000, 0x00000006, 0x00000004,
+ 0x0012C000, 0x00004000, 0x2E312E30, 0x25003030)}
+
+def main(argv):
+ lk = read(argv[2])
+
+ print("CHIP_ID: %s" % argv[1])
+ boot_arg = boot_args[argv[1]]
+ LK_MEM_ADDR = LK_MEM_ADDRs[argv[1]]
+
+ lk_wrapper = struct.pack("21I",
+ #LK_WRAPPER:
+ 0xe1a0000f, # 0: mov r0, pc
+ 0xe2400008, # 4: sub r0, r0, #8
+ 0xe59f1030, # 8: ldr r1, [pc, #48] ; 40 <COPY+0x1c>
+ 0xe0800001, # c: add r0, r0, r1
+ 0xe59f102c, # 10: ldr r1, [pc, #44] ; 44 <COPY+0x20>
+ 0xe59f202c, # 14: ldr r2, [pc, #44] ; 48 <COPY+0x24>
+ 0xe0812002, # 18: add r2, r1, r2
+ 0xe59f3028, # 1c: ldr r3, [pc, #40] ; 4c <COPY+0x28>
+ 0xe0822003, # 20: add r2, r2, r3
+ #COPY:
+ 0xe1510002, # 24: cmp r1, r2
+ 0x34903004, # 28: ldrcc r3, [r0], #4
+ 0x34813004, # 2c: strcc r3, [r1], #4
+ 0x3afffffb, # 30: bcc 24 <COPY>
+ 0xe59f4008, # 34: ldr r4, [pc, #8] ; 44 <COPY+0x20>
+ 0xe59f5008, # 38: ldr r5, [pc, #8] ; 48 <COPY+0x24>
+ 0xe59ff00c, # 3c: ldr pc, [pc, #12] ; 50 <COPY+0x2c>
+ BOOTARG_OFFSET, # 40: BOOTARG_OFFSET .word 0x11111111
+ LK_MEM_ADDR - len(boot_arg), # 44: BOOTARG_ADDR .word 0x22222222
+ len(boot_arg), # 48: BOOTARG_SIZE .word 0x33333333
+ len(lk), # 4c: LK_SIZE .word 0x44444444
+ LK_MEM_ADDR # 50: LK_ADDR .word 0x55555555
+ )
+
+ o = padding(lk_wrapper, BOOTARG_OFFSET, '\0') + boot_arg + lk
+ # padding to even-sized output
+ write(argv[3], padding(o, len(o)+len(o)%2, '\0'))
+
+
+if __name__ == "__main__":
+ main(sys.argv)
+
+
diff --git a/src/devtools/datool/tool/signfile-for-brom.sh b/src/devtools/datool/tool/signfile-for-brom.sh
new file mode 100755
index 0000000..335f291
--- /dev/null
+++ b/src/devtools/datool/tool/signfile-for-brom.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2015 MediaTek Inc. All rights reserved.
+# Tristan Shieh <tristan.shieh@mediatek.com>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+if [ $# -lt 2 -o $# -gt 3 ]
+then
+ echo "Usage: $0 private-key.pem filename [pss]"
+ exit -1
+fi
+
+TMPFILE1=$(mktemp)
+TMPFILE2=$(mktemp)
+
+python -c "
+import hashlib
+
+f = open('$2', 'rb')
+b = f.read()
+f.close()
+
+d = hashlib.sha256(b).digest()
+if '$3' != 'pss':
+ b = '\0\0'
+ for i in range(0, len(d), 2):
+ b += d[i + 1] + d[i]
+ b += '\0' * 222
+else:
+ b = d
+
+f = open('${TMPFILE1}', 'wb')
+f.write(b)
+f.close()
+"
+
+if [ -z "$3" -o "$3" != "pss" ]; then
+openssl rsautl -sign -inkey $1 -raw -in ${TMPFILE1} -out ${TMPFILE2}
+else
+openssl pkeyutl -sign -inkey $1 -in ${TMPFILE1} -out ${TMPFILE2} -pkeyopt digest:sha256 -pkeyopt rsa_padding_mode:pss -pkeyopt rsa_pss_saltlen:32
+fi
+RET=$?
+
+python -c "
+f = open('${TMPFILE2}', 'rb')
+d = f.read()
+f.close()
+b = ''
+if '$3' != 'pss':
+ for i in range(0, len(d), 2):
+ b += d[i + 1] + d[i]
+else:
+ b = d;
+f = open('$2.sign', 'wb')
+f.write(b)
+f.close()
+"
+
+if [ "$3" = "pss" ]; then
+ echo "Signature file $2.sign with pss padding is generated"
+else
+ echo "Signature file $2.sign with legacy padding is generated"
+fi
+
+rm -f ${TMPFILE1} ${TMPFILE2}
+exit ${RET}
diff --git a/src/devtools/datool/tool/signfile-for-pl.sh b/src/devtools/datool/tool/signfile-for-pl.sh
new file mode 100755
index 0000000..2f7070c
--- /dev/null
+++ b/src/devtools/datool/tool/signfile-for-pl.sh
@@ -0,0 +1,91 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2015 MediaTek Inc. All rights reserved.
+# Tristan Shieh <tristan.shieh@mediatek.com>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+
+if [ $# -ne 2 ]
+then
+ echo "Usage: $0 private-key.pem filename"
+ exit -1
+fi
+
+TMPFILE1=$(mktemp)
+TMPFILE2=$(mktemp)
+
+python -c "
+import hashlib
+import struct
+import os
+
+file_len = os.path.getsize('$2')
+b = struct.pack('16I', \
+ 0x53535353, 0x54535543, 0x00000000, 0x00000000, \
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+ 0x00000000, 0x00000001, file_len, 0x00000040, \
+ 0x00000000, file_len, file_len+0x40, 0x00000094, )
+
+f = open('$2', 'rb')
+b += f.read()
+f.close()
+
+d = hashlib.sha1(b).digest()
+
+f = open('${TMPFILE1}', 'wb')
+f.write(d)
+f.close()
+"
+
+openssl rsautl -sign -inkey $1 -in ${TMPFILE1} -out ${TMPFILE2}
+RET=$?
+
+python -c "
+import struct
+import os
+
+file_len = os.path.getsize('$2')
+b = struct.pack('16I', \
+ 0x53535353, 0x54535543, 0x00000000, 0x00000000, \
+ 0x00000000, 0x00000000, 0x00000000, 0x00000000, \
+ 0x00000000, 0x00000001, file_len, 0x00000040, \
+ 0x00000000, file_len, file_len+0x40, 0x00000094, )
+
+f = open('${TMPFILE2}', 'rb')
+b += f.read()
+f.close()
+
+f = open('${TMPFILE1}', 'rb')
+b += f.read(20)
+f.close()
+
+b += '\0' * 44
+
+f = open('$2.sign', 'wb')
+f.write(b)
+f.close()
+"
+
+rm -f ${TMPFILE1} ${TMPFILE2}
+exit ${RET}
diff --git a/src/devtools/met_drv_v2/Android.mk b/src/devtools/met_drv_v2/Android.mk
new file mode 100644
index 0000000..e0aef8b
--- /dev/null
+++ b/src/devtools/met_drv_v2/Android.mk
@@ -0,0 +1,17 @@
+LOCAL_PATH := $(call my-dir)
+
+# kernel version check
+KERNEL_VERSION := $(word 2,$(subst -, ,$(LINUX_KERNEL_VERSION)))
+MAJOR_VERSION := $(shell echo $(KERNEL_VERSION) | cut -f1 -d.)
+MINOR_VERSION := $(shell echo $(KERNEL_VERSION) | cut -f2 -d.)
+VERSION_CHECK := $(shell test $(MAJOR_VERSION) -ge 5 || test $(MAJOR_VERSION) -ge 4 -a $(MINOR_VERSION) -ge 19 && echo true)
+
+ifeq ($(VERSION_CHECK), true)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := met.ko
+LOCAL_STRIP_MODULE := true
+
+include $(MTK_KERNEL_MODULE)
+
+endif # Kernel version >= 4.19
diff --git a/src/devtools/met_drv_v2/Makefile b/src/devtools/met_drv_v2/Makefile
new file mode 100644
index 0000000..c496f00
--- /dev/null
+++ b/src/devtools/met_drv_v2/Makefile
@@ -0,0 +1,54 @@
+MET_ROOT_DIR := $(src)
+
+ifneq ($(MET_ROOT_DIR),)
+ MTK_PLATFORM := $(subst ",,$(CONFIG_MTK_PLATFORM))
+ MET_COMMON_DIR := $(wildcard $(MET_ROOT_DIR)/common)
+ MET_BUILD_DEFAULT := n
+
+ ifneq ($(MTK_PLATFORM),)
+ MET_PLF_DIR := $(wildcard $(MET_ROOT_DIR)/$(MTK_PLATFORM))
+ else
+ MET_PLF_DIR :=
+ endif
+
+ ifeq ($(CONFIG_MODULES),y)
+
+ ifeq ($(CONFIG_FTRACE),y)
+ ifeq ($(CONFIG_TRACING),y)
+ FTRACE_READY := y
+ endif
+ endif
+
+ ifeq ($(CONFIG_MTK_MET_PLF),m)
+ MET_BUILD_KO := y
+ endif
+
+ $(info ******** Start to build met_drv for $(MTK_PLATFORM) ********)
+ ifneq ($(MET_PLF_DIR),)
+ ifeq ($(FTRACE_READY),y)
+ ifeq ($(MET_BUILD_KO),y)
+ include $(MET_COMMON_DIR)/Kbuild
+ else
+ $(warning Not building met.ko due to CONFIG_MTK_MET_PLF is not set to m, build met default)
+ MET_BUILD_DEFAULT = y
+ endif
+ else
+ $(warning Not building met.ko due to CONFIG_FTRACE/CONFIG_TRACING is not set, build met default)
+ MET_BUILD_DEFAULT = y
+ endif
+ else
+ $(warning not support "$(MTK_PLATFORM)", build met default)
+ MET_BUILD_DEFAULT = y
+ endif
+ else #CONFIG_MODULES = n
+ $(warning Not building met.ko due to CONFIG_MODULES is not set, build met default)
+ MET_BUILD_DEFAULT := y
+ endif
+
+ ifeq ($(MET_BUILD_DEFAULT),y)
+ MET_DEF_DIR := $(MET_ROOT_DIR)/default
+ include $(MET_DEF_DIR)/Kbuild
+ endif
+else
+ $(info ******** MET_ROOT_DIR is empty ********)
+endif
diff --git a/src/devtools/met_drv_v2/Makefile.yocto b/src/devtools/met_drv_v2/Makefile.yocto
new file mode 100644
index 0000000..14e4add
--- /dev/null
+++ b/src/devtools/met_drv_v2/Makefile.yocto
@@ -0,0 +1,15 @@
+MODULE_NAME := met
+
+##############################################################
+# Compile settings
+##############################################################
+all:
+ make -C $(KERNEL_OUT) M=$(MET_DRIVER_DIR) modules
+
+clean:
+ make -C $(KERNEL_OUT) M=$(MET_DRIVER_DIR) clean
+ if [ -e $(MET_DRIVER_DIR)/$(MODULE_NAME).ko ]; then rm $(MET_DRIVER_DIR)/$(MODULE_NAME).ko; fi;
+
+.PHONY: all clean
+
+
diff --git a/src/devtools/met_drv_v2/common/Kbuild b/src/devtools/met_drv_v2/common/Kbuild
new file mode 100644
index 0000000..cf763b2
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/Kbuild
@@ -0,0 +1,551 @@
+################################################################################
+# MET Kernel module mode
+################################################################################
+ifeq ("$(CONFIG_MTK_MET_PLF)","m")
+$(info ======== Build met.ko ... ========)
+else
+$(info ======== MET Built in ... ========)
+endif
+
+MET_CORE := common
+
+obj-$(CONFIG_MTK_MET_PLF) := met.o
+
+ifneq ($(wildcard $(MET_PLF_DIR)/Kbuild.platform.inc),)
+ include $(MET_PLF_DIR)/Kbuild.platform.inc
+else
+ $(info ======= Missing $(MET_PLF_DIR)/Kbuild.platform.inc ========)
+endif
+
+ifneq ($(wildcard $(srctree)/drivers/misc/mediatek/include/mt-plat/sync_write.h),)
+ ccflags-y += -DUSE_KERNEL_SYNC_WRITE_H
+endif
+
+ifneq ($(wildcard $(srctree)/drivers/misc/mediatek/include/mt-plat/mtk_io.h),)
+ ccflags-y += -DUSE_KERNEL_MTK_IO_H
+endif
+
+ccflags-y += -DCONFIG_MET_MODULE
+ccflags-y += -DMET_PLF_USE
+ccflags-y += -I$(MET_COMMON_DIR)
+ccflags-y += -I$(MET_PLF_DIR)
+ccflags-y += -I$(srctree)/include/
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/leds/
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/leds/$(MTK_PLATFORM)/
+ccflags-y += -I$(srctree)/drivers/misc/mediatek/met_drv/core/
+
+ccflags-y += $(EXTRA_ARGS) $(EXTRA_CFLAGS)
+ccflags-y += -DMTK_PLATFORM=$(MTK_PLATFORM)
+#ccflags-y += -DONDIEMET_MOUNT_DEBUGFS
+
+met-y := $(MET_CORE)/met_main.o \
+ $(MET_CORE)/met_tag_ex.o \
+ $(MET_CORE)/interface.o \
+ $(MET_CORE)/sampler.o \
+ $(MET_CORE)/dummy_header.o \
+ $(MET_CORE)/util.o \
+ $(MET_CORE)/stat.o \
+ $(MET_CORE)/cookie.o \
+ $(MET_CORE)/mem_stat.o \
+ $(MET_CORE)/switch.o \
+ $(MET_CORE)/trace_event.o \
+ $(MET_CORE)/core_plf_init.o \
+ $(MET_CORE)/core_plf_trace.o
+
+CFLAGS_interface.o += -DMET_USER_EVENT_SUPPORT
+CFLAGS_met_tag_ex.o += -DMET_USER_EVENT_SUPPORT
+
+################################################################################
+# MET feature declaration
+################################################################################
+FEATURE_SPMTWAM := $(if $(FEATURE_SPMTWAM),$(FEATURE_SPMTWAM),y)
+FEATURE_SSPM_EMI := $(if $(FEATURE_SSPM_EMI),$(FEATURE_SSPM_EMI),y)
+FEATURE_GPU := $(if $(FEATURE_GPU),$(FEATURE_GPU),y)
+FEATURE_VCOREDVFS := $(if $(FEATURE_VCOREDVFS),$(FEATURE_VCOREDVFS),y)
+FEATURE_PTPOD := $(if $(FEATURE_PTPOD),$(FEATURE_PTPOD),y)
+FEATURE_CPUDSU := $(if $(FEATURE_CPUDSU),$(FEATURE_CPUDSU),y)
+FEATURE_WALLTIME := $(if $(FEATURE_WALLTIME),$(FEATURE_WALLTIME),y)
+FEATURE_SMI := $(if $(FEATURE_SMI),$(FEATURE_SMI),y)
+FEATURE_MET_BACKLIGHT := $(if $(FEATURE_MET_BACKLIGHT),$(FEATURE_MET_BACKLIGHT),y)
+FEATURE_EVENT_POWER := $(if $(FEATURE_EVENT_POWER),$(FEATURE_EVENT_POWER),y)
+FEATURE_ONDIEMET := $(if $(FEATURE_ONDIEMET),$(FEATURE_ONDIEMET),y)
+FEATURE_TINYSYS := $(if $(FEATURE_TINYSYS),$(FEATURE_TINYSYS),n)
+
+################################################################################
+# MET_CPU_PMU
+################################################################################
+$(info CPUPMU_VERSION = $(CPUPMU_VERSION))
+ifeq ("$(CPUPMU_VERSION)", "V8_2")
+ ccflags-y += -DCPUPMU_V8_2
+endif
+
+$(info ARCH = $(ARCH))
+ifeq ($(ARCH), mips)
+ met-y += $(MET_CORE)/mips_pmu_hw.o
+endif #ifeq ($(ARCH), mips)
+
+ifeq ($(ARCH), arm)
+ ccflags-y += -DCONFIG_MET_ARM_32BIT
+ met-y += $(MET_CORE)/cpu_pmu.o
+ met-y += $(MET_CORE)/v7_pmu_hw.o
+ met-y += $(MET_CORE)/v6_pmu_hw.o
+endif #ifeq ($(ARCH), arm)
+
+ifeq ($(ARCH), arm64)
+ met-y += $(MET_CORE)/cpu_pmu.o
+ met-y += $(MET_CORE)/v8_pmu_hw.o
+endif
+
+################################################################################
+# MET_CPU_FREQ
+################################################################################
+$(info CONFIG_CPU_FREQ = $(CONFIG_CPU_FREQ))
+ifeq ($(CONFIG_CPU_FREQ),y)
+ met-y += $(MET_CORE)/power.o
+endif
+
+################################################################################
+# MET_SPM_TWAM
+################################################################################
+$(info FEATURE_SPMTWAM = $(FEATURE_SPMTWAM))
+
+ifneq ($(FEATURE_SPMTWAM), n)
+ MET_SPM_TWAM := y
+
+ # for mtk_spm.h
+ ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/base/power/include/mtk_spm.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/
+ ccflags-y += -I$(MET_COMMON_DIR)/spmtwam/include/
+ else
+ MET_SPM_TWAM = n
+ $(info ========= Missing $(srctree)/drivers/misc/mediatek/base/power/include/mtk_spm.h ========)
+ $(info ======== disable MET_SPM_TWAM ========)
+ endif
+else
+ MET_SPM_TWAM := n
+endif
+
+$(info SPMTWAM_VERSION = $(SPMTWAM_VERSION))
+$(info SPMTWAM_IDLE_SIGNAL_SUPPORT = $(SPMTWAM_IDLE_SIGNAL_SUPPORT))
+
+ifeq ("$(SPMTWAM_IDLE_SIGNAL_SUPPORT)", "single")
+ ccflags-y += -DSPMTWAM_SINGLE_IDLE_SIGNAL
+endif
+
+ifeq ("$(SPMTWAM_IDLE_SIGNAL_SUPPORT)", "multiple")
+ ccflags-y += -DSPMTWAM_MULTIPLE_IDLE_SIGNAL
+endif
+
+ifeq ("$(SPMTWAM_VERSION)", "ap")
+ ccflags-y += -DSPMTWAM_AP
+ met-$(MET_SPM_TWAM) += $(MET_CORE)/spmtwam/ap/met_spmtwam.o
+endif
+
+ifeq ("$(SPMTWAM_VERSION)", "sspm")
+ ccflags-y += -DSPMTWAM_SSPM
+ met-$(MET_SPM_TWAM) += $(MET_CORE)/spmtwam/sspm/met_spmtwam.o
+endif
+
+################################################################################
+# MET_EMI
+################################################################################
+$(info FEATURE_SSPM_EMI = $(FEATURE_SSPM_EMI))
+
+ifeq ($(CONFIG_MTK_TINYSYS_SSPM_SUPPORT),y)
+ ifneq ($(FEATURE_ONDIEMET), n)
+ BUILD_SSPM_EMI := y
+ else ifneq ($(FEATURE_TINYSYS), n)
+ BUILD_SSPM_EMI := y
+ else
+ BUILD_SSPM_EMI := n
+ endif
+endif
+
+ifeq ($(BUILD_SSPM_EMI),y)
+ MET_EMI := $(if $(filter n,$(FEATURE_SSPM_EMI)),n,y)
+ ifeq ("$(EMI_SEDA_VERSION)", "SEDA3_5")
+ met-$(MET_EMI) += $(MET_CORE)/emi/SEDA3_5/met_emi.o \
+ $(MET_CORE)/emi/SEDA3_5/mtk_emi_bm.o
+ else ifeq ("$(EMI_SEDA_VERSION)", "SEDA3_6")
+ met-$(MET_EMI) += $(MET_CORE)/emi/SEDA3_6/met_emi.o \
+ $(MET_CORE)/emi/SEDA3_6/mtk_emi_bm.o
+ else
+ met-$(MET_EMI) += $(MET_CORE)/emi/SEDA3/met_emi.o \
+ $(MET_CORE)/emi/SEDA3/mtk_emi_bm.o
+ endif
+endif
+
+EMI_LOWEFF_SUPPORT := $(if $(EMI_LOWEFF_SUPPORT),$(EMI_LOWEFF_SUPPORT),n)
+ifeq ($(EMI_LOWEFF_SUPPORT), y)
+ subdir-ccflags-y += -DEMI_LOWEFF_SUPPORT
+endif
+
+################################################################################
+# MET_GPU
+################################################################################
+$(info FEATURE_GPU = $(FEATURE_GPU))
+
+ifneq ($(FEATURE_GPU), n)
+ MET_GPU := y
+
+ # for mtk_gpufreq.h
+ ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/mtk_gpufreq.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/
+ else ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/base/power/include/mtk_gpufreq.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/
+ else ifneq ("$(wildcard $(srctree)/drivers/gpu/mediatek/gpufreq/include/mtk_gpufreq.h)","")
+ ccflags-y += -I$(srctree)/drivers/gpu/mediatek/gpufreq/include/
+ else
+ MET_GPU = n
+ $(info ======= Missing $(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/mtk_gpufreq.h ========)
+ $(info ======= Missing $(srctree)/drivers/misc/mediatek/base/power/include/mtk_gpufreq.h ========)
+ $(info ======= Missing $(srctree)/drivers/gpu/mediatek/gpufreq/include/mtk_gpufreq.h ========)
+ $(info ======== disable MET_GPU ========)
+ endif
+
+ # for mtk_gpu_utility.h
+ ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/include/mt-plat/mtk_gpu_utility.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/
+ else ifneq ("$(wildcard $(srctree)/drivers/gpu/mediatek/mt-plat/mtk_gpu_utility.h)","")
+ ccflags-y += -I$(srctree)/drivers/gpu/mediatek/mt-plat/
+ else
+ MET_GPU = n
+ $(info ======== Missing $(srctree)/drivers/misc/mediatek/include/mt-plat/mtk_gpu_utility.h ========)
+ $(info ======== Missing $(srctree)/drivers/gpu/mediatek/mt-plat/mtk_gpu_utility.h ========)
+ $(info ======== disable MET_GPU ========)
+ endif
+
+ ifneq ($(CONFIG_MTK_GPU_SUPPORT), y)
+ MET_GPU = n
+ $(info ======== CONFIG_MTK_GPU_SUPPORT = n ========)
+ $(info ======== disable MET_GPU ========)
+ endif
+
+ GPU_STALL_CNT_TYPE := $(if $(GPU_STALL_CNT_TYPE),$(GPU_STALL_CNT_TYPE),multiple)
+ $(info GPU_STALL_CNT_TYPE = $(GPU_STALL_CNT_TYPE))
+
+ ifeq ("$(GPU_STALL_CNT_TYPE)", "single")
+ ccflags-y += -DGPU_STALL_CNT_SINGLE
+ endif
+else
+ MET_GPU := n
+endif
+
+met-$(MET_GPU) += $(MET_CORE)/mtk_gpu_metmonitor.o
+
+
+################################################################################
+# MET_VCOREDVFS
+################################################################################
+$(info FEATURE_VCOREDVFS = $(FEATURE_VCOREDVFS))
+
+ifneq ($(FEATURE_VCOREDVFS), n)
+ MET_VCOREDVFS := y
+
+ # for dvfsrc-exp.h
+ ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/include/mt-plat/dvfsrc-exp.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/
+ else
+ MET_VCOREDVFS = n
+ $(info ======== Missing $(srctree)/drivers/misc/mediatek/include/mt-plat/dvfsrc-exp.h ========)
+ $(info ======== disable MET_VCOREDVFS ========)
+ endif
+else
+ MET_VCOREDVFS := n
+endif
+
+ifneq ($(VCOREDVFS_OLD_VER),y)
+ met-$(MET_VCOREDVFS) += $(MET_CORE)/met_vcoredvfs.o
+else
+ ccflags-y += -DVCOREDVFS_OLD_VER
+ met-$(MET_VCOREDVFS) += $(MET_CORE)/met_vcoredvfs_44.o
+endif
+
+################################################################################
+# MET_PTPOD
+################################################################################
+$(info FEATURE_PTPOD = $(FEATURE_PTPOD))
+
+ifneq ($(FEATURE_PTPOD), n)
+ MET_PTPOD := y
+
+ # for mtk_gpufreq.h
+ ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/mtk_gpufreq.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/
+ else ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/base/power/include/mtk_gpufreq.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/base/power/include/
+ else ifneq ("$(wildcard $(srctree)/drivers/gpu/mediatek/gpufreq/include/mtk_gpufreq.h)","")
+ ccflags-y += -I$(srctree)/drivers/gpu/mediatek/gpufreq/include/
+ else
+ MET_PTPOD = n
+ $(info ======== Missing $(srctree)/drivers/misc/mediatek/base/power/$(MTK_PLATFORM)/mtk_gpufreq.h ========)
+ $(info ======== Missing $(srctree)/drivers/misc/mediatek/base/power/include/mtk_gpufreq.h ========)
+ $(info ======== Missing $(srctree)/drivers/gpu/mediatek/gpufreq/include/mtk_gpufreq.h ========)
+ $(info ======== disable MET_PTPOD ========)
+ endif
+
+ # for mtk_cpufreq_api.h
+ ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach/mtk_cpufreq_api.h)","")
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/
+ else
+ MET_PTPOD = n
+ $(info ======== Missing $(srctree)/drivers/misc/mediatek/include/mt-plat/$(MTK_PLATFORM)/include/mach/mtk_cpufreq_api.h ========)
+ $(info ======== disable MET_PTPOD ========)
+ endif
+
+ # for mtk_cpufreq_config.h
+ ifneq ("$(wildcard $(MET_PTPOD_INC)/mtk_cpufreq_config.h)","")
+ ccflags-y += -I$(MET_PTPOD_INC)
+ else
+ MET_PTPOD = n
+ $(info ======== Missing $(MET_PTPOD_INC)/mtk_cpufreq_config.h ========)
+ $(info ======== disable MET_PTPOD ========)
+ endif
+else
+ MET_PTPOD := n
+endif
+
+met-$(MET_PTPOD) += $(MET_CORE)/met_ptpod.o
+
+
+################################################################################
+# MET_CPUDSU
+################################################################################
+$(info FEATURE_CPUDSU = $(FEATURE_CPUDSU))
+
+MET_CPUDSU := $(if $(filter n,$(FEATURE_CPUDSU)),n,y)
+
+met-$(MET_CPUDSU) += $(MET_CORE)/cpu_dsu.o \
+ $(MET_CORE)/v8_dsu_hw.o
+
+################################################################################
+# MET_WALLTIME
+################################################################################
+$(info FEATURE_WALLTIME = $(FEATURE_WALLTIME))
+
+MET_WALLTIME := $(if $(filter n,$(FEATURE_WALLTIME)),n,y)
+
+met-$(MET_WALLTIME) += $(MET_CORE)/met_wall_time.o
+
+################################################################################
+# MET_SMI
+################################################################################
+$(info FEATURE_SMI = $(FEATURE_SMI))
+
+################################################################################
+# MET_BACKLIGHT
+################################################################################
+$(info FEATURE_MET_BACKLIGHT = $(FEATURE_MET_BACKLIGHT))
+
+MET_BACKLIGHT := $(if $(filter n,$(FEATURE_MET_BACKLIGHT)),n,y)
+
+met-$(MET_BACKLIGHT) += $(MET_CORE)/met_backlight.o
+
+################################################################################
+# EVENT_POWER
+################################################################################
+$(info FEATURE_EVENT_POWER = $(FEATURE_EVENT_POWER))
+
+ifeq ($(FEATURE_EVENT_POWER), y)
+ ccflags-y += -DMET_EVENT_POWER_SUPPORT
+endif
+
+################################################################################
+# On-die-met SSPM only module
+################################################################################
+ifeq ($(FEATURE_ONDIEMET), y)
+ FEATURE_ONDIEMET_WALLTIME := $(if $(FEATURE_ONDIEMET_WALLTIME),$(FEATURE_ONDIEMET_WALLTIME),y)
+else
+ FEATURE_ONDIEMET_WALLTIME := n
+endif
+
+$(info FEATURE_ONDIEMET = $(FEATURE_ONDIEMET))
+$(info FEATURE_ONDIEMET_WALLTIME = $(FEATURE_ONDIEMET_WALLTIME))
+
+ifneq ($(FEATURE_ONDIEMET), n)
+ subdir-ccflags-y += -DONDIEMET_SUPPORT
+
+ ifeq ($(CONFIG_MTK_TINYSYS_SSPM_SUPPORT),)
+ $(info CONFIG_MTK_TINYSYS_SSPM_SUPPORT = n)
+ else
+ $(info CONFIG_MTK_TINYSYS_SSPM_SUPPORT = $(CONFIG_MTK_TINYSYS_SSPM_SUPPORT))
+ endif
+
+ ifeq ($(CONFIG_MTK_TINYSYS_SSPM_SUPPORT),y)
+ subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/sspm
+ subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/sspm/$(MTK_PLATFORM)
+
+ met-y += $(MET_CORE)/ondiemet.o
+ met-y += $(MET_CORE)/ondiemet_log.o
+ met-y += $(MET_CORE)/sspm/ondiemet_sspm.o
+ met-y += $(MET_CORE)/sspm/sspm_ipi_handle.o
+ met-y += $(MET_CORE)/sspm/sspm_common.o
+ ccflags-y += -DMTK_TINYSYS_SSPM_SUPPORT
+
+ MET_SSPM_IF_INC := $(srctree)/drivers/misc/mediatek/sspm/
+ MET_SSPM_IF := sspm_ipi.h
+
+ # for sspm ipi interface
+ ifneq ("$(wildcard $(MET_SSPM_IF_INC)/$(MET_SSPM_IF))","")
+ ccflags-y += -I$(MET_SSPM_IF_INC)
+ SYS_SSPM_READY := y
+ else
+ $(info ======== Missing $(MET_SSPM_IF_INC)/$(MET_SSPM_IF) ========)
+ $(info ======== disable ALL ondiemet feature ========)
+
+ SYS_SSPM_READY := n
+ endif
+
+ # for dynamic allocate ondiemet dram buffer size
+ ifneq ($(DYNAMIC_ALLOC_ODM_BUF_SIZE),)
+ ccflags-y += -DDYNAMIC_ALLOC_ODM_BUF_SIZE=$(DYNAMIC_ALLOC_ODM_BUF_SIZE)
+ endif
+ else
+ $(info ======== CONFIG_MTK_TINYSYS_SSPM_SUPPORT = n ========)
+ $(info ======== disable ALL ondiemet feature ========)
+
+ SYS_SSPM_READY := n
+ endif
+
+ ifeq ($(SYS_SSPM_READY), y)
+ MET_SSPM_WALLTIME := $(if $(filter n,$(FEATURE_ONDIEMET_WALLTIME)),n,y)
+ met-$(MET_SSPM_WALLTIME) += $(MET_CORE)/sspm/sspm_walltime.o
+
+ MET_SMI := $(if $(filter n,$(FEATURE_SMI)),n,y)
+ met-$(MET_SMI) += $(MET_CORE)/sspm/sspm_met_smi.o
+ endif
+endif
+
+################################################################################
+# Tinysys MET module
+################################################################################
+FEATURE_TINYSYS := $(if $(FEATURE_TINYSYS),$(FEATURE_TINYSYS),n)
+$(info FEATURE_TINYSYS = $(FEATURE_TINYSYS))
+ifeq ($(FEATURE_TINYSYS),y)
+ ifeq ($(CONFIG_MTK_TINYSYS_MCUPM_SUPPORT),y)
+ $(info CONFIG_MTK_TINYSYS_MCUPM_SUPPORT = y)
+ else
+ $(info CONFIG_MTK_TINYSYS_MCUPM_SUPPORT = n)
+ FEATURE_CPU_EB_NUM := 0
+ endif
+ ifeq ($(CONFIG_MTK_TINYSYS_SCP_SUPPORT),y)
+ $(info CONFIG_MTK_TINYSYS_SCP_SUPPORT = y)
+ else
+ $(info CONFIG_MTK_TINYSYS_SCP_SUPPORT = n)
+ FEATURE_SCP_NUM := 0
+ endif
+ ifeq ($(CONFIG_MTK_TINYSYS_SSPM_SUPPORT),y)
+ $(info CONFIG_MTK_TINYSYS_SSPM_SUPPORT = y)
+ else
+ $(info CONFIG_MTK_TINYSYS_SSPM_SUPPORT = n)
+ FEATURE_SSPM_NUM := 0
+ endif
+
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/tinysys_log.o
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/tinysys_mgr.o
+ ccflags-y += -I$(MET_COMMON_DIR)/tinysys/$(TINYSYS_VERSION)
+
+ ccflags-y += -DFEATURE_SSPM_NUM=$(FEATURE_SSPM_NUM)
+ ccflags-y += -DFEATURE_CPU_EB_NUM=$(FEATURE_CPU_EB_NUM)
+ ccflags-y += -DFEATURE_SCP_NUM=$(FEATURE_SCP_NUM)
+
+ ifneq ($(FEATURE_CPU_EB_NUM),0)
+ $(info FEATURE_CPU_EB_NUM = $(FEATURE_CPU_EB_NUM))
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/cpu_eb/cpu_eb_met.o
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/cpu_eb/cpu_eb_met_log.o
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/cpu_eb/cpu_eb_met_ipi_handle.o
+ ccflags-y += -I$(MET_COMMON_DIR)/tinysys/$(TINYSYS_VERSION)/cpu_eb/
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/mcupm/$(MTK_PLATFORM)
+ ccflags-y += -DTINYSYS_CPU_EB_SUPPORT
+ endif
+
+ ifneq ($(FEATURE_SCP_NUM),0)
+ $(info FEATURE_SCP_NUM = $(FEATURE_SCP_NUM))
+ ccflags-y += -DTINYSYS_SCP_SUPPORT
+ endif
+
+ ifneq ($(FEATURE_SSPM_NUM),0)
+ $(info FEATURE_SSPM_NUM = $(FEATURE_SSPM_NUM))
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/sspm/sspm_met_log.o
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/sspm/sspm_met_ipi_handle.o
+ met-y += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/sspm/sspm_met_common.o
+ ccflags-y += -I$(MET_COMMON_DIR)/tinysys/$(TINYSYS_VERSION)/sspm
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/include
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/sspm/$(SSPM_VERSION)
+ ccflags-y += -I$(srctree)/drivers/misc/mediatek/sspm
+ ccflags-y += -DTINYSYS_SSPM_SUPPORT
+ ccflags-y += -DMTK_TINYSYS_SSPM_SUPPORT
+
+ SSPM_VERSION := $(if $(SSPM_VERSION),$(SSPM_VERSION),v1)
+ $(info SSPM_VERSION = $(SSPM_VERSION))
+ ifneq ($(SSPM_VERSION), v2)
+ MET_SSPM_COMM_INC := $(srctree)/drivers/misc/mediatek/sspm/$(SSPM_VERSION)
+ MET_SSPM_IF_INC := $(srctree)/drivers/misc/mediatek/sspm/$(SSPM_VERSION)
+ MET_SSPM_IF := sspm_ipi.h
+ MET_SSPM_IPI := sspm_ipi_define.h
+ else
+ MET_SSPM_COMM_INC := $(srctree)/drivers/misc/mediatek/sspm/$(SSPM_VERSION)
+ MET_SSPM_IF_INC := $(srctree)/include/linux/soc/mediatek
+ MET_SSPM_IF := mtk_tinysys_ipi.h
+ MET_SSPM_IPI := sspm_ipi_table.h
+ endif
+
+ ifneq ("$(wildcard $(srctree)/drivers/misc/mediatek/sspm/$(SSPM_VERSION)/$(MET_SSPM_IPI))","")
+ subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/sspm/$(SSPM_VERSION)
+ subdir-ccflags-y += -I$(srctree)/drivers/misc/mediatek/sspm
+ TINYSYS_SSPM_READY := y
+ else
+ $(info ======== Missing $(srctree)/drivers/misc/mediatek/sspm/$(MTK_PLATFORM)/$(MET_SSPM_IPI)========)
+ $(info ======== disable ALL tinysys SSPM feature ========)
+ TINYSYS_SSPM_READY := n
+ endif
+
+ # for smi_met_conf format
+ ifeq ($(SSPM_VERSION), v2)
+ ccflags-y += -DSSPM_VERSION_V2
+ ccflags-y += -DSMI_MASTER_8BIT
+ endif
+
+ # for sspm ipi interface
+ ifneq ("$(wildcard $(MET_SSPM_IF_INC)/$(MET_SSPM_IF))","")
+ ccflags-y += -I$(MET_SSPM_IF_INC)
+ ccflags-y += -I$(MET_SSPM_COMM_INC)
+ else
+ $(info ======== Missing $(MET_SSPM_IF_INC)/$(MET_SSPM_IF) ========)
+ $(info ======== disable ALL tinysys SSPM feature ========)
+ TINYSYS_SSPM_READY := n
+ endif
+
+ # for dynamic allocate ondiemet dram buffer size
+ ifneq ($(DYNAMIC_ALLOC_ODM_BUF_SIZE),)
+ ccflags-y += -DDYNAMIC_ALLOC_ODM_BUF_SIZE=$(DYNAMIC_ALLOC_ODM_BUF_SIZE)
+ endif
+ else
+ $(info ======== CONFIG_MTK_TINYSYS_SSPM_SUPPORT = n ========)
+ $(info ======== disable ALL tinysys SSPM feature ========)
+ TINYSYS_SSPM_READY := n
+ endif
+
+ ifeq ($(TINYSYS_SSPM_READY), y)
+ MET_SMI := $(if $(filter n,$(FEATURE_SMI)),n,y)
+ met-$(MET_SMI) += $(MET_CORE)/tinysys/$(TINYSYS_VERSION)/sspm/sspm_met_smi.o
+ endif
+endif
+
+##############################################################################################
+# include $(MET_PLF_DIR)/Kbuild
+##############################################################################################
+ifneq ($(wildcard $(MET_PLF_DIR)/Kbuild),)
+ include $(MET_PLF_DIR)/Kbuild
+else
+ $(info ======= Missing $(MET_PLF_DIR)/Kbuild ========)
+endif
+
+#################################################################################
+# add met_device flags
+#################################################################################
+ccflags-y += $(foreach v, $(filter MET_%,$(.VARIABLES)), $(if $(filter $($(v)),y),-D$(v)))
\ No newline at end of file
diff --git a/src/devtools/met_drv_v2/common/cookie.c b/src/devtools/met_drv_v2/common/cookie.c
new file mode 100644
index 0000000..b4d0129
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/cookie.c
@@ -0,0 +1,273 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/cpu.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <asm/irq_regs.h>
+#include <asm/stacktrace.h>
+#include <linux/stacktrace.h>
+#include "interface.h"
+#include "met_drv.h"
+
+#define LINE_SIZE 256
+
+struct cookie_info {
+ int depth;
+ int strlen;
+ char strbuf[LINE_SIZE];
+};
+
+static unsigned int back_trace_depth;
+static DEFINE_PER_CPU(struct cookie_info, info);
+static DEFINE_PER_CPU(int, cpu_status);
+
+static int reset_driver_stat(void)
+{
+ back_trace_depth = 0;
+ met_cookie.mode = 0;
+ return 0;
+}
+
+
+noinline void cookie(char *strbuf)
+{
+ MET_TRACE("%s\n", strbuf);
+}
+
+noinline void cookie2(char *strbuf)
+{
+ MET_TRACE("%s\n", strbuf);
+}
+
+static void get_kernel_cookie(unsigned long pc, struct cookie_info *pinfo)
+{
+ int ret;
+#if IS_ENABLED(CONFIG_MODULES)
+ off_t off;
+ struct module *mod = __module_address(pc);
+
+ if (mod) {
+ off = pc - (unsigned long)mod->core_layout.base;
+ ret = snprintf(pinfo->strbuf + pinfo->strlen, LINE_SIZE - pinfo->strlen,
+ ",%s,%lx", mod->name, off);
+ pinfo->strlen += ret;
+ /* cookie(current->comm, pc, mod->name, off, 1); */
+ } else
+#endif
+ {
+ ret =
+ snprintf(pinfo->strbuf + pinfo->strlen, LINE_SIZE - pinfo->strlen,
+ ",vmlinux,%lx", pc);
+ pinfo->strlen += ret;
+ /* cookie(current->comm, pc, "vmlinux", pc, 0); */
+ }
+}
+
+#if defined(__arm__)
+static int report_trace(struct stackframe *frame, void *d)
+{
+ struct cookie_info *pinfo = d;
+ unsigned long pc = frame->pc;
+
+ if (pinfo->depth > 0) {
+ get_kernel_cookie(pc, pinfo);
+ pinfo->depth--;
+ return 0;
+ }
+ return 1;
+}
+#endif
+
+static void kernel_backtrace(struct pt_regs *const regs, struct cookie_info *pinfo)
+{
+#if defined(__arm__)
+ struct stackframe frame;
+
+ frame.fp = regs->ARM_fp;
+ frame.sp = regs->ARM_sp;
+ frame.lr = regs->ARM_lr;
+ frame.pc = regs->ARM_pc;
+ walk_stackframe(&frame, report_trace, pinfo);
+#else
+ return;
+#endif
+}
+
+
+void met_cookie_polling(unsigned long long stamp, int cpu)
+{
+ struct pt_regs *regs;
+ struct cookie_info *pinfo;
+ unsigned long pc;
+ int ret, outflag = 0;
+ off_t off;
+
+ if (per_cpu(cpu_status, cpu) != MET_CPU_ONLINE)
+ return;
+
+ regs = get_irq_regs();
+
+ if (regs == 0)
+ return;
+
+ pc = profile_pc(regs);
+
+ pinfo = &(per_cpu(info, cpu));
+ pinfo->strlen = snprintf(pinfo->strbuf, LINE_SIZE, "%s,%lx", current->comm, pc);
+
+ if (user_mode(regs)) {
+ struct mm_struct *mm;
+ struct vm_area_struct *vma;
+ struct path *ppath;
+
+ mm = current->mm;
+ for (vma = find_vma(mm, pc); vma; vma = vma->vm_next) {
+
+ if (pc < vma->vm_start || pc >= vma->vm_end)
+ continue;
+
+ if (vma->vm_file) {
+ ppath = &(vma->vm_file->f_path);
+
+ if (vma->vm_flags & VM_DENYWRITE)
+ off = pc;
+ else
+ off = (vma->vm_pgoff << PAGE_SHIFT) + pc - vma->vm_start;
+
+ ret =
+ snprintf(pinfo->strbuf + pinfo->strlen,
+ LINE_SIZE - pinfo->strlen, ",%s,%lx",
+ (char *)(ppath->dentry->d_name.name), off);
+ pinfo->strlen += ret;
+ outflag = 1;
+ } else {
+ /* must be an anonymous map */
+ ret =
+ snprintf(pinfo->strbuf + pinfo->strlen,
+ LINE_SIZE - pinfo->strlen, ",nofile,%lx", pc);
+ pinfo->strlen += ret;
+ outflag = 1;
+ }
+ break;
+ }
+ } else {
+ /* kernel mode code */
+ if (back_trace_depth > 0) {
+ pinfo->depth = back_trace_depth + 1;
+ kernel_backtrace(regs, pinfo);
+ } else
+ get_kernel_cookie(pc, pinfo);
+ outflag = 1;
+ }
+
+ /* check task is resolvable */
+ if (outflag == 0)
+ return;
+
+ if (back_trace_depth == 0)
+ cookie(pinfo->strbuf);
+ else
+ cookie2(pinfo->strbuf);
+}
+
+
+static void met_cookie_start(void)
+{
+ int cpu = raw_smp_processor_id();
+ per_cpu(cpu_status, cpu) = MET_CPU_ONLINE;
+ /* return; */
+}
+
+static void met_cookie_stop(void)
+{
+ /* return; */
+}
+
+
+static int met_cookie_process_argument(const char *arg, int len)
+{
+ unsigned int value = 0;
+
+ if (met_parse_num(arg, &value, len) < 0) {
+ met_cookie.mode = 0;
+ return -EINVAL;
+ }
+
+ back_trace_depth = value;
+ met_cookie.mode = 1;
+
+ return 0;
+}
+
+static const char help[] =
+" --cookie enable sampling task and PC\n"
+" --cookie=N enable back trace (depth is N)\n";
+
+static int met_cookie_print_help(char *buf, int len)
+{
+ len = snprintf(buf, PAGE_SIZE, help);
+ return len;
+}
+
+
+static const char header[] =
+"# cookie: task_name,PC,cookie_name,offset\n"
+"met-info [000] 0.0: cookie_header: task_name,PC,cookie_name,offset\n";
+
+static const char header2_1[] = "# cookie2: task_name,PC,cookie,offset";
+static const char header2_2[] = "met-info [000] 0.0: cookie2_header: task_name,PC,cookie,offset";
+
+static int met_cookie_print_header(char *buf, int len)
+{
+ int i, ret;
+
+ if (back_trace_depth == 0) {
+ len = snprintf(buf, PAGE_SIZE, header);
+ } else {
+ len = snprintf(buf, PAGE_SIZE, header2_1);
+ for (i = 0; i < back_trace_depth; i++) {
+ ret = snprintf(buf + len, PAGE_SIZE, ",cookie%d,offset%d", i + 1, i + 1);
+ len += ret;
+ }
+ ret = snprintf(buf + len, PAGE_SIZE, "\n");
+ len += ret;
+
+ ret = snprintf(buf + len, PAGE_SIZE, header2_2);
+ len += ret;
+ for (i = 0; i < back_trace_depth; i++) {
+ ret = snprintf(buf + len, PAGE_SIZE, ",cookie%d,offset%d", i + 1, i + 1);
+ len += ret;
+ }
+ ret = snprintf(buf + len, PAGE_SIZE, "\n");
+ len += ret;
+ }
+
+ return len;
+}
+
+static void met_cookie_cpu_state_notify(long cpu, unsigned long action)
+{
+ per_cpu(cpu_status, cpu) = action;
+}
+
+struct metdevice met_cookie = {
+ .name = "cookie",
+ .type = MET_TYPE_PMU,
+ .cpu_related = 1,
+ .start = met_cookie_start,
+ .stop = met_cookie_stop,
+ .reset = reset_driver_stat,
+ .polling_interval = 1,
+ .timed_polling = met_cookie_polling,
+ .process_argument = met_cookie_process_argument,
+ .print_help = met_cookie_print_help,
+ .print_header = met_cookie_print_header,
+ .cpu_state_notify = met_cookie_cpu_state_notify,
+};
diff --git a/src/devtools/met_drv_v2/common/core_plf_init.c b/src/devtools/met_drv_v2/common/core_plf_init.c
new file mode 100644
index 0000000..f368b0d
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/core_plf_init.c
@@ -0,0 +1,413 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/kallsyms.h>
+#include "met_drv.h"
+#include "met_api.h"
+#include "interface.h"
+#include "core_plf_init.h"
+#include "met_kernel_symbol.h"
+
+#undef DEBUG
+
+#ifdef MET_GPU
+/*
+ * GPU
+ */
+bool (*mtk_get_gpu_loading_symbol)(unsigned int *pLoading);
+bool (*mtk_get_gpu_block_symbol)(unsigned int *pBlock);
+bool (*mtk_get_gpu_idle_symbol)(unsigned int *pIdle);
+bool (*mtk_get_gpu_dvfs_from_symbol)(enum MTK_GPU_DVFS_TYPE *peType, unsigned long *pulFreq);
+bool (*mtk_get_gpu_sub_loading_symbol)(unsigned int *pLoading);
+bool (*mtk_get_3D_fences_count_symbol)(int *pi32Count);
+bool (*mtk_get_gpu_memory_usage_symbol)(unsigned int *pMemUsage);
+bool (*mtk_get_gpu_power_loading_symbol)(unsigned int *pLoading);
+bool (*mtk_get_custom_boost_gpu_freq_symbol)(unsigned long *pulFreq);
+bool (*mtk_get_custom_upbound_gpu_freq_symbol)(unsigned long *pulFreq);
+bool (*mtk_get_vsync_based_target_freq_symbol)(unsigned long *pulFreq);
+bool (*mtk_get_vsync_offset_event_status_symbol)(unsigned int *pui32EventStatus);
+bool (*mtk_get_vsync_offset_debug_status_symbol)(unsigned int *pui32EventStatus);
+bool (*mtk_enable_gpu_perf_monitor_symbol)(bool enable);
+bool (*mtk_get_gpu_pmu_init_symbol)(struct GPU_PMU *pmus, int pmu_size, int *ret_size);
+bool (*mtk_get_gpu_pmu_swapnreset_symbol)(struct GPU_PMU *pmus, int pmu_size);
+#if 1
+bool (*mtk_get_gpu_pmu_deinit_symbol)(void);
+bool (*mtk_get_gpu_pmu_swapnreset_stop_symbol)(void);
+#endif
+unsigned int (*mt_gpufreq_get_cur_freq_symbol)(void);
+unsigned int (*mt_gpufreq_get_thermal_limit_freq_symbol)(void);
+bool (*mtk_register_gpu_power_change_symbol)(const char *name, void (*callback)(int power_on));
+bool (*mtk_unregister_gpu_power_change_symbol)(const char *name);
+#endif /* MET_GPU */
+
+#ifdef MET_VCOREDVFS
+/*
+ * VCORE DVFS
+ */
+#ifdef VCOREDVFS_OLD_VER
+
+#include <mtk_vcorefs_governor.h>
+#include <mtk_spm_vcore_dvfs.h>
+
+u32 (*spm_vcorefs_get_MD_status_symbol)(void);
+void (*spm_vcorefs_register_handler_symbol)(vcorefs_handler_t handler);
+void (*vcorefs_register_req_notify_symbol)(vcorefs_req_handler_t handler);
+char *(*governor_get_kicker_name_symbol)(int id);
+int (*vcorefs_enable_debug_isr_symbol)(bool);
+int (*vcorefs_get_hw_opp_symbol)(void);
+int (*vcorefs_get_curr_vcore_symbol)(void);
+int (*vcorefs_get_curr_ddr_symbol)(void);
+int *kicker_table_symbol;
+#else
+
+#include <dvfsrc-exp.h>
+
+#endif /* end else VCOREDVFS_OLD_VER*/
+int (*vcorefs_get_opp_info_num_symbol)(void);
+char ** (*vcorefs_get_opp_info_name_symbol)(void);
+unsigned int * (*vcorefs_get_opp_info_symbol)(void);
+int (*vcorefs_get_src_req_num_symbol)(void);
+char ** (*vcorefs_get_src_req_name_symbol)(void);
+unsigned int * (*vcorefs_get_src_req_symbol)(void);
+int (*vcorefs_get_num_opp_symbol)(void);
+
+#endif /* MET_VCOREDVFS */
+
+
+#ifdef MET_EMI
+void *(*mt_cen_emi_base_get_symbol)(void);
+void *(*mt_chn_emi_base_get_symbol)(int chn);
+unsigned int (*mtk_dramc_get_data_rate_symbol)(void);
+unsigned int (*mtk_dramc_get_ddr_type_symbol)(void);
+unsigned int (*get_cur_ddr_ratio_symbol)(void);
+#endif /* MET_EMI */
+
+#ifdef MET_PTPOD
+unsigned int (*mt_gpufreq_get_cur_volt_symbol)(void);
+unsigned int (*mt_cpufreq_get_cur_volt_symbol)(unsigned int cluster_id);
+#endif /* MET_PTPOD */
+
+#ifdef MET_SPM_TWAM
+/* ap side used */
+#ifdef SPMTWAM_AP
+void (*spm_twam_enable_monitor_symbol)(const struct twam_sig *twamsig, bool speed_mode);
+void (*spm_twam_register_handler_symbol)(twam_handler_t handler);
+void (*spm_twam_disable_monitor_symbol)(void);
+void (*spm_twam_set_idle_select_symbol)(unsigned int sel);
+void (*spm_twam_set_window_length_symbol)(unsigned int len);
+void (*spm_twam_set_mon_type_symbol)(struct twam_sig *mon);
+#endif
+
+/* sspm side used */
+#ifdef SPMTWAM_SSPM
+void (*spm_twam_enable_monitor_symbol)(bool en_monitor, bool debug_signal, twam_handler_t cb_handler);
+bool (*spm_twam_met_enable_symbol)(void);
+void (*spm_twam_config_channel_symbol)(struct twam_cfg *cfg, bool speed_mode, unsigned int window_len_hz);
+#endif
+#endif
+
+
+static int met_symbol_get(void)
+{
+#ifdef MET_GPU
+ _MET_SYMBOL_GET(mtk_get_gpu_loading);
+ _MET_SYMBOL_GET(mtk_get_gpu_block);
+ _MET_SYMBOL_GET(mtk_get_gpu_idle);
+ _MET_SYMBOL_GET(mtk_get_gpu_dvfs_from);
+ _MET_SYMBOL_GET(mtk_get_gpu_sub_loading);
+ _MET_SYMBOL_GET(mtk_get_3D_fences_count);
+ _MET_SYMBOL_GET(mtk_get_gpu_memory_usage);
+ _MET_SYMBOL_GET(mtk_get_gpu_power_loading);
+ _MET_SYMBOL_GET(mtk_get_custom_boost_gpu_freq);
+ _MET_SYMBOL_GET(mtk_get_custom_upbound_gpu_freq);
+ _MET_SYMBOL_GET(mtk_get_vsync_based_target_freq);
+ _MET_SYMBOL_GET(mtk_get_vsync_offset_event_status);
+ _MET_SYMBOL_GET(mtk_get_vsync_offset_debug_status);
+ _MET_SYMBOL_GET(mtk_enable_gpu_perf_monitor);
+ _MET_SYMBOL_GET(mtk_get_gpu_pmu_init);
+ _MET_SYMBOL_GET(mtk_get_gpu_pmu_swapnreset);
+ _MET_SYMBOL_GET(mt_gpufreq_get_cur_freq);
+ _MET_SYMBOL_GET(mt_gpufreq_get_thermal_limit_freq);
+ _MET_SYMBOL_GET(mtk_register_gpu_power_change);
+ _MET_SYMBOL_GET(mtk_unregister_gpu_power_change);
+#if 1
+ _MET_SYMBOL_GET(mtk_get_gpu_pmu_swapnreset_stop);
+ _MET_SYMBOL_GET(mtk_get_gpu_pmu_deinit);
+#endif
+#endif /* MET_GPU */
+
+#ifdef MET_VCOREDVFS
+ _MET_SYMBOL_GET(vcorefs_get_num_opp);
+ _MET_SYMBOL_GET(vcorefs_get_opp_info_num);
+ _MET_SYMBOL_GET(vcorefs_get_opp_info_name);
+ _MET_SYMBOL_GET(vcorefs_get_opp_info);
+ _MET_SYMBOL_GET(vcorefs_get_src_req_num);
+ _MET_SYMBOL_GET(vcorefs_get_src_req_name);
+ _MET_SYMBOL_GET(vcorefs_get_src_req);
+
+#ifdef VCOREDVFS_OLD_VER
+ _MET_SYMBOL_GET(spm_vcorefs_get_MD_status);
+ _MET_SYMBOL_GET(spm_vcorefs_register_handler);
+ _MET_SYMBOL_GET(vcorefs_register_req_notify);
+ _MET_SYMBOL_GET(governor_get_kicker_name);
+ _MET_SYMBOL_GET(vcorefs_enable_debug_isr);
+ _MET_SYMBOL_GET(vcorefs_get_hw_opp);
+ _MET_SYMBOL_GET(vcorefs_get_curr_vcore);
+ _MET_SYMBOL_GET(vcorefs_get_curr_ddr);
+ _MET_SYMBOL_GET(kicker_table);
+#endif
+
+#endif
+
+#ifdef MET_EMI
+ _MET_SYMBOL_GET(mt_cen_emi_base_get);
+ _MET_SYMBOL_GET(mt_chn_emi_base_get);
+ _MET_SYMBOL_GET(mtk_dramc_get_data_rate);
+ _MET_SYMBOL_GET(mtk_dramc_get_ddr_type);
+ _MET_SYMBOL_GET(get_cur_ddr_ratio);
+#endif
+
+#ifdef MET_PTPOD
+ _MET_SYMBOL_GET(mt_gpufreq_get_cur_volt);
+ _MET_SYMBOL_GET(mt_cpufreq_get_cur_volt);
+#endif
+
+#ifdef MET_SPM_TWAM
+ /* ap side used */
+#ifdef SPMTWAM_AP
+ _MET_SYMBOL_GET(spm_twam_enable_monitor);
+ _MET_SYMBOL_GET(spm_twam_register_handler);
+ _MET_SYMBOL_GET(spm_twam_disable_monitor);
+ _MET_SYMBOL_GET(spm_twam_set_idle_select);
+ _MET_SYMBOL_GET(spm_twam_set_window_length);
+ _MET_SYMBOL_GET(spm_twam_set_mon_type);
+#endif
+
+ /* sspm side used */
+#ifdef SPMTWAM_SSPM
+ _MET_SYMBOL_GET(spm_twam_enable_monitor);
+ _MET_SYMBOL_GET(spm_twam_met_enable);
+ _MET_SYMBOL_GET(spm_twam_config_channel);
+#endif
+#endif
+
+ return 0;
+}
+
+static int met_symbol_put(void)
+{
+#ifdef MET_GPU
+ _MET_SYMBOL_PUT(mtk_get_gpu_loading);
+ _MET_SYMBOL_PUT(mtk_get_gpu_block);
+ _MET_SYMBOL_PUT(mtk_get_gpu_idle);
+ _MET_SYMBOL_PUT(mtk_get_gpu_dvfs_from);
+ _MET_SYMBOL_PUT(mtk_get_gpu_sub_loading);
+ _MET_SYMBOL_PUT(mtk_get_3D_fences_count);
+ _MET_SYMBOL_PUT(mtk_get_gpu_memory_usage);
+ _MET_SYMBOL_PUT(mtk_get_gpu_power_loading);
+ _MET_SYMBOL_PUT(mtk_get_custom_boost_gpu_freq);
+ _MET_SYMBOL_PUT(mtk_get_custom_upbound_gpu_freq);
+ _MET_SYMBOL_PUT(mtk_get_vsync_based_target_freq);
+ _MET_SYMBOL_PUT(mtk_get_vsync_offset_event_status);
+ _MET_SYMBOL_PUT(mtk_get_vsync_offset_debug_status);
+ _MET_SYMBOL_PUT(mtk_enable_gpu_perf_monitor);
+ _MET_SYMBOL_PUT(mtk_get_gpu_pmu_init);
+ _MET_SYMBOL_PUT(mtk_get_gpu_pmu_swapnreset);
+ _MET_SYMBOL_PUT(mt_gpufreq_get_cur_freq);
+ _MET_SYMBOL_PUT(mt_gpufreq_get_thermal_limit_freq);
+ _MET_SYMBOL_PUT(mtk_register_gpu_power_change);
+ _MET_SYMBOL_PUT(mtk_unregister_gpu_power_change);
+#if 1
+ _MET_SYMBOL_PUT(mtk_get_gpu_pmu_swapnreset_stop);
+ _MET_SYMBOL_PUT(mtk_get_gpu_pmu_deinit);
+#endif
+#endif /* MET_GPU */
+
+#ifdef MET_VCOREDVFS
+ _MET_SYMBOL_PUT(vcorefs_get_num_opp);
+ _MET_SYMBOL_PUT(vcorefs_get_opp_info_num);
+ _MET_SYMBOL_PUT(vcorefs_get_opp_info_name);
+ _MET_SYMBOL_PUT(vcorefs_get_opp_info);
+ _MET_SYMBOL_PUT(vcorefs_get_src_req_num);
+ _MET_SYMBOL_PUT(vcorefs_get_src_req_name);
+ _MET_SYMBOL_PUT(vcorefs_get_src_req);
+
+#ifdef VCOREDVFS_OLD_VER
+ _MET_SYMBOL_PUT(spm_vcorefs_get_MD_status);
+ _MET_SYMBOL_PUT(spm_vcorefs_register_handler);
+ _MET_SYMBOL_PUT(vcorefs_register_req_notify);
+ _MET_SYMBOL_PUT(governor_get_kicker_name);
+ _MET_SYMBOL_PUT(vcorefs_enable_debug_isr);
+ _MET_SYMBOL_PUT(vcorefs_get_hw_opp);
+ _MET_SYMBOL_PUT(vcorefs_get_curr_vcore);
+ _MET_SYMBOL_PUT(vcorefs_get_curr_ddr);
+ _MET_SYMBOL_PUT(kicker_table);
+#endif
+
+#endif
+
+#ifdef MET_EMI
+ _MET_SYMBOL_PUT(mt_cen_emi_base_get);
+ _MET_SYMBOL_PUT(mt_chn_emi_base_get);
+ _MET_SYMBOL_PUT(mtk_dramc_get_data_rate);
+ _MET_SYMBOL_PUT(mtk_dramc_get_ddr_type);
+ _MET_SYMBOL_PUT(get_cur_ddr_ratio);
+#endif
+
+#ifdef MET_PTPOD
+ _MET_SYMBOL_PUT(mt_gpufreq_get_cur_volt);
+ _MET_SYMBOL_PUT(mt_cpufreq_get_cur_volt);
+#endif
+
+#ifdef MET_SPM_TWAM
+ /* ap side used */
+#ifdef SPMTWAM_AP
+ _MET_SYMBOL_PUT(spm_twam_enable_monitor);
+ _MET_SYMBOL_PUT(spm_twam_register_handler);
+ _MET_SYMBOL_PUT(spm_twam_disable_monitor);
+ _MET_SYMBOL_PUT(spm_twam_set_idle_select);
+ _MET_SYMBOL_PUT(spm_twam_set_window_length);
+ _MET_SYMBOL_PUT(spm_twam_set_mon_type);
+#endif
+
+ /* sspm side used */
+#ifdef SPMTWAM_SSPM
+ _MET_SYMBOL_PUT(spm_twam_enable_monitor);
+ _MET_SYMBOL_PUT(spm_twam_met_enable);
+ _MET_SYMBOL_PUT(spm_twam_config_channel);
+#endif
+#endif
+
+ return 0;
+}
+
+int core_plf_init(void)
+{
+ /*initial met external symbol*/
+ met_symbol_get();
+
+#ifdef MET_GPU
+ met_register(&met_gpu);
+ met_register(&met_gpudvfs);
+ met_register(&met_gpumem);
+ met_register(&met_gpupwr);
+ met_register(&met_gpu_pmu);
+#ifdef MET_GPU_STALL_MONITOR
+ met_register(&met_gpu_stall);
+#endif
+#endif
+
+#ifdef MET_VCOREDVFS
+ met_register(&met_vcoredvfs);
+#endif
+
+#ifdef MET_EMI
+ met_register(&met_sspm_emi);
+#endif
+
+#ifdef MET_SMI
+ met_register(&met_sspm_smi);
+#endif
+
+#ifdef MET_PTPOD
+ met_register(&met_ptpod);
+#endif
+
+#ifdef MET_WALLTIME
+ met_register(&met_wall_time);
+#endif
+
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+ met_register(&met_sspm_common);
+#endif
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#ifdef MET_SSPM_WALLTIME
+ met_register(&met_sspm_walltime);
+#endif
+#endif
+#endif
+
+#ifdef MET_CPUDSU
+ met_register(&met_cpudsu);
+#endif
+
+#ifdef MET_SPM_TWAM
+ met_register(&met_spmtwam);
+#endif
+
+#ifdef MET_BACKLIGHT
+ met_register(&met_backlight);
+#endif
+
+ return 0;
+}
+
+void core_plf_exit(void)
+{
+ /*release met external symbol*/
+ met_symbol_put();
+
+#ifdef MET_GPU
+ met_deregister(&met_gpu);
+ met_deregister(&met_gpudvfs);
+ met_deregister(&met_gpumem);
+ met_deregister(&met_gpupwr);
+ met_deregister(&met_gpu_pmu);
+#ifdef MET_GPU_STALL_MONITOR
+ met_deregister(&met_gpu_stall);
+#endif
+#endif
+
+#ifdef MET_VCOREDVFS
+ met_deregister(&met_vcoredvfs);
+#endif
+
+#ifdef MET_EMI
+ met_deregister(&met_sspm_emi);
+#endif
+
+#ifdef MET_SMI
+ met_deregister(&met_sspm_smi);
+#endif
+
+#ifdef MET_PTPOD
+ met_deregister(&met_ptpod);
+#endif
+
+#ifdef MET_WALLTIME
+ met_deregister(&met_wall_time);
+#endif
+
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ met_deregister(&met_sspm_common);
+#endif
+#endif
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#ifdef MET_SSPM_WALLTIME
+ met_deregister(&met_sspm_walltime);
+#endif
+#endif
+#endif
+
+#ifdef MET_CPUDSU
+ met_deregister(&met_cpudsu);
+#endif
+
+#ifdef MET_SPM_TWAM
+ met_deregister(&met_spmtwam);
+#endif
+
+#ifdef MET_BACKLIGHT
+ met_deregister(&met_backlight);
+#endif
+}
diff --git a/src/devtools/met_drv_v2/common/core_plf_init.h b/src/devtools/met_drv_v2/common/core_plf_init.h
new file mode 100644
index 0000000..248c556
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/core_plf_init.h
@@ -0,0 +1,221 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __CORE_PLF_INIT_H__
+#define __CORE_PLF_INIT_H__
+
+extern struct miscdevice met_device;
+
+/*
+ * MET External Symbol
+ */
+
+#ifdef MET_GPU
+/*
+ * GPU
+ */
+#include <mtk_gpu_utility.h>
+#include <mtk_gpufreq.h>
+#include "met_gpu_monitor.h"
+
+extern bool mtk_get_gpu_loading(unsigned int *pLoading);
+extern bool mtk_get_gpu_block(unsigned int *pBlock);
+extern bool mtk_get_gpu_idle(unsigned int *pIdle);
+extern bool mtk_get_gpu_dvfs_from(enum MTK_GPU_DVFS_TYPE *peType, unsigned long *pulFreq);
+extern bool mtk_get_gpu_sub_loading(unsigned int *pLoading);
+extern bool mtk_get_3D_fences_count(int *pi32Count);
+extern bool mtk_get_gpu_memory_usage(unsigned int *pMemUsage);
+extern bool mtk_get_gpu_power_loading(unsigned int *pLoading);
+extern bool mtk_get_custom_boost_gpu_freq(unsigned int *pui32FreqLevel);
+extern bool mtk_get_custom_upbound_gpu_freq(unsigned int *pui32FreqLevel);
+extern bool mtk_get_vsync_based_target_freq(unsigned long *pulFreq);
+extern bool mtk_get_vsync_offset_event_status(unsigned int *pui32EventStatus);
+extern bool mtk_get_vsync_offset_debug_status(unsigned int *pui32EventStatus);
+extern bool mtk_enable_gpu_perf_monitor(bool enable);
+extern bool mtk_get_gpu_pmu_init(struct GPU_PMU *pmus, int pmu_size, int *ret_size);
+extern bool mtk_get_gpu_pmu_swapnreset(struct GPU_PMU *pmus, int pmu_size);
+extern bool mtk_get_gpu_pmu_deinit(void);
+extern bool mtk_get_gpu_pmu_swapnreset_stop(void);
+
+extern bool (*mtk_get_gpu_loading_symbol)(unsigned int *pLoading);
+extern bool (*mtk_get_gpu_block_symbol)(unsigned int *pBlock);
+extern bool (*mtk_get_gpu_idle_symbol)(unsigned int *pIdle);
+extern bool (*mtk_get_gpu_dvfs_from_symbol)(enum MTK_GPU_DVFS_TYPE *peType, unsigned long *pulFreq);
+extern bool (*mtk_get_gpu_sub_loading_symbol)(unsigned int *pLoading);
+extern bool (*mtk_get_3D_fences_count_symbol)(int *pi32Count);
+extern bool (*mtk_get_gpu_memory_usage_symbol)(unsigned int *pMemUsage);
+extern bool (*mtk_get_gpu_power_loading_symbol)(unsigned int *pLoading);
+extern bool (*mtk_get_custom_boost_gpu_freq_symbol)(unsigned long *pulFreq);
+extern bool (*mtk_get_custom_upbound_gpu_freq_symbol)(unsigned long *pulFreq);
+extern bool (*mtk_get_vsync_based_target_freq_symbol)(unsigned long *pulFreq);
+extern bool (*mtk_get_vsync_offset_event_status_symbol)(unsigned int *pui32EventStatus);
+extern bool (*mtk_get_vsync_offset_debug_status_symbol)(unsigned int *pui32EventStatus);
+extern bool (*mtk_enable_gpu_perf_monitor_symbol)(bool enable);
+extern bool (*mtk_get_gpu_pmu_init_symbol)(struct GPU_PMU *pmus, int pmu_size, int *ret_size);
+extern bool (*mtk_get_gpu_pmu_swapnreset_symbol)(struct GPU_PMU *pmus, int pmu_size);
+extern bool (*mtk_get_gpu_pmu_deinit_symbol)(void);
+extern bool (*mtk_get_gpu_pmu_swapnreset_stop_symbol)(void);
+
+extern bool mtk_register_gpu_power_change(const char *name, void (*callback)(int power_on));
+extern bool mtk_unregister_gpu_power_change(const char *name);
+extern bool (*mtk_register_gpu_power_change_symbol)(const char *name,
+ void (*callback)(int power_on));
+extern bool (*mtk_unregister_gpu_power_change_symbol)(const char *name);
+
+
+extern unsigned int mt_gpufreq_get_cur_freq(void);
+extern unsigned int mt_gpufreq_get_thermal_limit_freq(void);
+extern unsigned int (*mt_gpufreq_get_cur_freq_symbol)(void);
+extern unsigned int (*mt_gpufreq_get_thermal_limit_freq_symbol)(void);
+
+extern struct metdevice met_gpu;
+extern struct metdevice met_gpudvfs;
+extern struct metdevice met_gpumem;
+extern struct metdevice met_gpupwr;
+extern struct metdevice met_gpu_pmu;
+#ifdef MET_GPU_STALL_MONITOR
+extern struct metdevice met_gpu_stall;
+#endif
+#endif /* MET_GPU */
+
+
+#ifdef MET_VCOREDVFS
+/*
+ * VCORE DVFS
+ */
+extern int vcorefs_get_num_opp(void);
+extern int vcorefs_get_opp_info_num(void);
+extern char ** vcorefs_get_opp_info_name(void);
+extern unsigned int * vcorefs_get_opp_info(void);
+extern int vcorefs_get_src_req_num(void);
+extern char ** vcorefs_get_src_req_name(void);
+extern unsigned int * vcorefs_get_src_req(void);
+
+extern int (*vcorefs_get_num_opp_symbol)(void);
+extern int (*vcorefs_get_opp_info_num_symbol)(void);
+extern char ** (*vcorefs_get_opp_info_name_symbol)(void);
+extern unsigned int * (*vcorefs_get_opp_info_symbol)(void);
+extern int (*vcorefs_get_src_req_num_symbol)(void);
+extern char ** (*vcorefs_get_src_req_name_symbol)(void);
+extern unsigned int * (*vcorefs_get_src_req_symbol)(void);
+
+
+#ifdef VCOREDVFS_OLD_VER
+
+#include <mtk_spm.h>
+#include <mtk_vcorefs_manager.h>
+
+extern char *governor_get_kicker_name(int id);
+extern int vcorefs_enable_debug_isr(bool);
+
+extern u32 (*spm_vcorefs_get_MD_status_symbol)(void);
+extern void (*spm_vcorefs_register_handler_symbol)(vcorefs_handler_t handler);
+extern void (*vcorefs_register_req_notify_symbol)(vcorefs_req_handler_t handler);
+extern char *(*governor_get_kicker_name_symbol)(int id);
+extern int (*vcorefs_enable_debug_isr_symbol)(bool);
+extern int (*vcorefs_get_hw_opp_symbol)(void);
+extern int (*vcorefs_get_curr_vcore_symbol)(void);
+extern int (*vcorefs_get_curr_ddr_symbol)(void);
+extern int *kicker_table_symbol;
+
+#endif /* VCOREDVFS_OLD_VER */
+
+extern struct metdevice met_vcoredvfs;
+
+#endif /* MET_VCOREDVFS */
+
+
+#ifdef MET_EMI
+extern void *mt_cen_emi_base_get(void);
+extern void *mt_chn_emi_base_get(void);
+extern unsigned int mtk_dramc_get_data_rate(void); /* in Mhz */
+extern unsigned int mtk_dramc_get_ddr_type(void);
+extern int get_cur_ddr_ratio(void);
+
+extern void *(*mt_cen_emi_base_get_symbol)(void);
+extern unsigned int (*mtk_dramc_get_data_rate_symbol)(void); /* in Mhz */
+extern unsigned int (*mtk_dramc_get_ddr_type_symbol)(void);
+extern unsigned int (*get_cur_ddr_ratio_symbol)(void);
+
+
+
+extern struct metdevice met_sspm_emi;
+#endif /* MET_EMI */
+
+#ifdef MET_SMI
+extern struct metdevice met_sspm_smi;
+#endif
+
+#ifdef MET_PTPOD
+#include <mtk_gpufreq.h>
+#include <mach/mtk_cpufreq_api.h>
+#include <mtk_cpufreq_config.h>
+
+extern unsigned int mt_gpufreq_get_cur_volt(void);
+extern unsigned int mt_cpufreq_get_cur_volt(unsigned int cluster_id);
+extern unsigned int (*mt_gpufreq_get_cur_volt_symbol)(void);
+extern unsigned int (*mt_cpufreq_get_cur_volt_symbol)(unsigned int cluster_id);
+
+extern struct metdevice met_ptpod;
+#endif /* MET_PTPOD */
+
+#ifdef MET_WALLTIME
+extern struct metdevice met_wall_time;
+#endif
+
+#ifdef MTK_TINYSYS_SSPM_SUPPORT
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+extern struct metdevice met_sspm_common;
+#endif
+#endif /* MTK_TINYSYS_SSPM_SUPPORT */
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#ifdef MET_SSPM_WALLTIME
+extern struct metdevice met_sspm_walltime;
+#endif
+#endif
+#endif /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT */
+
+#ifdef MET_CPUDSU
+extern struct metdevice met_cpudsu;
+#endif
+
+#ifdef MET_SPM_TWAM
+#include "mtk_spm.h"
+
+/* ap side used */
+#ifdef SPMTWAM_AP
+extern void spm_twam_enable_monitor(const struct twam_sig *twamsig, bool speed_mode);
+extern void spm_twam_register_handler(twam_handler_t handler);
+extern void spm_twam_disable_monitor(void);
+extern void spm_twam_set_idle_select(unsigned int sel);
+extern void spm_twam_set_window_length(unsigned int len);
+extern void spm_twam_set_mon_type(struct twam_sig *mon);
+
+extern void (*spm_twam_enable_monitor_symbol)(const struct twam_sig *twamsig, bool speed_mode);
+extern void (*spm_twam_register_handler_symbol)(twam_handler_t handler);
+extern void (*spm_twam_disable_monitor_symbol)(void);
+extern void (*spm_twam_set_idle_select_symbol)(unsigned int sel);
+extern void (*spm_twam_set_window_length_symbol)(unsigned int len);
+extern void (*spm_twam_set_mon_type_symbol)(struct twam_sig *mon);
+#endif
+
+/* sspm side used */
+#ifdef SPMTWAM_SSPM
+extern void spm_twam_enable_monitor(bool en_monitor, bool debug_signal, twam_handler_t cb_handler);
+extern bool spm_twam_met_enable(void);
+extern void spm_twam_config_channel(struct twam_cfg *cfg, bool speed_mode, unsigned int window_len_hz);
+
+extern void (*spm_twam_enable_monitor_symbol)(bool en_monitor, bool debug_signal, twam_handler_t cb_handler);
+extern bool (*spm_twam_met_enable_symbol)(void);
+extern void (*spm_twam_config_channel_symbol)(struct twam_cfg *cfg, bool speed_mode, unsigned int window_len_hz);
+#endif
+
+extern struct metdevice met_spmtwam;
+#endif
+
+
+#endif /*__CORE_PLF_INIT_H__*/
diff --git a/src/devtools/met_drv_v2/common/core_plf_trace.c b/src/devtools/met_drv_v2/common/core_plf_trace.c
new file mode 100644
index 0000000..2dcb896
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/core_plf_trace.c
@@ -0,0 +1,314 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+
+#include "met_drv.h"
+#include "interface.h"
+#include "trace.h"
+
+char *ms_formatH(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value)
+{
+ char *s = buf;
+ int len;
+
+ if (cnt == 0) {
+ buf[0] = '\0';
+ return buf;
+ }
+
+ switch (cnt % 4) {
+ case 1:
+ len = sprintf(s, "%x", value[0]);
+ s += len;
+ value += 1;
+ cnt -= 1;
+ break;
+ case 2:
+ len = sprintf(s, "%x,%x", value[0], value[1]);
+ s += len;
+ value += 2;
+ cnt -= 2;
+ break;
+ case 3:
+ len = sprintf(s, "%x,%x,%x", value[0], value[1], value[2]);
+ s += len;
+ value += 3;
+ cnt -= 3;
+ break;
+ case 0:
+ len = sprintf(s, "%x,%x,%x,%x", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ break;
+ }
+
+ while (cnt) {
+ len = sprintf(s, ",%x,%x,%x,%x", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ }
+
+ s[0] = '\0';
+
+ return s;
+}
+EXPORT_SYMBOL(ms_formatH);
+
+char *ms_formatD(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value)
+{
+ char *s = buf;
+ int len;
+
+ if (cnt == 0) {
+ buf[0] = '\0';
+ return buf;
+ }
+
+ switch (cnt % 4) {
+ case 1:
+ len = sprintf(s, "%u", value[0]);
+ s += len;
+ value += 1;
+ cnt -= 1;
+ break;
+ case 2:
+ len = sprintf(s, "%u,%u", value[0], value[1]);
+ s += len;
+ value += 2;
+ cnt -= 2;
+ break;
+ case 3:
+ len = sprintf(s, "%u,%u,%u", value[0], value[1], value[2]);
+ s += len;
+ value += 3;
+ cnt -= 3;
+ break;
+ case 0:
+ len = sprintf(s, "%u,%u,%u,%u", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ break;
+ }
+
+ while (cnt) {
+ len = sprintf(s, ",%u,%u,%u,%u", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ }
+
+ s[0] = '\0';
+
+ return s;
+}
+EXPORT_SYMBOL(ms_formatD);
+
+char *ms_formatH_ulong(char *__restrict__ buf, unsigned char cnt, unsigned long *__restrict__ value)
+{
+ char *s = buf;
+ int len;
+
+ if (cnt == 0) {
+ buf[0] = '\0';
+ return buf;
+ }
+
+ switch (cnt % 4) {
+ case 1:
+ len = sprintf(s, "%lx", value[0]);
+ s += len;
+ value += 1;
+ cnt -= 1;
+ break;
+ case 2:
+ len = sprintf(s, "%lx,%lx", value[0], value[1]);
+ s += len;
+ value += 2;
+ cnt -= 2;
+ break;
+ case 3:
+ len = sprintf(s, "%lx,%lx,%lx", value[0], value[1], value[2]);
+ s += len;
+ value += 3;
+ cnt -= 3;
+ break;
+ case 0:
+ len = sprintf(s, "%lx,%lx,%lx,%lx", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ break;
+ }
+
+ while (cnt) {
+ len = sprintf(s, ",%lx,%lx,%lx,%lx", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ }
+
+ s[0] = '\0';
+
+ return buf;
+}
+EXPORT_SYMBOL(ms_formatH_ulong);
+
+char *ms_formatD_ulong(char *__restrict__ buf, unsigned char cnt, unsigned long *__restrict__ value)
+{
+ char *s = buf;
+ int len;
+
+ if (cnt == 0) {
+ buf[0] = '\0';
+ return buf;
+ }
+
+ switch (cnt % 4) {
+ case 1:
+ len = sprintf(s, "%lu", value[0]);
+ s += len;
+ value += 1;
+ cnt -= 1;
+ break;
+ case 2:
+ len = sprintf(s, "%lu,%lu", value[0], value[1]);
+ s += len;
+ value += 2;
+ cnt -= 2;
+ break;
+ case 3:
+ len = sprintf(s, "%lu,%lu,%lu", value[0], value[1], value[2]);
+ s += len;
+ value += 3;
+ cnt -= 3;
+ break;
+ case 0:
+ len = sprintf(s, "%lu,%lu,%lu,%lu", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ break;
+ }
+
+ while (cnt) {
+ len = sprintf(s, ",%lu,%lu,%lu,%lu", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ }
+
+ s[0] = '\0';
+
+ return buf;
+}
+EXPORT_SYMBOL(ms_formatD_ulong);
+
+char *ms_formatH_EOL(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value)
+{
+ char *s = buf;
+ int len;
+
+ if (cnt == 0) {
+ buf[0] = '\0';
+ return buf;
+ }
+
+ switch (cnt % 4) {
+ case 1:
+ len = sprintf(s, "%x", value[0]);
+ s += len;
+ value += 1;
+ cnt -= 1;
+ break;
+ case 2:
+ len = sprintf(s, "%x,%x", value[0], value[1]);
+ s += len;
+ value += 2;
+ cnt -= 2;
+ break;
+ case 3:
+ len = sprintf(s, "%x,%x,%x", value[0], value[1], value[2]);
+ s += len;
+ value += 3;
+ cnt -= 3;
+ break;
+ case 0:
+ len = sprintf(s, "%x,%x,%x,%x", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ break;
+ }
+
+ while (cnt) {
+ len = sprintf(s, ",%x,%x,%x,%x", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ }
+
+ s[0] = '\n';
+ s[1] = '\0';
+
+ return s + 1;
+}
+EXPORT_SYMBOL(ms_formatH_EOL);
+
+char *ms_formatD_EOL(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value)
+{
+ char *s = buf;
+ int len;
+
+ if (cnt == 0) {
+ buf[0] = '\0';
+ return buf;
+ }
+
+ switch (cnt % 4) {
+ case 1:
+ len = sprintf(s, "%u", value[0]);
+ s += len;
+ value += 1;
+ cnt -= 1;
+ break;
+ case 2:
+ len = sprintf(s, "%u,%u", value[0], value[1]);
+ s += len;
+ value += 2;
+ cnt -= 2;
+ break;
+ case 3:
+ len = sprintf(s, "%u,%u,%u", value[0], value[1], value[2]);
+ s += len;
+ value += 3;
+ cnt -= 3;
+ break;
+ case 0:
+ len = sprintf(s, "%u,%u,%u,%u", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ break;
+ }
+
+ while (cnt) {
+ len = sprintf(s, ",%u,%u,%u,%u", value[0], value[1], value[2], value[3]);
+ s += len;
+ value += 4;
+ cnt -= 4;
+ }
+
+ s[0] = '\n';
+ s[1] = '\0';
+
+ return s + 1;
+}
+EXPORT_SYMBOL(ms_formatD_EOL);
+
diff --git a/src/devtools/met_drv_v2/common/core_plf_trace.h b/src/devtools/met_drv_v2/common/core_plf_trace.h
new file mode 100644
index 0000000..7387b68
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/core_plf_trace.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CORE_PLF_TRACE_H_
+#define _CORE_PLF_TRACE_H_
+
+#define HVALUE_SIZE 9 /* 8 chars (max value ffffffff) + 1 char (',' or NULL) */
+#define DVALUE_SIZE 12 /* 10 chars (max value 4,294,967,295) + 1 char (',' or NULL) */
+
+char *ms_formatH(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value);
+char *core_ms_formatD(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value);
+char *ms_formatH_ulong(char *__restrict__ buf, unsigned char cnt,
+ unsigned long *__restrict__ value);
+char *ms_formatD_ulong(char *__restrict__ buf, unsigned char cnt,
+ unsigned long *__restrict__ value);
+char *ms_formatH_EOL(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value);
+char *ms_formatD_EOL(char *__restrict__ buf, unsigned char cnt, unsigned int *__restrict__ value);
+
+#endif /* _CORE_PLF_TRACE_H_ */
diff --git a/src/devtools/met_drv_v2/common/cpu_dsu.c b/src/devtools/met_drv_v2/common/cpu_dsu.c
new file mode 100644
index 0000000..56c5b4b
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/cpu_dsu.c
@@ -0,0 +1,367 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/perf_event.h>
+#include "met_drv.h"
+#include "met_kernel_symbol.h"
+#include "interface.h"
+#include "trace.h"
+#include "cpu_dsu.h"
+#include "core_plf_init.h"
+
+
+struct cpu_dsu_hw *cpu_dsu;
+static int counter_cnt;
+static struct kobject *kobj_dsu;
+static int nr_arg;
+static unsigned long long perfCurr[MXNR_DSU_EVENTS];
+static unsigned long long perfPrev[MXNR_DSU_EVENTS];
+static int perfCntFirst[MXNR_DSU_EVENTS];
+static struct perf_event * pevent[MXNR_DSU_EVENTS];
+static struct perf_event_attr pevent_attr[MXNR_DSU_EVENTS];
+static unsigned int perf_device_type = 7;
+static ssize_t perf_type_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", perf_device_type);
+}
+
+static ssize_t perf_type_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t n)
+{
+ if (kstrtouint(buf, 0, &perf_device_type) != 0)
+ return -EINVAL;
+
+ return n;
+}
+static struct kobj_attribute perf_type_attr = __ATTR(perf_type, 0664, perf_type_show, perf_type_store);
+
+noinline void mp_dsu(unsigned char cnt, unsigned int *value)
+{
+ MET_GENERAL_PRINT(MET_TRACE, cnt, value);
+}
+
+static void dummy_handler(struct perf_event *event, struct perf_sample_data *data,
+ struct pt_regs *regs)
+{
+ /*
+ * Required as perf_event_create_kernel_counter() requires an overflow handler,
+ * even though all we do is poll.
+ */
+}
+
+static void perf_cpudsu_polling(unsigned long long stamp, int cpu)
+{
+ int event_count = cpu_dsu->event_count;
+ struct met_dsu *pmu = cpu_dsu->pmu;
+ int i, count;
+ unsigned long long delta;
+ struct perf_event *ev;
+ unsigned int pmu_value[MXNR_DSU_EVENTS];
+ u64 value;
+ int ret;
+
+ count = 0;
+ for (i = 0; i < event_count; i++) {
+ if (pmu[i].mode == 0)
+ continue;
+
+ ev = pevent[i];
+ if ((ev != NULL) && (ev->state == PERF_EVENT_STATE_ACTIVE)) {
+ if (!met_export_api_symbol->met_perf_event_read_local)
+ continue;
+
+ ret = met_export_api_symbol->met_perf_event_read_local(ev, &value);
+ if (ret < 0) {
+ PR_BOOTMSG_ONCE("[MET_DSU] perf_event_read_local fail (ret=%d)\n", ret);
+ pr_debug("[MET_DSU] perf_event_read_local fail (ret=%d)\n", ret);
+ continue;
+ }
+
+ perfCurr[i] = value;
+ delta = (perfCurr[i] - perfPrev[i]);
+ perfPrev[i] = perfCurr[i];
+ if (perfCntFirst[i] == 1) {
+ /* we shall omit delta counter when we get first counter */
+ perfCntFirst[i] = 0;
+ continue;
+ }
+ pmu_value[count] = (unsigned int)delta;
+ count++;
+ }
+ }
+
+ if (count == counter_cnt)
+ mp_dsu(count, pmu_value);
+}
+
+static int perf_thread_set_perf_events(unsigned int cpu)
+{
+ int i, size;
+ struct perf_event *ev;
+ struct perf_event_attr *ev_attr;
+ int event_count = cpu_dsu->event_count;
+ struct met_dsu *pmu = cpu_dsu->pmu;
+
+ size = sizeof(struct perf_event_attr);
+
+ for (i = 0; i < event_count; i++) {
+ pevent[i] = NULL;
+ if (!pmu[i].mode)
+ continue; /* Skip disabled counters */
+ perfPrev[i] = 0;
+ perfCurr[i] = 0;
+ ev_attr = pevent_attr+i;
+ memset(ev_attr, 0, size);
+ ev_attr->config = pmu[i].event;
+ ev_attr->type = perf_device_type;
+ ev_attr->size = size;
+ ev_attr->sample_period = 0;
+ ev_attr->pinned = 1;
+
+ ev = perf_event_create_kernel_counter(ev_attr, cpu, NULL, dummy_handler, NULL);
+ if (IS_ERR(ev))
+ continue;
+ if (ev->state != PERF_EVENT_STATE_ACTIVE) {
+ perf_event_release_kernel(ev);
+ continue;
+ }
+ pevent[i] = ev;
+ if (ev != NULL)
+ perf_event_enable(ev);
+
+ perfCntFirst[i] = 1;
+ } /* for all PMU counter */
+ return 0;
+}
+
+void met_perf_cpudsu_down(void)
+{
+ int i;
+ struct perf_event *ev;
+ int event_count;
+ struct met_dsu *pmu;
+
+ if (met_cpudsu.mode == 0)
+ return;
+ event_count = cpu_dsu->event_count;
+ pmu = cpu_dsu->pmu;
+ for (i = 0; i < event_count; i++) {
+ if (!pmu[i].mode)
+ continue;
+ ev = pevent[i];
+ if ((ev != NULL) && (ev->state == PERF_EVENT_STATE_ACTIVE)) {
+ perf_event_disable(ev);
+ perf_event_release_kernel(ev);
+ }
+ pevent[i] = NULL;
+ }
+ //perf_delayed_work_setup = NULL;
+}
+
+inline static void met_perf_cpudsu_start(int cpu)
+{
+ if (met_cpudsu.mode == 0)
+ return;
+ if (cpu != 0)
+ return;
+ perf_thread_set_perf_events(cpu);
+}
+
+static int cpudsu_create_subfs(struct kobject *parent)
+{
+ int ret = 0;
+ cpu_dsu = cpu_dsu_hw_init();
+ if (cpu_dsu == NULL) {
+ PR_BOOTMSG("Failed to init CPU PMU HW!!\n");
+ return -ENODEV;
+ }
+ kobj_dsu = parent;
+ ret = sysfs_create_file(kobj_dsu, &perf_type_attr.attr);
+ if (ret != 0) {
+ PR_BOOTMSG("Failed to create perf_type in sysfs\n");
+ goto out;
+ }
+ out:
+ return ret;
+}
+
+static void cpudsu_delete_subfs(void)
+{
+}
+
+void met_perf_cpudsu_polling(unsigned long long stamp, int cpu)
+{
+ perf_cpudsu_polling(stamp, cpu);
+}
+
+static void cpudsu_start(void)
+{
+ int cpu = raw_smp_processor_id();
+ for_each_online_cpu(cpu)
+ met_perf_cpudsu_start(cpu);
+}
+
+static void cpudsu_stop(void)
+{
+ met_perf_cpudsu_down();
+}
+
+static const char header[] =
+ "met-info [000] 0.0: met_dsu_pmu_header: DSU";
+
+static const char help[] =
+ " --dsu=EVENT select DSU-PMU events.\n"
+ " you can enable at most \"%d general purpose events\"\n";
+
+static int cpudsu_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help, cpu_dsu->event_count);
+}
+
+static int reset_driver_stat(void)
+{
+ int i;
+ int event_count;
+ struct met_dsu *pmu;
+
+ met_cpudsu.mode = 0;
+ event_count = cpu_dsu->event_count;
+ pmu = cpu_dsu->pmu;
+ counter_cnt = 0;
+ nr_arg = 0;
+ for (i = 0; i < event_count; i++) {
+ pmu[i].mode = MODE_DISABLED;
+ pmu[i].event = 0;
+ pmu[i].freq = 0;
+ }
+ return 0;
+}
+
+static int cpudsu_print_header(char *buf, int len)
+{
+ int first;
+ int i, ret;
+ int event_count;
+ struct met_dsu *pmu;
+ ret = 0;
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "# mp_dsu: pmu_value1, ...\n");
+ event_count = cpu_dsu->event_count;
+ pmu = cpu_dsu->pmu;
+ first = 1;
+ for (i = 0; i < event_count; i++) {
+ if (pmu[i].mode == 0)
+ continue;
+ if (first) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, header);
+ first = 0;
+ }
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, ",0x%x", pmu[i].event);
+ pmu[i].mode = 0;
+ }
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ reset_driver_stat();
+ return ret;
+}
+
+static int met_parse_num_list(char *arg, int len, int *list, int list_cnt)
+{
+ int nr_num = 0;
+ char *num;
+ int num_len;
+
+ /* search ',' as the splitter */
+ while (len) {
+ num = arg;
+ num_len = 0;
+ if (list_cnt <= 0)
+ return -1;
+ while (len) {
+ len--;
+ if (*arg == ',') {
+ *(arg++) = '\0';
+ break;
+ }
+ arg++;
+ num_len++;
+ }
+ if (met_parse_num(num, list, num_len) < 0)
+ return -1;
+ list++;
+ list_cnt--;
+ nr_num++;
+ }
+ return nr_num;
+}
+
+static int cpudsu_process_argument(const char *arg, int len)
+{
+ int nr_events, event_list[MXNR_DSU_EVENTS]={0};
+ int i;
+ int nr_counters;
+ struct met_dsu *pmu;
+ int arg_nr;
+ int counters;
+ int event_no;
+
+ /* get event_list */
+ if ((nr_events = met_parse_num_list((char*)arg, len, event_list, ARRAY_SIZE(event_list))) <= 0)
+ goto arg_out;
+
+ /* for each cpu in cpu_list, add all the events in event_list */
+ nr_counters = cpu_dsu->event_count;
+ pmu = cpu_dsu->pmu;
+ arg_nr = nr_arg;
+
+ /*
+ * setup nr_counters for linux native perf mode.
+ * because the selected events are stored in pmu,
+ * so nr_counters can't large then event count in pmu.
+ */
+ counters = perf_num_counters();
+ if (counters < nr_counters)
+ nr_counters = counters;
+
+ if (nr_counters == 0)
+ goto arg_out;
+
+ for (i = 0; i < nr_events; i++) {
+ event_no = event_list[i];
+ /*
+ * check if event is duplicate,
+ * but may not include 0xff when met_cpu_dsu_method == 0.
+ */
+ if (cpu_dsu->check_event(pmu, arg_nr, event_no) < 0)
+ goto arg_out;
+ if (arg_nr >= nr_counters)
+ goto arg_out;
+ pmu[arg_nr].mode = MODE_POLLING;
+ pmu[arg_nr].event = event_no;
+ pmu[arg_nr].freq = 0;
+ arg_nr++;
+ counter_cnt++;
+ }
+ nr_arg = arg_nr;
+ met_cpudsu.mode = 1;
+ return 0;
+
+arg_out:
+ reset_driver_stat();
+ return -EINVAL;
+}
+
+struct metdevice met_cpudsu = {
+ .name = "dsu",
+ .type = MET_TYPE_PMU,
+ .cpu_related = 0,
+ .create_subfs = cpudsu_create_subfs,
+ .delete_subfs = cpudsu_delete_subfs,
+ .start = cpudsu_start,
+ .stop = cpudsu_stop,
+ .polling_interval = 1,
+ .timed_polling = met_perf_cpudsu_polling,
+ .print_help = cpudsu_print_help,
+ .print_header = cpudsu_print_header,
+ .process_argument = cpudsu_process_argument
+};
diff --git a/src/devtools/met_drv_v2/common/cpu_dsu.h b/src/devtools/met_drv_v2/common/cpu_dsu.h
new file mode 100644
index 0000000..373857f
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/cpu_dsu.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CPU_DSU_H_
+#define _CPU_DSU_H_
+
+#include <linux/device.h>
+
+#define MODE_DISABLED 0
+#define MODE_INTERRUPT 1
+#define MODE_POLLING 2
+
+#define MXNR_CPU NR_CPUS
+
+#define MXNR_DSU_EVENTS 8 /* max number of pmu counter for armv8 is 6+1 */
+struct met_dsu {
+ unsigned char mode;
+ unsigned short event;
+ unsigned long freq;
+ struct kobject *kobj_cpu_dsu;
+};
+
+struct cpu_dsu_hw {
+ const char *name;
+ int nr_cnt;
+ int (*check_event)(struct met_dsu *pmu, int idx, int event);
+ void (*start)(struct met_dsu *pmu, int count);
+ void (*stop)(int count);
+ unsigned int (*polling)(struct met_dsu *pmu, int count, unsigned int *pmu_value);
+ struct met_dsu *pmu;
+ int event_count;
+};
+
+
+struct cpu_dsu_hw *cpu_dsu_hw_init(void);
+
+
+
+#endif /* _CPU_DSU_H_ */
diff --git a/src/devtools/met_drv_v2/common/cpu_pmu.c b/src/devtools/met_drv_v2/common/cpu_pmu.c
new file mode 100644
index 0000000..06fc9d0
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/cpu_pmu.c
@@ -0,0 +1,1195 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpu_pm.h>
+#include <linux/perf_event.h>
+
+#if (IS_ENABLED(CONFIG_ARM64) || IS_ENABLED(CONFIG_ARM))
+#include <linux/platform_device.h>
+#include <linux/perf/arm_pmu.h>
+#endif
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/perf/arm_pmu.h>
+#include <linux/irqreturn.h>
+#include <linux/irq_work.h>
+#include "met_drv.h"
+#include "met_kernel_symbol.h"
+#include "interface.h"
+#include "trace.h"
+#include "cpu_pmu.h"
+#include "mtk_typedefs.h"
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#elif defined(TINYSYS_SSPM_SUPPORT)
+#include "tinysys_sspm.h"
+#include "tinysys_mgr.h" /* for ondiemet_module */
+#include "sspm_met_ipi_handle.h"
+#endif
+#endif
+
+struct cpu_pmu_hw *cpu_pmu;
+static int counter_cnt[MXNR_CPU];
+static int nr_arg[MXNR_CPU];
+
+int met_perf_cpupmu_status;
+
+static int mtk_pmu_event_enable = 0;
+static struct kobject *kobj_cpu;
+DECLARE_KOBJ_ATTR_INT(mtk_pmu_event_enable, mtk_pmu_event_enable);
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(mtk_pmu_event_enable); \
+ } while (0)
+
+DEFINE_MUTEX(handle_irq_lock);
+irqreturn_t (*handle_irq_orig)(struct arm_pmu *pmu);
+
+#if IS_ENABLED(CONFIG_CPU_PM)
+static int use_cpu_pm_pmu_notifier = 0;
+
+/* helper notifier for maintaining pmu states before cpu state transition */
+static int cpu_pm_pmu_notify(struct notifier_block *b,
+ unsigned long cmd,
+ void *p)
+{
+ int ii;
+ int cpu, count;
+ unsigned int pmu_value[MXNR_PMU_EVENTS];
+
+ if (!met_perf_cpupmu_status)
+ return NOTIFY_OK;
+
+ cpu = raw_smp_processor_id();
+
+ switch (cmd) {
+ case CPU_PM_ENTER:
+ count = cpu_pmu->polling(cpu_pmu->pmu[cpu], cpu_pmu->event_count[cpu], pmu_value);
+ for (ii = 0; ii < count; ii ++)
+ cpu_pmu->cpu_pm_unpolled_loss[cpu][ii] += pmu_value[ii];
+
+ cpu_pmu->stop(cpu_pmu->event_count[cpu]);
+ break;
+ case CPU_PM_ENTER_FAILED:
+ case CPU_PM_EXIT:
+ cpu_pmu->start(cpu_pmu->pmu[cpu], cpu_pmu->event_count[cpu]);
+ break;
+ default:
+ return NOTIFY_DONE;
+ }
+ return NOTIFY_OK;
+}
+
+struct notifier_block cpu_pm_pmu_notifier = {
+ .notifier_call = cpu_pm_pmu_notify,
+};
+#endif
+
+static DEFINE_PER_CPU(unsigned long long[MXNR_PMU_EVENTS], perfCurr);
+static DEFINE_PER_CPU(unsigned long long[MXNR_PMU_EVENTS], perfPrev);
+static DEFINE_PER_CPU(int[MXNR_PMU_EVENTS], perfCntFirst);
+static DEFINE_PER_CPU(struct perf_event * [MXNR_PMU_EVENTS], pevent);
+static DEFINE_PER_CPU(struct perf_event_attr [MXNR_PMU_EVENTS], pevent_attr);
+static DEFINE_PER_CPU(int, perfSet);
+static DEFINE_PER_CPU(int, cpu_status);
+
+#ifdef CPUPMU_V8_2
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#ifdef USE_KERNEL_SYNC_WRITE_H
+#include <mt-plat/sync_write.h>
+#else
+#include "sync_write.h"
+#endif
+
+#ifdef USE_KERNEL_MTK_IO_H
+#include <mt-plat/mtk_io.h>
+#else
+#include "mtk_io.h"
+#endif
+
+static char mcucfg_desc[] = "mediatek,mcucfg";
+static void __iomem *mcucfg_base = NULL;
+#define DBG_CONTROL_CPU6 ((unsigned long)mcucfg_base + 0x3000 + 0x308) /* DBG_CONTROL */
+#define DBG_CONTROL_CPU7 ((unsigned long)mcucfg_base + 0x3800 + 0x308) /* DBG_CONTROL */
+#define ENABLE_MTK_PMU_EVENTS_OFFSET 1
+static int restore_dbg_ctrl_cpu6;
+static int restore_dbg_ctrl_cpu7;
+
+int cpu_pmu_debug_init(void)
+{
+ struct device_node *node = NULL;
+ unsigned int value6,value7;
+
+ /*for A75 MTK internal event*/
+ if (mcucfg_base == NULL) {
+ node = of_find_compatible_node(NULL, NULL, mcucfg_desc);
+ if (node == NULL) {
+ MET_TRACE("[MET_PMU_DB] of_find node == NULL\n");
+ pr_debug("[MET_PMU_DB] of_find node == NULL\n");
+ goto out;
+ }
+ mcucfg_base = of_iomap(node, 0);
+ of_node_put(node);
+ if (mcucfg_base == NULL) {
+ MET_TRACE("[MET_PMU_DB] mcucfg_base == NULL\n");
+ pr_debug("[MET_PMU_DB] mcucfg_base == NULL\n");
+ goto out;
+ }
+ MET_TRACE("[MET_PMU_DB] regbase %08lx\n", DBG_CONTROL_CPU7);
+ pr_debug("[MET_PMU_DB] regbase %08lx\n", DBG_CONTROL_CPU7);
+ }
+
+ value6 = readl(IOMEM(DBG_CONTROL_CPU6));
+ if (value6 & (1 << ENABLE_MTK_PMU_EVENTS_OFFSET)) {
+ restore_dbg_ctrl_cpu6 = 1;
+ } else {
+ restore_dbg_ctrl_cpu6 = 0;
+ mt_reg_sync_writel(value6 | (1 << ENABLE_MTK_PMU_EVENTS_OFFSET), DBG_CONTROL_CPU6);
+ }
+
+ value7 = readl(IOMEM(DBG_CONTROL_CPU7));
+ if (value7 & (1 << ENABLE_MTK_PMU_EVENTS_OFFSET)) {
+ restore_dbg_ctrl_cpu7 = 1;
+ } else {
+ restore_dbg_ctrl_cpu7 = 0;
+ mt_reg_sync_writel(value7 | (1 << ENABLE_MTK_PMU_EVENTS_OFFSET), DBG_CONTROL_CPU7);
+ }
+
+ value6 = readl(IOMEM(DBG_CONTROL_CPU6));
+ value7 = readl(IOMEM(DBG_CONTROL_CPU7));
+ MET_TRACE("[MET_PMU_DB]DBG_CONTROL_CPU6 = %08x, DBG_CONTROL_CPU7 = %08x\n", value6, value7);
+ pr_debug("[MET_PMU_DB]DBG_CONTROL_CPU6 = %08x, DBG_CONTROL_CPU7 = %08x\n", value6, value7);
+ return 1;
+
+out:
+ if (mcucfg_base != NULL) {
+ iounmap(mcucfg_base);
+ mcucfg_base = NULL;
+ }
+ MET_TRACE("[MET_PMU_DB]DBG_CONTROL init error");
+ pr_debug("[MET_PMU_DB]DBG_CONTROL init error");
+ return 0;
+}
+
+int cpu_pmu_debug_uninit(void)
+{
+ unsigned int value6,value7;
+
+ if (restore_dbg_ctrl_cpu6 == 0) {
+ value6 = readl(IOMEM(DBG_CONTROL_CPU6));
+ mt_reg_sync_writel(value6 & (~(1 << ENABLE_MTK_PMU_EVENTS_OFFSET)), DBG_CONTROL_CPU6);
+ }
+ if (restore_dbg_ctrl_cpu7 == 0) {
+ value7 = readl(IOMEM(DBG_CONTROL_CPU7));
+ mt_reg_sync_writel(value7 & (~(1 << ENABLE_MTK_PMU_EVENTS_OFFSET)), DBG_CONTROL_CPU7);
+ }
+
+ value6 = readl(IOMEM(DBG_CONTROL_CPU6));
+ value7 = readl(IOMEM(DBG_CONTROL_CPU7));
+ MET_TRACE("[MET_PMU_DB]DBG_CONTROL_CPU6 = %08x, DBG_CONTROL_CPU7 = %08x\n", value6, value7);
+ pr_debug("[MET_PMU_DB]DBG_CONTROL_CPU6 = %08x, DBG_CONTROL_CPU7 = %08x\n", value6, value7);
+
+ if (mcucfg_base != NULL) {
+ iounmap(mcucfg_base);
+ mcucfg_base = NULL;
+ }
+ restore_dbg_ctrl_cpu6 = 0;
+ restore_dbg_ctrl_cpu7 = 0;
+ return 1;
+}
+#endif
+
+
+
+
+noinline void mp_cpu(unsigned char cnt, unsigned int *value)
+{
+ MET_GENERAL_PRINT(MET_TRACE, cnt, value);
+}
+
+static void dummy_handler(struct perf_event *event, struct perf_sample_data *data,
+ struct pt_regs *regs)
+{
+ /*
+ * Required as perf_event_create_kernel_counter() requires an overflow handler,
+ * even though all we do is poll.
+ */
+}
+
+static void perf_cpupmu_polling(unsigned long long stamp, int cpu)
+{
+ int event_count = cpu_pmu->event_count[cpu];
+ struct met_pmu *pmu = cpu_pmu->pmu[cpu];
+ int i, count;
+ unsigned long long delta;
+ struct perf_event *ev;
+ unsigned int pmu_value[MXNR_PMU_EVENTS];
+ u64 value;
+ int ret;
+
+ if (per_cpu(perfSet, cpu) == 0)
+ return;
+
+ count = 0;
+ for (i = 0; i < event_count; i++) {
+ if (pmu[i].mode == 0)
+ continue;
+
+ ev = per_cpu(pevent, cpu)[i];
+ if ((ev != NULL) && (ev->state == PERF_EVENT_STATE_ACTIVE)) {
+ if (!met_export_api_symbol->met_perf_event_read_local)
+ continue;
+
+ ret = met_export_api_symbol->met_perf_event_read_local(ev, &value);
+ if (ret < 0) {
+ PR_BOOTMSG_ONCE("[MET_PMU] perf_event_read_local fail (ret=%d)\n", ret);
+ pr_debug("[MET_PMU] perf_event_read_local fail (ret=%d)\n", ret);
+ continue;
+ }
+
+ per_cpu(perfCurr, cpu)[i] = value;
+ delta = (per_cpu(perfCurr, cpu)[i] - per_cpu(perfPrev, cpu)[i]);
+ per_cpu(perfPrev, cpu)[i] = per_cpu(perfCurr, cpu)[i];
+ if (per_cpu(perfCntFirst, cpu)[i] == 1) {
+ /* we shall omit delta counter when we get first counter */
+ per_cpu(perfCntFirst, cpu)[i] = 0;
+ continue;
+ }
+ pmu_value[count] = (unsigned int)delta;
+ count++;
+ }
+ }
+
+ if (count == counter_cnt[cpu])
+ mp_cpu(count, pmu_value);
+}
+
+static struct perf_event* perf_event_create(int cpu, unsigned short event, int count)
+{
+ struct perf_event_attr *ev_attr;
+ struct perf_event *ev;
+
+ ev_attr = per_cpu(pevent_attr, cpu)+count;
+ memset(ev_attr, 0, sizeof(*ev_attr));
+ if (event == 0xff) {
+ ev_attr->config = PERF_COUNT_HW_CPU_CYCLES;
+ ev_attr->type = PERF_TYPE_HARDWARE;
+ } else {
+ ev_attr->config = event;
+ ev_attr->type = PERF_TYPE_RAW;
+ }
+ ev_attr->size = sizeof(*ev_attr);
+ ev_attr->sample_period = 0;
+ ev_attr->pinned = 1;
+
+ ev = perf_event_create_kernel_counter(ev_attr, cpu, NULL, dummy_handler, NULL);
+ if (IS_ERR(ev))
+ return NULL;
+ do {
+ if (ev->state == PERF_EVENT_STATE_ACTIVE)
+ break;
+ if (ev->state == PERF_EVENT_STATE_ERROR) {
+ perf_event_enable(ev);
+ if (ev->state == PERF_EVENT_STATE_ACTIVE)
+ break;
+ }
+ perf_event_release_kernel(ev);
+ return NULL;
+ } while (0);
+
+ return ev;
+}
+
+static void perf_event_release(int cpu, struct perf_event *ev)
+{
+ if (ev->state == PERF_EVENT_STATE_ACTIVE)
+ perf_event_disable(ev);
+ perf_event_release_kernel(ev);
+}
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#define PMU_OVERFLOWED_MASK 0xffffffff
+
+static inline int pmu_has_overflowed(u32 pmovsr)
+{
+ return pmovsr & PMU_OVERFLOWED_MASK;
+}
+
+static irqreturn_t perf_event_handle_irq_ignore_overflow(struct arm_pmu *pmu)
+{
+ u32 pmovsr;
+
+ pmovsr = cpu_pmu->pmu_read_clear_overflow_flag();
+
+ if (!pmu_has_overflowed(pmovsr)) {
+ return IRQ_NONE;
+ }
+ else {
+ irq_work_run();
+ return IRQ_HANDLED;
+ }
+}
+#endif
+#endif
+
+static int perf_thread_set_perf_events(int cpu)
+{
+ int i, size;
+ struct perf_event *ev;
+
+ size = sizeof(struct perf_event_attr);
+ if (per_cpu(perfSet, cpu) == 0) {
+ int event_count = cpu_pmu->event_count[cpu];
+ struct met_pmu *pmu = cpu_pmu->pmu[cpu];
+ for (i = 0; i < event_count; i++) {
+ if (!pmu[i].mode)
+ continue; /* Skip disabled counters */
+ ev = perf_event_create(cpu, pmu[i].event, i);
+ if (ev == NULL) {
+ met_cpupmu.mode = 0;
+ met_perf_cpupmu_status = 0;
+
+ MET_TRACE("[MET_PMU] cpu %d failed to register pmu event %4x\n", cpu, pmu[i].event);
+ pr_notice("[MET_PMU] cpu %d failed to register pmu event %4x\n", cpu, pmu[i].event);
+ continue;
+ }
+
+ /*
+ * in perf-event implementation, hardware pmu slot and cycle counter
+ * was mapped to perf_event::hw::idx as follows:
+ *
+ * | idx | hardware slot |
+ * |-----+---------------|
+ * | 0 | pmccntr_el0 |
+ * | 1 | 0 |
+ * | 2 | 1 |
+ * | 3 | 2 |
+ * | 4 | 3 |
+ * | 5 | 4 |
+ * | 6 | 5 |
+ */
+ if (ev->hw.idx != 0) {
+ MET_TRACE("[MET_PMU] cpu %d registered in pmu slot: [%d] evt=%#04x\n",
+ cpu, ev->hw.idx-1, pmu[i].event);
+ pr_debug("[MET_PMU] cpu %d registered in pmu slot: [%d] evt=%#04x\n",
+ cpu, ev->hw.idx-1, pmu[i].event);
+ } else if (ev->hw.idx == 0) {
+ MET_TRACE("[MET_PMU] cpu %d registered cycle count evt=%#04x\n",
+ cpu, pmu[i].event);
+ pr_debug("[MET_PMU] cpu %d registered cycle count evt=%#04x\n",
+ cpu, pmu[i].event);
+ }
+
+ per_cpu(pevent, cpu)[i] = ev;
+ per_cpu(perfPrev, cpu)[i] = 0;
+ per_cpu(perfCurr, cpu)[i] = 0;
+ perf_event_enable(ev);
+ per_cpu(perfCntFirst, cpu)[i] = 1;
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ if (met_cpupmu.ondiemet_mode) {
+ struct arm_pmu *armpmu;
+ armpmu = container_of(ev->pmu, struct arm_pmu, pmu);
+ mutex_lock(&handle_irq_lock);
+ if (armpmu && armpmu->handle_irq != perf_event_handle_irq_ignore_overflow) {
+ pr_debug("[MET_PMU] replaced original handle_irq=%p with dummy function\n",
+ armpmu->handle_irq);
+ handle_irq_orig = armpmu->handle_irq;
+ armpmu->handle_irq = perf_event_handle_irq_ignore_overflow;
+ }
+ mutex_unlock(&handle_irq_lock);
+ }
+#endif
+#endif
+ } /* for all PMU counter */
+ per_cpu(perfSet, cpu) = 1;
+ } /* for perfSet */
+
+ return 0;
+}
+
+static void met_perf_cpupmu_start(int cpu)
+{
+ if (met_cpupmu.mode == 0)
+ return;
+
+ perf_thread_set_perf_events(cpu);
+}
+
+static void perf_thread_down(int cpu)
+{
+ int i;
+ struct perf_event *ev;
+ int event_count;
+ struct met_pmu *pmu;
+
+ if (per_cpu(perfSet, cpu) == 0)
+ return;
+
+ per_cpu(perfSet, cpu) = 0;
+ event_count = cpu_pmu->event_count[cpu];
+ pmu = cpu_pmu->pmu[cpu];
+ for (i = 0; i < event_count; i++) {
+ ev = per_cpu(pevent, cpu)[i];
+ if (ev != NULL) {
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ if (met_cpupmu.ondiemet_mode) {
+ struct arm_pmu *armpmu;
+ armpmu = container_of(ev->pmu, struct arm_pmu, pmu);
+ mutex_lock(&handle_irq_lock);
+ if (armpmu && armpmu->handle_irq == perf_event_handle_irq_ignore_overflow) {
+ pr_debug("[MET_PMU] restore original handle_irq=%p\n", handle_irq_orig);
+ armpmu->handle_irq = handle_irq_orig;
+ handle_irq_orig = NULL;
+ }
+ mutex_unlock(&handle_irq_lock);
+ }
+#endif
+#endif
+
+ perf_event_release(cpu, ev);
+ per_cpu(pevent, cpu)[i] = NULL;
+ }
+ }
+}
+
+static void met_perf_cpupmu_stop(int cpu)
+{
+ perf_thread_down(cpu);
+}
+
+static int cpupmu_create_subfs(struct kobject *parent)
+{
+ int ret = 0;
+
+ cpu_pmu = cpu_pmu_hw_init();
+ if (cpu_pmu == NULL) {
+ PR_BOOTMSG("Failed to init CPU PMU HW!!\n");
+ return -ENODEV;
+ }
+
+ kobj_cpu = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+ do { \
+ ret = sysfs_create_file(kobj_cpu, &attr_name ## _attr.attr); \
+ if (ret != 0) { \
+ pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+ } while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+ return 0;
+}
+
+static void cpupmu_delete_subfs(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_cpu, &attr_name ## _attr.attr)
+
+ if (kobj_cpu != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_cpu = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+}
+
+void met_perf_cpupmu_polling(unsigned long long stamp, int cpu)
+{
+ int count;
+ unsigned int pmu_value[MXNR_PMU_EVENTS];
+
+ if (per_cpu(cpu_status, cpu) != MET_CPU_ONLINE)
+ return;
+
+ if (met_cpu_pmu_method) {
+ perf_cpupmu_polling(stamp, cpu);
+ } else {
+ count = cpu_pmu->polling(cpu_pmu->pmu[cpu], cpu_pmu->event_count[cpu], pmu_value);
+
+#if IS_ENABLED(CONFIG_CPU_PM)
+ if (met_cpu_pm_pmu_reconfig) {
+ int ii;
+ for (ii = 0; ii < count; ii ++)
+ pmu_value[ii] += cpu_pmu->cpu_pm_unpolled_loss[cpu][ii];
+ }
+#endif
+
+ mp_cpu(count, pmu_value);
+
+#if IS_ENABLED(CONFIG_CPU_PM)
+ if (met_cpu_pm_pmu_reconfig) {
+ memset(cpu_pmu->cpu_pm_unpolled_loss[cpu], 0, sizeof (cpu_pmu->cpu_pm_unpolled_loss[0]));
+ }
+#endif
+ }
+}
+
+static void cpupmu_start(void)
+{
+ int cpu = raw_smp_processor_id();
+
+ if (!met_cpu_pmu_method) {
+ nr_arg[cpu] = 0;
+ cpu_pmu->start(cpu_pmu->pmu[cpu], cpu_pmu->event_count[cpu]);
+
+ met_perf_cpupmu_status = 1;
+ per_cpu(cpu_status, cpu) = MET_CPU_ONLINE;
+ }
+}
+
+
+static void cpupmu_unique_start(void)
+{
+ int cpu;
+
+#ifdef CPUPMU_V8_2
+ int ret = 0;
+ if (mtk_pmu_event_enable == 1){
+ ret = cpu_pmu_debug_init();
+ if (ret == 0)
+ PR_BOOTMSG("Failed to init CPU PMU debug!!\n");
+ }
+#endif
+
+#if IS_ENABLED(CONFIG_CPU_PM)
+ use_cpu_pm_pmu_notifier = 0;
+ if (met_cpu_pm_pmu_reconfig) {
+ if (met_cpu_pmu_method) {
+ met_cpu_pm_pmu_reconfig = 0;
+ MET_TRACE("[MET_PMU] met_cpu_pmu_method=%d, met_cpu_pm_pmu_reconfig forced disabled\n", met_cpu_pmu_method);
+ pr_debug("[MET_PMU] met_cpu_pmu_method=%d, met_cpu_pm_pmu_reconfig forced disabled\n", met_cpu_pmu_method);
+ } else {
+ memset(cpu_pmu->cpu_pm_unpolled_loss, 0, sizeof (cpu_pmu->cpu_pm_unpolled_loss));
+ cpu_pm_register_notifier(&cpu_pm_pmu_notifier);
+ use_cpu_pm_pmu_notifier = 1;
+ }
+ }
+#else
+ if (met_cpu_pm_pmu_reconfig) {
+ met_cpu_pm_pmu_reconfig = 0;
+ MET_TRACE("[MET_PMU] CONFIG_CPU_PM=%d, met_cpu_pm_pmu_reconfig forced disabled\n", CONFIG_CPU_PM);
+ pr_debug("[MET_PMU] CONFIG_CPU_PM=%d, met_cpu_pm_pmu_reconfig forced disabled\n", CONFIG_CPU_PM);
+ }
+#endif
+ MET_TRACE("[MET_PMU] met_cpu_pm_pmu_reconfig=%u\n", met_cpu_pm_pmu_reconfig);
+ pr_debug("[MET_PMU] met_cpu_pm_pmu_reconfig=%u\n", met_cpu_pm_pmu_reconfig);
+
+ if (met_cpu_pmu_method) {
+ for_each_possible_cpu(cpu) {
+ met_perf_cpupmu_start(cpu);
+
+ met_perf_cpupmu_status = 1;
+ per_cpu(cpu_status, cpu) = MET_CPU_ONLINE;
+ }
+ }
+
+ return;
+}
+
+static void cpupmu_stop(void)
+{
+ int cpu = raw_smp_processor_id();
+
+ met_perf_cpupmu_status = 0;
+
+ if (!met_cpu_pmu_method)
+ cpu_pmu->stop(cpu_pmu->event_count[cpu]);
+}
+
+static void cpupmu_unique_stop(void)
+{
+ int cpu;
+
+ if (met_cpu_pmu_method) {
+ for_each_possible_cpu(cpu) {
+ met_perf_cpupmu_stop(cpu);
+ }
+ }
+
+#ifdef CPUPMU_V8_2
+ if (mtk_pmu_event_enable == 1)
+ cpu_pmu_debug_uninit();
+#endif
+
+#if IS_ENABLED(CONFIG_CPU_PM)
+ if (use_cpu_pm_pmu_notifier) {
+ cpu_pm_unregister_notifier(&cpu_pm_pmu_notifier);
+ }
+#endif
+ return;
+}
+
+static const char cache_line_header[] =
+ "met-info [000] 0.0: met_cpu_cache_line_size: %d\n";
+static const char header[] =
+ "met-info [000] 0.0: met_cpu_header_v2: %d";
+
+static const char help[] =
+ " --pmu-cpu-evt=[cpu_list:]event_list select CPU-PMU events in %s\n"
+ " cpu_list: specify the cpu_id list or apply to all the cores\n"
+ " example: 0,1,2\n"
+ " event_list: specify the event number\n"
+ " example: 0x8,0xff\n";
+
+static int cpupmu_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help, cpu_pmu->cpu_name);
+}
+
+static int reset_driver_stat(void)
+{
+ int cpu, i;
+ int event_count;
+ struct met_pmu *pmu;
+
+ met_cpupmu.mode = 0;
+ for_each_possible_cpu(cpu) {
+ event_count = cpu_pmu->event_count[cpu];
+ pmu = cpu_pmu->pmu[cpu];
+ counter_cnt[cpu] = 0;
+ nr_arg[cpu] = 0;
+ for (i = 0; i < event_count; i++) {
+ pmu[i].mode = MODE_DISABLED;
+ pmu[i].event = 0;
+ pmu[i].freq = 0;
+ }
+ }
+
+ return 0;
+}
+
+static int cpupmu_print_header(char *buf, int len)
+{
+ int cpu, i, ret, first;
+ int event_count;
+ struct met_pmu *pmu;
+
+ ret = 0;
+
+ /*append CPU PMU access method*/
+ if (met_cpu_pmu_method)
+ ret += snprintf(buf + ret, len,
+ "met-info [000] 0.0: CPU_PMU_method: perf APIs\n");
+ else
+ ret += snprintf(buf + ret, len,
+ "met-info [000] 0.0: CPU_PMU_method: MET pmu driver\n");
+
+ /*append cache line size*/
+ ret += snprintf(buf + ret, len - ret, cache_line_header, cache_line_size());
+ ret += snprintf(buf + ret, len - ret, "# mp_cpu: pmu_value1, ...\n");
+
+ for_each_possible_cpu(cpu) {
+ event_count = cpu_pmu->event_count[cpu];
+ pmu = cpu_pmu->pmu[cpu];
+ first = 1;
+ for (i = 0; i < event_count; i++) {
+ if (pmu[i].mode == 0)
+ continue;
+ if (first) {
+ ret += snprintf(buf + ret, len - ret, header, cpu);
+ first = 0;
+ }
+ ret += snprintf(buf + ret, len - ret, ",0x%x", pmu[i].event);
+ pmu[i].mode = 0;
+ }
+ if (!first)
+ ret += snprintf(buf + ret, len - ret, "\n");
+ }
+
+ reset_driver_stat();
+
+ return ret;
+}
+
+static int met_parse_num_list(char *arg, int len, int *list, int list_cnt)
+{
+ int nr_num = 0;
+ char *num;
+ int num_len;
+
+ /* search ',' as the splitter */
+ while (len) {
+ num = arg;
+ num_len = 0;
+ if (list_cnt <= 0)
+ return -1;
+ while (len) {
+ len--;
+ if (*arg == ',') {
+ *(arg++) = '\0';
+ break;
+ }
+ arg++;
+ num_len++;
+ }
+ if (met_parse_num(num, list, num_len) < 0)
+ return -1;
+ list++;
+ list_cnt--;
+ nr_num++;
+ }
+
+ return nr_num;
+}
+
+static const struct perf_pmu_events_attr *
+perf_event_get_evt_attr_by_name(const struct perf_event *ev,
+ const char *name) {
+ struct arm_pmu *arm_pmu;
+ struct attribute **attrp;
+ struct device_attribute *dev_attr_p;
+ struct perf_pmu_events_attr *ev_attr_p;
+
+ arm_pmu = container_of(ev->pmu, struct arm_pmu, pmu);
+
+ for (attrp = arm_pmu->attr_groups[ARMPMU_ATTR_GROUP_EVENTS]->attrs;
+ *attrp != NULL;
+ attrp ++) {
+
+ dev_attr_p = container_of(*attrp, struct device_attribute, attr);
+ ev_attr_p = container_of(dev_attr_p, struct perf_pmu_events_attr, attr);
+
+ if (0 == strcmp((*attrp)->name, name)) {
+ return ev_attr_p;
+ }
+ }
+
+ return NULL;
+}
+
+static int cpupmu_process_argument(const char *arg, int len)
+{
+ char *arg1 = (char*)arg;
+ int len1 = len;
+ int cpu, cpu_list[MXNR_CPU];
+ int nr_events, event_list[MXNR_PMU_EVENTS]={0};
+ int i;
+ int nr_counters;
+ struct met_pmu *pmu;
+ int arg_nr;
+ int event_no;
+ int is_cpu_cycle_evt;
+ const struct perf_pmu_events_attr *ev_attr_p;
+
+ /*
+ * split cpu_list and event_list by ':'
+ * arg, len: cpu_list when found (i < len)
+ * arg1, len1: event_list
+ */
+ for (i = 0; i < len; i++) {
+ if (arg[i] == ':') {
+ arg1[i] = '\0';
+ arg1 += i+1;
+ len1 = len - i - 1;
+ len = i;
+ break;
+ }
+ }
+
+ /*
+ * setup cpu_list array
+ * 1: selected
+ * 0: unselected
+ */
+ if (arg1 != arg) { /* is cpu_id list specified? */
+ int list[MXNR_CPU]={0}, cnt;
+ int cpu_id;
+ if ((cnt = met_parse_num_list((char*)arg, len, list, ARRAY_SIZE(list))) <= 0)
+ goto arg_out;
+ memset(cpu_list, 0, sizeof(cpu_list));
+ for (i = 0; i < cnt; i++) {
+ cpu_id = list[i];
+ if (cpu_id < 0 || cpu_id >= ARRAY_SIZE(cpu_list))
+ goto arg_out;
+ cpu_list[cpu_id] = 1;
+ }
+ }
+ else
+ memset(cpu_list, 1, sizeof(cpu_list));
+
+ /* get event_list */
+ if ((nr_events = met_parse_num_list(arg1, len1, event_list, ARRAY_SIZE(event_list))) <= 0)
+ goto arg_out;
+
+ /* for each cpu in cpu_list, add all the events in event_list */
+ for_each_possible_cpu(cpu) {
+ pmu = cpu_pmu->pmu[cpu];
+ arg_nr = nr_arg[cpu];
+
+ if (cpu_list[cpu] == 0)
+ continue;
+
+ if (met_cpu_pmu_method) {
+ nr_counters = perf_num_counters();
+ } else {
+ nr_counters = cpu_pmu->event_count[cpu];
+ }
+
+ pr_debug("[MET_PMU] pmu slot count=%d\n", nr_counters);
+
+ if (nr_counters == 0)
+ goto arg_out;
+
+ for (i = 0; i < nr_events; i++) {
+ event_no = event_list[i];
+ is_cpu_cycle_evt = 0;
+ /*
+ * check if event is duplicate, but does not include 0xff
+ */
+ if (cpu_pmu->check_event(pmu, arg_nr, event_no) < 0)
+ goto arg_out;
+
+ /*
+ * test if this event is available when in perf_APIs mode
+ */
+ if (met_cpu_pmu_method) {
+ struct perf_event *ev;
+
+ if (!cpu_pmu->perf_event_get_evttype) {
+ MET_TRACE("[MET_PMU] cpu_pmu->perf_event_get_evttype=NULL, "
+ "met pmu on perf-event was not supported on this platform\n");
+ pr_debug("[MET_PMU] cpu_pmu->perf_event_get_evttype=NULL, "
+ "met pmu on perf-event was not supported on this platform\n");
+ goto arg_out;
+ }
+
+ ev = perf_event_create(cpu, event_no, arg_nr);
+ if (ev == NULL) {
+ pr_debug("!!!!!!!! [MET_PMU] failed pmu alloction test (event_no=%#04x)\n", event_no);
+ goto arg_out;
+ } else {
+ perf_event_release(cpu, ev);
+ }
+
+ ev_attr_p = perf_event_get_evt_attr_by_name(ev, "cpu_cycles");
+ if (ev_attr_p && cpu_pmu->perf_event_get_evttype(ev) == ev_attr_p->id)
+ is_cpu_cycle_evt = 1;
+ }
+
+ if (met_cpu_pmu_method) {
+ if (is_cpu_cycle_evt) {
+ if (pmu[nr_counters-1].mode == MODE_POLLING)
+ goto arg_out;
+ pmu[nr_counters-1].mode = MODE_POLLING;
+ pmu[nr_counters-1].event = event_no;
+ pmu[nr_counters-1].freq = 0;
+ } else {
+ if (arg_nr >= (nr_counters - 1))
+ goto arg_out;
+ pmu[arg_nr].mode = MODE_POLLING;
+ pmu[arg_nr].event = event_no;
+ pmu[arg_nr].freq = 0;
+ arg_nr++;
+ }
+ } else {
+ if (event_no == 0xff) {
+ if (pmu[nr_counters-1].mode == MODE_POLLING)
+ goto arg_out;
+ pmu[nr_counters-1].mode = MODE_POLLING;
+ pmu[nr_counters-1].event = 0xff;
+ pmu[nr_counters-1].freq = 0;
+ } else {
+ if (arg_nr >= (nr_counters - 1))
+ goto arg_out;
+ pmu[arg_nr].mode = MODE_POLLING;
+ pmu[arg_nr].event = event_no;
+ pmu[arg_nr].freq = 0;
+ arg_nr++;
+ }
+ }
+ counter_cnt[cpu]++;
+ }
+ nr_arg[cpu] = arg_nr;
+ }
+
+ met_cpupmu.mode = 1;
+ return 0;
+
+arg_out:
+ reset_driver_stat();
+ return -EINVAL;
+}
+
+static void cpupmu_cpu_state_notify(long cpu, unsigned long action)
+{
+ per_cpu(cpu_status, cpu) = action;
+
+#if (IS_ENABLED(CONFIG_ARM64) || IS_ENABLED(CONFIG_ARM))
+ if (met_cpu_pmu_method && action == MET_CPU_OFFLINE) {
+ struct perf_event *event = NULL;
+ struct arm_pmu *armpmu = NULL;
+ struct platform_device *pmu_device = NULL;
+ int irq = 0;
+
+ event = per_cpu(pevent, cpu)[0];
+ if (event)
+ armpmu = to_arm_pmu(event->pmu);
+ pr_debug("!!!!!!!! %s_%ld, event=%p\n", __FUNCTION__, cpu, event);
+
+ if (armpmu)
+ pmu_device = armpmu->plat_device;
+ pr_debug("!!!!!!!! %s_%ld, armpmu=%p\n", __FUNCTION__, cpu, armpmu);
+
+ if (pmu_device)
+ irq = platform_get_irq(pmu_device, 0);
+ pr_debug("!!!!!!!! %s_%ld, pmu_device=%p\n", __FUNCTION__, cpu, pmu_device);
+
+ if (irq > 0)
+ disable_percpu_irq(irq);
+ pr_debug("!!!!!!!! %s_%ld, irq=%d\n", __FUNCTION__, cpu, irq);
+ }
+#endif
+}
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+static void sspm_pmu_start(void)
+{
+ ondiemet_module[ONDIEMET_SSPM] |= ID_PMU;
+
+ if (met_cpupmu.ondiemet_mode == 1)
+ cpupmu_start();
+}
+
+static int cycle_count_mode_enabled(int cpu) {
+
+ int event_cnt;
+ struct met_pmu *pmu;
+
+ pmu = cpu_pmu->pmu[cpu];
+
+ if (met_cpu_pmu_method) {
+ event_cnt = perf_num_counters();
+ } else {
+ event_cnt = cpu_pmu->event_count[cpu];
+ }
+
+ return pmu[event_cnt-1].mode == MODE_POLLING;
+}
+
+static void ipi_config_pmu_counter_cnt(void) {
+
+ int ret, cpu, ii, cnt_num;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+ struct hw_perf_event *hwc;
+ unsigned int base_offset;
+
+ for_each_possible_cpu(cpu) {
+ for (ii = 0; ii < 4; ii++)
+ ipi_buf[ii] = 0;
+
+ ipi_buf[0] = MET_MAIN_ID | (MID_PMU << MID_BIT_SHIFT) | MET_ARGU | SET_PMU_EVT_CNT;
+ /*
+ * XXX: on sspm side, cycle counter was not counted in
+ * total event number `counter_cnt', but controlled by
+ * an addtional argument `SET_PMU_CYCCNT_ENABLE' instead
+ */
+ cnt_num = (cycle_count_mode_enabled(cpu) ?
+ (counter_cnt[cpu]-1) : counter_cnt[cpu]);
+ ipi_buf[1] = (cpu << 16) | (cnt_num & 0xffff);
+
+ MET_TRACE("[MET_PMU][IPI_CONFIG] core=%d, pmu_counter_cnt=%d\n", cpu, cnt_num);
+ pr_debug("[MET_PMU][IPI_CONFIG] core=%d, pmu_counter_cnt=%d\n", cpu, cnt_num);
+
+ MET_TRACE("[MET_PMU][IPI_CONFIG] sspm_buf_available=%d, in_interrupt()=%lu\n", sspm_buf_available, in_interrupt());
+ pr_debug("[MET_PMU][IPI_CONFIG] sspm_buf_available=%d, in_interrupt()=%lu\n", sspm_buf_available, in_interrupt());
+
+ if (sspm_buf_available == 1) {
+ ret = met_ipi_to_sspm_command((void *) ipi_buf, 0, &rdata, 1);
+ }
+
+ for (ii = 0; ii < 4; ii++)
+ ipi_buf[ii] = 0;
+
+ if (per_cpu(pevent, cpu)[0]) {
+ hwc = &(per_cpu(pevent, cpu)[0]->hw);
+ base_offset = hwc->idx-1;
+ } else {
+ base_offset = 0;
+ }
+
+ ipi_buf[0] = MET_MAIN_ID | (MID_PMU << MID_BIT_SHIFT) | MET_ARGU | SET_PMU_BASE_OFFSET;
+ ipi_buf[1] = (cpu << 16) | (base_offset & 0xffff);
+
+ MET_TRACE("[MET_PMU][IPI_CONFIG] core=%d, base offset set to %u\n", cpu, base_offset);
+ pr_debug("[MET_PMU][IPI_CONFIG] core=%d, base offset set to %u\n", cpu, base_offset);
+
+ if (sspm_buf_available == 1) {
+ ret = met_ipi_to_sspm_command((void *) ipi_buf, 0, &rdata, 1);
+ }
+
+ if (cycle_count_mode_enabled(cpu)) {
+
+ for (ii = 0; ii < 4; ii++)
+ ipi_buf[ii] = 0;
+
+ ipi_buf[0] = MET_MAIN_ID | (MID_PMU << MID_BIT_SHIFT) | MET_ARGU | SET_PMU_CYCCNT_ENABLE;
+ ipi_buf[1] = cpu & 0xffff;
+
+ MET_TRACE("[MET_PMU][IPI_CONFIG] core=%d, pmu cycle cnt enable\n", cpu);
+ pr_debug("[MET_PMU][IPI_CONFIG] core=%d, pmu cycle cnt enable\n", cpu);
+
+ if (sspm_buf_available == 1) {
+ ret = met_ipi_to_sspm_command((void *) ipi_buf, 0, &rdata, 1);
+ }
+ }
+ }
+}
+
+static int __is_perf_event_hw_slot_seq_order(int cpu) {
+
+ struct hw_perf_event *hwc, *hwc_prev;
+ int event_count = cpu_pmu->event_count[cpu];
+ int ii;
+
+ /*
+ * perf-event descriptor list would not have any hole
+ * (excepts special 0xff, which will always be the last element)
+ */
+ if (per_cpu(pevent, cpu)[0] == NULL)
+ return 1;
+
+ /*
+ * XXX: no need to check the last slot,
+ * which is reserved for 0xff
+ */
+ for (ii = 1; ii < event_count - 1; ii++) {
+
+ if (per_cpu(pevent, cpu)[ii] == NULL)
+ return 1;
+
+ hwc = &(per_cpu(pevent, cpu)[ii]->hw);
+ hwc_prev = &(per_cpu(pevent, cpu)[ii-1]->hw);
+
+ if (hwc->idx != hwc_prev->idx + 1)
+ return 0;
+ }
+
+ return 1;
+}
+
+static int __validate_sspm_compatibility(void) {
+
+ int cpu;
+
+ for_each_possible_cpu(cpu) {
+
+ if (!__is_perf_event_hw_slot_seq_order(cpu)) {
+ MET_TRACE("[MET_PMU] pmu not sequentially allocated on cpu %d\n"
+ ,cpu);
+ pr_debug("[MET_PMU] pmu not sequentially allocated on cpu %d\n"
+ ,cpu);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static void sspm_pmu_unique_start(void) {
+
+ if (met_cpupmu.ondiemet_mode == 1)
+ cpupmu_unique_start();
+
+ if (met_cpupmu.ondiemet_mode == 1) {
+ if (__validate_sspm_compatibility() == -1) {
+ MET_TRACE("[MET_PMU] turned off sspm side polling\n");
+ pr_debug("[MET_PMU] turned off sspm side polling\n");
+ /* return without sending init IPIs, leaving sspm side to poll nothing */
+ return;
+ }
+ }
+
+ ipi_config_pmu_counter_cnt();
+}
+
+static void sspm_pmu_unique_stop(void)
+{
+ if (met_cpupmu.ondiemet_mode == 1)
+ cpupmu_unique_stop();
+ return;
+}
+
+static void sspm_pmu_stop(void)
+{
+ if (met_cpupmu.ondiemet_mode == 1)
+ cpupmu_stop();
+}
+
+static const char sspm_pmu_header[] = "met-info [000] 0.0: pmu_sampler: sspm\n";
+
+static int sspm_pmu_print_header(char *buf, int len)
+{
+ int ret;
+
+ ret = snprintf(buf, len, sspm_pmu_header);
+
+ if (met_cpupmu.ondiemet_mode == 1)
+ ret += cpupmu_print_header(buf + ret, len - ret);
+
+ return ret;
+}
+
+static int sspm_pmu_process_argument(const char *arg, int len)
+{
+ if (met_cpupmu.ondiemet_mode == 1) {
+
+ if (!cpu_pmu->pmu_read_clear_overflow_flag) {
+ MET_TRACE("[MET_PMU] cpu_pmu->pmu_read_clear_overflow_flag=NULL, "
+ "pmu on sspm was not supported on this platform\n");
+ pr_debug("[MET_PMU] cpu_pmu->pmu_read_clear_overflow_flag=NULL, "
+ "pmu on sspm was not supported on this platform\n");
+ return -EINVAL;
+ }
+
+ return cpupmu_process_argument(arg, len);
+ }
+ return 0;
+}
+#endif /* end of #if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT) */
+#endif /* end of #if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) */
+
+struct metdevice met_cpupmu = {
+ .name = "cpu",
+ .type = MET_TYPE_PMU,
+ .cpu_related = 1,
+ .create_subfs = cpupmu_create_subfs,
+ .delete_subfs = cpupmu_delete_subfs,
+ .start = cpupmu_start,
+ .uniq_start = cpupmu_unique_start,
+ .stop = cpupmu_stop,
+ .uniq_stop = cpupmu_unique_stop,
+ .polling_interval = 1,
+ .timed_polling = met_perf_cpupmu_polling,
+ .print_help = cpupmu_print_help,
+ .print_header = cpupmu_print_header,
+ .process_argument = cpupmu_process_argument,
+ .cpu_state_notify = cpupmu_cpu_state_notify,
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ .ondiemet_mode = 1,
+ .ondiemet_start = sspm_pmu_start,
+ .uniq_ondiemet_start = sspm_pmu_unique_start,
+ .uniq_ondiemet_stop = sspm_pmu_unique_stop,
+ .ondiemet_stop = sspm_pmu_stop,
+ .ondiemet_print_header = sspm_pmu_print_header,
+ .ondiemet_process_argument = sspm_pmu_process_argument
+#endif
+#endif
+};
diff --git a/src/devtools/met_drv_v2/common/cpu_pmu.h b/src/devtools/met_drv_v2/common/cpu_pmu.h
new file mode 100644
index 0000000..4623462
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/cpu_pmu.h
@@ -0,0 +1,66 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _CPU_PMU_H_
+#define _CPU_PMU_H_
+
+#include <linux/device.h>
+#include <linux/perf_event.h>
+
+#define MODE_DISABLED 0
+#define MODE_INTERRUPT 1
+#define MODE_POLLING 2
+
+#define MXSIZE_PMU_DESC 32
+#define MXNR_CPU NR_CPUS
+
+#define MXNR_PMU_EVENTS 8 /* max number of pmu counter for armv8 is 6+1 */
+struct met_pmu {
+ unsigned char mode;
+ unsigned short event;
+ unsigned long freq;
+ struct kobject *kobj_cpu_pmu;
+};
+
+struct cpu_pmu_hw {
+ const char *name;
+ const char *cpu_name;
+ int nr_cnt;
+ int (*get_event_desc)(int idx, int event, char *event_desc);
+ int (*check_event)(struct met_pmu *pmu, int idx, int event);
+ void (*start)(struct met_pmu *pmu, int count);
+ void (*stop)(int count);
+ unsigned int (*polling)(struct met_pmu *pmu, int count, unsigned int *pmu_value);
+ unsigned long (*perf_event_get_evttype)(struct perf_event *ev);
+ u32 (*pmu_read_clear_overflow_flag)(void);
+ struct met_pmu *pmu[MXNR_CPU];
+ int event_count[MXNR_CPU];
+ /*
+ * used for compensation of pmu counter loss
+ * between end of polling and start of cpu pm
+ */
+ unsigned int cpu_pm_unpolled_loss[MXNR_CPU][MXNR_PMU_EVENTS];
+};
+
+struct pmu_desc {
+ unsigned int event;
+ char name[MXSIZE_PMU_DESC];
+};
+
+typedef enum {
+ SET_PMU_EVT_CNT = 0x0,
+ SET_PMU_CYCCNT_ENABLE = 0x1,
+ SET_PMU_BASE_OFFSET = 0x02
+} PMU_IPI_Type;
+
+struct cpu_pmu_hw *cpu_pmu_hw_init(void);
+
+extern struct cpu_pmu_hw *cpu_pmu;
+extern noinline void mp_cpu(unsigned char cnt, unsigned int *value);
+
+extern int met_perf_cpupmu_status;
+extern void met_perf_cpupmu_polling(unsigned long long stamp, int cpu);
+
+#endif /* _CPU_PMU_H_ */
diff --git a/src/devtools/met_drv_v2/common/dummy_header.c b/src/devtools/met_drv_v2/common/dummy_header.c
new file mode 100644
index 0000000..c09e378
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/dummy_header.c
@@ -0,0 +1,100 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+
+#include "interface.h"
+#include "met_drv.h"
+
+static struct kobject *kobj_met_dummy;
+static char header_str[PAGE_SIZE];
+static int header_str_len;
+struct metdevice met_dummy_header;
+
+static ssize_t dummy_str_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+static ssize_t dummy_str_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n);
+static struct kobj_attribute dummy_attr = __ATTR(dummy_str, 0664, dummy_str_show, dummy_str_store);
+
+
+static ssize_t dummy_str_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int ret;
+
+ ret = snprintf(buf, PAGE_SIZE, "%s", header_str);
+
+ return ret;
+}
+
+static ssize_t dummy_str_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n)
+{
+ int ret = 0;
+ char *ptr = header_str;
+
+ if ((header_str_len + strlen(buf)) < PAGE_SIZE) {
+ ret = snprintf(ptr + header_str_len, PAGE_SIZE - header_str_len, "%s\n", buf);
+ header_str_len += ret;
+ }
+ met_dummy_header.mode = 1;
+
+ return n;
+}
+
+static int dummy_reset(void)
+{
+ met_dummy_header.mode = 0;
+ memset(header_str, 0x00, PAGE_SIZE);
+ header_str_len = 0;
+
+ return 0;
+}
+
+static int dummy_print_header(char *buf, int len)
+{
+ if (header_str_len > 0)
+ len = snprintf(buf, PAGE_SIZE, "%s", header_str);
+ else
+ len = snprintf(buf, PAGE_SIZE, "# dummy header is empty\n");
+
+ return len;
+}
+
+static int dummy_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ kobj_met_dummy = parent;
+ ret = sysfs_create_file(kobj_met_dummy, &dummy_attr.attr);
+ if (ret != 0) {
+ pr_debug("Failed to create montype0 in sysfs\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void dummy_delete(void)
+{
+ sysfs_remove_file(kobj_met_dummy, &dummy_attr.attr);
+ kobj_met_dummy = NULL;
+}
+
+struct metdevice met_dummy_header = {
+ .name = "dummy_header",
+ .type = MET_TYPE_MISC,
+ .cpu_related = 0,
+ .start = NULL,
+ .stop = NULL,
+ .reset = dummy_reset,
+ .polling_interval = 0,
+ .timed_polling = NULL,
+ .print_help = NULL,
+ .print_header = dummy_print_header,
+ .create_subfs = dummy_create,
+ .delete_subfs = dummy_delete,
+};
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3/met_emi.c b/src/devtools/met_drv_v2/common/emi/SEDA3/met_emi.c
new file mode 100644
index 0000000..ad8b411
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3/met_emi.c
@@ -0,0 +1,1048 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/string.h>
+
+#if IS_ENABLED(CONFIG_ARM)
+//#include <asm/dma-mapping.h> /* arm_coherent_dma_ops */
+#endif /* CONFIG_ARM */
+
+#include <linux/dma-mapping.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "core_plf_init.h"
+/* #include "plf_trace.h" */
+#include "mtk_emi_bm.h"
+#include "interface.h"
+#include "met_dramc.h"
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#elif defined(TINYSYS_SSPM_SUPPORT)
+#include "tinysys_sspm.h"
+#include "tinysys_mgr.h" /* for ondiemet_module */
+#endif
+#endif
+
+
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+int emi_TP_busfiltr_enable;
+int emi_tsct_enable = 1;
+int emi_mdct_enable = 1;
+
+static int bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+
+static int msel_enable;
+static unsigned int msel_group1 = _GP_1_Default;
+static unsigned int msel_group2 = _GP_2_Default;
+static unsigned int msel_group3 = _GP_3_Default;
+
+/* Global variables */
+static struct kobject *kobj_emi;
+
+static int ttype1_16_en = BM_TTYPE1_16_DISABLE;
+static int ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+static int dramc_pdir_enable = 1;
+static int dram_chann_num = 1;
+
+static int times;
+static ssize_t test_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ int i;
+ unsigned int *src_addr_v = NULL;
+ dma_addr_t src_addr_p;
+#if IS_ENABLED(CONFIG_ARM)
+ struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_dma_ops);
+#endif /* CONFIG_ARM */
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+ if (kstrtoint(buf, 10, ×) != 0)
+ return -EINVAL;
+ if (times < 0)
+ return -EINVAL;
+
+ if (times > 5000)
+ return -EINVAL;
+
+#if IS_ENABLED(CONFIG_ARM)
+ if (ops && ops->alloc) {
+ (met_device.this_device)->coherent_dma_mask = DMA_BIT_MASK(32);
+ src_addr_v = ops->alloc(met_device.this_device,
+ PAGE_SIZE,
+ &src_addr_p,
+ GFP_KERNEL,
+ 0);
+ }
+#endif /* CONFIG_ARM */
+
+#if IS_ENABLED(CONFIG_ARM64)
+ /* dma_alloc */
+ src_addr_v = dma_alloc_coherent(met_device.this_device,
+ PAGE_SIZE,
+ &src_addr_p,
+ GFP_KERNEL);
+#endif /* CONFIG_ARM64 */
+
+ if (src_addr_v == NULL) {
+#ifdef CONFIG_MET_MODULE
+ met_tag_oneshot_real(0, "test dma alloc fail", PAGE_SIZE);
+#else
+ met_tag_oneshot(0, "test dma alloc fail", PAGE_SIZE);
+#endif
+ return -ENOMEM;
+ }
+
+ preempt_disable();
+#ifdef CONFIG_MET_MODULE
+ met_tag_start_real(0, "TEST_EMI");
+#else
+ met_tag_start(0, "TEST_EMI");
+#endif
+ for (i = 0; i < times; i++) {
+ memset(src_addr_v, 2*i, PAGE_SIZE);
+#ifdef CONFIG_MET_MODULE
+ met_tag_oneshot_real(0, "TEST_EMI", PAGE_SIZE);
+#else
+ met_tag_oneshot(0, "TEST_EMI", PAGE_SIZE);
+#endif
+ }
+#ifdef CONFIG_MET_MODULE
+ met_tag_end_real(0, "TEST_EMI");
+#else
+ met_tag_end(0, "TEST_EMI");
+#endif
+
+ my_preempt_enable();
+
+#if IS_ENABLED(CONFIG_ARM)
+ /* dma_free */
+ if (ops && ops->free) {
+ ops->free(met_device.this_device,
+ PAGE_SIZE,
+ src_addr_v,
+ src_addr_p,
+ 0);
+ }
+#endif /* CONFIG_ARM */
+
+#if IS_ENABLED(CONFIG_ARM64)
+ /* dma_free */
+ if (src_addr_v != NULL)
+ dma_free_coherent(met_device.this_device,
+ PAGE_SIZE,
+ src_addr_v,
+ src_addr_p);
+#endif /* CONFIG_ARM64 */
+
+ return n;
+}
+
+/*======================================================================*/
+/* KOBJ Declarations */
+/*======================================================================*/
+DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable);
+DECLARE_KOBJ_ATTR_INT(msel_enable, msel_enable);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group1, msel_group1, msel_group1 > 0 && msel_group1 <= _ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group2, msel_group2, msel_group2 > 0 && msel_group2 <= _ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group3, msel_group3, msel_group3 > 0 && msel_group3 <= _ALL);
+
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype1_16_en,
+ KOBJ_ITEM_LIST(
+ { BM_TTYPE1_16_ENABLE, "ENABLE" },
+ { BM_TTYPE1_16_DISABLE, "DISABLE" }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST(ttype1_16_en, ttype1_16_en, ttype1_16_en);
+
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype17_21_en,
+ KOBJ_ITEM_LIST(
+ { BM_TTYPE17_21_ENABLE, "ENABLE" },
+ { BM_TTYPE17_21_DISABLE, "DISABLE" }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST(ttype17_21_en, ttype17_21_en, ttype17_21_en);
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_master,
+ KOBJ_ITEM_LIST(
+ { _M0, "M0" },
+ { _M1, "M1" },
+ { _M2, "M2" },
+ { _M3, "M3" },
+ { _M4, "M4" },
+ { _M5, "M5" },
+ { _M6, "M6" },
+ { _M7, "M7" }
+ )
+ );
+
+
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+ ttype_nbeat,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_1BEAT, 1 },
+ { BM_TRANS_TYPE_2BEAT, 2 },
+ { BM_TRANS_TYPE_3BEAT, 3 },
+ { BM_TRANS_TYPE_4BEAT, 4 },
+ { BM_TRANS_TYPE_5BEAT, 5 },
+ { BM_TRANS_TYPE_6BEAT, 6 },
+ { BM_TRANS_TYPE_7BEAT, 7 },
+ { BM_TRANS_TYPE_8BEAT, 8 },
+ { BM_TRANS_TYPE_9BEAT, 9 },
+ { BM_TRANS_TYPE_10BEAT, 10 },
+ { BM_TRANS_TYPE_11BEAT, 11 },
+ { BM_TRANS_TYPE_12BEAT, 12 },
+ { BM_TRANS_TYPE_13BEAT, 13 },
+ { BM_TRANS_TYPE_14BEAT, 14 },
+ { BM_TRANS_TYPE_15BEAT, 15 },
+ { BM_TRANS_TYPE_16BEAT, 16 }
+ )
+ );
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+ ttype_nbyte,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_1Byte, 1 },
+ { BM_TRANS_TYPE_2Byte, 2 },
+ { BM_TRANS_TYPE_4Byte, 4 },
+ { BM_TRANS_TYPE_8Byte, 8 },
+ { BM_TRANS_TYPE_16Byte, 16 },
+ { BM_TRANS_TYPE_32Byte, 32 }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_burst,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_BURST_INCR, "INCR" },
+ { BM_TRANS_TYPE_BURST_WRAP, "WRAP" }
+ )
+ );
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_rw,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_RW_DEFAULT, "DEFAULT" },
+ { BM_TRANS_RW_READONLY, "R" },
+ { BM_TRANS_RW_WRITEONLY, "W" },
+ { BM_TRANS_RW_RWBOTH, "BOTH" }
+ )
+ );
+
+
+DECLARE_KOBJ_ATTR_SHOW_INT(test, times);
+
+DECLARE_KOBJ_ATTR(test);
+
+
+static int high_priority_filter;
+DECLARE_KOBJ_ATTR_HEX(high_priority_filter, high_priority_filter);
+
+
+static int ttype_master_val[21];
+static int ttype_busid_val[21];
+static int ttype_nbeat_val[21];
+static int ttype_nbyte_val[21];
+static int ttype_burst_val[21];
+static int ttype_rw_val[21];
+
+#define DECLARE_KOBJ_TTYPE_MASTER(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _master, ttype_master_val[nr - 1], ttype_master)
+
+#define DECLARE_KOBJ_TTYPE_NBEAT(nr) \
+ DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbeat, ttype_nbeat_val[nr - 1], ttype_nbeat)
+
+#define DECLARE_KOBJ_TTYPE_NBYTE(nr) \
+ DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbyte, ttype_nbyte_val[nr - 1], ttype_nbyte)
+
+#define DECLARE_KOBJ_TTYPE_BURST(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _burst, ttype_burst_val[nr - 1], ttype_burst)
+
+#define DECLARE_KOBJ_TTYPE_RW(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _rw, ttype_rw_val[nr - 1], ttype_rw)
+
+#define DECLARE_KOBJ_TTYPE_BUSID_VAL(nr) \
+ DECLARE_KOBJ_ATTR_HEX(ttype ## nr ## _busid, ttype_busid_val[nr - 1])
+
+DECLARE_KOBJ_TTYPE_MASTER(1);
+DECLARE_KOBJ_TTYPE_NBEAT(1);
+DECLARE_KOBJ_TTYPE_NBYTE(1);
+DECLARE_KOBJ_TTYPE_BURST(1);
+DECLARE_KOBJ_TTYPE_RW(1);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(1);
+
+DECLARE_KOBJ_TTYPE_MASTER(2);
+DECLARE_KOBJ_TTYPE_NBEAT(2);
+DECLARE_KOBJ_TTYPE_NBYTE(2);
+DECLARE_KOBJ_TTYPE_BURST(2);
+DECLARE_KOBJ_TTYPE_RW(2);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(2);
+
+DECLARE_KOBJ_TTYPE_MASTER(3);
+DECLARE_KOBJ_TTYPE_NBEAT(3);
+DECLARE_KOBJ_TTYPE_NBYTE(3);
+DECLARE_KOBJ_TTYPE_BURST(3);
+DECLARE_KOBJ_TTYPE_RW(3);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(3);
+
+DECLARE_KOBJ_TTYPE_MASTER(4);
+DECLARE_KOBJ_TTYPE_NBEAT(4);
+DECLARE_KOBJ_TTYPE_NBYTE(4);
+DECLARE_KOBJ_TTYPE_BURST(4);
+DECLARE_KOBJ_TTYPE_RW(4);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(4);
+
+DECLARE_KOBJ_TTYPE_MASTER(5);
+DECLARE_KOBJ_TTYPE_NBEAT(5);
+DECLARE_KOBJ_TTYPE_NBYTE(5);
+DECLARE_KOBJ_TTYPE_BURST(5);
+DECLARE_KOBJ_TTYPE_RW(5);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(5);
+
+DECLARE_KOBJ_TTYPE_MASTER(6);
+DECLARE_KOBJ_TTYPE_NBEAT(6);
+DECLARE_KOBJ_TTYPE_NBYTE(6);
+DECLARE_KOBJ_TTYPE_BURST(6);
+DECLARE_KOBJ_TTYPE_RW(6);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(6);
+
+DECLARE_KOBJ_TTYPE_MASTER(7);
+DECLARE_KOBJ_TTYPE_NBEAT(7);
+DECLARE_KOBJ_TTYPE_NBYTE(7);
+DECLARE_KOBJ_TTYPE_BURST(7);
+DECLARE_KOBJ_TTYPE_RW(7);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(7);
+
+DECLARE_KOBJ_TTYPE_MASTER(8);
+DECLARE_KOBJ_TTYPE_NBEAT(8);
+DECLARE_KOBJ_TTYPE_NBYTE(8);
+DECLARE_KOBJ_TTYPE_BURST(8);
+DECLARE_KOBJ_TTYPE_RW(8);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(8);
+
+DECLARE_KOBJ_TTYPE_MASTER(9);
+DECLARE_KOBJ_TTYPE_NBEAT(9);
+DECLARE_KOBJ_TTYPE_NBYTE(9);
+DECLARE_KOBJ_TTYPE_BURST(9);
+DECLARE_KOBJ_TTYPE_RW(9);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(9);
+
+DECLARE_KOBJ_TTYPE_MASTER(10);
+DECLARE_KOBJ_TTYPE_NBEAT(10);
+DECLARE_KOBJ_TTYPE_NBYTE(10);
+DECLARE_KOBJ_TTYPE_BURST(10);
+DECLARE_KOBJ_TTYPE_RW(10);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(10);
+
+DECLARE_KOBJ_TTYPE_MASTER(11);
+DECLARE_KOBJ_TTYPE_NBEAT(11);
+DECLARE_KOBJ_TTYPE_NBYTE(11);
+DECLARE_KOBJ_TTYPE_BURST(11);
+DECLARE_KOBJ_TTYPE_RW(11);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(11);
+
+DECLARE_KOBJ_TTYPE_MASTER(12);
+DECLARE_KOBJ_TTYPE_NBEAT(12);
+DECLARE_KOBJ_TTYPE_NBYTE(12);
+DECLARE_KOBJ_TTYPE_BURST(12);
+DECLARE_KOBJ_TTYPE_RW(12);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(12);
+
+DECLARE_KOBJ_TTYPE_MASTER(13);
+DECLARE_KOBJ_TTYPE_NBEAT(13);
+DECLARE_KOBJ_TTYPE_NBYTE(13);
+DECLARE_KOBJ_TTYPE_BURST(13);
+DECLARE_KOBJ_TTYPE_RW(13);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(13);
+
+DECLARE_KOBJ_TTYPE_MASTER(14);
+DECLARE_KOBJ_TTYPE_NBEAT(14);
+DECLARE_KOBJ_TTYPE_NBYTE(14);
+DECLARE_KOBJ_TTYPE_BURST(14);
+DECLARE_KOBJ_TTYPE_RW(14);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(14);
+
+DECLARE_KOBJ_TTYPE_MASTER(15);
+DECLARE_KOBJ_TTYPE_NBEAT(15);
+DECLARE_KOBJ_TTYPE_NBYTE(15);
+DECLARE_KOBJ_TTYPE_BURST(15);
+DECLARE_KOBJ_TTYPE_RW(15);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(15);
+
+DECLARE_KOBJ_TTYPE_MASTER(16);
+DECLARE_KOBJ_TTYPE_NBEAT(16);
+DECLARE_KOBJ_TTYPE_NBYTE(16);
+DECLARE_KOBJ_TTYPE_BURST(16);
+DECLARE_KOBJ_TTYPE_RW(16);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(16);
+
+DECLARE_KOBJ_TTYPE_MASTER(17);
+DECLARE_KOBJ_TTYPE_NBEAT(17);
+DECLARE_KOBJ_TTYPE_NBYTE(17);
+DECLARE_KOBJ_TTYPE_BURST(17);
+DECLARE_KOBJ_TTYPE_RW(17);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(17);
+
+DECLARE_KOBJ_TTYPE_MASTER(18);
+DECLARE_KOBJ_TTYPE_NBEAT(18);
+DECLARE_KOBJ_TTYPE_NBYTE(18);
+DECLARE_KOBJ_TTYPE_BURST(18);
+DECLARE_KOBJ_TTYPE_RW(18);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(18);
+
+DECLARE_KOBJ_TTYPE_MASTER(19);
+DECLARE_KOBJ_TTYPE_NBEAT(19);
+DECLARE_KOBJ_TTYPE_NBYTE(19);
+DECLARE_KOBJ_TTYPE_BURST(19);
+DECLARE_KOBJ_TTYPE_RW(19);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(19);
+
+DECLARE_KOBJ_TTYPE_MASTER(20);
+DECLARE_KOBJ_TTYPE_NBEAT(20);
+DECLARE_KOBJ_TTYPE_NBYTE(20);
+DECLARE_KOBJ_TTYPE_BURST(20);
+DECLARE_KOBJ_TTYPE_RW(20);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(20);
+
+DECLARE_KOBJ_TTYPE_MASTER(21);
+DECLARE_KOBJ_TTYPE_NBEAT(21);
+DECLARE_KOBJ_TTYPE_NBYTE(21);
+DECLARE_KOBJ_TTYPE_BURST(21);
+DECLARE_KOBJ_TTYPE_RW(21);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(21);
+
+#define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \
+ do { \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _master); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _nbeat); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _nbyte); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _burst); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _busid); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _rw); \
+ } while (0)
+
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(high_priority_filter); \
+ KOBJ_ATTR_ITEM(emi_TP_busfiltr_enable); \
+ KOBJ_ATTR_ITEM(msel_enable); \
+ KOBJ_ATTR_ITEM(msel_group1); \
+ KOBJ_ATTR_ITEM(msel_group2); \
+ KOBJ_ATTR_ITEM(msel_group3); \
+ KOBJ_ATTR_ITEM(ttype17_21_en); \
+ KOBJ_ATTR_ITEM(ttype1_16_en); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(1); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(2); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(3); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(4); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(5); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(6); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(7); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(8); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(9); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(10); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(11); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(12); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(13); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(14); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(15); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(16); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(17); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(18); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(19); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(20); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(21); \
+ KOBJ_ATTR_ITEM(test); \
+ } while (0)
+
+/*======================================================================*/
+/* EMI Operations */
+/*======================================================================*/
+static void emi_init(void)
+{
+ unsigned int bmrw0_val = 0, bmrw1_val = 0, i, enable;
+ unsigned int msel_group_val[4];
+
+ MET_BM_SaveCfg();
+
+ /* get dram channel number */
+ dram_chann_num = MET_EMI_GetDramChannNum();
+
+ if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+ if (msel_enable) {
+ msel_group_val[0] = _ALL;
+ msel_group_val[1] = msel_group1;
+ msel_group_val[2] = msel_group2;
+ msel_group_val[3] = msel_group3;
+ } else {
+ msel_group_val[0] = _ALL;
+ msel_group_val[1] = _ALL;
+ msel_group_val[2] = _ALL;
+ msel_group_val[3] = _ALL;
+ }
+
+ MET_BM_SetLatencyCounter(1);
+
+ for (i = 1; i <= 4; i++) {
+ MET_BM_SetMonitorCounter(i,
+ msel_group_val[i - 1] & _ALL,
+ BM_TRANS_TYPE_4BEAT |
+ BM_TRANS_TYPE_8Byte |
+ BM_TRANS_TYPE_BURST_WRAP);
+ MET_BM_SetbusID(i, 0);
+ MET_BM_SetbusID_En(i, 0);
+ }
+ for (i = 0; i < 4; i++)
+ MET_BM_Set_WsctTsct_id_sel(i, 0);
+
+ } else if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable == 1)) {
+ MET_BM_SetLatencyCounter(1);
+
+ for (i = 1; i <= 4; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+ MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+ MET_BM_SetbusID_En(i, 0);
+ }
+ for (i = 0; i < 4; i++)
+ MET_BM_Set_WsctTsct_id_sel(i, 1);
+
+ } else if ((ttype1_16_en == BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+ MET_BM_SetLatencyCounter(0);
+
+ for (i = 1; i <= 16; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+
+ MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+
+ MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+ }
+ for (i = 0; i < 4; i++)
+ MET_BM_Set_WsctTsct_id_sel(i, 0);
+ } else { /* (ttype1_16_en == BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable == 1) */
+
+ MET_BM_SetLatencyCounter(0);
+
+ for (i = 1; i <= 16; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+
+ MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+
+ MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+ }
+ for (i = 0; i < 4; i++)
+ MET_BM_Set_WsctTsct_id_sel(i, 1);
+ }
+
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+ for (i = 17; i <= 21; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+ MET_BM_SetbusID(i, ttype_busid_val[i - 1]);
+
+ MET_BM_SetbusID_En(i, (ttype_busid_val[i - 1] > 0xffff) ? 0 : 1);
+ }
+ }
+
+ bmrw0_val = (
+ (ttype_rw_val[0] << 0) | (ttype_rw_val[1] << 2) |
+ (ttype_rw_val[2] << 4) | (ttype_rw_val[3] << 6) |
+ (ttype_rw_val[4] << 8) | (ttype_rw_val[5] << 10) |
+ (ttype_rw_val[6] << 12) | (ttype_rw_val[7] << 14) |
+ (ttype_rw_val[8] << 16) | (ttype_rw_val[9] << 18) |
+ (ttype_rw_val[10] << 20) | (ttype_rw_val[11] << 22) |
+ (ttype_rw_val[12] << 24) | (ttype_rw_val[13] << 26) |
+ (ttype_rw_val[14] << 28) | (ttype_rw_val[15] << 30));
+
+ bmrw1_val = (
+ (ttype_rw_val[16] << 0) | (ttype_rw_val[17] << 2) |
+ (ttype_rw_val[18] << 4) | (ttype_rw_val[19] << 6) |
+ (ttype_rw_val[20] << 8));
+
+ MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+ for (i = 0; i < BM_COUNTER_MAX; i++) {
+ if ((high_priority_filter & (1 << i)) == 0)
+ enable = 0;
+ else
+ enable = 1;
+
+ MET_BM_SetUltraHighFilter(i + 1, enable);
+ }
+
+}
+
+static inline int do_emi(void)
+{
+ return met_sspm_emi.mode;
+}
+
+/*======================================================================*/
+/* MET Device Operations */
+/*======================================================================*/
+static int emi_inited;
+static int met_emi_create(struct kobject *parent)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < 21; i++) {
+ ttype_master_val[i] = _M0;
+ ttype_nbeat_val[i] = BM_TRANS_TYPE_1BEAT;
+ ttype_nbyte_val[i] = BM_TRANS_TYPE_8Byte;
+ ttype_burst_val[i] = BM_TRANS_TYPE_BURST_INCR;
+ ttype_busid_val[i] = 0xfffff;
+ ttype_rw_val[i] = BM_TRANS_RW_DEFAULT;
+ }
+ ret = MET_BM_Init();
+ if (ret != 0) {
+ pr_debug("MET_BM_Init failed!!!\n");
+ ret = 0;
+ } else
+ emi_inited = 1;
+
+ kobj_emi = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+do { \
+ ret = sysfs_create_file(kobj_emi, &attr_name##_attr.attr); \
+ if (ret != 0) { \
+ pr_debug("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+} while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+ return ret;
+}
+
+static void met_emi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_emi, &attr_name##_attr.attr)
+ if (kobj_emi != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_emi = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+
+ if (emi_inited)
+ MET_BM_DeInit();
+}
+
+
+static void met_emi_resume(void)
+{
+ if (!do_emi())
+ return;
+
+ emi_init();
+}
+
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+static const char help[] = " --emi monitor EMI banwidth\n";
+
+#define TTYPE_NAME_STR_LEN 64
+/* static char ttype_name[21][TTYPE_NAME_STR_LEN]; */
+
+static int emi_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static int emi_print_header(char *buf, int len)
+{
+ int ret = 0;
+/* int ret_m[21]; */
+ int i = 0;
+ unsigned int dram_data_rate_MHz;
+ unsigned int DRAM_TYPE;
+
+ if ((ttype1_16_en != BM_TTYPE1_16_ENABLE) && (emi_TP_busfiltr_enable != 1)) {
+ if (msel_enable) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+ msel_group1 & _ALL,
+ msel_group2 & _ALL,
+ msel_group3 & _ALL);
+ } else {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+ _ALL & _ALL,
+ _ALL & _ALL,
+ _ALL & _ALL);
+ }
+ } else {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_emi_ttype_master: %x,%x,%x,%x\n",
+ ttype_master_val[0], ttype_master_val[1], ttype_master_val[2], ttype_master_val[3]);
+
+ if (emi_TP_busfiltr_enable == 1) {
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_emi_ttype_busid: %x,%x,%x,%x\n",
+ ttype_busid_val[0], ttype_busid_val[1], ttype_busid_val[2], ttype_busid_val[3]);
+ }
+ }
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_rw_cfg: ");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "BOTH");
+
+ for (i = 0; i < 21; i++) {
+ if (ttype_rw_val[i] == BM_TRANS_RW_DEFAULT)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, ",DEFAULT");
+ else if (ttype_rw_val[i] == BM_TRANS_RW_READONLY)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, ",R");
+ else if (ttype_rw_val[i] == BM_TRANS_RW_WRITEONLY)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, ",W");
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, ",BOTH");
+ }
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_emi_ultra_filter: %x\n", high_priority_filter);
+
+ /* ttype header */
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+ int i = 0;
+ int j = 0;
+
+ /* ttype master list */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_master_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+ if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_master_list_item[j].val);
+ }
+ }
+ }
+ /* remove the last comma */
+ snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+ /* ttype busid list */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_busid_list: ");
+ for (i = 0; i < 21; i++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%x,", ttype_busid_val[i]);
+
+ snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+ /* ttype nbeat list */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbeat_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_nbeat_list_item); j++) {
+ if (ttype_nbeat_val[i] == ttype_nbeat_list_item[j].key) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbeat_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+ /* ttype nbyte list */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_nbyte_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_nbyte_list_item); j++) {
+ if (ttype_nbyte_val[i] == ttype_nbyte_list_item[j].key) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d,", ttype_nbyte_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+ /* ttype burst list */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_burst_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_burst_list_item); j++) {
+ if (ttype_burst_val[i] == ttype_burst_list_item[j].key) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", ttype_burst_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, PAGE_SIZE - ret + 1, "\n");
+
+ /* ttype enable */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_emi_ttype_enable: %d,%d\n",ttype1_16_en, ttype17_21_en);
+ }
+ /*IP version*/
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: DRAMC_VER: %d\n", DRAMC_VER);
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: EMI_VER: %d.%d\n", EMI_VER_MAJOR, EMI_VER_MINOR);
+#if 1 /* move to AP side print header */
+//#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT
+ dram_chann_num = MET_EMI_GetDramChannNum();
+ /* met_dram_chann_num_header
+ * channel number
+ * LP4: 2, LP3: 1
+ */
+
+ /*
+ * the ddr type define :
+ * enum DDRTYPE {
+ * TYPE_LPDDR3 = 1,
+ * TYPE_LPDDR4,
+ * TYPE_LPDDR4X,
+ * TYPE_LPDDR2
+ * };
+ */
+ if (mtk_dramc_get_ddr_type_symbol) {
+ DRAM_TYPE = mtk_dramc_get_ddr_type_symbol();
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_type: %d\n", DRAM_TYPE);
+
+ if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, DRAM_EMI_BASECLOCK_RATE_LP4,
+ DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, DRAM_EMI_BASECLOCK_RATE_LP3,
+ DRAM_IO_BUS_WIDTH_LP3, DRAM_DATARATE);
+ } else
+ METERROR("[%s][%d]mtk_dramc_get_ddr_type_symbol = NULL , use the TYPE_LPDDR3 setting\n", __func__, __LINE__);
+
+
+ /* met_emi_clockrate */
+ if (mtk_dramc_get_data_rate_symbol) {
+ dram_data_rate_MHz = mtk_dramc_get_data_rate_symbol();
+ } else {
+ METERROR("mtk_dramc_get_data_rate_symbol = NULL\n");
+ dram_data_rate_MHz = 0;
+ }
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_dram_clockrate: %d\n",
+ dram_data_rate_MHz);
+
+ /*dram bank num*/
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_dram_rank_num_header: %u,%u\n", MET_EMI_GetDramRankNum(),
+ MET_EMI_GetDramRankNum());
+#if 0
+ /* ms_emi header */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "# ms_emi: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+ for (i = 0; i < dram_chann_num; i++) {
+ if (i != 0)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ ",");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "read_bytes_%d,write_bytes_%d", i, i);
+ }
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+#endif
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_emi_header: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+ for (i = 0; i < dram_chann_num; i++) {
+ if (i != 0)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ ",");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "read_bytes_%d,write_bytes_%d", i, i);
+ }
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+ /*TSCT header*/
+ if (emi_tsct_enable == 1) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: ms_emi_tsct_header: ms_emi_tsct,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "tsct1,tsct2,tsct3\n");
+ }
+
+ /*MDCT header*/
+ if (emi_mdct_enable == 1) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: ms_emi_mdct_header: ms_emi_mdct,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "RD_ULTRA,RD_MDMCU\n");
+ }
+
+ /* met_bw_limiter_header */
+ if (bw_limiter_enable == BM_BW_LIMITER_ENABLE) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_bw_limiter_header: CLK,");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "ARBA,ARBB,ARBC,ARBD,ARBE,ARBF,ARBG,ARBH,BWCT0,BWCT1,BWCT2,BWCT3,BWCT4,BWST0,BWST1,BWCT0_2ND,BWCT1_2ND,BWST_2ND\n");
+ }
+
+ /* DRAM DVFS header */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: DRAM_DVFS_header: datarate(MHz)\n");
+
+ /*PDIR met_dramc_header*/
+ if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 ) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: met_dramc_header: ");
+ for (i = 0; i < dram_chann_num; i++) {
+ if (i != 0)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ ",");
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "freerun_26m_%d,", i);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "rk0_pre_sb_%d,rk0_pre_pd_%d,rk0_act_sb_%d,rk0_act_pd_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "rk1_pre_sb_%d,rk1_pre_pd_%d,rk1_act_sb_%d,rk1_act_pd_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "rk2_pre_sb_%d,rk2_pre_pd_%d,rk2_act_sb_%d,rk2_act_pd_%d", i, i, i, i);
+ }
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+ }
+
+ /* DRS header */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "met-info [000] 0.0: emi_drs_header: ch0_RANK1_GP(%%),ch0_RANK1_SF(%%),ch0_ALL_SF(%%),ch1_RANK1_GP(%%),ch1_RANK1_SF(%%),ch1_ALL_SF(%%)\n");
+#endif
+ return ret;
+}
+
+static int ondiemet_emi_print_header(char *buf, int len)
+{
+ return emi_print_header(buf, len);
+}
+
+static void MET_BM_IPI_REGISTER_CB(void)
+{
+ int ret, i;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_REGISTER_CB;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+static void MET_BM_IPI_configs(void)
+{
+ int ret, i;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_EBM_CONFIGS1;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+static void ondiemet_emi_start(void)
+{
+ MET_BM_IPI_REGISTER_CB();
+ if (!emi_inited) {
+ if (MET_BM_Init() != 0) {
+ met_sspm_emi.mode = 0;
+ pr_notice("MET_BM_Init failed!!!\n");
+ return;
+ }
+ emi_inited = 1;
+ }
+ MET_BM_IPI_configs();
+
+ if (do_emi())
+ emi_init();
+
+ ondiemet_module[ONDIEMET_SSPM] |= ID_EMI;
+}
+
+static void emi_uninit(void)
+{
+ MET_BM_RestoreCfg();
+}
+
+static void ondiemet_emi_stop(void)
+{
+ if (!emi_inited)
+ return;
+
+ if (do_emi())
+ emi_uninit();
+}
+#endif /* end of #if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT) */
+#endif /* end of #if defined(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) */
+
+struct metdevice met_sspm_emi = {
+ .name = "emi",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_emi_create,
+ .delete_subfs = met_emi_delete,
+ .resume = met_emi_resume,
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ .ondiemet_start = ondiemet_emi_start,
+ .ondiemet_stop = ondiemet_emi_stop,
+ .ondiemet_print_help = emi_print_help,
+ .ondiemet_print_header = ondiemet_emi_print_header,
+#endif
+#endif
+ .ondiemet_mode = 1,
+};
+EXPORT_SYMBOL(met_sspm_emi);
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3/mtk_emi_bm.c b/src/devtools/met_drv_v2/common/emi/SEDA3/mtk_emi_bm.c
new file mode 100644
index 0000000..924d118
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3/mtk_emi_bm.c
@@ -0,0 +1,342 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <asm/io.h>
+
+#ifdef USE_KERNEL_SYNC_WRITE_H
+#include <mt-plat/sync_write.h>
+#else
+#include "sync_write.h"
+#endif
+
+#ifdef USE_KERNEL_MTK_IO_H
+#include <mt-plat/mtk_io.h>
+#else
+#include "mtk_io.h"
+#endif
+
+/* #include "mtk_typedefs.h" */
+#include "core_plf_init.h"
+#include "mtk_emi_bm.h"
+#include "met_drv.h"
+#include "interface.h"
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#elif defined(TINYSYS_SSPM_SUPPORT)
+#include "tinysys_sspm.h"
+#include "tinysys_mgr.h" /* for ondiemet_module */
+#endif
+#endif
+
+#undef DEBUG
+
+#define emi_readl readl
+#define emi_reg_sync_writel mt_reg_sync_writel
+
+#define MASK_MASTER 0xFF
+#define MASK_TRANS_TYPE 0xFF
+
+static void __iomem *BaseAddrEMI;
+const unsigned int emi_config[] = {
+ EMI_BMEN,
+ EMI_MSEL,
+ EMI_MSEL2,
+ EMI_MSEL3,
+ EMI_MSEL4,
+ EMI_MSEL5,
+ EMI_MSEL6,
+ EMI_MSEL7,
+ EMI_MSEL8,
+ EMI_MSEL9,
+ EMI_MSEL10,
+ EMI_BMID0,
+ EMI_BMID1,
+ EMI_BMID2,
+ EMI_BMID3,
+ EMI_BMID4,
+ EMI_BMID5,
+ EMI_BMID6,
+ EMI_BMID7,
+ EMI_BMID8,
+ EMI_BMID9,
+ EMI_BMID10,
+ EMI_BMEN1,
+ EMI_BMEN2,
+ EMI_BMRW0,
+ EMI_BMRW1
+};
+#define EMI_CONFIG_MX_NR (sizeof(emi_config)/sizeof(unsigned int))
+static unsigned int emi_config_val[EMI_CONFIG_MX_NR];
+
+int MET_BM_Init(void)
+{
+ /*emi*/
+ if (mt_cen_emi_base_get_symbol) {
+ BaseAddrEMI = mt_cen_emi_base_get_symbol();
+ } else {
+ pr_debug("mt_cen_emi_base_get_symbol = NULL\n");
+ PR_BOOTMSG_ONCE("mt_cen_emi_base_get_symbol = NULL\n");
+ BaseAddrEMI = 0;
+ }
+
+ if (BaseAddrEMI == 0) {
+ pr_debug("BaseAddrEMI = 0\n");
+ PR_BOOTMSG_ONCE("BaseAddrEMI = 0\n");
+ return -1;
+ }
+ pr_debug("MET EMI: map emi to %p\n", BaseAddrEMI);
+ PR_BOOTMSG("MET EMI: map emi to %p\n", BaseAddrEMI);
+
+ return 0;
+}
+
+void MET_BM_DeInit(void)
+{
+}
+
+void MET_BM_SaveCfg(void)
+{
+ int i;
+
+ for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+ emi_config_val[i] = emi_readl(IOMEM(ADDR_EMI + emi_config[i]));
+}
+
+void MET_BM_RestoreCfg(void)
+{
+ int i;
+
+ for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+ emi_reg_sync_writel(emi_config_val[i], ADDR_EMI + emi_config[i]);
+}
+
+int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+ const unsigned int master, const unsigned int trans_type)
+{
+ unsigned int value, addr;
+ const unsigned int iMask = (MASK_TRANS_TYPE << 8) | MASK_MASTER;
+
+ if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+ return BM_ERR_WRONG_REQ;
+
+
+ if (counter_num == 1) {
+ addr = EMI_BMEN;
+ value = (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) |
+ ((trans_type & MASK_TRANS_TYPE) << 24) | ((master & MASK_MASTER) << 16);
+ } else {
+ addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+
+ value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+
+ value |= (((trans_type & MASK_TRANS_TYPE) << 8) |
+ (master & MASK_MASTER)) << ((counter_num % 2) * 16);
+ }
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val)
+{
+
+ unsigned int value_origin;
+
+ value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+ MET_TRACE("[MET_EMI_settype1] value_origin: %x\n", value_origin);
+ if (value_origin != bmrw0_val) {
+ emi_reg_sync_writel(bmrw0_val, ADDR_EMI + EMI_BMRW0);
+ MET_TRACE("[MET_EMI_settype1] bmrw0_val: %x, value_origin: %x\n", bmrw0_val,
+ value_origin);
+ }
+
+ value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW1));
+ MET_TRACE("[MET_EMI_settype2] value_origin: %x\n", value_origin);
+ if (value_origin != bmrw1_val) {
+ emi_reg_sync_writel(bmrw1_val, ADDR_EMI + EMI_BMRW1);
+ MET_TRACE("[MET_EMI_settype2] bmrw0_val: %x, value_origin: %x\n", bmrw1_val,
+ value_origin);
+
+ }
+ return BM_REQ_OK;
+}
+
+int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable)
+{
+ unsigned int value;
+
+ if (counter_num > 3)
+ return BM_ERR_WRONG_REQ;
+
+ value =
+ ((emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & (~(1 << (28 + counter_num)))) |
+ (enable << (28 + counter_num)));
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetbusID_En(const unsigned int counter_num,
+ const unsigned int enable)
+{
+ unsigned int value;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+ return BM_ERR_WRONG_REQ;
+
+ if (enable == 0) {
+
+ value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+ & ~(1 << (counter_num - 1)));
+ } else {
+
+ value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+ | (1 << (counter_num - 1)));
+ }
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetbusID(const unsigned int counter_num,
+ const unsigned int id)
+{
+ unsigned int value, addr, shift_num;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX))
+ return BM_ERR_WRONG_REQ;
+
+
+ addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
+ shift_num = ((counter_num - 1) % 2) * 16;
+
+ value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(EMI_BMID_MASK << shift_num);
+
+
+ if (id <= 0xffff)
+ value |= id << shift_num;
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable)
+{
+ unsigned int value;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+ return BM_ERR_WRONG_REQ;
+
+
+ value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN1))
+ & ~(1 << (counter_num - 1)))
+ | (enable << (counter_num - 1));
+
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN1);
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetLatencyCounter(unsigned int enable)
+{
+ unsigned int value;
+
+ value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & ~(0x3 << 24);
+ if (enable == 1)
+ value |= (0x2 << 24);
+
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+ return BM_REQ_OK;
+}
+
+unsigned int MET_EMI_GetDramChannNum(void)
+{
+ int num = -1;
+
+ if (BaseAddrEMI) {
+ num = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+ num = ((num >> 8) & 0x0000003);
+ } else {
+ return 1;
+ }
+
+ if (num == M0_DOUBLE_HALF_BW_1CH)
+ return 1;
+ else if (num == M0_DOUBLE_HALF_BW_2CH)
+ return 2;
+ else if (num == M0_DOUBLE_HALF_BW_4CH)
+ return 4;
+ else /* default return single channel */
+ return 1;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum(void)
+{
+ int dual_rank = 0;
+
+ if (BaseAddrEMI) {
+ dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+ dual_rank = ((dual_rank >> 17) & RANK_MASK);
+ } else {
+ return DUAL_RANK;
+ }
+
+ if (dual_rank == DISABLE_DUAL_RANK_MODE)
+ return ONE_RANK;
+ else /* default return dual rank */
+ return DUAL_RANK;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum_CHN1(void)
+{
+ int dual_rank = 0;
+
+ if (BaseAddrEMI) {
+ dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+ dual_rank = ((dual_rank >> 16) & RANK_MASK);
+ } else {
+ return DUAL_RANK;
+ }
+
+ if (dual_rank == DISABLE_DUAL_RANK_MODE)
+ return ONE_RANK;
+ else /* default return dual rank */
+ return DUAL_RANK;
+}
+
+unsigned int MET_EMI_Get_BaseClock_Rate(void)
+{
+ unsigned int DRAM_TYPE;
+
+ if (get_cur_ddr_ratio_symbol)
+ return get_cur_ddr_ratio_symbol();
+ else {
+
+ if (mtk_dramc_get_ddr_type_symbol) {
+ DRAM_TYPE = mtk_dramc_get_ddr_type_symbol();
+
+ if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+ return DRAM_EMI_BASECLOCK_RATE_LP4;
+ else
+ return DRAM_EMI_BASECLOCK_RATE_LP3;
+
+ } else {
+ return DRAM_EMI_BASECLOCK_RATE_LP4;
+ }
+ }
+}
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3/mtk_emi_bm.h b/src/devtools/met_drv_v2/common/emi/SEDA3/mtk_emi_bm.h
new file mode 100644
index 0000000..4e8baf6
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3/mtk_emi_bm.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+
+#ifndef __MT_MET_EMI_BM_H__
+#define __MT_MET_EMI_BM_H__
+
+#define EMI_VER_MAJOR 3
+#define EMI_VER_MINOR 0
+
+
+#define DRAM_EMI_BASECLOCK_RATE_LP4 4
+#define DRAM_EMI_BASECLOCK_RATE_LP3 2
+
+#define DRAM_IO_BUS_WIDTH_LP4 16
+#define DRAM_IO_BUS_WIDTH_LP3 32
+
+#define DRAM_DATARATE 2
+
+#define ADDR_EMI ((unsigned long) BaseAddrEMI)
+
+/*========================================================*/
+/*EMI configuration by project*/
+/*Change config start*/
+/*========================================================*/
+#define _GP_1_Default (_M0 | _M1)
+#define _GP_2_Default (_M2 | _M5)
+#define _GP_3_Default (_M6 | _M7)
+
+
+/*========================================================*/
+/*Change config end*/
+/*========================================================*/
+
+
+#define _M0 (0x01)
+#define _M1 (0x02)
+#define _M2 (0x04)
+#define _M3 (0x08)
+#define _M4 (0x10)
+#define _M5 (0x20)
+#define _M6 (0x40)
+#define _M7 (0x80)
+#define _ALL (0xFF)
+
+enum BM_RW_Type {
+ BM_BOTH_READ_WRITE,
+ BM_READ_ONLY,
+ BM_WRITE_ONLY
+};
+
+enum {
+ BM_TRANS_TYPE_1BEAT = 0x0,
+ BM_TRANS_TYPE_2BEAT,
+ BM_TRANS_TYPE_3BEAT,
+ BM_TRANS_TYPE_4BEAT,
+ BM_TRANS_TYPE_5BEAT,
+ BM_TRANS_TYPE_6BEAT,
+ BM_TRANS_TYPE_7BEAT,
+ BM_TRANS_TYPE_8BEAT,
+ BM_TRANS_TYPE_9BEAT,
+ BM_TRANS_TYPE_10BEAT,
+ BM_TRANS_TYPE_11BEAT,
+ BM_TRANS_TYPE_12BEAT,
+ BM_TRANS_TYPE_13BEAT,
+ BM_TRANS_TYPE_14BEAT,
+ BM_TRANS_TYPE_15BEAT,
+ BM_TRANS_TYPE_16BEAT,
+ BM_TRANS_TYPE_1Byte = 0 << 4,
+ BM_TRANS_TYPE_2Byte = 1 << 4,
+ BM_TRANS_TYPE_4Byte = 2 << 4,
+ BM_TRANS_TYPE_8Byte = 3 << 4,
+ BM_TRANS_TYPE_16Byte = 4 << 4,
+ BM_TRANS_TYPE_32Byte = 5 << 4,
+ BM_TRANS_TYPE_BURST_WRAP = 0 << 7,
+ BM_TRANS_TYPE_BURST_INCR = 1 << 7
+};
+
+enum {
+ BM_TRANS_RW_DEFAULT = 0x0,
+ BM_TRANS_RW_READONLY,
+ BM_TRANS_RW_WRITEONLY,
+ BM_TRANS_RW_RWBOTH
+};
+
+
+#define EMI_BMID_MASK (0xFFFF)
+#define BM_COUNTER_MAX (21)
+
+#define BM_REQ_OK (0)
+#define BM_ERR_WRONG_REQ (-1)
+#define BM_ERR_OVERRUN (-2)
+
+#define BM_TTYPE1_16_ENABLE (0)
+#define BM_TTYPE1_16_DISABLE (-1)
+#define BM_TTYPE17_21_ENABLE (0)
+#define BM_TTYPE17_21_DISABLE (-1)
+
+#define BM_BW_LIMITER_ENABLE (0)
+#define BM_BW_LIMITER_DISABLE (-1)
+
+#define M0_DOUBLE_HALF_BW_1CH (0x0)
+#define M0_DOUBLE_HALF_BW_2CH (0x1)
+#define M0_DOUBLE_HALF_BW_4CH (0x2)
+
+/* EMI Rank configuration */
+enum {
+ DISABLE_DUAL_RANK_MODE = 0,
+ ENABLE_DUAL_RANK_MODE,
+};
+
+#define RANK_MASK 0x1
+#define ONE_RANK 1
+#define DUAL_RANK 2
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+enum BM_EMI_IPI_Type {
+ SET_BASE_EMI = 0x0,
+ SET_EBM_CONFIGS1 = 0x7,
+ SET_EBM_CONFIGS2 = 0x8,
+ SET_REGISTER_CB = 0x9,
+};
+#endif
+#endif
+
+#define EMI_OFF 0x0000
+#define EMI_CONA (0x000-EMI_OFF)
+#define EMI_BMEN (0x400-EMI_OFF)
+#define EMI_MSEL (0x440-EMI_OFF)
+#define EMI_MSEL2 (0x468-EMI_OFF)
+#define EMI_MSEL3 (0x470-EMI_OFF)
+#define EMI_MSEL4 (0x478-EMI_OFF)
+#define EMI_MSEL5 (0x480-EMI_OFF)
+#define EMI_MSEL6 (0x488-EMI_OFF)
+#define EMI_MSEL7 (0x490-EMI_OFF)
+#define EMI_MSEL8 (0x498-EMI_OFF)
+#define EMI_MSEL9 (0x4A0-EMI_OFF)
+#define EMI_MSEL10 (0x4A8-EMI_OFF)
+
+#define EMI_BMID0 (0x4B0-EMI_OFF)
+#define EMI_BMID1 (0x4B4-EMI_OFF)
+#define EMI_BMID2 (0x4B8-EMI_OFF)
+#define EMI_BMID3 (0x4BC-EMI_OFF)
+#define EMI_BMID4 (0x4C0-EMI_OFF)
+#define EMI_BMID5 (0x4C4-EMI_OFF)
+#define EMI_BMID6 (0x4C8-EMI_OFF)
+#define EMI_BMID7 (0x4CC-EMI_OFF)
+#define EMI_BMID8 (0x4D0-EMI_OFF)
+#define EMI_BMID9 (0x4D4-EMI_OFF)
+#define EMI_BMID10 (0x4D8-EMI_OFF)
+
+#define EMI_BMEN1 (0x4E0-EMI_OFF)
+#define EMI_BMEN2 (0x4E8-EMI_OFF)
+#define EMI_BMRW0 (0x4F8-EMI_OFF)
+#define EMI_BMRW1 (0x4FC-EMI_OFF)
+
+
+extern unsigned int MET_EMI_GetDramRankNum(void);
+extern unsigned int MET_EMI_GetDramRankNum_CHN1(void);
+
+
+unsigned int MET_EMI_GetDramChannNum(void);
+
+extern int MET_BM_Init(void);
+extern void MET_BM_DeInit(void);
+extern void MET_BM_SaveCfg(void);
+extern void MET_BM_RestoreCfg(void);
+extern int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+ const unsigned int master, const unsigned int trans_type);
+extern int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val);
+extern int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable);
+extern int MET_BM_SetbusID_En(const unsigned int counter_num,
+ const unsigned int enable);
+extern int MET_BM_SetbusID(const unsigned int counter_num,
+ const unsigned int id);
+extern int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable);
+extern int MET_BM_SetLatencyCounter(unsigned int enable);
+extern unsigned int MET_EMI_Get_BaseClock_Rate(void);
+#endif /* !__MT_MET_EMI_BM_H__ */
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3_5/met_emi.c b/src/devtools/met_drv_v2/common/emi/SEDA3_5/met_emi.c
new file mode 100644
index 0000000..c0d78cf
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3_5/met_emi.c
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "core_plf_init.h"
+#include "mtk_emi_bm_function.h"
+#include "interface.h"
+#include "met_dramc.h"
+
+
+/*======================================================================*/
+/* MET Device Operations */
+/*======================================================================*/
+
+static int met_emi_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ ret = met_emi_create_basic(parent, &met_sspm_emi);
+ return ret;
+}
+
+static void met_emi_delete(void)
+{
+ met_emi_delete_basic();
+}
+
+static void met_emi_resume(void)
+{
+ met_emi_resume_basic();
+}
+
+static int emi_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, emi_help_msg);
+}
+
+static int emi_print_header(char *buf, int len)
+{
+ len = emi_print_header_basic(buf,len);
+ return len;
+}
+
+static int ondiemet_emi_print_header(char *buf, int len)
+{
+ return emi_print_header(buf, len);
+}
+
+static void ondiemet_emi_start(void)
+{
+ ondiemet_emi_start_basic();
+}
+
+static void ondiemet_emi_stop(void)
+{
+ ondiemet_emi_stop_basic();
+}
+
+
+struct metdevice met_sspm_emi = {
+ .name = "emi",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_emi_create,
+ .delete_subfs = met_emi_delete,
+ .resume = met_emi_resume,
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ .ondiemet_start = ondiemet_emi_start,
+ .ondiemet_stop = ondiemet_emi_stop,
+ .ondiemet_print_help = emi_print_help,
+ .ondiemet_print_header = ondiemet_emi_print_header,
+#endif
+#endif
+ .ondiemet_mode = 1,
+};
+EXPORT_SYMBOL(met_sspm_emi);
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm.c b/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm.c
new file mode 100644
index 0000000..53133fb
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm.c
@@ -0,0 +1,3261 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#ifdef USE_KERNEL_SYNC_WRITE_H
+#include <mt-plat/sync_write.h>
+#else
+#include "sync_write.h"
+#endif
+
+#ifdef USE_KERNEL_MTK_IO_H
+#include <mt-plat/mtk_io.h>
+#else
+#include "mtk_io.h"
+#endif
+
+#include "mtk_typedefs.h"
+#include "core_plf_init.h"
+#include "mtk_emi_bm.h"
+#include "mtk_emi_bm_function.h"
+
+#include "met_drv.h"
+#include "interface.h"
+
+#include "met_dramc.h"
+#include "met_reg_addr.h"
+
+#undef DEBUG
+#undef debug_reg
+#ifdef debug_reg
+static inline unsigned int emi_readl(void __iomem *padr)
+{
+ unsigned int tmp;
+
+ tmp = readl(padr);
+ MET_TRACE("[MET_EMI] RD_Reg: %p: %08x\n", padr, tmp);
+ return tmp;
+}
+
+static inline void __emi_reg_sync_writel(unsigned int data, void __iomem *padr)
+{
+ unsigned int tmp;
+
+ mt_reg_sync_writel(data, padr);
+ tmp = readl(padr);
+ MET_TRACE("[MET_EMI] WR_Reg: %p: %08x, %08x\n", padr, data, tmp);
+}
+
+#define emi_reg_sync_writel(data, adr) __emi_reg_sync_writel(data, IOMEM(adr))
+
+#else
+#define emi_readl readl
+#define emi_reg_sync_writel mt_reg_sync_writel
+#endif
+
+
+
+
+void __iomem *BaseAddrEMI;
+void __iomem *BaseAddrCHN_EMI[2];
+
+
+#define CH0_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[0]) + 0x284)
+#define CH1_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[1]) + 0x284)
+const unsigned int emi_config[] = {
+ EMI_BMEN,
+ EMI_MSEL,
+ EMI_MSEL2,
+ EMI_MSEL3,
+ EMI_MSEL4,
+ EMI_MSEL5,
+ EMI_MSEL6,
+ EMI_MSEL7,
+ EMI_MSEL8,
+ EMI_MSEL9,
+ EMI_MSEL10,
+ EMI_BMID0,
+ EMI_BMID1,
+ EMI_BMID2,
+ EMI_BMID3,
+ EMI_BMID4,
+ EMI_BMID5,
+ EMI_BMID6,
+ EMI_BMID7,
+ EMI_BMID8,
+ EMI_BMID9,
+ EMI_BMID10,
+ EMI_BMEN1,
+ EMI_BMEN2,
+ EMI_BMRW0,
+ EMI_BMRW1,
+ EMI_DBWA,
+ EMI_DBWB,
+ EMI_DBWC,
+ EMI_DBWD,
+ EMI_DBWE,
+ EMI_DBWF,
+ EMI_DBWI,
+ EMI_DBWJ,
+ EMI_DBWK,
+ EMI_DBWA_2ND,
+ EMI_DBWB_2ND,
+ EMI_DBWC_2ND,
+ EMI_DBWD_2ND,
+ EMI_DBWE_2ND,
+ EMI_DBWF_2ND,
+ EMI_TTYPE1_CONA,
+ EMI_TTYPE1_CONB,
+ EMI_TTYPE2_CONA,
+ EMI_TTYPE2_CONB,
+ EMI_TTYPE3_CONA,
+ EMI_TTYPE3_CONB,
+ EMI_TTYPE4_CONA,
+ EMI_TTYPE4_CONB,
+ EMI_TTYPE5_CONA,
+ EMI_TTYPE5_CONB,
+ EMI_TTYPE6_CONA,
+ EMI_TTYPE6_CONB,
+ EMI_TTYPE7_CONA,
+ EMI_TTYPE7_CONB,
+ EMI_TTYPE8_CONA,
+ EMI_TTYPE8_CONB,
+ EMI_TTYPE9_CONA,
+ EMI_TTYPE9_CONB,
+ EMI_TTYPE10_CONA,
+ EMI_TTYPE10_CONB,
+ EMI_TTYPE11_CONA,
+ EMI_TTYPE11_CONB,
+ EMI_TTYPE12_CONA,
+ EMI_TTYPE12_CONB,
+ EMI_TTYPE13_CONA,
+ EMI_TTYPE13_CONB,
+ EMI_TTYPE14_CONA,
+ EMI_TTYPE14_CONB,
+ EMI_TTYPE15_CONA,
+ EMI_TTYPE15_CONB,
+ EMI_TTYPE16_CONA,
+ EMI_TTYPE16_CONB,
+ EMI_TTYPE17_CONA,
+ EMI_TTYPE17_CONB,
+ EMI_TTYPE18_CONA,
+ EMI_TTYPE18_CONB,
+ EMI_TTYPE19_CONA,
+ EMI_TTYPE19_CONB,
+ EMI_TTYPE20_CONA,
+ EMI_TTYPE20_CONB,
+ EMI_TTYPE21_CONA,
+ EMI_TTYPE21_CONB
+};
+#define EMI_CONFIG_MX_NR (sizeof(emi_config)/sizeof(unsigned int))
+static unsigned int emi_config_val[EMI_CONFIG_MX_NR];
+
+const unsigned int emi_chn_config[] = {
+ CHN_EMI_LOWEFF_CTL0
+};
+#define EMI_CHN_CONFIG_MX_NR (sizeof(emi_chn_config)/sizeof(unsigned int))
+static unsigned int emi_chn_config_val[MET_MAX_DRAM_CH_NUM][EMI_CHN_CONFIG_MX_NR];
+
+enum MET_EMI_DEFAULT_VAL_LIST{
+ e_MET_DRAM_FREQ = 0,
+ e_MET_DRAM_TYPE,
+ e_MET_DDR_RATIO,
+
+ NR_MET_DEFAULT_VAL,
+};
+
+unsigned int met_emi_default_val[NR_MET_DEFAULT_VAL];
+
+
+/* get the emi base addr */
+int MET_BM_Init(void)
+{
+ int i;
+ /*emi*/
+#ifndef EMI_REG_BASE
+ if (mt_cen_emi_base_get_symbol) {
+ BaseAddrEMI = mt_cen_emi_base_get_symbol();
+ } else {
+ METERROR("mt_cen_emi_base_get_symbol = NULL, use the pre-define addr to mmap\n");
+ PR_BOOTMSG_ONCE("mt_cen_emi_base_get_symbol = NULL, use the pre-define addr to mmap\n");
+ BaseAddrEMI = 0;
+ }
+#else
+ BaseAddrEMI = ioremap(EMI_REG_BASE, EMI_REG_SIZE);
+#endif
+
+ if (BaseAddrEMI == 0) {
+ METERROR("BaseAddrEMI = 0\n");
+ PR_BOOTMSG_ONCE("BaseAddrEMI = 0\n");
+ return -1;
+ }
+ pr_debug("MET EMI: map emi to %p\n", BaseAddrEMI);
+ PR_BOOTMSG("MET EMI: map emi to %p\n", BaseAddrEMI);
+
+ /* emi channel */
+ dram_chann_num = MET_EMI_GetDramChannNum();
+
+#ifndef EMI_CHN_BASE
+ if (!mt_chn_emi_base_get_symbol) {
+ for(i=0; i<dram_chann_num; i++) {
+ BaseAddrCHN_EMI[i] = mt_chn_emi_base_get_symbol(i);
+
+ if (BaseAddrCHN_EMI[i] == 0) {
+ METERROR("BaseAddrCHN_EMI[%d] = 0\n", i);
+ PR_BOOTMSG_ONCE("BaseAddrCHN_EMI[%d] = 0\n", i);
+ return -1;
+ }
+ METINFO("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+ PR_BOOTMSG("MET EMI: map BaseAddrCHN_EMI[%d] to %p\n", idx, BaseAddrCHN_EMI[idx]);
+ }
+ }
+#else
+ for(i=0; i<dram_chann_num; i++) {
+ BaseAddrCHN_EMI[i] = ioremap(EMI_CHN_BASE(i), EMI_CH_REG_SIZE);
+ if (BaseAddrCHN_EMI[i] == 0) {
+ METERROR("BaseAddrCHN_EMI[%d] = 0\n", i);
+ PR_BOOTMSG_ONCE("ioremap EMI_CHN_BASE(i) to BaseAddrCHN_EMI[%d] = 0\n", i);
+ return -1;
+ }
+ }
+#endif
+ /* set the init value */
+ met_emi_default_val[e_MET_DRAM_FREQ] = DRAM_FREQ_DEFAULT;
+ met_emi_default_val[e_MET_DRAM_TYPE] = DRAM_TYPE_DEFAULT;
+ met_emi_default_val[e_MET_DDR_RATIO] = DDR_RATIO_DEFAULT;
+
+
+ return 0;
+}
+
+
+void MET_BM_DeInit(void)
+{
+}
+
+void MET_BM_SaveCfg(void)
+{
+ int i;
+
+ /* emi central */
+ for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+ emi_config_val[i] = emi_readl(IOMEM(ADDR_EMI + emi_config[i]));
+
+ /* emi channel */
+#if 0
+ for (j = 0; j < dram_chann_num; j++) {
+ for (i = 0; i < EMI_CHN_CONFIG_MX_NR; i++) {
+ // emi_reg_sync_writel(emi_chn_config_val[j][i], BaseAddrCHN_EMI[j] + emi_chn_config[i]);
+ emi_chn_config_val[j][i] = emi_readl(IOMEM(BaseAddrCHN_EMI[j] + emi_chn_config[i]));
+ }
+ }
+#else
+ /*only ch0 have CHN_EMI_LOWEFF_CTL0 now*/
+ for (i = 0; i < EMI_CHN_CONFIG_MX_NR; i++) {
+ emi_chn_config_val[0][i] = emi_readl(IOMEM(BaseAddrCHN_EMI[0] + emi_chn_config[i]));
+ }
+#endif
+}
+
+void MET_BM_RestoreCfg(void)
+{
+ int i;
+
+ /* emi central */
+ for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+ emi_reg_sync_writel(emi_config_val[i], ADDR_EMI + emi_config[i]);
+
+ /* emi channel */
+#if 0
+ for (j = 0; j < dram_chann_num; j++) {
+ for (i = 0; i < EMI_CHN_CONFIG_MX_NR; i++) {
+ emi_reg_sync_writel(emi_chn_config_val[j][i], BaseAddrCHN_EMI[j] + emi_chn_config[i]);
+ }
+ }
+#else
+ for (i = 0; i < EMI_CHN_CONFIG_MX_NR; i++) {
+ emi_reg_sync_writel(emi_chn_config_val[0][i], BaseAddrCHN_EMI[0] + emi_chn_config[i]);
+ }
+#endif
+}
+
+void MET_BM_SetReadWriteType(const unsigned int ReadWriteType)
+{
+ const unsigned int value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN));
+
+ /*
+ * ReadWriteType: 00/11 --> both R/W
+ * 01 --> only R
+ * 10 --> only W
+ */
+ emi_reg_sync_writel((value & 0xFFFFFFCF) | (ReadWriteType << 4), ADDR_EMI + EMI_BMEN);
+}
+
+int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+ const unsigned int master, const unsigned int trans_type)
+{
+ unsigned int value, addr;
+ const unsigned int iMask = (MASK_TRANS_TYPE << 8) | MASK_MASTER;
+
+ if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+ return BM_ERR_WRONG_REQ;
+
+
+ if (counter_num == 1) {
+ addr = EMI_BMEN;
+ value = (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) |
+ ((trans_type & MASK_TRANS_TYPE) << 24) | ((master & MASK_MASTER) << 16);
+ } else {
+ addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+ /* clear master and transaction type fields */
+ value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+ /* set master and transaction type fields */
+ value |= (((trans_type & MASK_TRANS_TYPE) << 8) |
+ (master & MASK_MASTER)) << ((counter_num % 2) * 16);
+ }
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val)
+{
+
+ unsigned int value_origin;
+
+ value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW0));
+ MET_TRACE("[MET_EMI_settype1] value_origin: %x\n", value_origin);
+ if (value_origin != bmrw0_val) {
+ emi_reg_sync_writel(bmrw0_val, ADDR_EMI + EMI_BMRW0);
+ MET_TRACE("[MET_EMI_settype1] bmrw0_val: %x, value_origin: %x\n", bmrw0_val,
+ value_origin);
+ }
+
+
+ value_origin = emi_readl(IOMEM(ADDR_EMI + EMI_BMRW1));
+ MET_TRACE("[MET_EMI_settype2] value_origin: %x\n", value_origin);
+ if (value_origin != bmrw1_val) {
+ emi_reg_sync_writel(bmrw1_val, ADDR_EMI + EMI_BMRW1);
+ MET_TRACE("[MET_EMI_settype2] bmrw0_val: %x, value_origin: %x\n", bmrw1_val,
+ value_origin);
+
+ }
+ return BM_REQ_OK;
+}
+
+int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable)
+{
+ unsigned int value;
+
+ if (counter_num > 3)
+ return BM_ERR_WRONG_REQ;
+
+ value =
+ ((emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & (~(1 << (28 + counter_num)))) |
+ (enable << (28 + counter_num)));
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master)
+{
+ unsigned int value, addr;
+ const unsigned int iMask = 0x7F;
+
+ if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+ return BM_ERR_WRONG_REQ;
+
+
+ if (counter_num == 1) {
+ addr = EMI_BMEN;
+ value =
+ (emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << 16)) | ((master & iMask) << 16);
+ } else {
+ addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+ /* clear master and transaction type fields */
+ value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+ /* set master and transaction type fields */
+ value |= ((master & iMask) << ((counter_num % 2) * 16));
+ }
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID_En(const unsigned int counter_num,
+ const unsigned int enable)
+{
+ unsigned int value;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+ return BM_ERR_WRONG_REQ;
+
+ if (enable == 0) {
+ /* clear EMI ID selection Enabling SEL_ID_EN */
+ value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+ & ~(1 << (counter_num - 1)));
+ } else {
+ /* enable EMI ID selection Enabling SEL_ID_EN */
+ value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2))
+ | (1 << (counter_num - 1)));
+ }
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID(const unsigned int counter_num,
+ const unsigned int id)
+{
+ unsigned int value, addr, shift_num;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX))
+ return BM_ERR_WRONG_REQ;
+
+ /* offset of EMI_BMIDx register */
+ addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
+ shift_num = ((counter_num - 1) % 2) * 16;
+ /* clear SELx_ID field */
+ value = emi_readl(IOMEM(ADDR_EMI + addr)) & ~(EMI_BMID_MASK << shift_num);
+
+ /* set SELx_ID field */
+ if (id <= 0xffff) /*bigger then 0xff_ff : no select busid in master, reset busid as 0*/
+ value |= id << shift_num;
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable)
+{
+ unsigned int value;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+ return BM_ERR_WRONG_REQ;
+
+
+ value = (emi_readl(IOMEM(ADDR_EMI + EMI_BMEN1))
+ & ~(1 << (counter_num - 1)))
+ | (enable << (counter_num - 1));
+
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN1);
+
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetLatencyCounter(unsigned int enable)
+{
+ unsigned int value;
+
+ value = emi_readl(IOMEM(ADDR_EMI + EMI_BMEN2)) & ~(0x3 << 24);
+ /*
+ * emi_ttype1 -- emi_ttype8 change as total latencies
+ * for m0 -- m7,
+ * and emi_ttype9 -- emi_ttype16 change as total transaction counts
+ * for m0 -- m7
+ */
+ if (enable == 1)
+ value |= (0x2 << 24);
+
+ emi_reg_sync_writel(value, ADDR_EMI + EMI_BMEN2);
+
+ return BM_REQ_OK;
+}
+
+
+
+unsigned int MET_EMI_GetDramChannNum(void)
+{
+ int num = -1;
+
+ if (BaseAddrEMI) {
+ num = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+ num = ((num >> 8) & 0x0000003);
+ } else {
+ return 1;
+ }
+
+ if (num == M0_DOUBLE_HALF_BW_1CH)
+ return 1;
+ else if (num == M0_DOUBLE_HALF_BW_2CH)
+ return 2;
+ else if (num == M0_DOUBLE_HALF_BW_4CH)
+ return 4;
+ else /* default return single channel */
+ return 1;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum(void)
+{
+ int dual_rank = 0;
+
+ if (BaseAddrEMI) {
+ dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+ dual_rank = ((dual_rank >> 17) & RANK_MASK);
+ } else {
+ return DUAL_RANK;
+ }
+
+ if (dual_rank == DISABLE_DUAL_RANK_MODE)
+ return ONE_RANK;
+ else /* default return dual rank */
+ return DUAL_RANK;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum_CHN1(void)
+{
+ int dual_rank = 0;
+
+ if (BaseAddrEMI) {
+ dual_rank = emi_readl(IOMEM(ADDR_EMI + EMI_CONA));
+ dual_rank = ((dual_rank >> 16) & RANK_MASK);
+ } else {
+ return DUAL_RANK;
+ }
+
+ if (dual_rank == DISABLE_DUAL_RANK_MODE)
+ return ONE_RANK;
+ else /* default return dual rank */
+ return DUAL_RANK;
+}
+
+
+#ifdef EMI_LOWEFF_SUPPORT
+int MET_EMI_Get_LOWEFF_CTL0(int channel){
+
+ if ( (channel<0) || (channel>=MET_MAX_DRAM_CH_NUM))
+ return 0;
+
+ if (BaseAddrCHN_EMI[channel]) {
+ return emi_readl(IOMEM(BaseAddrCHN_EMI[channel] + CHN_EMI_LOWEFF_CTL0));
+ } else {
+ return 0;
+ }
+}
+
+int MET_BM_SetLOWEFF_master_rw(unsigned chan, unsigned int *wmask_msel , unsigned int *ageexp_msel, unsigned int *ageexp_rw)
+{
+ unsigned int value;
+
+ const unsigned int Mask_master = 0xFF;
+ const unsigned int offset_wmask_master= 16;
+ const unsigned int offset_ageexp_master= 24;
+
+ const unsigned int Mask_rw = 0x3;
+ const unsigned int offset_rw = 3;
+
+ if ( (chan < 0) || (chan >= MET_MAX_DRAM_CH_NUM))
+ return -1;
+
+ if (BaseAddrCHN_EMI[chan]) {
+ value = emi_readl(IOMEM(BaseAddrCHN_EMI[chan] + CHN_EMI_LOWEFF_CTL0));
+
+ /* wmask msel */
+ value = (value & ~(Mask_master << offset_wmask_master)) | ((*(wmask_msel + chan) & Mask_master) << offset_wmask_master);
+ /* age msel */
+ value = (value & ~(Mask_master << offset_ageexp_master)) | ((*(ageexp_msel + chan) & Mask_master) << offset_ageexp_master);
+ /* age rw */
+ value = (value & ~(Mask_rw << offset_rw)) | ((*(ageexp_rw + chan) & Mask_rw) << offset_rw);
+
+ emi_reg_sync_writel(value, BaseAddrCHN_EMI[chan] + CHN_EMI_LOWEFF_CTL0);
+ } else {
+ return -1;
+ }
+ return BM_REQ_OK;
+}
+
+#endif
+
+/* For SEDA3.5 wsct setting*/
+/* EMI_DBWX[15:8], X=A~F (SEL_MASTER) */
+/* RW: EMI_DBWX[1:0], X=A~F */
+int MET_BM_SetWSCT_master_rw(unsigned int *master , unsigned int *rw)
+{
+ unsigned int value, addr;
+ int i;
+
+ const unsigned int Mask_master = 0xFF;
+ const unsigned int offset_master = 8;
+
+ const unsigned int Mask_rw = 0x3;
+ const unsigned int offset_rw = 0;
+
+ for (i=0; i<WSCT_AMOUNT; i++) {
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_master << offset_master)) | ((*(master+i) & Mask_master) << offset_master);
+ value = (value & ~(Mask_rw << offset_rw)) | ((*(rw+i) & Mask_rw) << offset_rw);
+
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+ }
+
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetWSCT_high_priority(unsigned int *disable, unsigned int *select)
+{
+ unsigned int value, addr;
+ int i;
+
+ const unsigned int Mask_disable = 0x1;
+ const unsigned int offset_disable = 2;
+
+ const unsigned int Mask_select = 0xF;
+ const unsigned int offset_select = 28;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+ value = (value & ~(Mask_disable << offset_disable)) | ((*(disable+i) & Mask_disable) << offset_disable);
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ /* ultra level setting */
+ addr = EMI_DBWA_2ND + i*4;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+ value = (value & ~(Mask_select << offset_select)) | ((*(select+i) & Mask_select) << offset_select);
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+ }
+ return BM_REQ_OK;
+}
+
+/* busid enbale: EMI_DBWX[3], X=A~F */
+/* busid sel: EMI_DBWX[28:16], X=A~F (SEL_ID_TMP) */
+/* busid mask : EMI_DBWY[12:0] ??EMI_DBWY[28:16], Y=I~K (SEL_ID_MSK) */
+int MET_BM_SetWSCT_busid_idmask(unsigned int *busid, unsigned int *idMask)
+{
+ unsigned int value, addr;
+ unsigned int enable_tmp, busid_tmp, idmask_tmp;
+ int i;
+
+ const unsigned int Mask_busid = 0xFFFF;
+ const unsigned int offset_busid = 16;
+
+ const unsigned int Mask_enable = 0x1;
+ const unsigned int offset_enable = 3;
+
+ const unsigned int Mask_idMask = 0xFFFF;
+ const unsigned int offset_idMask_even = 0;
+ const unsigned int offset_idMask_odd = 16;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+
+ /*enable, SEL_ID_TMP*/
+ if (*(busid+i)>0xffff) {
+ enable_tmp = 0;
+ busid_tmp = 0xFFFF;
+ idmask_tmp = 0xFFFF;
+ }
+ else {
+ enable_tmp = 1;
+ busid_tmp = *(busid+i) & Mask_busid;
+ idmask_tmp = *(idMask+i) & Mask_idMask;
+ }
+
+
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_busid << offset_busid)) | (busid_tmp << offset_busid);
+ value = (value & ~(Mask_enable << offset_enable)) | (enable_tmp << offset_enable);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ /*SEL_ID_MSK*/
+ addr = EMI_DBWI + (i/2)*4;
+
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ if (i%2==0)
+ value = (value & ~(Mask_idMask << offset_idMask_even)) | (idmask_tmp << offset_idMask_even);
+ else
+ value = (value & ~(Mask_idMask << offset_idMask_odd)) | (idmask_tmp << offset_idMask_odd);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+ }
+
+
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetWSCT_chn_rank_sel(unsigned int *chn_rank_sel)
+{
+ unsigned int value, addr;
+ int i;
+
+ const unsigned int Mask = 0xF;
+ const unsigned int offset = 12;
+
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ addr = EMI_DBWA_2ND + i*4;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask << offset)) | ((*(chn_rank_sel+i) & Mask) << offset);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+ }
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetWSCT_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd)
+{
+ unsigned int value, addr;
+ int i;
+
+ const unsigned int Mask_dis = 0x1, Mask_low_bnd = 0x1FF, Mask_up_bnd = 0x1FF;
+ const unsigned int offset_dis = 4, offset_low_bnd = 16 , offset_up_bnd = 0 ;
+
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_dis << offset_dis)) | ((*(bnd_dis+i) & Mask_dis) << offset_dis);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+
+ addr = EMI_DBWA_2ND + i*4;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_low_bnd << offset_low_bnd)) | ((*(low_bnd+i) & Mask_low_bnd) << offset_low_bnd);
+ value = (value & ~(Mask_up_bnd << offset_up_bnd)) | ((*(up_bnd+i) & Mask_up_bnd) << offset_up_bnd);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+ }
+ return BM_REQ_OK;
+
+}
+
+int MET_BM_SetTSCT_busid_enable(unsigned int *enable)
+{
+ int i;
+
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ MET_BM_Set_WsctTsct_id_sel(i, *(enable+i));
+ }
+
+ return BM_REQ_OK;
+}
+
+//use the origin together, MET_BM_SetUltraHighFilter()
+/* EMI_TTYPEN_CONA [23:20], N=1~21 (HPRI_SEL) */
+int MET_BM_SetTtype_high_priority_sel(unsigned int _high_priority_filter, unsigned int *select)
+{
+ int i;
+ unsigned int enable;
+ unsigned int value, addr;
+
+ const unsigned int Mask_sel = 0xF;
+ const unsigned int offset_sel = 20;
+
+ for (i = 0; i < BM_COUNTER_MAX; i++) {
+ if ((_high_priority_filter & (1 << i)) == 0){
+ enable = 0;
+ }
+ else {
+ enable = 1;
+ }
+
+ MET_BM_SetUltraHighFilter(i + 1, enable);
+
+ /* ultra level select */
+ addr = EMI_TTYPE1_CONA + i*8;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_sel << offset_sel)) | ((*(select+i) & Mask_sel) << offset_sel);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ }
+
+ return BM_REQ_OK;
+}
+
+
+//always call this API to init the reg
+//related API, MET_BM_SetbusID, MET_BM_SetbusID_En
+int MET_BM_SetTtype_busid_idmask(unsigned int *busid, unsigned int *idMask, int _ttype1_16_en, int _ttype17_21_en)
+{
+ int i;
+ unsigned int value, addr;
+
+ const unsigned int Mask_idMask = 0xFFFF;
+ const unsigned int offset_idMask = 0;
+
+ if (_ttype1_16_en != BM_TTYPE1_16_ENABLE) {
+ /* mask set 0x1FFF , busid set disable*/
+ for (i = 1; i <= 16; i++) {
+ *(busid + i - 1) = 0xfffff;
+ *(idMask + i - 1) = 0xFFFF;
+ }
+ }
+
+ if (_ttype17_21_en != BM_TTYPE17_21_ENABLE) {
+ for (i = 17; i <= 21; i++) {
+ *(busid + i - 1) = 0xfffff;
+ *(idMask + i - 1) = 0xFFFF;
+ }
+ }
+
+ for (i = 1; i <= BM_COUNTER_MAX; i++) {
+ MET_BM_SetbusID(i, *(busid + i - 1));
+ MET_BM_SetbusID_En(i, ( *(busid + i - 1) > 0xffff) ? 0 : 1);
+
+ /* set idMask */
+ addr = EMI_TTYPE1_CONA + (i-1)*8;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_idMask << offset_idMask)) | ((*(idMask+i-1) & Mask_idMask) << offset_idMask);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+ }
+
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetTtype_chn_rank_sel(unsigned int *chn_rank_sel)
+{
+ unsigned int value, addr;
+ int i;
+
+ const unsigned int Mask = 0xF;
+ const unsigned int offset = 16;
+
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ addr = EMI_TTYPE1_CONA + i*8;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask << offset)) | ((*(chn_rank_sel+i) & Mask) << offset);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+ }
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetTtype_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd)
+{
+ unsigned int value, addr;
+ int i;
+
+ const unsigned int Mask_dis = 0x1, Mask_low_bnd = 0x1FF, Mask_up_bnd = 0x1FF;
+ const unsigned int offset_dis = 24, offset_low_bnd = 16 , offset_up_bnd = 0 ;
+
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+
+ /* set dis bit */
+ addr = EMI_TTYPE1_CONA + i*8;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_dis << offset_dis)) | ((*(bnd_dis+i) & Mask_dis) << offset_dis);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+
+
+ addr = EMI_TTYPE1_CONB + i*8;
+ value = emi_readl(IOMEM(ADDR_EMI + addr));
+
+ value = (value & ~(Mask_low_bnd << offset_low_bnd)) | ((*(low_bnd+i) & Mask_low_bnd) << offset_low_bnd);
+ value = (value & ~(Mask_up_bnd << offset_up_bnd)) | ((*(up_bnd+i) & Mask_up_bnd) << offset_up_bnd);
+
+ emi_reg_sync_writel(value, ADDR_EMI + addr);
+ }
+ return BM_REQ_OK;
+}
+
+unsigned int MET_EMI_Get_CONH_2ND(void)
+{
+ return readl(IOMEM(ADDR_EMI + EMI_CONH_2ND));
+}
+
+
+
+/* for file node use*/
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+/*ondiemet emi sampling interval in us */
+int emi_tsct_enable = 1;
+int emi_mdct_enable = 1;
+int emi_TP_busfiltr_enable;
+int mdmcu_sel_enable;
+unsigned int rd_mdmcu_rsv_num = 0x5;
+int metemi_func_opt;
+
+int met_emi_regdump;
+/* Dynamic MonitorCounter selection !!!EXPERIMENT!!! */
+int msel_enable;
+unsigned int msel_group1 = BM_MASTER_ALL;
+unsigned int msel_group2 = BM_MASTER_ALL;
+unsigned int msel_group3 = BM_MASTER_ALL;
+
+
+/* Global variables */
+struct kobject *kobj_emi;
+int rwtype = BM_BOTH_READ_WRITE;
+
+/* BW Limiter */
+/*#define CNT_COUNTDOWN (1000-1)*/ /* 1000 * 1ms = 1sec */
+/* static int countdown; */
+int bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+
+/* TTYPE counter */
+int ttype1_16_en = BM_TTYPE1_16_DISABLE;
+int ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+int dramc_pdir_enable;
+int dram_chann_num = 1;
+
+int ttype_master_val[21];
+int ttype_busid_val[21];
+int ttype_nbeat_val[21];
+int ttype_nbyte_val[21];
+int ttype_burst_val[21];
+int ttype_rw_val[21];
+
+unsigned int msel_group_ext_val[WSCT_AMOUNT];
+unsigned int wsct_rw_val[WSCT_AMOUNT];
+
+char* const delim_comma = ",";
+char* const delim_coclon = ":";
+
+
+char msel_group_ext[FILE_NODE_DATA_LEN] = {'\0'};
+char wsct_rw[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int WSCT_HPRI_DIS[WSCT_AMOUNT];
+unsigned int WSCT_HPRI_SEL[WSCT_AMOUNT];
+char wsct_high_priority_enable[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int wsct_busid_val[WSCT_AMOUNT];
+unsigned int wsct_idMask_val[WSCT_AMOUNT];
+
+char wsct_busid[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int wsct_chn_rank_sel_val[WSCT_AMOUNT];
+char wsct_chn_rank_sel[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int wsct_byte_low_bnd_val[WSCT_AMOUNT];
+unsigned int wsct_byte_up_bnd_val[WSCT_AMOUNT];
+unsigned int wsct_byte_bnd_dis[WSCT_AMOUNT];
+char wsct_burst_range[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int tsct_busid_enable_val[TSCT_AMOUNT];
+char tsct_busid_enable[FILE_NODE_DATA_LEN] = {'\0'};
+
+/* use the origin para high_priority_filter to save the en/dis setting */
+int high_priority_filter;
+unsigned int TTYPE_HPRI_SEL[BM_COUNTER_MAX];
+char ttype_high_priority_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int ttype_idMask_val[BM_COUNTER_MAX];
+char ttype_busid_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int ttype_chn_rank_sel_val[BM_COUNTER_MAX];
+char ttype_chn_rank_sel[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int ttype_byte_low_bnd_val[BM_COUNTER_MAX];
+unsigned int ttype_byte_up_bnd_val[BM_COUNTER_MAX];
+unsigned int ttype_byte_bnd_dis[BM_COUNTER_MAX];
+char ttype_burst_range[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int wmask_msel_val[MET_MAX_DRAM_CH_NUM];
+char wmask_msel[FILE_NODE_DATA_LEN] = {'\0'};
+
+unsigned int ageexp_msel_val[MET_MAX_DRAM_CH_NUM];
+unsigned int ageexp_rw_val[MET_MAX_DRAM_CH_NUM];
+char ageexp_msel_rw[FILE_NODE_DATA_LEN] = {'\0'};
+
+
+int reserve_wsct_setting;
+
+
+char header_str[MAX_HEADER_LEN];
+
+unsigned int output_header_len;
+unsigned int output_str_len;
+
+int emi_use_ondiemet = 0;
+int emi_inited;
+
+
+char default_val[FILE_NODE_DATA_LEN] = {'\0'};
+
+void _clear_default_val(void) {
+ met_emi_default_val[e_MET_DRAM_FREQ] = DRAM_FREQ_DEFAULT;
+ met_emi_default_val[e_MET_DRAM_TYPE] = DRAM_TYPE_DEFAULT;
+ met_emi_default_val[e_MET_DDR_RATIO] = DDR_RATIO_DEFAULT;
+ /*WSCT 4~5 default is ultra, pre-ultra total*/
+ default_val[0] = '\0';
+}
+
+ssize_t default_val_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= default_val;
+ char *_id = NULL, *_value = NULL;
+ int id_int = 0;
+
+ _clear_default_val();
+
+ snprintf(default_val, FILE_NODE_DATA_LEN, "%s", buf);
+ default_val[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:0xff , (ID,master_group)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _value = strsep(&token, delim_coclon);
+
+ // PR_BOOTMSG("_id[%s] _value[%s]\n",_id,_value);
+
+ if (_id == NULL || _value == NULL) {
+ PR_BOOTMSG("err: _id[%s] _value[%s], para can't be NULL\n",_id,_value);
+ _clear_default_val();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to int err\n",_id);
+ _clear_default_val();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < NR_MET_DEFAULT_VAL) {
+ if (kstrtouint(_value, 0, &met_emi_default_val[id_int]) != 0) {
+ PR_BOOTMSG("_value[%s] trans to hex err\n",_value);
+ _clear_default_val();
+ return -EINVAL;
+ }
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, NR_MET_DEFAULT_VAL-1);
+ _clear_default_val();
+ return -EINVAL;
+ }
+ }
+ return n;
+}
+
+ssize_t default_val_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int i;
+ int ret = 0;
+
+ for (i=0; i<NR_MET_DEFAULT_VAL; i++)
+ {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%d:%d \n", i, met_emi_default_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_msel_group_ext(void) {
+ int i;
+
+ for (i=0; i<WSCT_AMOUNT; i++) {
+ msel_group_ext_val[i] = BM_MASTER_ALL;
+ }
+ /*WSCT 4~5 default is ultra, pre-ultra total*/
+ msel_group_ext[0] = '\0';
+}
+
+ssize_t msel_group_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ /*parse wsct_id:group,
+ 1. split data by ","
+ 2. split subdata by ":"
+ 3. check the value is OK
+
+ don't clear the setting, do this by echo 1 > clear_setting
+ */
+
+ char *token, *cur= msel_group_ext;
+ char *_id = NULL, *_master_group = NULL;
+ int id_int = 0;
+
+ _clear_msel_group_ext();
+
+ snprintf(msel_group_ext, FILE_NODE_DATA_LEN, "%s", buf);
+ msel_group_ext[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:0xff , (ID,master_group)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _master_group = strsep(&token, delim_coclon);
+
+ // PR_BOOTMSG("_id[%s] _master_group[%s]\n",_id,_master_group);
+
+ if (_id == NULL || _master_group == NULL) {
+ PR_BOOTMSG("err: _id[%s] _master_group[%s], para can't be NULL\n",_id,_master_group);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ if (kstrtouint(_master_group, 0, &msel_group_ext_val[id_int]) != 0) {
+ PR_BOOTMSG("master_group[%s] trans to hex err\n",_master_group);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",msel_group_ext);
+ /*PR_BOOTMSG("msel_group_ext_store size para n[%d]\n",n);*/
+ int i;
+ PR_BOOTMSG("save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=%X\n",i,msel_group_ext_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t msel_group_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"%d:%X\n", i, msel_group_ext_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_wsct_rw(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_rw_val[i] = BM_WSCT_RW_RWBOTH;
+ }
+ wsct_rw[0] = '\0';
+}
+
+ssize_t wsct_rw_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_rw;
+ char *_id = NULL, *_rw_type = NULL;
+ int id_int = 0;
+
+ _clear_wsct_rw();
+
+ snprintf(wsct_rw, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_rw[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _rw_type = strsep(&token, delim_coclon);
+
+ if (_id == NULL || _rw_type == NULL) {
+ PR_BOOTMSG("err: _id[%s] _rw_type[%s], para can't be NULL\n",_id, _rw_type);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+
+ PR_BOOTMSG("_id[%s] _rw_type[%s]\n",_id, _rw_type);
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ if ( 0 == strncmp("NONE",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_DISABLE;
+ else if (0 == strncmp("R",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_READONLY;
+ else if (0 == strncmp("W",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_WRITEONLY;
+ else if (0 == strncmp("RW",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_RWBOTH;
+ else {
+ PR_BOOTMSG("_id[%s] has err rwtype[%s]\n", _id, _rw_type);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("wsct_rw_store input data [%s]\n",wsct_rw);
+ int i;
+ PR_BOOTMSG("rwtype save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=%d\n",i,wsct_rw_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t wsct_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"%d:%X\n", i, wsct_rw_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_wsct_high_priority_enable(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ WSCT_HPRI_DIS[i] = 1;
+ WSCT_HPRI_SEL[i] = 0xF;
+ }
+
+ WSCT_HPRI_DIS[4] = 0;
+ WSCT_HPRI_SEL[4] = 0x8; /* ultra */
+
+ WSCT_HPRI_DIS[5] = 0;
+ WSCT_HPRI_SEL[5] = 0x4; /* pre_ultra */
+
+
+ wsct_high_priority_enable[0] = '\0';
+}
+
+ssize_t wsct_high_priority_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_high_priority_enable;
+ char *_id = NULL, *_enable = NULL, *_level = NULL;
+ int id_int = 0, level_int = 0;
+
+ _clear_wsct_high_priority_enable();
+
+ snprintf(wsct_high_priority_enable, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_high_priority_enable[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _enable = strsep(&token, delim_coclon);
+ _level = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _enable[%s] _level[%s]\n",_id, _enable, _level);
+
+ if (_id == NULL || _enable == NULL || _level == NULL ) {
+ PR_BOOTMSG("err : _id[%s] _enable[%s] _level[%s], para can't be NULL\n",_id, _enable, _level);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ if ( 0 == strncmp("disable", _enable, 7)) {
+
+ WSCT_HPRI_DIS[id_int] = 1;
+ WSCT_HPRI_SEL[id_int] = 0xf;
+ } else if ( 0 == strncmp("enable", _enable, 6)) {
+
+ WSCT_HPRI_DIS[id_int] = 0;
+ if (kstrtouint(_level, 0, &level_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans ultraLevel[%s] to hex err\n",_id, _level);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+ WSCT_HPRI_SEL[id_int] = level_int & 0xF;
+ } else {
+ PR_BOOTMSG("_id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",wsct_high_priority_enable);
+ int i;
+ PR_BOOTMSG("wsct_high_priority_enable save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=(%X,%X)\n", i, WSCT_HPRI_DIS[i], WSCT_HPRI_SEL[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t wsct_high_priority_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"%d:%X:%X\n", i, WSCT_HPRI_DIS[i], WSCT_HPRI_SEL[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_wsct_busid(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_busid_val[i] = 0xfffff;
+ wsct_idMask_val[i] = 0xFFFF;
+ }
+ wsct_busid[0] = '\0';
+}
+
+ssize_t wsct_busid_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_busid;
+
+ char *_id = NULL, *_busid = NULL, *_idMask = NULL;
+ int id_int = 0, busid_int = 0, idMask_int = 0;
+
+ _clear_wsct_busid();
+
+ snprintf(wsct_busid, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_busid[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _busid = strsep(&token, delim_coclon);
+ _idMask = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _busid[%s] _idMask[%s]\n",_id, _busid, _idMask);
+
+ if (_id == NULL || _busid == NULL || _idMask == NULL) {
+ PR_BOOTMSG("err: _id[%s] _busid[%s] _idMask[%s] ,parameter can't be NULL\n",_id, _busid, _idMask);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+ if (kstrtouint(_busid, 0, &busid_int) != 0) {
+ PR_BOOTMSG("_busid[%s] trans to hex err\n",_busid);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+ if (kstrtouint(_idMask, 0, &idMask_int) != 0) {
+ PR_BOOTMSG("_idMask[%s] trans to hex err\n",_idMask);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ wsct_busid_val[id_int] = busid_int;
+ wsct_idMask_val[id_int] = idMask_int;
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",wsct_busid);
+ int i;
+ PR_BOOTMSG("wsct_busid save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d](busid,idMask)=(%X,%X)\n", i, wsct_busid_val[i], wsct_idMask_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t wsct_busid_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"%d:%X:%X\n", i, wsct_busid_val[i], wsct_idMask_val[i]);
+ }
+ return strlen(buf);
+}
+
+
+void _clear_wsct_chn_rank_sel(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_chn_rank_sel_val[i] = 0xF;
+ }
+ wsct_chn_rank_sel[0] = '\0';
+}
+
+ssize_t wsct_chn_rank_sel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_chn_rank_sel;
+ char *_id = NULL, *_chn_rank = NULL;
+ int id_int = 0, chn_rank_int = 0;
+
+ _clear_wsct_chn_rank_sel();
+
+ snprintf(wsct_chn_rank_sel, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_chn_rank_sel[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _chn_rank = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _chn_rank[%s]\n",_id, _chn_rank);
+
+ if (_id == NULL || _chn_rank == NULL) {
+ PR_BOOTMSG("err : _id[%s] _chn_rank[%s], para can't be NULL\n",_id, _chn_rank);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+ if (kstrtouint(_chn_rank, 0, &chn_rank_int) != 0) {
+ PR_BOOTMSG("_chn_rank[%s] trans to hex err\n",_id);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ wsct_chn_rank_sel_val[id_int] = chn_rank_int;
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("wsct_chn_rank_sel input data [%s]\n",wsct_chn_rank_sel);
+ int i;
+ PR_BOOTMSG("wsct_chn_rank_sel_val save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=%X\n",i,wsct_chn_rank_sel_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t wsct_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"%d:%X\n", i, wsct_chn_rank_sel_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_wsct_burst_range(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_byte_low_bnd_val[i] = 0x0;
+ wsct_byte_up_bnd_val[i] = 0x1FF;
+ wsct_byte_bnd_dis[i] = 1;
+ }
+ wsct_burst_range[0] = '\0';
+}
+
+ ssize_t wsct_burst_range_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_burst_range;
+ char *_id = NULL, *_low_bnd = NULL, *_up_bnd = NULL;
+ int id_int = 0, low_bnd_int = 0, up_bnd_int = 0;
+
+ _clear_wsct_burst_range();
+
+ snprintf(wsct_burst_range, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_burst_range[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _low_bnd = strsep(&token, delim_coclon);
+ _up_bnd = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _low_bnd[%s] _up_bnd[%s]\n",_id, _low_bnd, _up_bnd);
+
+ if (_id == NULL || _low_bnd == NULL || _up_bnd == NULL) {
+ PR_BOOTMSG("err : _id[%s] _low_bnd[%s] _up_bnd[%s], para can't be NULL\n",_id, _low_bnd, _up_bnd);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_low_bnd, 0, &low_bnd_int) != 0) {
+ PR_BOOTMSG("_low_bnd[%s] trans to hex err\n",_id);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_up_bnd, 0, &up_bnd_int) != 0) {
+ PR_BOOTMSG("_up_bnd[%s] trans to hex err\n",_id);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ wsct_byte_low_bnd_val[id_int] = low_bnd_int;
+ wsct_byte_up_bnd_val[id_int] = up_bnd_int;
+ wsct_byte_bnd_dis[id_int] = 0;
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("wsct_burst_range_store input data [%s]\n",wsct_burst_range);
+ int i;
+ PR_BOOTMSG("wsct_burst_range save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d](low_bnd,up_bnd)=(%X,%X)\n",i,wsct_byte_low_bnd_val[i],wsct_byte_up_bnd_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t wsct_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"%d:%d:%X:%X\n",
+ i, wsct_byte_bnd_dis[i],wsct_byte_low_bnd_val[i], wsct_byte_up_bnd_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_tsct_busid_enable(void) {
+ int i;
+
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ tsct_busid_enable_val[i] = 0;
+ }
+ tsct_busid_enable[0] = '\0';
+}
+
+ssize_t tsct_busid_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= tsct_busid_enable;
+ char *_id = NULL, *_enable = NULL;
+ int id_int = 0;
+
+ _clear_tsct_busid_enable();
+
+ snprintf(tsct_busid_enable, FILE_NODE_DATA_LEN, "%s", buf);
+ tsct_busid_enable[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _enable = strsep(&token, delim_coclon);
+
+
+ PR_BOOTMSG("_id[%s] _enable[%s]\n",_id, _enable);
+
+ if (_id == NULL || _enable == NULL) {
+ PR_BOOTMSG("err : _id[%s] _enable[%s], para can't be NULL\n",_id, _enable);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < TSCT_AMOUNT) {
+ if ( 0 == strncmp("disable", _enable, 7)) {
+ tsct_busid_enable_val[id_int] = 0;
+ } else if ( 0 == strncmp("enable", _enable, 6)) {
+ tsct_busid_enable_val[id_int] = 1;
+ } else {
+ PR_BOOTMSG("_id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, TSCT_AMOUNT-1);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("tsct_busid_enable input data [%s]\n",tsct_busid_enable);
+ int i;
+ PR_BOOTMSG("wsct_high_priority_enable save data\n");
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=(%d)\n", i, tsct_busid_enable_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t tsct_busid_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"%d:%X\n", i, tsct_busid_enable_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_ttype_high_priority_ext(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ TTYPE_HPRI_SEL[i] = 0xf;
+ }
+
+ high_priority_filter = 0x0;
+ ttype_high_priority_ext[0] = '\0';
+}
+
+ssize_t ttype_high_priority_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_high_priority_ext;
+ char *_id = NULL, *_enable = NULL, *_level = NULL;
+ int id_int = 0, level_int = 0;
+
+ _clear_ttype_high_priority_ext();
+
+ snprintf(ttype_high_priority_ext, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_high_priority_ext[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _enable = strsep(&token, delim_coclon);
+ _level = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _enable[%s] _level[%s]\n",_id, _enable, _level);
+
+ if (_id == NULL || _enable == NULL || _level == NULL ) {
+ PR_BOOTMSG("err : _id[%s] _enable[%s] _level[%s], para can't be NULL\n",_id, _enable, _level);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+
+ id_int = id_int - 1;
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ if ( 0 == strncmp("disable", _enable, 7)) {
+
+ high_priority_filter = ( high_priority_filter & ~(1<<id_int) ) | ( 0<<id_int );
+ TTYPE_HPRI_SEL[id_int] = 0xf;
+ } else if ( 0 == strncmp("enable", _enable, 6)) {
+
+ high_priority_filter = ( high_priority_filter & ~(1<<id_int) ) | ( 1<<id_int );
+ if (kstrtouint(_level, 0, &level_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans ultraLevel[%s] to hex err\n",_id, _level);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+ TTYPE_HPRI_SEL[id_int] = level_int & 0xF;
+ } else {
+ PR_BOOTMSG("ttype_high_priority_ext: _id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",ttype_high_priority_ext);
+
+ int i;
+ PR_BOOTMSG("wsct_high_priority_enable save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d]=(%X,%X)\n", i+1, high_priority_filter>>i & 0x1, TTYPE_HPRI_SEL[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t ttype_high_priority_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"id[%d]=(%X,%X)\n", i+1, high_priority_filter>>i & 0x1, TTYPE_HPRI_SEL[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_ttype_busid_ext(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ttype_busid_val[i] = 0xfffff;
+ ttype_idMask_val[i] = 0xFFFF;
+ }
+ ttype_busid_ext[0] = '\0';
+}
+
+/*id: 1~21*/
+ssize_t ttype_busid_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_busid_ext;
+
+ char *_id = NULL, *_busid = NULL, *_idMask = NULL;
+ int id_int = 0, busid_int = 0, idMask_int = 0;
+
+ _clear_ttype_busid_ext();
+
+ snprintf(ttype_busid_ext, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_busid_ext[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _busid = strsep(&token, delim_coclon);
+ _idMask = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _busid[%s] _idMask[%s]\n",_id, _busid, _idMask);
+
+ if (_id == NULL || _busid == NULL || _idMask == NULL) {
+ PR_BOOTMSG("err: ttype_busid_ext _id[%s] _busid[%s] _idMask[%s] ,parameter can't be NULL\n",_id, _busid, _idMask);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+ if (kstrtouint(_busid, 0, &busid_int) != 0) {
+ PR_BOOTMSG("_busid[%s] trans to hex err\n",_busid);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+ if (kstrtouint(_idMask, 0, &idMask_int) != 0) {
+ PR_BOOTMSG("_idMask[%s] trans to hex err\n",_idMask);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+
+ id_int = id_int - 1;
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ ttype_busid_val[id_int] = busid_int;
+ ttype_idMask_val[id_int] = idMask_int;
+
+ } else {
+ PR_BOOTMSG("ttype_busid_ext id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("ttype_busid_ext input data [%s]\n",ttype_busid_ext);
+
+ int i;
+ PR_BOOTMSG("ttype_busid_ext save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d](busid,idMask)=(%X,%X)\n", i+1, ttype_busid_val[i], ttype_idMask_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t ttype_busid_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"id[%d](busid,idMask)=(%X,%X)\n", i+1, ttype_busid_val[i], ttype_idMask_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_ttype_chn_rank_sel(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ttype_chn_rank_sel_val[i] = 0xF;
+ }
+ ttype_chn_rank_sel[0] = '\0';
+}
+
+ssize_t ttype_chn_rank_sel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_chn_rank_sel;
+ char *_id = NULL, *_chn_rank = NULL;
+ int id_int = 0, chn_rank_int = 0;
+
+ _clear_ttype_chn_rank_sel();
+
+ snprintf(ttype_chn_rank_sel, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_chn_rank_sel[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _chn_rank = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _chn_rank[%s]\n",_id, _chn_rank);
+
+ if (_id == NULL || _chn_rank == NULL) {
+ PR_BOOTMSG("err (ttype_chn_rank_sel): _id[%s] _chn_rank[%s], para can't be NULL\n",_id, _chn_rank);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+ if (kstrtouint(_chn_rank, 0, &chn_rank_int) != 0) {
+ PR_BOOTMSG("_chn_rank[%s] trans to hex err\n",_id);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+
+ id_int = id_int -1;
+
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ ttype_chn_rank_sel[id_int] = chn_rank_int;
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("ttype_chn_rank_sel input data [%s]\n",ttype_chn_rank_sel);
+
+ int i;
+ PR_BOOTMSG("wsct_chn_rank_sel_val save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d]=%X\n",i+1,ttype_chn_rank_sel[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t ttype_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"id[%d]=%X\n",i+1,ttype_chn_rank_sel[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_ttype_burst_range(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ttype_byte_low_bnd_val[i] = 0x0;
+ ttype_byte_up_bnd_val[i] = 0x1FF;
+ ttype_byte_bnd_dis[i] = 1;
+ }
+ ttype_burst_range[0] = '\0';
+}
+
+ssize_t ttype_burst_range_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_burst_range;
+ char *_id = NULL, *_low_bnd = NULL, *_up_bnd = NULL;
+ int id_int = 0, low_bnd_int = 0, up_bnd_int = 0;
+
+ _clear_ttype_burst_range();
+
+ snprintf(ttype_burst_range, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_burst_range[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _low_bnd = strsep(&token, delim_coclon);
+ _up_bnd = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _low_bnd[%s] _up_bnd[%s]\n",_id, _low_bnd, _up_bnd);
+
+ if (_id == NULL || _low_bnd == NULL || _up_bnd == NULL) {
+ PR_BOOTMSG("err (ttype_burst_range): _id[%s] _low_bnd[%s] _up_bnd[%s], para can't be NULL\n",
+ _id, _low_bnd, _up_bnd);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_low_bnd, 0, &low_bnd_int) != 0) {
+ PR_BOOTMSG("_low_bnd[%s] trans to hex err\n",_id);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_up_bnd, 0, &up_bnd_int) != 0) {
+ PR_BOOTMSG("_up_bnd[%s] trans to hex err\n",_id);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+
+ id_int = id_int - 1;
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ ttype_byte_low_bnd_val[id_int] = low_bnd_int;
+ ttype_byte_up_bnd_val[id_int] = up_bnd_int;
+ ttype_byte_bnd_dis[id_int] = 0;
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int, BM_COUNTER_MAX);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("ttype_burst_range_store input data [%s]\n",ttype_burst_range);
+
+ int i;
+ PR_BOOTMSG("ttype_burst_range save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d](low_bnd,up_bnd)=(%X,%X)\n",i+1,ttype_byte_low_bnd_val[i],ttype_byte_up_bnd_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t ttype_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,"id[%d](low_bnd,up_bnd)=(%X,%X)\n",
+ i+1, ttype_byte_low_bnd_val[i], ttype_byte_up_bnd_val[i]);
+ }
+ return strlen(buf);
+}
+
+void _clear_wmask_msel(void)
+{
+ int i;
+
+ for(i=0;i<MET_MAX_DRAM_CH_NUM;i++) {
+ wmask_msel_val[i] = 0xFF;
+ }
+ wmask_msel[0] = '\0';
+}
+
+ssize_t wmask_msel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ /* EX: 0:rw,1:r */
+ char *token, *cur= wmask_msel;
+ char *_id = NULL, *_master_group = NULL;
+ int id_int = 0;
+
+ _clear_wmask_msel();
+
+ snprintf(wmask_msel, FILE_NODE_DATA_LEN, "%s", buf);
+ wmask_msel[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:0xff , (ID,master_group)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _master_group = strsep(&token, delim_coclon);
+
+ /*PR_BOOTMSG("wmask_msel: _id[%s] _master_group[%s]\n",_id,_master_group);*/
+
+ if (_id == NULL || _master_group == NULL) {
+ PR_BOOTMSG("wmask_msel err: _id[%s] _master_group[%s], para can't be NULL\n",_id,_master_group);
+ _clear_wmask_msel();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("wmask_msel _id[%s] trans to hex err\n",_id);
+ _clear_wmask_msel();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < MET_MAX_DRAM_CH_NUM) {
+ if (kstrtouint(_master_group, 0, &wmask_msel_val[id_int]) != 0) {
+ PR_BOOTMSG("master_group[%s] trans to hex err\n",_master_group);
+ _clear_wmask_msel();
+ return -EINVAL;
+ }
+ } else {
+ PR_BOOTMSG("wmask_msel id[%d] exceed the range, it must be 0~%d\n",id_int, MET_MAX_DRAM_CH_NUM-1);
+ _clear_wmask_msel();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",wmask_msel);
+ /*PR_BOOTMSG("msel_group_ext_store size para n[%d]\n",n);*/
+ int i;
+ PR_BOOTMSG("save data\n");
+ for (i=0;i<MET_MAX_DRAM_CH_NUM;i++) {
+ PR_BOOTMSG("id[%d]=%X\n",i,wmask_msel_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t wmask_msel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0; i<dram_chann_num && i< MET_MAX_DRAM_CH_NUM; i++) {
+ ret += snprintf( buf + ret, PAGE_SIZE-ret, "%d:%d \n",i ,wmask_msel_val[i]);
+ }
+
+ return strlen(buf);
+}
+
+void _clear_ageexp_msel_rw(void)
+{
+ int i;
+
+ for(i=0;i<MET_MAX_DRAM_CH_NUM;i++) {
+ ageexp_msel_val[i] = 0xFF;
+ ageexp_rw_val[i] = 0x3;
+ }
+ ageexp_msel_rw[0] = '\0';
+}
+
+ssize_t ageexp_msel_rw_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ /* EX: 0:rw,1:r */
+ char *token, *cur= ageexp_msel_rw;
+ char *_id = NULL, *_master_group = NULL, *_rw_type = NULL;
+ int id_int = 0;
+
+ _clear_ageexp_msel_rw();
+
+ snprintf(ageexp_msel_rw, FILE_NODE_DATA_LEN, "%s", buf);
+ ageexp_msel_rw[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ /*PR_BOOTMSG("token: %s\n",token);*/
+ /*token EX: 4:0xff , (ID,master_group)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _master_group = strsep(&token, delim_coclon);
+ _rw_type = strsep(&token, delim_coclon);
+
+ // PR_BOOTMSG("ageexp_msel_rw: _id[%s] _master_group[%s] rwtype[%s]\n",_id,_master_group,_rw_type);
+
+ if (_id == NULL || _master_group == NULL || _rw_type==NULL) {
+ PR_BOOTMSG("ageexp_msel_rw err: _id[%s] _master_group[%s] rwtype[%s], para can't be NULL\n",_id,_master_group,_rw_type);
+ _clear_ageexp_msel_rw();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("ageexp_msel_rw _id[%s] trans to hex err\n",_id);
+ _clear_ageexp_msel_rw();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < MET_MAX_DRAM_CH_NUM) {
+ if (kstrtouint(_master_group, 0, &ageexp_msel_val[id_int]) != 0) {
+ PR_BOOTMSG("ageexp_msel_rw master_group[%s] trans to hex err\n",_master_group);
+ _clear_ageexp_msel_rw();
+ return -EINVAL;
+ }
+
+ if ( 0 == strncmp("NONE",_rw_type,4))
+ ageexp_rw_val[id_int] = BM_WSCT_RW_DISABLE;
+ else if (0 == strncmp("R",_rw_type,4))
+ ageexp_rw_val[id_int] = BM_WSCT_RW_READONLY;
+ else if (0 == strncmp("W",_rw_type,4))
+ ageexp_rw_val[id_int] = BM_WSCT_RW_WRITEONLY;
+ else if (0 == strncmp("RW",_rw_type,4))
+ ageexp_rw_val[id_int] = BM_WSCT_RW_RWBOTH;
+ else {
+ PR_BOOTMSG("ageexp_msel_rw _id[%s] has err rwtype[%s]\n", _id, _rw_type);
+ _clear_ageexp_msel_rw();
+ return -EINVAL;
+ }
+ } else {
+ PR_BOOTMSG("ageexp_msel_rw id[%d] exceed the range, it must be 0~%d\n",id_int, MET_MAX_DRAM_CH_NUM-1);
+ _clear_ageexp_msel_rw();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",ageexp_msel_rw);
+ /*PR_BOOTMSG("msel_group_ext_store size para n[%d]\n",n);*/
+ int i;
+ PR_BOOTMSG("save data\n");
+ for (i=0;i<MET_MAX_DRAM_CH_NUM;i++) {
+ PR_BOOTMSG("id[%d]=%X:%X\n",i, ageexp_msel_val[i], ageexp_rw_val[i]);
+ }
+#endif
+ return n;
+}
+
+ssize_t ageexp_msel_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ ssize_t ret = 0;
+ int i;
+
+ for (i=0; i<dram_chann_num && i< MET_MAX_DRAM_CH_NUM; i++) {
+ ret += snprintf( buf + ret, PAGE_SIZE-ret, "%d:%d:%d \n",i ,ageexp_msel_val[i], ageexp_rw_val[i]);
+ }
+
+ return strlen(buf);
+}
+
+
+/* KOBJ: emi_clock_rate */
+ssize_t sspm_support_feature_show(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "0x%x\n", get_sspm_support_feature());
+}
+
+
+void _clear_setting(void) {
+ /*clear all file node para here*/
+ int i;
+ PR_BOOTMSG("clear EMI file node setting\n");
+
+ _clear_default_val();
+ _clear_msel_group_ext();
+ _clear_wsct_rw();
+ _clear_wsct_high_priority_enable();
+ _clear_wsct_busid();
+ _clear_wsct_chn_rank_sel();
+ _clear_wsct_burst_range();
+
+ _clear_tsct_busid_enable();
+ _clear_ttype_high_priority_ext();
+ _clear_ttype_busid_ext();
+ _clear_ttype_chn_rank_sel();
+ _clear_ttype_burst_range();
+#ifdef EMI_LOWEFF_SUPPORT
+ _clear_wmask_msel();
+ _clear_ageexp_msel_rw();
+#endif
+ reserve_wsct_setting = 0;
+
+
+
+
+ emi_TP_busfiltr_enable = 0;
+
+ high_priority_filter = 0x0;
+ rwtype = BM_BOTH_READ_WRITE;
+ dramc_pdir_enable = 1;
+ met_emi_regdump = 0;
+
+ msel_enable = 0;
+ msel_group1 = BM_MASTER_ALL;
+ msel_group2 = BM_MASTER_ALL;
+ msel_group3 = BM_MASTER_ALL;
+
+
+ bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+ ttype1_16_en = BM_TTYPE1_16_DISABLE;
+ ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+
+ for (i = 0; i < 21; i++) {
+ ttype_master_val[i] = BM_MASTER_M0;
+ ttype_nbeat_val[i] = BM_TRANS_TYPE_1BEAT;
+ ttype_nbyte_val[i] = BM_TRANS_TYPE_8Byte;
+ ttype_burst_val[i] = BM_TRANS_TYPE_BURST_INCR;
+ ttype_busid_val[i] = 0xfffff; /*default disable ttype bus sel if busid > 0xff_ff */
+ ttype_rw_val[i] = BM_TRANS_RW_DEFAULT;
+ }
+ emi_tsct_enable = 0;
+ emi_mdct_enable = 0;
+ metemi_func_opt = 0xf00e;
+ rd_mdmcu_rsv_num = 0;
+ mdmcu_sel_enable = 0;
+
+}
+
+ssize_t clear_setting_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ if (value == 1)
+ _clear_setting();
+
+ return n;
+}
+
+
+
+struct kobj_attribute clear_setting_attr = __ATTR_WO(clear_setting); // OK
+struct kobj_attribute msel_group_ext_attr = __ATTR(msel_group_ext, 0664, msel_group_ext_show, msel_group_ext_store); //OK
+struct kobj_attribute wsct_rw_attr = __ATTR(wsct_rw, 0664, wsct_rw_show, wsct_rw_store);
+struct kobj_attribute wsct_high_priority_enable_attr = __ATTR(wsct_high_priority_enable, 0664, wsct_high_priority_enable_show, wsct_high_priority_enable_store);
+struct kobj_attribute wsct_busid_attr = __ATTR(wsct_busid, 0664, wsct_busid_show, wsct_busid_store);
+struct kobj_attribute wsct_chn_rank_sel_attr = __ATTR(wsct_chn_rank_sel, 0664, wsct_chn_rank_sel_show, wsct_chn_rank_sel_store);
+struct kobj_attribute wsct_burst_range_attr = __ATTR(wsct_burst_range, 0664, wsct_burst_range_show, wsct_burst_range_store);
+struct kobj_attribute tsct_busid_enable_attr = __ATTR(tsct_busid_enable, 0664, tsct_busid_enable_show, tsct_busid_enable_store);
+struct kobj_attribute ttype_high_priority_ext_attr = __ATTR(ttype_high_priority_ext, 0664, ttype_high_priority_ext_show, ttype_high_priority_ext_store);
+struct kobj_attribute ttype_busid_ext_attr = __ATTR(ttype_busid_ext, 0664, ttype_busid_ext_show, ttype_busid_ext_store);
+struct kobj_attribute ttype_chn_rank_sel_attr = __ATTR(ttype_chn_rank_sel, 0664, ttype_chn_rank_sel_show, ttype_chn_rank_sel_store);
+struct kobj_attribute ttype_burst_range_attr = __ATTR(ttype_burst_range, 0664, ttype_burst_range_show, ttype_burst_range_store);
+
+struct kobj_attribute wmask_msel_attr = __ATTR(wmask_msel, 0664, wmask_msel_show, wmask_msel_store);
+struct kobj_attribute ageexp_msel_rw_attr = __ATTR(ageexp_msel_rw, 0664, ageexp_msel_rw_show, ageexp_msel_rw_store);
+struct kobj_attribute default_val_attr = __ATTR(default_val, 0664, default_val_show, default_val_store); //OK
+DECLARE_KOBJ_ATTR_RO(sspm_support_feature);
+
+void emi_init(void)
+{
+ unsigned int bmrw0_val, bmrw1_val, i;
+ /*unsigned int msel_group_val[4];*/
+
+ /*save origianl EMI config*/
+ MET_BM_SaveCfg();
+
+ /* get dram channel number */
+ dram_chann_num = MET_EMI_GetDramChannNum();
+
+ /* Init. EMI bus monitor */
+ MET_BM_SetReadWriteType(rwtype);
+
+ /*handle the ori */
+
+ if (ttype1_16_en != BM_TTYPE1_16_ENABLE) {
+ MET_BM_SetLatencyCounter(1); /*enable latency count*/
+ }
+ else {
+ MET_BM_SetLatencyCounter(0); /*disable latency count*/
+
+ for (i = 1; i <= 16; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+ }
+ }
+
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+ for (i = 17; i <= 21; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+ }
+ }
+
+ PR_BOOTMSG("[%s]reserve_wsct_setting=%d\n",__func__,reserve_wsct_setting);
+
+ if (reserve_wsct_setting == 0) {
+ /* wsct 0 : total-all*/
+ msel_group_ext_val[0] = BM_MASTER_ALL;
+ wsct_rw_val[0] = BM_WSCT_RW_RWBOTH;
+ WSCT_HPRI_DIS[0] = 1;
+ WSCT_HPRI_SEL[0] = 0xF;
+ wsct_busid_val[0] = 0xFFFFF;
+ wsct_idMask_val[0] = 0xFFFF;
+ wsct_chn_rank_sel_val[0] = 0xF;
+ wsct_byte_bnd_dis[0] = 1;
+
+ /* wsct 4 : total-ultra*/
+ msel_group_ext_val[4] = BM_MASTER_ALL;
+ wsct_rw_val[4] = BM_WSCT_RW_RWBOTH;
+ WSCT_HPRI_DIS[4] = 0;
+ WSCT_HPRI_SEL[4] = 0x8; /* ultra */
+ wsct_busid_val[4] = 0xFFFFF;
+ wsct_idMask_val[4] = 0xFFFF;
+ wsct_chn_rank_sel_val[4] = 0xF;
+ wsct_byte_bnd_dis[4] = 1;
+
+ /* wsct 5 : total-pre_ultra*/
+ msel_group_ext_val[5] = BM_MASTER_ALL;
+ wsct_rw_val[5] = BM_WSCT_RW_RWBOTH;
+ WSCT_HPRI_DIS[5] = 0;
+ WSCT_HPRI_SEL[5] = 0x4; /* pre_ultra */
+ wsct_busid_val[5] = 0xFFFFF;
+ wsct_idMask_val[5] = 0xFFFF;
+ wsct_chn_rank_sel_val[5] = 0xF;
+ wsct_byte_bnd_dis[5] = 1;
+ }
+
+ if (msel_enable) {
+ /* if old file node set, use the value */
+ if ( msel_group1 != BM_MASTER_ALL )
+ msel_group_ext_val[1] = msel_group1;
+
+ if ( msel_group2 != BM_MASTER_ALL )
+ msel_group_ext_val[2] = msel_group2;
+
+ if ( msel_group3 != BM_MASTER_ALL )
+ msel_group_ext_val[3] = msel_group3;
+
+ } else {
+ for ( i=1; i<=3; i++) {
+ msel_group_ext_val[i] = BM_MASTER_ALL;
+ }
+ }
+
+ MET_BM_SetWSCT_master_rw(msel_group_ext_val, wsct_rw_val);
+ MET_BM_SetWSCT_high_priority(WSCT_HPRI_DIS, WSCT_HPRI_SEL);
+ MET_BM_SetWSCT_busid_idmask(wsct_busid_val, wsct_idMask_val);
+ MET_BM_SetWSCT_chn_rank_sel(wsct_chn_rank_sel_val);
+ MET_BM_SetWSCT_burst_range(wsct_byte_bnd_dis, wsct_byte_low_bnd_val, wsct_byte_up_bnd_val);
+ MET_BM_SetTSCT_busid_enable(tsct_busid_enable_val);
+
+ MET_BM_SetTtype_high_priority_sel(high_priority_filter, TTYPE_HPRI_SEL);
+ MET_BM_SetTtype_busid_idmask(ttype_busid_val, ttype_idMask_val, ttype1_16_en, ttype17_21_en);
+ MET_BM_SetTtype_chn_rank_sel(ttype_chn_rank_sel_val);
+ MET_BM_SetTtype_burst_range(ttype_byte_bnd_dis, ttype_byte_low_bnd_val, ttype_byte_up_bnd_val);
+
+#ifdef EMI_LOWEFF_SUPPORT
+ /*
+ for (i=0; i<dram_chann_num && i< MET_MAX_DRAM_CH_NUM; i++) {
+ MET_BM_SetLOWEFF_master_rw(i, wmask_msel_val, ageexp_msel_val, ageexp_rw_val);
+ }
+ */
+ MET_BM_SetLOWEFF_master_rw(0, wmask_msel_val, ageexp_msel_val, ageexp_rw_val);
+#endif
+
+ bmrw0_val = 0;
+ for (i = 0; i < 16; i++)
+ bmrw0_val |= (ttype_rw_val[i] << (i * 2));
+
+ bmrw1_val = 0;
+ for (i = 16; i < 21; i++)
+ bmrw1_val |= (ttype_rw_val[i] << ((i-16) * 2));
+
+ MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+}
+
+/*restore the emi origin setting , prevent infect other module*/
+void emi_uninit(void)
+{
+ MET_BM_RestoreCfg();
+}
+
+void MET_BM_IPI_REGISTER_CB(void)
+{
+ int ret, i;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_REGISTER_CB;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+
+void MET_BM_IPI_configs(void)
+{
+ int ret, i;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_EBM_CONFIGS1;
+ ipi_buf[2] = EMI_VER_MAJOR << 24 | EMI_VER_MINOR << 16 | DRAMC_VER << 8 | 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+
+unsigned int get_sspm_support_feature(void)
+{
+ unsigned int rdata=0;
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ int ret, i;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_REQ_AP2MD ;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+#endif
+#endif
+ return rdata;
+}
+
+unsigned check_sspm_support(unsigned int module_id)
+{
+ unsigned int suppor_list = get_sspm_support_feature();
+
+ /*PR_BOOTMSG("sspm_support_module:%x\n",suppor_list);*/
+#if 1
+ return (suppor_list & module_id);
+#else
+ /*force to AP polling*/
+ return 0;
+#endif
+}
+
+
+
+unsigned int MET_GET_DRAM_TYPE()
+{
+/*
+enum DRAM_TYPE {
+??TYPE_DDR1 = 1,
+??TYPE_LPDDR2,
+??TYPE_LPDDR3,
+??TYPE_PCDDR3,
+??TYPE_LPDDR4,
+??TYPE_LPDDR4X,
+??TYPE_LPDDR4P
+};
+*/
+ unsigned int dram_type;
+
+ if (mtk_dramc_get_ddr_type_symbol) {
+ dram_type = mtk_dramc_get_ddr_type_symbol();
+ if (dram_type == 0)
+ dram_type = met_emi_default_val[e_MET_DRAM_TYPE];
+ } else {
+ dram_type = met_emi_default_val[e_MET_DRAM_TYPE];
+ }
+ return dram_type;
+}
+
+/* get the ddr ratio */
+unsigned int MET_EMI_Get_BaseClock_Rate(void)
+{
+#if 0
+ unsigned int DRAM_TYPE;
+
+ if (get_cur_ddr_ratio_symbol)
+ return get_cur_ddr_ratio_symbol();
+ else {
+
+ if (mtk_dramc_get_ddr_type_symbol) {
+ DRAM_TYPE = mtk_dramc_get_ddr_type_symbol();
+
+ if ((DRAM_TYPE == 2) || (DRAM_TYPE == 3))
+ return DRAM_EMI_BASECLOCK_RATE_LP4;
+ else
+ return DRAM_EMI_BASECLOCK_RATE_LP3;
+
+ } else {
+ return DRAM_EMI_BASECLOCK_RATE_LP4;
+ }
+ }
+#else
+ unsigned int ddr_ratio = 0;
+
+ if (get_cur_ddr_ratio_symbol){
+ ddr_ratio = get_cur_ddr_ratio_symbol();
+
+ if (ddr_ratio == 0)
+ ddr_ratio = met_emi_default_val[e_MET_DDR_RATIO];
+ } else {
+ ddr_ratio = met_emi_default_val[e_MET_DDR_RATIO];
+ }
+ return ddr_ratio;
+#endif
+}
+
+unsigned met_get_dram_data_rate(void)
+{
+ unsigned int dram_data_rate_MHz = 0;
+
+ if (mtk_dramc_get_data_rate_symbol) {
+ dram_data_rate_MHz = mtk_dramc_get_data_rate_symbol();
+ if (dram_data_rate_MHz == 0)
+ dram_data_rate_MHz = met_emi_default_val[e_MET_DRAM_FREQ];
+ } else {
+ // METERROR("mtk_dramc_get_data_rate_symbol = NULL\n");
+ // ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ##_EMI_warning: mtk_dramc_get_data_rate_symbol = NULL\n");
+ dram_data_rate_MHz = met_emi_default_val[e_MET_DRAM_FREQ];
+ }
+ return dram_data_rate_MHz;
+}
+
+int emi_create_header(char *buf, int buf_len)
+{
+ int ret = 0;
+ int i = 0;
+
+ unsigned int dram_data_rate_MHz;
+ unsigned int DRAM_TYPE;
+ unsigned int base_clock_rate;
+
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_wsct_amount: %d\n",WSCT_AMOUNT);
+
+ /* master selection header */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+ msel_group_ext_val[1] & BM_MASTER_ALL,
+ msel_group_ext_val[2] & BM_MASTER_ALL,
+ msel_group_ext_val[3] & BM_MASTER_ALL);
+
+ /*Ttype RW type header*/
+ PR_BOOTMSG("rwtype=%d\n",rwtype);
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_rw_cfg: ");
+ if (rwtype == BM_READ_ONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "R");
+ else if (rwtype == BM_WRITE_ONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "W");
+ else
+ ret += snprintf(buf + ret, buf_len - ret, "BOTH");
+
+ for (i = 0; i < 21; i++) {
+ if (ttype_rw_val[i] == BM_TRANS_RW_DEFAULT)
+ ret += snprintf(buf + ret, buf_len - ret, ",DEFAULT");
+ else if (ttype_rw_val[i] == BM_TRANS_RW_READONLY)
+ ret += snprintf(buf + ret, buf_len - ret, ",R");
+ else if (ttype_rw_val[i] == BM_TRANS_RW_WRITEONLY)
+ ret += snprintf(buf + ret, buf_len - ret, ",W");
+ else /*BM_TRANS_RW_RWBOTH*/
+ ret += snprintf(buf + ret, buf_len - ret, ",BOTH");
+ }
+ ret += snprintf(buf + ret, buf_len - ret, "\n");
+
+ /*ultra header*/
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_ultra_filter: %x\n", high_priority_filter);
+
+ /* ttype header */
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+ int i = 0;
+ int j = 0;
+
+ /* ttype master list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_master_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+ if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%s,", ttype_master_list_item[j].val);
+ }
+ }
+ }
+ /* remove the last comma */
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype busid list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_busid_list: ");
+ for (i = 0; i < 21; i++)
+ ret += snprintf(buf + ret, buf_len - ret, "%x,", ttype_busid_val[i]);
+
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype nbeat list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_nbeat_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_nbeat_list_item); j++) {
+ if (ttype_nbeat_val[i] == ttype_nbeat_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,", ttype_nbeat_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype nbyte list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_nbyte_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_nbyte_list_item); j++) {
+ if (ttype_nbyte_val[i] == ttype_nbyte_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,", ttype_nbyte_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype burst list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_burst_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_burst_list_item); j++) {
+ if (ttype_burst_val[i] == ttype_burst_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%s,", ttype_burst_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ }
+ /* ttype enable */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_enable: %d,%d\n",ttype1_16_en, ttype17_21_en);
+
+
+#if 1 /*SEDA 3.5*/
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_msel_ext: %x,%x,%x\n",
+ msel_group_ext_val[0] & BM_MASTER_ALL,
+ msel_group_ext_val[4] & BM_MASTER_ALL,
+ msel_group_ext_val[5] & BM_MASTER_ALL);
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_rw: ");
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ if (wsct_rw_val[i] == BM_WSCT_RW_RWBOTH)
+ ret += snprintf(buf + ret, buf_len - ret, "RW,");
+ else if (wsct_rw_val[i] == BM_WSCT_RW_READONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "R,");
+ else if (wsct_rw_val[i] == BM_WSCT_RW_WRITEONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "W,");
+ else /*disable*/
+ ret += snprintf(buf + ret, buf_len - ret, "NONE,");
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_HPRI_DIS: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",WSCT_HPRI_DIS[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_HPRI_SEL: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",WSCT_HPRI_SEL[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_busid: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_busid_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_idMask: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_idMask_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_chn_rank_sel: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_chn_rank_sel_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_byte_bnd_dis: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",wsct_byte_bnd_dis[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_byte_low_bnd: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_byte_low_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_byte_up_bnd: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_byte_up_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: tsct_busid_enable: ");
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",tsct_busid_enable_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /***************************** ttype ****************************************/
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: TTYPE_HPRI_SEL: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",TTYPE_HPRI_SEL[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_idMask: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_idMask_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_chn_rank_sel: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_chn_rank_sel_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_byte_bnd_dis: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",ttype_byte_bnd_dis[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_byte_low_bnd_val: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_byte_low_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_byte_up_bnd_val: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_byte_up_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+ }
+#endif
+
+#ifdef EMI_NUM
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: EMI_NUM: %d\n", EMI_NUM);
+#endif
+ /*IP version*/
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: DRAMC_VER: %d\n", DRAMC_VER);
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: EMI_VER: %d.%d\n", EMI_VER_MAJOR, EMI_VER_MINOR);
+
+#if 1 /* SEDA3.5 header print move to AP side */
+ dram_chann_num = MET_EMI_GetDramChannNum();
+ /* met_dram_chann_num_header
+ * channel number
+ * LP4: 2, LP3: 1
+ */
+
+ /*
+ * the ddr type define :
+ * enum DDRTYPE {
+ * TYPE_DDR1 = 1,
+ * TYPE_LPDDR2,
+ * TYPE_LPDDR3,
+ * TYPE_PCDDR3,
+ * TYPE_LPDDR4,
+ * TYPE_LPDDR4X,
+ * TYPE_LPDDR4P
+ * };
+ */
+
+ if (!get_cur_ddr_ratio_symbol){
+ PR_BOOTMSG("[%s][%d]get_cur_ddr_ratio_symbol = NULL , use the TYPE_LPDDR4 setting\n", __func__, __LINE__);
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ##_EMI_warning: get_cur_ddr_ratio_symbol = NULL , use the TYPE_LPDDR4 setting\n");
+ }
+
+#if 1
+ DRAM_TYPE = MET_GET_DRAM_TYPE();
+ base_clock_rate = MET_EMI_Get_BaseClock_Rate();
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_type: %d\n", DRAM_TYPE);
+
+ if ((DRAM_TYPE == 5) || (DRAM_TYPE == 6) || (DRAM_TYPE == 7))
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, base_clock_rate,
+ DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+ else
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, base_clock_rate,
+ DRAM_IO_BUS_WIDTH_LP3, DRAM_DATARATE);
+#else
+ if (mtk_dramc_get_ddr_type_symbol) {
+
+ DRAM_TYPE = mtk_dramc_get_ddr_type_symbol();
+ base_clock_rate = MET_EMI_Get_BaseClock_Rate();
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_type: %d\n", DRAM_TYPE);
+
+ if ((DRAM_TYPE == 5) || (DRAM_TYPE == 6) || (DRAM_TYPE == 7))
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, base_clock_rate,
+ DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+ else
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, base_clock_rate,
+ DRAM_IO_BUS_WIDTH_LP3, DRAM_DATARATE);
+ } else {
+
+ METERROR("[%s][%d]mtk_dramc_get_ddr_type_symbol = NULL , use the TYPE_LPDDR4 setting\n", __func__, __LINE__);
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ##_EMI_warning: mtk_dramc_get_ddr_type_symbol = NULL , use the TYPE_LPDDR4 setting\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, DDR_RATIO_DEFAULT,
+ DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+ }
+#endif
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: metemi_func_opt_header: %d\n",
+ metemi_func_opt);
+
+#if 1
+ /* met_emi_clockrate */
+ dram_data_rate_MHz = met_get_dram_data_rate();
+
+#else
+ if (get_dram_data_rate_symbol) {
+ dram_data_rate_MHz = get_dram_data_rate_symbol();
+ } else {
+ METERROR("get_dram_data_rate_symbol = NULL\n");
+ dram_data_rate_MHz = 0;
+ }
+#endif
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_dram_clockrate: %d\n",
+ dram_data_rate_MHz);
+
+ /* 1 : by ondiemet, 0: by pure linux */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: ##_emi_use_ondiemet: %u,%X\n",
+ emi_use_ondiemet, get_sspm_support_feature());
+
+ /*dram bank num*/
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_dram_rank_num_header: %u,%u\n", MET_EMI_GetDramRankNum(),
+ MET_EMI_GetDramRankNum());
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_header: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+ for (i = 0; i < dram_chann_num; i++) {
+ if (i != 0)
+ ret += snprintf(buf + ret, buf_len - ret,
+ ",");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "read_bytes_%d,write_bytes_%d", i, i);
+ }
+ ret += snprintf(buf + ret, buf_len - ret, "\n");
+
+ /*TSCT header*/
+ if (emi_tsct_enable == 1) {
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: ms_emi_tsct_header: ms_emi_tsct,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "tsct1,tsct2,tsct3\n");
+ }
+
+ /*MDCT header*/
+ if (emi_mdct_enable == 1) {
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: ms_emi_mdct_header: ms_emi_mdct,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "RD_ULTRA,RD_MDMCU\n");
+ }
+
+
+ /* met_bw_rgtor_header */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_bw_rgtor_unit_header: %x\n", MET_EMI_Get_CONH_2ND());
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_bw_rglr_header: metadata\n");
+
+
+ /* DRAM DVFS header */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: DRAM_DVFS_header: datarate(MHz)\n");
+
+ /*PDIR met_dramc_header*/
+ if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 ) {
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_dramc_header: ");
+ for (i = 0; i < dram_chann_num; i++) {
+ if (i != 0)
+ ret += snprintf(buf + ret, buf_len - ret,
+ ",");
+ ret += snprintf(buf + ret, buf_len - ret, "freerun_26m_%d,", i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "rk0_pre_sb_%d,rk0_pre_pd_%d,rk0_act_sb_%d,rk0_act_pd_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "rk1_pre_sb_%d,rk1_pre_pd_%d,rk1_act_sb_%d,rk1_act_pd_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "rk2_pre_sb_%d,rk2_pre_pd_%d,rk2_act_sb_%d,rk2_act_pd_%d", i, i, i, i);
+ }
+ ret += snprintf(buf + ret, buf_len - ret, "\n");
+ }
+
+ /* DRS header */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: emi_drs_header: ch0_RANK1_GP(%%),ch0_RANK1_SF(%%),ch0_ALL_SF(%%),ch1_RANK1_GP(%%),ch1_RANK1_SF(%%),ch1_ALL_SF(%%)\n");
+#endif
+
+#ifdef EMI_LOWEFF_SUPPORT
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: chn_emi_loweff_ctl0: ");
+ /*
+ for (i = 0; i < dram_chann_num && i<MET_MAX_DRAM_CH_NUM; i++) {
+
+ ret += snprintf(buf + ret, buf_len - ret, "%x",MET_EMI_Get_LOWEFF_CTL0(i));
+
+ if( i< (dram_chann_num-1))
+ ret += snprintf(buf + ret, buf_len - ret, ",");
+ }
+ ret += snprintf(buf + ret, buf_len - ret, "\n");
+ */
+ ret += snprintf(buf + ret, buf_len - ret, "%x\n",MET_EMI_Get_LOWEFF_CTL0(0));
+
+#endif
+ return ret;
+}
+
+static struct metdevice *emi_device;
+
+int met_emi_create_basic(struct kobject *parent, struct metdevice *emi_dev)
+{
+ int ret = 0;
+
+ _clear_setting();
+
+ ret = MET_BM_Init();
+ if (ret != 0) {
+ pr_notice("MET_BM_Init failed!!!\n");
+ ret = 0; /* will retry later */
+ } else {
+ emi_inited = 1;
+ }
+
+ kobj_emi = parent;
+ emi_device = emi_dev;
+
+PR_BOOTMSG("MET sspm_support_list=%X \n",get_sspm_support_feature());
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+ do { \
+ ret = sysfs_create_file(kobj_emi, &attr_name ## _attr.attr); \
+ if (ret != 0) { \
+ pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+ } while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+ return ret;
+}
+
+int do_emi(void)
+{
+ return emi_device->mode;
+}
+
+void met_emi_delete_basic(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_emi, &attr_name##_attr.attr)
+ if (kobj_emi != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_emi = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+
+ if (emi_inited)
+ MET_BM_DeInit();
+
+ emi_device = NULL;
+}
+
+void met_emi_resume_basic(void)
+{
+ if (!do_emi())
+ return;
+
+ emi_init();
+}
+
+int emi_print_header_basic(char *buf, int len)
+{
+ if( (strlen(header_str) - output_str_len) > PAGE_SIZE ){
+ char output_buf[PAGE_SIZE/4];
+
+ strncpy(output_buf, header_str+output_str_len, (PAGE_SIZE/4) -1);
+ output_buf[(PAGE_SIZE/4) - 1] = '\0';
+
+ len = snprintf(buf, PAGE_SIZE, "%s", output_buf);
+ output_str_len += len;
+ emi_device->header_read_again = 1;
+
+ PR_BOOTMSG("EMI header read again!\n");
+ }
+ else{
+ len = snprintf(buf, PAGE_SIZE, "%s\n", header_str+output_str_len);
+
+ /* reset state */
+ emi_device->header_read_again = 0;
+ output_header_len = 0;
+ output_str_len = 0;
+ }
+ return len;
+}
+
+void ondiemet_emi_start_basic(void)
+{
+ int ret;
+
+ emi_use_ondiemet = 1;
+
+ MET_BM_IPI_REGISTER_CB();
+ if (!emi_inited) {
+ if (MET_BM_Init() != 0) {
+ emi_device->mode = 0;
+ pr_notice("MET_BM_Init failed!!!\n");
+ return;
+ }
+ emi_inited = 1;
+ }
+ MET_BM_IPI_configs();
+
+ if (do_emi())
+ emi_init();
+
+ ondiemet_module[ONDIEMET_SSPM] |= ID_EMI;
+ ret = emi_create_header(header_str, MAX_HEADER_LEN);
+
+ emi_device->header_read_again = 0;
+ output_header_len = 0;
+ output_str_len = 0;
+}
+
+void ondiemet_emi_stop_basic(void)
+{
+ if (!emi_inited)
+ return;
+
+ if (do_emi())
+ emi_uninit();
+}
+
+/*para*/
+EXPORT_SYMBOL(emi_inited);
+EXPORT_SYMBOL(output_str_len);
+EXPORT_SYMBOL(dramc_pdir_enable);
+EXPORT_SYMBOL(kobj_emi);
+EXPORT_SYMBOL(emi_mdct_enable);
+EXPORT_SYMBOL(rd_mdmcu_rsv_num);
+EXPORT_SYMBOL(met_emi_regdump);
+EXPORT_SYMBOL(output_header_len);
+EXPORT_SYMBOL(BaseAddrEMI);
+EXPORT_SYMBOL(BaseAddrCHN_EMI);
+EXPORT_SYMBOL(header_str);
+EXPORT_SYMBOL(ttype1_16_en);
+EXPORT_SYMBOL(ttype17_21_en);
+EXPORT_SYMBOL(emi_tsct_enable);
+EXPORT_SYMBOL(emi_use_ondiemet);
+EXPORT_SYMBOL(dram_chann_num);
+EXPORT_SYMBOL(metemi_func_opt);
+EXPORT_SYMBOL(mdmcu_sel_enable);
+
+
+
+/*func*/
+EXPORT_SYMBOL(emi_init);
+EXPORT_SYMBOL(ondiemet_emi_start_basic);
+EXPORT_SYMBOL(do_emi);
+EXPORT_SYMBOL(emi_create_header);
+EXPORT_SYMBOL(MET_EMI_Get_BaseClock_Rate);
+EXPORT_SYMBOL(emi_uninit);
+EXPORT_SYMBOL(met_emi_create_basic);
+EXPORT_SYMBOL(met_emi_delete_basic);
+EXPORT_SYMBOL(emi_print_header_basic);
+EXPORT_SYMBOL(MET_EMI_GetDramChannNum);
+EXPORT_SYMBOL(MET_BM_Init);
+EXPORT_SYMBOL(check_sspm_support);
+EXPORT_SYMBOL(met_get_dram_data_rate);
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm.h b/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm.h
new file mode 100644
index 0000000..05a6a6f
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm.h
@@ -0,0 +1,911 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+
+#ifndef __MT_MET_EMI_BM_BASIC_H__
+#define __MT_MET_EMI_BM_BASIC_H__
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#elif defined(TINYSYS_SSPM_SUPPORT)
+#include "tinysys_sspm.h"
+#include "tinysys_mgr.h" /* for ondiemet_module */
+#include "sspm_met_ipi_handle.h"
+#endif
+#endif
+
+
+/*define MARGAUX*/
+
+#define EMI_VER_MAJOR 3
+#define EMI_VER_MINOR 5
+
+#define MET_MAX_DRAM_CH_NUM 4
+
+#define FILE_NODE_DATA_LEN 512
+#define WSCT_AMOUNT 6
+#define TSCT_AMOUNT 3
+
+
+#define DRAM_EMI_BASECLOCK_RATE_LP4 4
+#define DRAM_EMI_BASECLOCK_RATE_LP3 2
+
+#define DRAM_IO_BUS_WIDTH_LP4 16
+#define DRAM_IO_BUS_WIDTH_LP3 32
+
+#define DRAM_DATARATE 2
+
+#define DRAM_FREQ_DEFAULT 3733
+#define DDR_RATIO_DEFAULT 8
+#define DRAM_TYPE_DEFAULT 3
+
+#define ADDR_EMI ((unsigned long)BaseAddrEMI)
+
+#define MASK_MASTER 0xFF
+#define MASK_TRANS_TYPE 0xFF
+
+#define BM_MASTER_M0 (0x01)
+#define BM_MASTER_M1 (0x02)
+#define BM_MASTER_M2 (0x04)
+#define BM_MASTER_M3 (0x08)
+#define BM_MASTER_M4 (0x10)
+#define BM_MASTER_M5 (0x20)
+#define BM_MASTER_M6 (0x40)
+#define BM_MASTER_M7 (0x80)
+#define BM_MASTER_ALL (0xFF)
+
+
+enum BM_RW_Type {
+ BM_BOTH_READ_WRITE,
+ BM_READ_ONLY,
+ BM_WRITE_ONLY
+};
+
+enum {
+ BM_TRANS_TYPE_1BEAT = 0x0,
+ BM_TRANS_TYPE_2BEAT,
+ BM_TRANS_TYPE_3BEAT,
+ BM_TRANS_TYPE_4BEAT,
+ BM_TRANS_TYPE_5BEAT,
+ BM_TRANS_TYPE_6BEAT,
+ BM_TRANS_TYPE_7BEAT,
+ BM_TRANS_TYPE_8BEAT,
+ BM_TRANS_TYPE_9BEAT,
+ BM_TRANS_TYPE_10BEAT,
+ BM_TRANS_TYPE_11BEAT,
+ BM_TRANS_TYPE_12BEAT,
+ BM_TRANS_TYPE_13BEAT,
+ BM_TRANS_TYPE_14BEAT,
+ BM_TRANS_TYPE_15BEAT,
+ BM_TRANS_TYPE_16BEAT,
+ BM_TRANS_TYPE_1Byte = 0 << 4,
+ BM_TRANS_TYPE_2Byte = 1 << 4,
+ BM_TRANS_TYPE_4Byte = 2 << 4,
+ BM_TRANS_TYPE_8Byte = 3 << 4,
+ BM_TRANS_TYPE_16Byte = 4 << 4,
+ BM_TRANS_TYPE_32Byte = 5 << 4,
+ BM_TRANS_TYPE_BURST_WRAP = 0 << 7,
+ BM_TRANS_TYPE_BURST_INCR = 1 << 7
+};
+
+enum {
+ BM_TRANS_RW_DEFAULT = 0x0,
+ BM_TRANS_RW_READONLY,
+ BM_TRANS_RW_WRITEONLY,
+ BM_TRANS_RW_RWBOTH
+};
+
+enum {
+ BM_WSCT_RW_DISABLE = 0x0,
+ BM_WSCT_RW_READONLY,
+ BM_WSCT_RW_WRITEONLY,
+ BM_WSCT_RW_RWBOTH
+};
+
+/*coda busid 12bit, but HW support 16 bit*/
+#define EMI_BMID_MASK (0xFFFF)
+#define BM_COUNTER_MAX (21)
+
+enum {
+ BUS_MON_EN_SHIFT = 0,
+ BUS_MON_PAUSE_SHIFT = 1,
+ BUS_MON_IDLE_SHIFT = 3,
+ BC_OVERRUN_SHIFT = 8,
+ DRAMC_CG_SHIFT = 9,
+};
+
+#define BM_REQ_OK (0)
+#define BM_ERR_WRONG_REQ (-1)
+#define BM_ERR_OVERRUN (-2)
+
+#define BM_WSCT_TSCT_IDSEL_ENABLE (0)
+#define BM_WSCT_TSCT_IDSEL_DISABLE (-1)
+#define BM_TTYPE1_16_ENABLE (0)
+#define BM_TTYPE1_16_DISABLE (-1)
+#define BM_TTYPE17_21_ENABLE (0)
+#define BM_TTYPE17_21_DISABLE (-1)
+#define BM_BW_LIMITER_ENABLE (0)
+#define BM_BW_LIMITER_DISABLE (-1)
+
+#define M0_DOUBLE_HALF_BW_1CH (0x0)
+#define M0_DOUBLE_HALF_BW_2CH (0x1)
+#define M0_DOUBLE_HALF_BW_4CH (0x2)
+
+/* EMI Rank configuration */
+enum {
+ DISABLE_DUAL_RANK_MODE = 0,
+ ENABLE_DUAL_RANK_MODE,
+};
+
+#define RANK_MASK 0x1
+#define ONE_RANK 1
+#define DUAL_RANK 2
+
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+enum BM_EMI_IPI_Type {
+ SET_BASE_EMI = 0x0,
+ SET_EBM_CONFIGS1 = 0x7,
+ SET_EBM_CONFIGS2 = 0x8,
+ SET_REGISTER_CB = 0x9,
+};
+#endif
+#endif
+
+
+#define EMI_OFF 0x0000
+#define EMI_CONA (0x000-EMI_OFF)
+#define EMI_CONH (0x038-EMI_OFF)
+#define EMI_CONH_2ND (0x03C-EMI_OFF)
+#define EMI_CONM (0x060-EMI_OFF)
+#define EMI_CONO (0x070-EMI_OFF)
+
+#define EMI_MDCT (0x078 - EMI_OFF)
+#define EMI_MDCT_2ND (0x07C - EMI_OFF)
+
+#define EMI_ARBA (0x100 - EMI_OFF)
+#define EMI_ARBB (0x108 - EMI_OFF)
+#define EMI_ARBC (0x110 - EMI_OFF)
+#define EMI_ARBD (0x118 - EMI_OFF)
+#define EMI_ARBE (0x120 - EMI_OFF)
+#define EMI_ARBF (0x128 - EMI_OFF)
+#define EMI_ARBG (0x130 - EMI_OFF)
+#define EMI_ARBG_2ND (0x134 - EMI_OFF)
+#define EMI_ARBH (0x138 - EMI_OFF)
+
+
+#define EMI_BMEN (0x400-EMI_OFF)
+#define EMI_MSEL (0x440 - EMI_OFF)
+#define EMI_MSEL2 (0x468 - EMI_OFF)
+#define EMI_MSEL3 (0x470 - EMI_OFF)
+#define EMI_MSEL4 (0x478 - EMI_OFF)
+#define EMI_MSEL5 (0x480 - EMI_OFF)
+#define EMI_MSEL6 (0x488 - EMI_OFF)
+#define EMI_MSEL7 (0x490 - EMI_OFF)
+#define EMI_MSEL8 (0x498 - EMI_OFF)
+#define EMI_MSEL9 (0x4A0 - EMI_OFF)
+#define EMI_MSEL10 (0x4A8 - EMI_OFF)
+
+#define EMI_BMID0 (0x4B0 - EMI_OFF)
+#define EMI_BMID1 (0x4B4 - EMI_OFF)
+#define EMI_BMID2 (0x4B8 - EMI_OFF)
+#define EMI_BMID3 (0x4BC - EMI_OFF)
+#define EMI_BMID4 (0x4C0 - EMI_OFF)
+#define EMI_BMID5 (0x4C4 - EMI_OFF)
+#define EMI_BMID6 (0x4C8 - EMI_OFF)
+#define EMI_BMID7 (0x4CC - EMI_OFF)
+#define EMI_BMID8 (0x4D0 - EMI_OFF)
+#define EMI_BMID9 (0x4D4 - EMI_OFF)
+#define EMI_BMID10 (0x4D8 - EMI_OFF)
+
+#define EMI_BMEN1 (0x4E0 - EMI_OFF)
+#define EMI_BMEN2 (0x4E8 - EMI_OFF)
+#define EMI_BMRW0 (0x4F8 - EMI_OFF)
+#define EMI_BMRW1 (0x4FC - EMI_OFF)
+
+
+/* SEDA 3.5 New! reg*/
+/* For WSCT setting*/
+#define EMI_DBWA (0xF00 - EMI_OFF)
+#define EMI_DBWB (0xF04 - EMI_OFF)
+#define EMI_DBWC (0xF08 - EMI_OFF)
+#define EMI_DBWD (0xF0C - EMI_OFF)
+#define EMI_DBWE (0xF10 - EMI_OFF)
+#define EMI_DBWF (0xF14 - EMI_OFF)
+
+
+#define EMI_DBWA_2ND (0xF2C - EMI_OFF)
+#define EMI_DBWB_2ND (0xF30 - EMI_OFF)
+#define EMI_DBWC_2ND (0xF34 - EMI_OFF)
+#define EMI_DBWD_2ND (0xF38 - EMI_OFF)
+#define EMI_DBWE_2ND (0xF3C - EMI_OFF)
+#define EMI_DBWF_2ND (0xF40 - EMI_OFF)
+
+#define EMI_DBWI (0xF20 - EMI_OFF) /* SEL_ID_MSK*/
+#define EMI_DBWJ (0xF24 - EMI_OFF)
+#define EMI_DBWK (0xF28 - EMI_OFF)
+
+/* For Ttype setting */
+#define EMI_TTYPE1_CONA (0xF50 - EMI_OFF)
+#define EMI_TTYPE1_CONB (0xF54 - EMI_OFF)
+#define EMI_TTYPE2_CONA (0xF58 - EMI_OFF)
+#define EMI_TTYPE2_CONB (0xF5C - EMI_OFF)
+#define EMI_TTYPE3_CONA (0xF60 - EMI_OFF)
+#define EMI_TTYPE3_CONB (0xF64 - EMI_OFF)
+#define EMI_TTYPE4_CONA (0xF68 - EMI_OFF)
+#define EMI_TTYPE4_CONB (0xF6C - EMI_OFF)
+#define EMI_TTYPE5_CONA (0xF70 - EMI_OFF)
+#define EMI_TTYPE5_CONB (0xF74 - EMI_OFF)
+#define EMI_TTYPE6_CONA (0xF78 - EMI_OFF)
+#define EMI_TTYPE6_CONB (0xF7C - EMI_OFF)
+#define EMI_TTYPE7_CONA (0xF80 - EMI_OFF)
+#define EMI_TTYPE7_CONB (0xF84 - EMI_OFF)
+#define EMI_TTYPE8_CONA (0xF88 - EMI_OFF)
+#define EMI_TTYPE8_CONB (0xF8C - EMI_OFF)
+#define EMI_TTYPE9_CONA (0xF90 - EMI_OFF)
+#define EMI_TTYPE9_CONB (0xF94 - EMI_OFF)
+#define EMI_TTYPE10_CONA (0xF98 - EMI_OFF)
+#define EMI_TTYPE10_CONB (0xF9C - EMI_OFF)
+#define EMI_TTYPE11_CONA (0xFA0 - EMI_OFF)
+#define EMI_TTYPE11_CONB (0xFA4 - EMI_OFF)
+#define EMI_TTYPE12_CONA (0xFA8 - EMI_OFF)
+#define EMI_TTYPE12_CONB (0xFAC - EMI_OFF)
+#define EMI_TTYPE13_CONA (0xFB0 - EMI_OFF)
+#define EMI_TTYPE13_CONB (0xFB4 - EMI_OFF)
+#define EMI_TTYPE14_CONA (0xFB8 - EMI_OFF)
+#define EMI_TTYPE14_CONB (0xFBC - EMI_OFF)
+#define EMI_TTYPE15_CONA (0xFC0 - EMI_OFF)
+#define EMI_TTYPE15_CONB (0xFC4 - EMI_OFF)
+#define EMI_TTYPE16_CONA (0xFC8 - EMI_OFF)
+#define EMI_TTYPE16_CONB (0xFCC - EMI_OFF)
+#define EMI_TTYPE17_CONA (0xFD0 - EMI_OFF)
+#define EMI_TTYPE17_CONB (0xFD4 - EMI_OFF)
+#define EMI_TTYPE18_CONA (0xFD8 - EMI_OFF)
+#define EMI_TTYPE18_CONB (0xFDC - EMI_OFF)
+#define EMI_TTYPE19_CONA (0xFE0 - EMI_OFF)
+#define EMI_TTYPE19_CONB (0xFE4 - EMI_OFF)
+#define EMI_TTYPE20_CONA (0xFE8 - EMI_OFF)
+#define EMI_TTYPE20_CONB (0xFEC - EMI_OFF)
+#define EMI_TTYPE21_CONA (0xFF0 - EMI_OFF)
+#define EMI_TTYPE21_CONB (0xFF4 - EMI_OFF)
+
+/* low effeciency */
+#define CHN_EMI_LOWEFF_CTL0 (0x500)
+// #define WMASK_PID_OFFSET
+// #define AGEXP_PID_OFFSET
+
+
+/* met_drv define & global var */
+#define CNT_COUNTDOWN (0)
+
+/* extern struct metdevice met_sspm_emi; */
+
+extern int emi_tsct_enable;
+extern int emi_mdct_enable;
+extern int emi_TP_busfiltr_enable;
+extern int mdmcu_sel_enable;
+extern unsigned int rd_mdmcu_rsv_num;
+extern int metemi_func_opt;
+
+extern int met_emi_regdump;
+
+extern int msel_enable;
+extern unsigned int msel_group1;
+extern unsigned int msel_group2;
+extern unsigned int msel_group3;
+
+extern struct kobject *kobj_emi;
+extern int rwtype;
+
+ /* 1ms */
+extern int bw_limiter_enable;
+
+extern int ttype1_16_en;
+extern int ttype17_21_en;
+
+extern int dramc_pdir_enable;
+extern int dram_chann_num;
+
+extern int high_priority_filter;
+
+extern int ttype_master_val[21];
+extern int ttype_busid_val[21];
+extern int ttype_nbeat_val[21];
+extern int ttype_nbyte_val[21];
+extern int ttype_burst_val[21];
+extern int ttype_rw_val[21];
+
+extern unsigned int msel_group_ext_val[WSCT_AMOUNT];
+extern unsigned int wsct_rw_val[WSCT_AMOUNT];
+extern char* const delim_comma;
+extern char* const delim_coclon;
+
+extern char msel_group_ext[FILE_NODE_DATA_LEN];
+
+extern unsigned int WSCT_HPRI_DIS[WSCT_AMOUNT];
+extern unsigned int WSCT_HPRI_SEL[WSCT_AMOUNT];
+extern char wsct_high_priority_enable[FILE_NODE_DATA_LEN];
+
+/*wsct_busid*/
+extern unsigned int wsct_busid_val[WSCT_AMOUNT];
+extern unsigned int wsct_idMask_val[WSCT_AMOUNT];
+extern char wsct_busid[FILE_NODE_DATA_LEN];
+
+/* wsct_chn_rank_sel */
+extern unsigned int wsct_chn_rank_sel_val[WSCT_AMOUNT];
+extern char wsct_chn_rank_sel[FILE_NODE_DATA_LEN];
+
+/* wsct_burst_range */
+extern unsigned int wsct_byte_low_bnd_val[WSCT_AMOUNT];
+extern unsigned int wsct_byte_up_bnd_val[WSCT_AMOUNT];
+extern unsigned int wsct_byte_bnd_dis[WSCT_AMOUNT];
+extern char wsct_burst_range[FILE_NODE_DATA_LEN];
+
+/* tsct_busid_enable */
+extern unsigned int tsct_busid_enable_val[TSCT_AMOUNT];
+extern char tsct_busid_enable[FILE_NODE_DATA_LEN];
+/* ttype_high_priority_ext */
+extern unsigned int TTYPE_HPRI_SEL[BM_COUNTER_MAX];
+extern char ttype_high_priority_ext[FILE_NODE_DATA_LEN];
+/* ttype_busid_ext */
+extern unsigned int ttype_idMask_val[BM_COUNTER_MAX];
+extern char ttype_busid_ext[FILE_NODE_DATA_LEN];
+/* ttype_chn_rank_sel */
+extern unsigned int ttype_chn_rank_sel_val[BM_COUNTER_MAX];
+extern char ttype_chn_rank_sel[FILE_NODE_DATA_LEN];
+
+/* ttype_burst_range */
+extern unsigned int ttype_byte_low_bnd_val[BM_COUNTER_MAX];
+extern unsigned int ttype_byte_up_bnd_val[BM_COUNTER_MAX];
+extern unsigned int ttype_byte_bnd_dis[BM_COUNTER_MAX];
+extern char ttype_burst_range[FILE_NODE_DATA_LEN];
+
+
+extern unsigned int wmask_msel_val[MET_MAX_DRAM_CH_NUM];
+extern char wmask_msel[FILE_NODE_DATA_LEN];
+
+extern unsigned int ageexp_msel_val[MET_MAX_DRAM_CH_NUM];
+extern unsigned int ageexp_rw_val[MET_MAX_DRAM_CH_NUM];
+extern char ageexp_msel_rw[FILE_NODE_DATA_LEN];
+
+extern char default_val[FILE_NODE_DATA_LEN];
+
+extern int reserve_wsct_setting;
+
+extern struct kobj_attribute clear_setting_attr;
+extern struct kobj_attribute msel_group_ext_attr;
+extern struct kobj_attribute wsct_rw_attr;
+extern struct kobj_attribute wsct_high_priority_enable_attr;
+extern struct kobj_attribute wsct_busid_attr;
+extern struct kobj_attribute wsct_chn_rank_sel_attr;
+extern struct kobj_attribute wsct_burst_range_attr;
+extern struct kobj_attribute tsct_busid_enable_attr;
+extern struct kobj_attribute ttype_high_priority_ext_attr;
+extern struct kobj_attribute ttype_busid_ext_attr;
+extern struct kobj_attribute ttype_chn_rank_sel_attr;
+extern struct kobj_attribute ttype_burst_range_attr;
+
+/* for header print*/
+#define MAX_HEADER_LEN (1024 * 6)
+extern char header_str[MAX_HEADER_LEN];
+extern unsigned int output_header_len;
+extern unsigned int output_str_len;
+
+
+
+extern int emi_use_ondiemet;
+extern int emi_inited;
+
+enum SSPM_Mode {
+ CUSTOMER_MODE = 0x0,
+ UNDEFINE_MODE = 0x1,
+ INTERNAL_MODE = 0X2780
+};
+
+
+/*======================================================================*/
+/* KOBJ Declarations */
+/*======================================================================*/
+DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable);
+DECLARE_KOBJ_ATTR_INT(emi_regdump, met_emi_regdump);
+DECLARE_KOBJ_ATTR_INT(msel_enable, msel_enable);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group1, msel_group1, msel_group1 > 0 && msel_group1 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group2, msel_group2, msel_group2 > 0 && msel_group2 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group3, msel_group3, msel_group3 > 0 && msel_group3 <= BM_MASTER_ALL);
+
+
+/* KOBJ: rwtype */
+DECLARE_KOBJ_ATTR_INT_CHECK(rwtype, rwtype, rwtype >= 0 && rwtype <= BM_WRITE_ONLY);
+
+
+/* KOBJ: ttype1_16_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype1_16_en,
+ KOBJ_ITEM_LIST(
+ { BM_TTYPE1_16_ENABLE, "ENABLE" },
+ { BM_TTYPE1_16_DISABLE, "DISABLE" }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST(ttype1_16_en, ttype1_16_en, ttype1_16_en);
+
+/* KOBJ: ttype17_21_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype17_21_en,
+ KOBJ_ITEM_LIST(
+ { BM_TTYPE17_21_ENABLE, "ENABLE" },
+ { BM_TTYPE17_21_DISABLE, "DISABLE" }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST(ttype17_21_en, ttype17_21_en, ttype17_21_en);
+
+/* KOBJ: bw_limiter_enable */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ bw_limiter_enable,
+ KOBJ_ITEM_LIST(
+ { BM_BW_LIMITER_ENABLE, "ENABLE" },
+ { BM_BW_LIMITER_DISABLE, "DISABLE" }
+ )
+ );
+
+DECLARE_KOBJ_ATTR_STR_LIST(bw_limiter_enable, bw_limiter_enable, bw_limiter_enable);
+
+/* KOBJ: ttype_master */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_master,
+ KOBJ_ITEM_LIST(
+ { BM_MASTER_M0, "M0" },
+ { BM_MASTER_M1, "M1" },
+ { BM_MASTER_M2, "M2" },
+ { BM_MASTER_M3, "M3" },
+ { BM_MASTER_M4, "M4" },
+ { BM_MASTER_M5, "M5" },
+ { BM_MASTER_M6, "M6" },
+ { BM_MASTER_M7, "M7" }
+ )
+ );
+
+
+/* KOBJ: ttypeX_nbeat, ttypeX_nbyte, ttypeX_burst */
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+ ttype_nbeat,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_1BEAT, 1 },
+ { BM_TRANS_TYPE_2BEAT, 2 },
+ { BM_TRANS_TYPE_3BEAT, 3 },
+ { BM_TRANS_TYPE_4BEAT, 4 },
+ { BM_TRANS_TYPE_5BEAT, 5 },
+ { BM_TRANS_TYPE_6BEAT, 6 },
+ { BM_TRANS_TYPE_7BEAT, 7 },
+ { BM_TRANS_TYPE_8BEAT, 8 },
+ { BM_TRANS_TYPE_9BEAT, 9 },
+ { BM_TRANS_TYPE_10BEAT, 10 },
+ { BM_TRANS_TYPE_11BEAT, 11 },
+ { BM_TRANS_TYPE_12BEAT, 12 },
+ { BM_TRANS_TYPE_13BEAT, 13 },
+ { BM_TRANS_TYPE_14BEAT, 14 },
+ { BM_TRANS_TYPE_15BEAT, 15 },
+ { BM_TRANS_TYPE_16BEAT, 16 }
+ )
+ );
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+ ttype_nbyte,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_1Byte, 1 },
+ { BM_TRANS_TYPE_2Byte, 2 },
+ { BM_TRANS_TYPE_4Byte, 4 },
+ { BM_TRANS_TYPE_8Byte, 8 },
+ { BM_TRANS_TYPE_16Byte, 16 },
+ { BM_TRANS_TYPE_32Byte, 32 }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_burst,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_BURST_INCR, "INCR" },
+ { BM_TRANS_TYPE_BURST_WRAP, "WRAP" }
+ )
+ );
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_rw,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_RW_DEFAULT, "DEFAULT" },
+ { BM_TRANS_RW_READONLY, "R" },
+ { BM_TRANS_RW_WRITEONLY, "W" },
+ { BM_TRANS_RW_RWBOTH, "BOTH" }
+ )
+ );
+
+
+DECLARE_KOBJ_ATTR_INT(dramc_pdir_enable, dramc_pdir_enable);
+
+DECLARE_KOBJ_ATTR_HEX(high_priority_filter, high_priority_filter);
+
+#define DECLARE_KOBJ_TTYPE_MASTER(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _master, ttype_master_val[nr - 1], ttype_master)
+
+#define DECLARE_KOBJ_TTYPE_NBEAT(nr) \
+ DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbeat, ttype_nbeat_val[nr - 1], ttype_nbeat)
+
+#define DECLARE_KOBJ_TTYPE_NBYTE(nr) \
+ DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbyte, ttype_nbyte_val[nr - 1], ttype_nbyte)
+
+#define DECLARE_KOBJ_TTYPE_BURST(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _burst, ttype_burst_val[nr - 1], ttype_burst)
+
+#define DECLARE_KOBJ_TTYPE_RW(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _rw, ttype_rw_val[nr - 1], ttype_rw)
+
+#define DECLARE_KOBJ_TTYPE_BUSID_VAL(nr) \
+ DECLARE_KOBJ_ATTR_HEX(ttype ## nr ## _busid, ttype_busid_val[nr - 1])
+
+DECLARE_KOBJ_TTYPE_MASTER(1);
+DECLARE_KOBJ_TTYPE_NBEAT(1);
+DECLARE_KOBJ_TTYPE_NBYTE(1);
+DECLARE_KOBJ_TTYPE_BURST(1);
+DECLARE_KOBJ_TTYPE_RW(1);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(1);
+
+DECLARE_KOBJ_TTYPE_MASTER(2);
+DECLARE_KOBJ_TTYPE_NBEAT(2);
+DECLARE_KOBJ_TTYPE_NBYTE(2);
+DECLARE_KOBJ_TTYPE_BURST(2);
+DECLARE_KOBJ_TTYPE_RW(2);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(2);
+
+DECLARE_KOBJ_TTYPE_MASTER(3);
+DECLARE_KOBJ_TTYPE_NBEAT(3);
+DECLARE_KOBJ_TTYPE_NBYTE(3);
+DECLARE_KOBJ_TTYPE_BURST(3);
+DECLARE_KOBJ_TTYPE_RW(3);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(3);
+
+DECLARE_KOBJ_TTYPE_MASTER(4);
+DECLARE_KOBJ_TTYPE_NBEAT(4);
+DECLARE_KOBJ_TTYPE_NBYTE(4);
+DECLARE_KOBJ_TTYPE_BURST(4);
+DECLARE_KOBJ_TTYPE_RW(4);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(4);
+
+DECLARE_KOBJ_TTYPE_MASTER(5);
+DECLARE_KOBJ_TTYPE_NBEAT(5);
+DECLARE_KOBJ_TTYPE_NBYTE(5);
+DECLARE_KOBJ_TTYPE_BURST(5);
+DECLARE_KOBJ_TTYPE_RW(5);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(5);
+
+DECLARE_KOBJ_TTYPE_MASTER(6);
+DECLARE_KOBJ_TTYPE_NBEAT(6);
+DECLARE_KOBJ_TTYPE_NBYTE(6);
+DECLARE_KOBJ_TTYPE_BURST(6);
+DECLARE_KOBJ_TTYPE_RW(6);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(6);
+
+DECLARE_KOBJ_TTYPE_MASTER(7);
+DECLARE_KOBJ_TTYPE_NBEAT(7);
+DECLARE_KOBJ_TTYPE_NBYTE(7);
+DECLARE_KOBJ_TTYPE_BURST(7);
+DECLARE_KOBJ_TTYPE_RW(7);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(7);
+
+DECLARE_KOBJ_TTYPE_MASTER(8);
+DECLARE_KOBJ_TTYPE_NBEAT(8);
+DECLARE_KOBJ_TTYPE_NBYTE(8);
+DECLARE_KOBJ_TTYPE_BURST(8);
+DECLARE_KOBJ_TTYPE_RW(8);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(8);
+
+DECLARE_KOBJ_TTYPE_MASTER(9);
+DECLARE_KOBJ_TTYPE_NBEAT(9);
+DECLARE_KOBJ_TTYPE_NBYTE(9);
+DECLARE_KOBJ_TTYPE_BURST(9);
+DECLARE_KOBJ_TTYPE_RW(9);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(9);
+
+DECLARE_KOBJ_TTYPE_MASTER(10);
+DECLARE_KOBJ_TTYPE_NBEAT(10);
+DECLARE_KOBJ_TTYPE_NBYTE(10);
+DECLARE_KOBJ_TTYPE_BURST(10);
+DECLARE_KOBJ_TTYPE_RW(10);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(10);
+
+DECLARE_KOBJ_TTYPE_MASTER(11);
+DECLARE_KOBJ_TTYPE_NBEAT(11);
+DECLARE_KOBJ_TTYPE_NBYTE(11);
+DECLARE_KOBJ_TTYPE_BURST(11);
+DECLARE_KOBJ_TTYPE_RW(11);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(11);
+
+DECLARE_KOBJ_TTYPE_MASTER(12);
+DECLARE_KOBJ_TTYPE_NBEAT(12);
+DECLARE_KOBJ_TTYPE_NBYTE(12);
+DECLARE_KOBJ_TTYPE_BURST(12);
+DECLARE_KOBJ_TTYPE_RW(12);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(12);
+
+DECLARE_KOBJ_TTYPE_MASTER(13);
+DECLARE_KOBJ_TTYPE_NBEAT(13);
+DECLARE_KOBJ_TTYPE_NBYTE(13);
+DECLARE_KOBJ_TTYPE_BURST(13);
+DECLARE_KOBJ_TTYPE_RW(13);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(13);
+
+DECLARE_KOBJ_TTYPE_MASTER(14);
+DECLARE_KOBJ_TTYPE_NBEAT(14);
+DECLARE_KOBJ_TTYPE_NBYTE(14);
+DECLARE_KOBJ_TTYPE_BURST(14);
+DECLARE_KOBJ_TTYPE_RW(14);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(14);
+
+DECLARE_KOBJ_TTYPE_MASTER(15);
+DECLARE_KOBJ_TTYPE_NBEAT(15);
+DECLARE_KOBJ_TTYPE_NBYTE(15);
+DECLARE_KOBJ_TTYPE_BURST(15);
+DECLARE_KOBJ_TTYPE_RW(15);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(15);
+
+DECLARE_KOBJ_TTYPE_MASTER(16);
+DECLARE_KOBJ_TTYPE_NBEAT(16);
+DECLARE_KOBJ_TTYPE_NBYTE(16);
+DECLARE_KOBJ_TTYPE_BURST(16);
+DECLARE_KOBJ_TTYPE_RW(16);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(16);
+
+DECLARE_KOBJ_TTYPE_MASTER(17);
+DECLARE_KOBJ_TTYPE_NBEAT(17);
+DECLARE_KOBJ_TTYPE_NBYTE(17);
+DECLARE_KOBJ_TTYPE_BURST(17);
+DECLARE_KOBJ_TTYPE_RW(17);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(17);
+
+DECLARE_KOBJ_TTYPE_MASTER(18);
+DECLARE_KOBJ_TTYPE_NBEAT(18);
+DECLARE_KOBJ_TTYPE_NBYTE(18);
+DECLARE_KOBJ_TTYPE_BURST(18);
+DECLARE_KOBJ_TTYPE_RW(18);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(18);
+
+DECLARE_KOBJ_TTYPE_MASTER(19);
+DECLARE_KOBJ_TTYPE_NBEAT(19);
+DECLARE_KOBJ_TTYPE_NBYTE(19);
+DECLARE_KOBJ_TTYPE_BURST(19);
+DECLARE_KOBJ_TTYPE_RW(19);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(19);
+
+DECLARE_KOBJ_TTYPE_MASTER(20);
+DECLARE_KOBJ_TTYPE_NBEAT(20);
+DECLARE_KOBJ_TTYPE_NBYTE(20);
+DECLARE_KOBJ_TTYPE_BURST(20);
+DECLARE_KOBJ_TTYPE_RW(20);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(20);
+
+DECLARE_KOBJ_TTYPE_MASTER(21);
+DECLARE_KOBJ_TTYPE_NBEAT(21);
+DECLARE_KOBJ_TTYPE_NBYTE(21);
+DECLARE_KOBJ_TTYPE_BURST(21);
+DECLARE_KOBJ_TTYPE_RW(21);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(21);
+
+
+#define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \
+ do { \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _master); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _nbeat); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _nbyte); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _burst); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _busid); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _rw); \
+ } while (0)
+
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(high_priority_filter); \
+ KOBJ_ATTR_ITEM(emi_TP_busfiltr_enable); \
+ KOBJ_ATTR_ITEM(msel_enable); \
+ KOBJ_ATTR_ITEM(msel_group1); \
+ KOBJ_ATTR_ITEM(msel_group2); \
+ KOBJ_ATTR_ITEM(msel_group3); \
+ KOBJ_ATTR_ITEM(rwtype); \
+ KOBJ_ATTR_ITEM(ttype17_21_en); \
+ KOBJ_ATTR_ITEM(ttype1_16_en); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(1); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(2); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(3); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(4); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(5); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(6); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(7); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(8); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(9); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(10); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(11); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(12); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(13); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(14); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(15); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(16); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(17); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(18); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(19); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(20); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(21); \
+ KOBJ_ATTR_ITEM(bw_limiter_enable); \
+ KOBJ_ATTR_ITEM(dramc_pdir_enable); \
+ KOBJ_ATTR_ITEM(clear_setting);\
+ KOBJ_ATTR_ITEM(msel_group_ext);\
+ KOBJ_ATTR_ITEM(wsct_rw);\
+ KOBJ_ATTR_ITEM(wsct_high_priority_enable);\
+ KOBJ_ATTR_ITEM(wsct_busid);\
+ KOBJ_ATTR_ITEM(wsct_chn_rank_sel);\
+ KOBJ_ATTR_ITEM(wsct_burst_range);\
+ KOBJ_ATTR_ITEM(tsct_busid_enable);\
+ KOBJ_ATTR_ITEM(ttype_high_priority_ext);\
+ KOBJ_ATTR_ITEM(ttype_busid_ext);\
+ KOBJ_ATTR_ITEM(ttype_chn_rank_sel);\
+ KOBJ_ATTR_ITEM(ttype_burst_range);\
+ KOBJ_ATTR_ITEM(reserve_wsct_setting);\
+ KOBJ_ATTR_ITEM(emi_regdump); \
+ KOBJ_ATTR_ITEM(wmask_msel); \
+ KOBJ_ATTR_ITEM(ageexp_msel_rw); \
+ KOBJ_ATTR_ITEM(default_val); \
+ KOBJ_ATTR_ITEM(sspm_support_feature); \
+ } while (0)
+
+
+DECLARE_KOBJ_ATTR_INT(reserve_wsct_setting, reserve_wsct_setting);
+
+extern int MET_BM_Init(void);
+extern void MET_BM_DeInit(void);
+extern void MET_BM_SaveCfg(void);
+extern void MET_BM_RestoreCfg(void);
+
+
+
+extern int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+ const unsigned int master, const unsigned int trans_type);
+extern int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val);
+extern int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable);
+extern int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master);
+extern int MET_BM_SetbusID_En(const unsigned int counter_num,
+ const unsigned int enable);
+extern int MET_BM_SetbusID(const unsigned int counter_num,
+ const unsigned int id);
+extern int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable);
+extern int MET_BM_SetLatencyCounter(unsigned int enable);
+extern void MET_BM_SetReadWriteType(const unsigned int ReadWriteType);
+
+extern unsigned int MET_EMI_GetDramRankNum(void);
+extern unsigned int MET_EMI_GetDramRankNum_CHN1(void);
+
+
+extern unsigned int MET_EMI_GetDramChannNum(void);
+extern unsigned int MET_EMI_Get_CONH_2ND(void);
+
+/* SEDA 3.5 NEW */
+extern int MET_BM_SetWSCT_master_rw(unsigned int *master , unsigned int *rw);
+extern int MET_BM_SetWSCT_high_priority(unsigned int *disable, unsigned int *select);
+extern int MET_BM_SetWSCT_busid_idmask(unsigned int *busid, unsigned int *idMask);
+extern int MET_BM_SetWSCT_chn_rank_sel(unsigned int *chn_rank_sel);
+extern int MET_BM_SetWSCT_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd);
+extern int MET_BM_SetTSCT_busid_enable(unsigned int *enable);
+extern int MET_BM_SetTtype_high_priority_sel(unsigned int _high_priority_filter, unsigned int *select);
+extern int MET_BM_SetTtype_busid_idmask(unsigned int *busid, unsigned int *idMask, int _ttype1_16_en, int _ttype17_21_en);
+extern int MET_BM_SetTtype_chn_rank_sel(unsigned int *chn_rank_sel);
+extern int MET_BM_SetTtype_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd);
+extern unsigned int MET_EMI_Get_BaseClock_Rate(void);
+
+
+/* file node controll */
+extern void _clear_msel_group_ext(void);
+extern ssize_t msel_group_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t msel_group_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_wsct_rw(void);
+extern ssize_t wsct_rw_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t wsct_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_wsct_high_priority_enable(void);
+extern ssize_t wsct_high_priority_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t wsct_high_priority_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_wsct_busid(void);
+extern ssize_t wsct_busid_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t wsct_busid_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_wsct_chn_rank_sel(void);
+extern ssize_t wsct_chn_rank_sel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t wsct_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_wsct_burst_range(void);
+extern ssize_t wsct_burst_range_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t wsct_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_tsct_busid_enable(void);
+extern ssize_t tsct_busid_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t tsct_busid_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_ttype_high_priority_ext(void);
+extern ssize_t ttype_high_priority_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t ttype_high_priority_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_ttype_busid_ext(void);
+extern ssize_t ttype_busid_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t ttype_busid_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_ttype_chn_rank_sel(void);
+extern ssize_t ttype_chn_rank_sel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t ttype_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+extern void _clear_ttype_burst_range(void);
+extern ssize_t ttype_burst_range_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t ttype_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+
+extern ssize_t wmask_msel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t wmask_msel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+
+extern ssize_t ageexp_msel_rw_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+extern ssize_t ageexp_msel_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+
+extern void _clear_setting(void);
+extern ssize_t clear_setting_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n);
+
+extern void emi_init(void);
+extern void emi_uninit(void);
+
+extern void MET_BM_IPI_configs(void);
+extern void MET_BM_IPI_REGISTER_CB(void);
+
+
+extern unsigned int get_sspm_support_feature(void);
+extern unsigned check_sspm_support(unsigned int module_id);
+extern int emi_create_header(char *buf, int buf_len);
+
+extern int met_emi_create_basic(struct kobject *parent, struct metdevice *emi_dev);
+extern void met_emi_delete_basic(void);
+extern void met_emi_resume_basic(void);
+
+extern int do_emi(void);
+extern int emi_print_header_basic(char *buf, int len);
+extern void ondiemet_emi_start_basic(void);
+extern void ondiemet_emi_stop_basic(void);
+
+extern unsigned met_get_dram_data_rate(void);
+extern unsigned int MET_GET_DRAM_TYPE(void);
+
+#endif /* !__MT_MET_EMI_BM_BASIC_H__ */
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm_function.h b/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm_function.h
new file mode 100644
index 0000000..6e1209c
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3_5/mtk_emi_bm_function.h
@@ -0,0 +1,9 @@
+#define emi_help_msg " --emi monitor EMI banwidth\n"
+
+extern int met_emi_create_basic(struct kobject *parent, struct metdevice *emi_dev);
+extern void met_emi_delete_basic(void);
+extern void met_emi_resume_basic(void);
+
+extern int emi_print_header_basic(char *buf, int len);
+extern void ondiemet_emi_start_basic(void);
+extern void ondiemet_emi_stop_basic(void);
\ No newline at end of file
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3_6/met_emi.c b/src/devtools/met_drv_v2/common/emi/SEDA3_6/met_emi.c
new file mode 100644
index 0000000..11adb93
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3_6/met_emi.c
@@ -0,0 +1,2318 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "core_plf_init.h"
+#include "mtk_emi_bm.h"
+#include "interface.h"
+#include "met_dramc.h"
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT)
+#include "sspm/ondiemet_sspm.h"
+#elif defined(TINYSYS_SSPM_SUPPORT)
+#include "tinysys_sspm.h"
+#include "tinysys_mgr.h" /* for ondiemet_module */
+#endif
+#endif
+
+#define MAX_HEADER_LEN (1024 * 6)
+static char header_str[MAX_HEADER_LEN];
+
+static unsigned int output_header_len;
+static unsigned int output_str_len;
+
+/* #define FILE_NODE_DBG */
+
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+/*ondiemet emi sampling interval in us */
+int emi_tsct_enable = 1;
+int emi_mdct_enable = 1;
+int emi_TP_busfiltr_enable;
+
+
+/* Dynamic MonitorCounter selection !!!EXPERIMENT!!! */
+static int msel_enable;
+static unsigned int msel_group1 = BM_MASTER_ALL;
+static unsigned int msel_group2 = BM_MASTER_ALL;
+static unsigned int msel_group3 = BM_MASTER_ALL;
+
+
+/* Global variables */
+static struct kobject *kobj_emi;
+static int rwtype = BM_BOTH_READ_WRITE;
+
+/* BW Limiter */
+/*#define CNT_COUNTDOWN (1000-1)*/ /* 1000 * 1ms = 1sec */
+#define CNT_COUNTDOWN (0) /* 1ms */
+/* static int countdown; */
+static int bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+
+/* TTYPE counter */
+static int ttype1_16_en = BM_TTYPE1_16_DISABLE;
+static int ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+static int dramc_pdir_enable;
+static int dram_chann_num = 1;
+
+enum SSPM_Mode {
+ CUSTOMER_MODE = 0x0,
+ UNDEFINE_MODE = 0x1,
+ INTERNAL_MODE = 0X2780
+};
+
+
+
+/*======================================================================*/
+/* KOBJ Declarations */
+/*======================================================================*/
+
+
+DECLARE_KOBJ_ATTR_INT(emi_TP_busfiltr_enable, emi_TP_busfiltr_enable);
+
+
+DECLARE_KOBJ_ATTR_INT(msel_enable, msel_enable);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group1, msel_group1, msel_group1 > 0 && msel_group1 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group2, msel_group2, msel_group2 > 0 && msel_group2 <= BM_MASTER_ALL);
+DECLARE_KOBJ_ATTR_HEX_CHECK(msel_group3, msel_group3, msel_group3 > 0 && msel_group3 <= BM_MASTER_ALL);
+
+
+
+/* KOBJ: rwtype */
+DECLARE_KOBJ_ATTR_INT_CHECK(rwtype, rwtype, rwtype >= 0 && rwtype <= BM_WRITE_ONLY);
+
+/*
+static unsigned int get_emi_clock_rate(unsigned int dram_data_rate_MHz)
+{
+ unsigned int DRAM_TYPE;
+
+ if (mtk_dramc_get_ddr_type_symbol) {
+ DRAM_TYPE = mtk_dramc_get_ddr_type_symbol();
+
+ if ((DRAM_TYPE == 5) || (DRAM_TYPE == 6) || (DRAM_TYPE == 7))
+ return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP4 / DRAM_DATARATE;
+ else
+ return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP3 / DRAM_DATARATE;
+ } else {
+ METERROR("[%s][%d]mtk_dramc_get_ddr_type_symbol = NULL , use the TYPE_LPDDR4 setting\n", __func__, __LINE__);
+ return dram_data_rate_MHz / DRAM_EMI_BASECLOCK_RATE_LP4 / DRAM_DATARATE;
+ }
+}
+*/
+
+/* KOBJ: ttype1_16_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype1_16_en,
+ KOBJ_ITEM_LIST(
+ { BM_TTYPE1_16_ENABLE, "ENABLE" },
+ { BM_TTYPE1_16_DISABLE, "DISABLE" }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST(ttype1_16_en, ttype1_16_en, ttype1_16_en);
+
+/* KOBJ: ttype17_21_en */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype17_21_en,
+ KOBJ_ITEM_LIST(
+ { BM_TTYPE17_21_ENABLE, "ENABLE" },
+ { BM_TTYPE17_21_DISABLE, "DISABLE" }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST(ttype17_21_en, ttype17_21_en, ttype17_21_en);
+
+/* KOBJ: bw_limiter_enable */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ bw_limiter_enable,
+ KOBJ_ITEM_LIST(
+ { BM_BW_LIMITER_ENABLE, "ENABLE" },
+ { BM_BW_LIMITER_DISABLE, "DISABLE" }
+ )
+ );
+
+DECLARE_KOBJ_ATTR_STR_LIST(bw_limiter_enable, bw_limiter_enable, bw_limiter_enable);
+
+/* KOBJ: ttype_master */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_master,
+ KOBJ_ITEM_LIST(
+ { BM_MASTER_M0, "M0" },
+ { BM_MASTER_M1, "M1" },
+ { BM_MASTER_M2, "M2" },
+ { BM_MASTER_M3, "M3" },
+ { BM_MASTER_M4, "M4" },
+ { BM_MASTER_M5, "M5" },
+ { BM_MASTER_M6, "M6" },
+ { BM_MASTER_M7, "M7" }
+ )
+ );
+
+
+/* KOBJ: ttypeX_nbeat, ttypeX_nbyte, ttypeX_burst */
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+ ttype_nbeat,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_1BEAT, 1 },
+ { BM_TRANS_TYPE_2BEAT, 2 },
+ { BM_TRANS_TYPE_3BEAT, 3 },
+ { BM_TRANS_TYPE_4BEAT, 4 },
+ { BM_TRANS_TYPE_5BEAT, 5 },
+ { BM_TRANS_TYPE_6BEAT, 6 },
+ { BM_TRANS_TYPE_7BEAT, 7 },
+ { BM_TRANS_TYPE_8BEAT, 8 },
+ { BM_TRANS_TYPE_9BEAT, 9 },
+ { BM_TRANS_TYPE_10BEAT, 10 },
+ { BM_TRANS_TYPE_11BEAT, 11 },
+ { BM_TRANS_TYPE_12BEAT, 12 },
+ { BM_TRANS_TYPE_13BEAT, 13 },
+ { BM_TRANS_TYPE_14BEAT, 14 },
+ { BM_TRANS_TYPE_15BEAT, 15 },
+ { BM_TRANS_TYPE_16BEAT, 16 }
+ )
+ );
+DECLARE_KOBJ_ATTR_INT_LIST_ITEM(
+ ttype_nbyte,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_1Byte, 1 },
+ { BM_TRANS_TYPE_2Byte, 2 },
+ { BM_TRANS_TYPE_4Byte, 4 },
+ { BM_TRANS_TYPE_8Byte, 8 },
+ { BM_TRANS_TYPE_16Byte, 16 },
+ { BM_TRANS_TYPE_32Byte, 32 }
+ )
+ );
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_burst,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_TYPE_BURST_INCR, "INCR" },
+ { BM_TRANS_TYPE_BURST_WRAP, "WRAP" }
+ )
+ );
+
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ ttype_rw,
+ KOBJ_ITEM_LIST(
+ { BM_TRANS_RW_DEFAULT, "DEFAULT" },
+ { BM_TRANS_RW_READONLY, "R" },
+ { BM_TRANS_RW_WRITEONLY, "W" },
+ { BM_TRANS_RW_RWBOTH, "BOTH" }
+ )
+ );
+
+
+DECLARE_KOBJ_ATTR_INT(dramc_pdir_enable, dramc_pdir_enable);
+
+/*enable high priority filter*/
+static int high_priority_filter;
+DECLARE_KOBJ_ATTR_HEX(high_priority_filter, high_priority_filter);
+
+
+
+/**/
+static int ttype_master_val[21];
+static int ttype_busid_val[21];
+static int ttype_nbeat_val[21];
+static int ttype_nbyte_val[21];
+static int ttype_burst_val[21];
+static int ttype_rw_val[21];
+
+#define DECLARE_KOBJ_TTYPE_MASTER(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _master, ttype_master_val[nr - 1], ttype_master)
+
+#define DECLARE_KOBJ_TTYPE_NBEAT(nr) \
+ DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbeat, ttype_nbeat_val[nr - 1], ttype_nbeat)
+
+#define DECLARE_KOBJ_TTYPE_NBYTE(nr) \
+ DECLARE_KOBJ_ATTR_INT_LIST(ttype ## nr ## _nbyte, ttype_nbyte_val[nr - 1], ttype_nbyte)
+
+#define DECLARE_KOBJ_TTYPE_BURST(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _burst, ttype_burst_val[nr - 1], ttype_burst)
+
+#define DECLARE_KOBJ_TTYPE_RW(nr) \
+ DECLARE_KOBJ_ATTR_STR_LIST(ttype ## nr ## _rw, ttype_rw_val[nr - 1], ttype_rw)
+
+#define DECLARE_KOBJ_TTYPE_BUSID_VAL(nr) \
+ DECLARE_KOBJ_ATTR_HEX(ttype ## nr ## _busid, ttype_busid_val[nr - 1])
+
+DECLARE_KOBJ_TTYPE_MASTER(1);
+DECLARE_KOBJ_TTYPE_NBEAT(1);
+DECLARE_KOBJ_TTYPE_NBYTE(1);
+DECLARE_KOBJ_TTYPE_BURST(1);
+DECLARE_KOBJ_TTYPE_RW(1);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(1);
+
+DECLARE_KOBJ_TTYPE_MASTER(2);
+DECLARE_KOBJ_TTYPE_NBEAT(2);
+DECLARE_KOBJ_TTYPE_NBYTE(2);
+DECLARE_KOBJ_TTYPE_BURST(2);
+DECLARE_KOBJ_TTYPE_RW(2);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(2);
+
+DECLARE_KOBJ_TTYPE_MASTER(3);
+DECLARE_KOBJ_TTYPE_NBEAT(3);
+DECLARE_KOBJ_TTYPE_NBYTE(3);
+DECLARE_KOBJ_TTYPE_BURST(3);
+DECLARE_KOBJ_TTYPE_RW(3);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(3);
+
+DECLARE_KOBJ_TTYPE_MASTER(4);
+DECLARE_KOBJ_TTYPE_NBEAT(4);
+DECLARE_KOBJ_TTYPE_NBYTE(4);
+DECLARE_KOBJ_TTYPE_BURST(4);
+DECLARE_KOBJ_TTYPE_RW(4);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(4);
+
+DECLARE_KOBJ_TTYPE_MASTER(5);
+DECLARE_KOBJ_TTYPE_NBEAT(5);
+DECLARE_KOBJ_TTYPE_NBYTE(5);
+DECLARE_KOBJ_TTYPE_BURST(5);
+DECLARE_KOBJ_TTYPE_RW(5);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(5);
+
+DECLARE_KOBJ_TTYPE_MASTER(6);
+DECLARE_KOBJ_TTYPE_NBEAT(6);
+DECLARE_KOBJ_TTYPE_NBYTE(6);
+DECLARE_KOBJ_TTYPE_BURST(6);
+DECLARE_KOBJ_TTYPE_RW(6);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(6);
+
+DECLARE_KOBJ_TTYPE_MASTER(7);
+DECLARE_KOBJ_TTYPE_NBEAT(7);
+DECLARE_KOBJ_TTYPE_NBYTE(7);
+DECLARE_KOBJ_TTYPE_BURST(7);
+DECLARE_KOBJ_TTYPE_RW(7);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(7);
+
+DECLARE_KOBJ_TTYPE_MASTER(8);
+DECLARE_KOBJ_TTYPE_NBEAT(8);
+DECLARE_KOBJ_TTYPE_NBYTE(8);
+DECLARE_KOBJ_TTYPE_BURST(8);
+DECLARE_KOBJ_TTYPE_RW(8);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(8);
+
+DECLARE_KOBJ_TTYPE_MASTER(9);
+DECLARE_KOBJ_TTYPE_NBEAT(9);
+DECLARE_KOBJ_TTYPE_NBYTE(9);
+DECLARE_KOBJ_TTYPE_BURST(9);
+DECLARE_KOBJ_TTYPE_RW(9);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(9);
+
+DECLARE_KOBJ_TTYPE_MASTER(10);
+DECLARE_KOBJ_TTYPE_NBEAT(10);
+DECLARE_KOBJ_TTYPE_NBYTE(10);
+DECLARE_KOBJ_TTYPE_BURST(10);
+DECLARE_KOBJ_TTYPE_RW(10);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(10);
+
+DECLARE_KOBJ_TTYPE_MASTER(11);
+DECLARE_KOBJ_TTYPE_NBEAT(11);
+DECLARE_KOBJ_TTYPE_NBYTE(11);
+DECLARE_KOBJ_TTYPE_BURST(11);
+DECLARE_KOBJ_TTYPE_RW(11);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(11);
+
+DECLARE_KOBJ_TTYPE_MASTER(12);
+DECLARE_KOBJ_TTYPE_NBEAT(12);
+DECLARE_KOBJ_TTYPE_NBYTE(12);
+DECLARE_KOBJ_TTYPE_BURST(12);
+DECLARE_KOBJ_TTYPE_RW(12);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(12);
+
+DECLARE_KOBJ_TTYPE_MASTER(13);
+DECLARE_KOBJ_TTYPE_NBEAT(13);
+DECLARE_KOBJ_TTYPE_NBYTE(13);
+DECLARE_KOBJ_TTYPE_BURST(13);
+DECLARE_KOBJ_TTYPE_RW(13);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(13);
+
+DECLARE_KOBJ_TTYPE_MASTER(14);
+DECLARE_KOBJ_TTYPE_NBEAT(14);
+DECLARE_KOBJ_TTYPE_NBYTE(14);
+DECLARE_KOBJ_TTYPE_BURST(14);
+DECLARE_KOBJ_TTYPE_RW(14);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(14);
+
+DECLARE_KOBJ_TTYPE_MASTER(15);
+DECLARE_KOBJ_TTYPE_NBEAT(15);
+DECLARE_KOBJ_TTYPE_NBYTE(15);
+DECLARE_KOBJ_TTYPE_BURST(15);
+DECLARE_KOBJ_TTYPE_RW(15);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(15);
+
+DECLARE_KOBJ_TTYPE_MASTER(16);
+DECLARE_KOBJ_TTYPE_NBEAT(16);
+DECLARE_KOBJ_TTYPE_NBYTE(16);
+DECLARE_KOBJ_TTYPE_BURST(16);
+DECLARE_KOBJ_TTYPE_RW(16);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(16);
+
+DECLARE_KOBJ_TTYPE_MASTER(17);
+DECLARE_KOBJ_TTYPE_NBEAT(17);
+DECLARE_KOBJ_TTYPE_NBYTE(17);
+DECLARE_KOBJ_TTYPE_BURST(17);
+DECLARE_KOBJ_TTYPE_RW(17);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(17);
+
+DECLARE_KOBJ_TTYPE_MASTER(18);
+DECLARE_KOBJ_TTYPE_NBEAT(18);
+DECLARE_KOBJ_TTYPE_NBYTE(18);
+DECLARE_KOBJ_TTYPE_BURST(18);
+DECLARE_KOBJ_TTYPE_RW(18);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(18);
+
+DECLARE_KOBJ_TTYPE_MASTER(19);
+DECLARE_KOBJ_TTYPE_NBEAT(19);
+DECLARE_KOBJ_TTYPE_NBYTE(19);
+DECLARE_KOBJ_TTYPE_BURST(19);
+DECLARE_KOBJ_TTYPE_RW(19);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(19);
+
+DECLARE_KOBJ_TTYPE_MASTER(20);
+DECLARE_KOBJ_TTYPE_NBEAT(20);
+DECLARE_KOBJ_TTYPE_NBYTE(20);
+DECLARE_KOBJ_TTYPE_BURST(20);
+DECLARE_KOBJ_TTYPE_RW(20);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(20);
+
+DECLARE_KOBJ_TTYPE_MASTER(21);
+DECLARE_KOBJ_TTYPE_NBEAT(21);
+DECLARE_KOBJ_TTYPE_NBYTE(21);
+DECLARE_KOBJ_TTYPE_BURST(21);
+DECLARE_KOBJ_TTYPE_RW(21);
+DECLARE_KOBJ_TTYPE_BUSID_VAL(21);
+
+
+static unsigned int get_sspm_support_feature(void)
+{
+ unsigned int rdata=0;
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ int ret, i;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_REQ_AP2MD ;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+#endif
+#endif
+ return rdata;
+}
+
+/* SEDA 3.5 ext */
+static unsigned int msel_group_ext_val[WSCT_AMOUNT];
+static unsigned int wsct_rw_val[WSCT_AMOUNT];
+
+char* const delim_comma = ",";
+char* const delim_coclon = ":";
+
+
+char msel_group_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_msel_group_ext(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ msel_group_ext_val[i] = BM_MASTER_ALL;
+ }
+
+ /*WSCT 4~5 default is ultra, pre-ultra total*/
+ msel_group_ext[0] = '\0';
+}
+
+static ssize_t msel_group_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ /*parse wsct_id:group,
+ 1. split data by ","
+ 2. split subdata by ":"
+ 3. check the value is OK
+
+ don't clear the setting, do this by echo 1 > clear_setting
+ */
+
+ char *token, *cur= msel_group_ext;
+ char *_id = NULL, *_master_group = NULL;
+ int id_int = 0;
+
+ _clear_msel_group_ext();
+
+ snprintf(msel_group_ext, FILE_NODE_DATA_LEN, "%s", buf);
+ msel_group_ext[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:0xff , (ID,master_group)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _master_group = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _master_group[%s]\n",_id,_master_group);
+
+ if (_id == NULL || _master_group == NULL) {
+ PR_BOOTMSG("err: _id[%s] _master_group[%s], para can't be NULL\n",_id,_master_group);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ if (kstrtouint(_master_group, 0, &msel_group_ext_val[id_int]) != 0) {
+ PR_BOOTMSG("master_group[%s] trans to hex err\n",_master_group);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_msel_group_ext();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",msel_group_ext);
+ /*PR_BOOTMSG("msel_group_ext_store size para n[%d]\n",n);*/
+ int i;
+ PR_BOOTMSG("save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=%X\n",i,msel_group_ext_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t msel_group_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", msel_group_ext);
+}
+
+
+char wsct_rw[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_rw(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_rw_val[i] = BM_WSCT_RW_RWBOTH;
+ }
+ wsct_rw[0] = '\0';
+}
+
+static ssize_t wsct_rw_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_rw;
+ char *_id = NULL, *_rw_type = NULL;
+ int id_int = 0;
+
+ _clear_wsct_rw();
+
+ snprintf(wsct_rw, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_rw[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _rw_type = strsep(&token, delim_coclon);
+
+ if (_id == NULL || _rw_type == NULL) {
+ PR_BOOTMSG("err: _id[%s] _rw_type[%s], para can't be NULL\n",_id, _rw_type);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+
+ PR_BOOTMSG("_id[%s] _rw_type[%s]\n",_id, _rw_type);
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ if ( 0 == strncmp("NONE",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_DISABLE;
+ else if (0 == strncmp("R",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_READONLY;
+ else if (0 == strncmp("W",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_WRITEONLY;
+ else if (0 == strncmp("RW",_rw_type,4))
+ wsct_rw_val[id_int] = BM_WSCT_RW_RWBOTH;
+ else {
+ PR_BOOTMSG("_id[%s] has err rwtype[%s]\n", _id, _rw_type);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_rw();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("wsct_rw_store input data [%s]\n",wsct_rw);
+ int i;
+ PR_BOOTMSG("rwtype save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=%d\n",i,wsct_rw_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t wsct_rw_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", wsct_rw);
+}
+
+
+static unsigned int WSCT_HPRI_DIS[WSCT_AMOUNT];
+static unsigned int WSCT_HPRI_SEL[WSCT_AMOUNT];
+char wsct_high_priority_enable[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_high_priority_enable(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ WSCT_HPRI_DIS[i] = 1;
+ WSCT_HPRI_SEL[i] = 0xF;
+ }
+
+ WSCT_HPRI_DIS[4] = 0;
+ WSCT_HPRI_SEL[4] = 0x8; /* ultra */
+
+ WSCT_HPRI_DIS[5] = 0;
+ WSCT_HPRI_SEL[5] = 0x4; /* pre_ultra */
+
+
+ wsct_high_priority_enable[0] = '\0';
+}
+
+static ssize_t wsct_high_priority_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_high_priority_enable;
+ char *_id = NULL, *_enable = NULL, *_level = NULL;
+ int id_int = 0, level_int = 0;
+
+ _clear_wsct_high_priority_enable();
+
+ snprintf(wsct_high_priority_enable, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_high_priority_enable[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _enable = strsep(&token, delim_coclon);
+ _level = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _enable[%s] _level[%s]\n",_id, _enable, _level);
+
+ if (_id == NULL || _enable == NULL || _level == NULL ) {
+ PR_BOOTMSG("err : _id[%s] _enable[%s] _level[%s], para can't be NULL\n",_id, _enable, _level);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ if ( 0 == strncmp("disable", _enable, 7)) {
+
+ WSCT_HPRI_DIS[id_int] = 1;
+ WSCT_HPRI_SEL[id_int] = 0xf;
+ } else if ( 0 == strncmp("enable", _enable, 6)) {
+
+ WSCT_HPRI_DIS[id_int] = 0;
+ if (kstrtouint(_level, 0, &level_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans ultraLevel[%s] to hex err\n",_id, _level);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+ WSCT_HPRI_SEL[id_int] = level_int & 0xF;
+ } else {
+ PR_BOOTMSG("_id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_high_priority_enable();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",wsct_high_priority_enable);
+ int i;
+ PR_BOOTMSG("wsct_high_priority_enable save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=(%X,%X)\n", i, WSCT_HPRI_DIS[i], WSCT_HPRI_SEL[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t wsct_high_priority_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", wsct_high_priority_enable);
+}
+
+
+static unsigned int wsct_busid_val[WSCT_AMOUNT];
+static unsigned int wsct_idMask_val[WSCT_AMOUNT];
+
+char wsct_busid[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_busid(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_busid_val[i] = 0xfffff;
+ wsct_idMask_val[i] = 0x1FFF;
+ }
+ wsct_busid[0] = '\0';
+}
+
+static ssize_t wsct_busid_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_busid;
+
+ char *_id = NULL, *_busid = NULL, *_idMask = NULL;
+ int id_int = 0, busid_int = 0, idMask_int = 0;
+
+ _clear_wsct_busid();
+
+ snprintf(wsct_busid, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_busid[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _busid = strsep(&token, delim_coclon);
+ _idMask = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _busid[%s] _idMask[%s]\n",_id, _busid, _idMask);
+
+ if (_id == NULL || _busid == NULL || _idMask == NULL) {
+ PR_BOOTMSG("err: _id[%s] _busid[%s] _idMask[%s] ,parameter can't be NULL\n",_id, _busid, _idMask);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+ if (kstrtouint(_busid, 0, &busid_int) != 0) {
+ PR_BOOTMSG("_busid[%s] trans to hex err\n",_busid);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+ if (kstrtouint(_idMask, 0, &idMask_int) != 0) {
+ PR_BOOTMSG("_idMask[%s] trans to hex err\n",_idMask);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ wsct_busid_val[id_int] = busid_int;
+ wsct_idMask_val[id_int] = idMask_int;
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_busid();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",wsct_busid);
+ int i;
+ PR_BOOTMSG("wsct_busid save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d](busid,idMask)=(%X,%X)\n", i, wsct_busid_val[i], wsct_idMask_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t wsct_busid_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", wsct_busid);
+}
+
+
+static unsigned int wsct_chn_rank_sel_val[WSCT_AMOUNT];
+char wsct_chn_rank_sel[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_chn_rank_sel(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_chn_rank_sel_val[i] = 0xF;
+ }
+ wsct_chn_rank_sel[0] = '\0';
+}
+
+static ssize_t wsct_chn_rank_sel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_chn_rank_sel;
+ char *_id = NULL, *_chn_rank = NULL;
+ int id_int = 0, chn_rank_int = 0;
+
+ _clear_wsct_chn_rank_sel();
+
+ snprintf(wsct_chn_rank_sel, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_chn_rank_sel[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _chn_rank = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _chn_rank[%s]\n",_id, _chn_rank);
+
+ if (_id == NULL || _chn_rank == NULL) {
+ PR_BOOTMSG("err : _id[%s] _chn_rank[%s], para can't be NULL\n",_id, _chn_rank);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+ if (kstrtouint(_chn_rank, 0, &chn_rank_int) != 0) {
+ PR_BOOTMSG("_chn_rank[%s] trans to hex err\n",_id);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ wsct_chn_rank_sel_val[id_int] = chn_rank_int;
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_chn_rank_sel();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("wsct_chn_rank_sel input data [%s]\n",wsct_chn_rank_sel);
+ int i;
+ PR_BOOTMSG("wsct_chn_rank_sel_val save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=%X\n",i,wsct_chn_rank_sel_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t wsct_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", wsct_chn_rank_sel);
+}
+
+static unsigned int wsct_byte_low_bnd_val[WSCT_AMOUNT];
+static unsigned int wsct_byte_up_bnd_val[WSCT_AMOUNT];
+static unsigned int wsct_byte_bnd_dis[WSCT_AMOUNT];
+char wsct_burst_range[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_wsct_burst_range(void) {
+ int i;
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ wsct_byte_low_bnd_val[i] = 0x0;
+ wsct_byte_up_bnd_val[i] = 0x1FF;
+ wsct_byte_bnd_dis[i] = 1;
+ }
+ wsct_burst_range[0] = '\0';
+}
+
+static ssize_t wsct_burst_range_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= wsct_burst_range;
+ char *_id = NULL, *_low_bnd = NULL, *_up_bnd = NULL;
+ int id_int = 0, low_bnd_int = 0, up_bnd_int = 0;
+
+ _clear_wsct_burst_range();
+
+ snprintf(wsct_burst_range, FILE_NODE_DATA_LEN, "%s", buf);
+ wsct_burst_range[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _low_bnd = strsep(&token, delim_coclon);
+ _up_bnd = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _low_bnd[%s] _up_bnd[%s]\n",_id, _low_bnd, _up_bnd);
+
+ if (_id == NULL || _low_bnd == NULL || _up_bnd == NULL) {
+ PR_BOOTMSG("err : _id[%s] _low_bnd[%s] _up_bnd[%s], para can't be NULL\n",_id, _low_bnd, _up_bnd);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_low_bnd, 0, &low_bnd_int) != 0) {
+ PR_BOOTMSG("_low_bnd[%s] trans to hex err\n",_id);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_up_bnd, 0, &up_bnd_int) != 0) {
+ PR_BOOTMSG("_up_bnd[%s] trans to hex err\n",_id);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+
+ if ( id_int >= 0 && id_int < WSCT_AMOUNT) {
+ wsct_byte_low_bnd_val[id_int] = low_bnd_int;
+ wsct_byte_up_bnd_val[id_int] = up_bnd_int;
+ wsct_byte_bnd_dis[id_int] = 0;
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, WSCT_AMOUNT-1);
+ _clear_wsct_burst_range();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("wsct_burst_range_store input data [%s]\n",wsct_burst_range);
+ int i;
+ PR_BOOTMSG("wsct_burst_range save data\n");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d](low_bnd,up_bnd)=(%X,%X)\n",i,wsct_byte_low_bnd_val[i],wsct_byte_up_bnd_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t wsct_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", wsct_burst_range);
+}
+
+
+
+static unsigned int tsct_busid_enable_val[TSCT_AMOUNT];
+char tsct_busid_enable[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_tsct_busid_enable(void) {
+ int i;
+
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ tsct_busid_enable_val[i] = 0;
+ }
+ tsct_busid_enable[0] = '\0';
+}
+
+static ssize_t tsct_busid_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= tsct_busid_enable;
+ char *_id = NULL, *_enable = NULL;
+ int id_int = 0;
+
+ _clear_tsct_busid_enable();
+
+ snprintf(tsct_busid_enable, FILE_NODE_DATA_LEN, "%s", buf);
+ tsct_busid_enable[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _enable = strsep(&token, delim_coclon);
+
+
+ PR_BOOTMSG("_id[%s] _enable[%s]\n",_id, _enable);
+
+ if (_id == NULL || _enable == NULL) {
+ PR_BOOTMSG("err : _id[%s] _enable[%s], para can't be NULL\n",_id, _enable);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+
+
+ if ( id_int >= 0 && id_int < TSCT_AMOUNT) {
+ if ( 0 == strncmp("disable", _enable, 7)) {
+ tsct_busid_enable_val[id_int] = 0;
+ } else if ( 0 == strncmp("enable", _enable, 6)) {
+ tsct_busid_enable_val[id_int] = 1;
+ } else {
+ PR_BOOTMSG("_id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 0~%d\n",id_int, TSCT_AMOUNT-1);
+ _clear_tsct_busid_enable();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("tsct_busid_enable input data [%s]\n",tsct_busid_enable);
+ int i;
+ PR_BOOTMSG("wsct_high_priority_enable save data\n");
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ PR_BOOTMSG("id[%d]=(%d)\n", i, tsct_busid_enable_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t tsct_busid_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", tsct_busid_enable);
+}
+
+
+/* use the origin para high_priority_filter to save the en/dis setting */
+static unsigned int TTYPE_HPRI_SEL[BM_COUNTER_MAX];
+char ttype_high_priority_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_high_priority_ext(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ TTYPE_HPRI_SEL[i] = 0xf;
+ }
+
+ high_priority_filter = 0x0;
+ ttype_high_priority_ext[0] = '\0';
+}
+
+static ssize_t ttype_high_priority_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_high_priority_ext;
+ char *_id = NULL, *_enable = NULL, *_level = NULL;
+ int id_int = 0, level_int = 0;
+
+ _clear_ttype_high_priority_ext();
+
+ snprintf(ttype_high_priority_ext, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_high_priority_ext[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _enable = strsep(&token, delim_coclon);
+ _level = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _enable[%s] _level[%s]\n",_id, _enable, _level);
+
+ if (_id == NULL || _enable == NULL || _level == NULL ) {
+ PR_BOOTMSG("err : _id[%s] _enable[%s] _level[%s], para can't be NULL\n",_id, _enable, _level);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+
+ id_int = id_int - 1;
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ if ( 0 == strncmp("disable", _enable, 7)) {
+
+ high_priority_filter = ( high_priority_filter & ~(1<<id_int) ) | ( 0<<id_int );
+ TTYPE_HPRI_SEL[id_int] = 0xf;
+ } else if ( 0 == strncmp("enable", _enable, 6)) {
+
+ high_priority_filter = ( high_priority_filter & ~(1<<id_int) ) | ( 1<<id_int );
+ if (kstrtouint(_level, 0, &level_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans ultraLevel[%s] to hex err\n",_id, _level);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+ TTYPE_HPRI_SEL[id_int] = level_int & 0xF;
+ } else {
+ PR_BOOTMSG("ttype_high_priority_ext: _id[%s] has err enable[%s] (enable/disable)\n", _id, _enable);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+ _clear_ttype_high_priority_ext();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("input data [%s]\n",ttype_high_priority_ext);
+
+ int i;
+ PR_BOOTMSG("wsct_high_priority_enable save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d]=(%X,%X)\n", i+1, high_priority_filter>>i & 0x1, TTYPE_HPRI_SEL[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t ttype_high_priority_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", ttype_high_priority_ext);
+}
+
+
+static unsigned int ttype_idMask_val[BM_COUNTER_MAX];
+char ttype_busid_ext[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_busid_ext(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ttype_busid_val[i] = 0xfffff;
+ ttype_idMask_val[i] = 0x1FFF;
+ }
+ ttype_busid_ext[0] = '\0';
+}
+
+/*id: 1~21*/
+static ssize_t ttype_busid_ext_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_busid_ext;
+
+ char *_id = NULL, *_busid = NULL, *_idMask = NULL;
+ int id_int = 0, busid_int = 0, idMask_int = 0;
+
+ _clear_ttype_busid_ext();
+
+ snprintf(ttype_busid_ext, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_busid_ext[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:R , 5:W (ID,RW)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _busid = strsep(&token, delim_coclon);
+ _idMask = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _busid[%s] _idMask[%s]\n",_id, _busid, _idMask);
+
+ if (_id == NULL || _busid == NULL || _idMask == NULL) {
+ PR_BOOTMSG("err: ttype_busid_ext _id[%s] _busid[%s] _idMask[%s] ,parameter can't be NULL\n",_id, _busid, _idMask);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+ if (kstrtouint(_busid, 0, &busid_int) != 0) {
+ PR_BOOTMSG("_busid[%s] trans to hex err\n",_busid);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+ if (kstrtouint(_idMask, 0, &idMask_int) != 0) {
+ PR_BOOTMSG("_idMask[%s] trans to hex err\n",_idMask);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+
+ id_int = id_int - 1;
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ ttype_busid_val[id_int] = busid_int;
+ ttype_idMask_val[id_int] = idMask_int;
+
+ } else {
+ PR_BOOTMSG("ttype_busid_ext id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+ _clear_ttype_busid_ext();
+ return -EINVAL;
+ }
+ }
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("ttype_busid_ext input data [%s]\n",ttype_busid_ext);
+
+ int i;
+ PR_BOOTMSG("ttype_busid_ext save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d](busid,idMask)=(%X,%X)\n", i+1, ttype_busid_val[i], ttype_idMask_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t ttype_busid_ext_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", ttype_busid_ext);
+}
+
+
+static unsigned int ttype_chn_rank_sel_val[BM_COUNTER_MAX];
+char ttype_chn_rank_sel[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_chn_rank_sel(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ttype_chn_rank_sel_val[i] = 0xF;
+ }
+ ttype_chn_rank_sel[0] = '\0';
+}
+
+static ssize_t ttype_chn_rank_sel_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_chn_rank_sel;
+ char *_id = NULL, *_chn_rank = NULL;
+ int id_int = 0, chn_rank_int = 0;
+
+ _clear_ttype_chn_rank_sel();
+
+ snprintf(ttype_chn_rank_sel, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_chn_rank_sel[n-1]='\0';
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _chn_rank = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _chn_rank[%s]\n",_id, _chn_rank);
+
+ if (_id == NULL || _chn_rank == NULL) {
+ PR_BOOTMSG("err (ttype_chn_rank_sel): _id[%s] _chn_rank[%s], para can't be NULL\n",_id, _chn_rank);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+ if (kstrtouint(_chn_rank, 0, &chn_rank_int) != 0) {
+ PR_BOOTMSG("_chn_rank[%s] trans to hex err\n",_id);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+
+ id_int = id_int -1;
+
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ ttype_chn_rank_sel[id_int] = chn_rank_int;
+
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int+1, BM_COUNTER_MAX);
+ _clear_ttype_chn_rank_sel();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("ttype_chn_rank_sel input data [%s]\n",ttype_chn_rank_sel);
+
+ int i;
+ PR_BOOTMSG("wsct_chn_rank_sel_val save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d]=%X\n",i+1,ttype_chn_rank_sel[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t ttype_chn_rank_sel_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", ttype_chn_rank_sel);
+}
+
+
+static unsigned int ttype_byte_low_bnd_val[BM_COUNTER_MAX];
+static unsigned int ttype_byte_up_bnd_val[BM_COUNTER_MAX];
+static unsigned int ttype_byte_bnd_dis[BM_COUNTER_MAX];
+char ttype_burst_range[FILE_NODE_DATA_LEN] = {'\0'};
+
+static void _clear_ttype_burst_range(void) {
+ int i;
+
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ttype_byte_low_bnd_val[i] = 0x0;
+ ttype_byte_up_bnd_val[i] = 0x1FF;
+ ttype_byte_bnd_dis[i] = 1;
+ }
+ ttype_burst_range[0] = '\0';
+}
+
+static ssize_t ttype_burst_range_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ char *token, *cur= ttype_burst_range;
+ char *_id = NULL, *_low_bnd = NULL, *_up_bnd = NULL;
+ int id_int = 0, low_bnd_int = 0, up_bnd_int = 0;
+
+ _clear_ttype_burst_range();
+
+ snprintf(ttype_burst_range, FILE_NODE_DATA_LEN, "%s", buf);
+ ttype_burst_range[n-1]='\0';
+
+
+ while (cur != NULL) {
+ token = strsep(&cur, delim_comma);
+ PR_BOOTMSG("token: %s\n",token);
+ /*token EX: 4:f , 5:C (ID,chn_rnk_sel)*/
+
+ _id = strsep(&token, delim_coclon); // ID
+ _low_bnd = strsep(&token, delim_coclon);
+ _up_bnd = strsep(&token, delim_coclon);
+
+ PR_BOOTMSG("_id[%s] _low_bnd[%s] _up_bnd[%s]\n",_id, _low_bnd, _up_bnd);
+
+ if (_id == NULL || _low_bnd == NULL || _up_bnd == NULL) {
+ PR_BOOTMSG("err (ttype_burst_range): _id[%s] _low_bnd[%s] _up_bnd[%s], para can't be NULL\n",
+ _id, _low_bnd, _up_bnd);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+
+ if (kstrtouint(_id, 0, &id_int) != 0) {
+ PR_BOOTMSG("_id[%s] trans to hex err\n",_id);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_low_bnd, 0, &low_bnd_int) != 0) {
+ PR_BOOTMSG("_low_bnd[%s] trans to hex err\n",_id);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+ if (kstrtouint(_up_bnd, 0, &up_bnd_int) != 0) {
+ PR_BOOTMSG("_up_bnd[%s] trans to hex err\n",_id);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+
+ id_int = id_int - 1;
+ if ( id_int >= 0 && id_int < BM_COUNTER_MAX) {
+ ttype_byte_low_bnd_val[id_int] = low_bnd_int;
+ ttype_byte_up_bnd_val[id_int] = up_bnd_int;
+ ttype_byte_bnd_dis[id_int] = 0;
+ } else {
+ PR_BOOTMSG("id[%d] exceed the range, it must be 1~%d\n",id_int, BM_COUNTER_MAX);
+ _clear_ttype_burst_range();
+ return -EINVAL;
+ }
+ }
+
+#ifdef FILE_NODE_DBG
+ PR_BOOTMSG("ttype_burst_range_store input data [%s]\n",ttype_burst_range);
+
+ int i;
+ PR_BOOTMSG("ttype_burst_range save data\n");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ PR_BOOTMSG("id[%d](low_bnd,up_bnd)=(%X,%X)\n",i+1,ttype_byte_low_bnd_val[i],ttype_byte_up_bnd_val[i]);
+ }
+#endif
+ return n;
+}
+
+static ssize_t ttype_burst_range_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%s\n", ttype_burst_range);
+}
+
+static int reserve_wsct_setting;
+DECLARE_KOBJ_ATTR_INT(reserve_wsct_setting, reserve_wsct_setting);
+
+static void _clear_setting(void) {
+ /*clear all file node para here*/
+
+ PR_BOOTMSG("clear EMI file node setting\n");
+
+ _clear_msel_group_ext();
+ _clear_wsct_rw();
+ _clear_wsct_high_priority_enable();
+ _clear_wsct_busid();
+ _clear_wsct_chn_rank_sel();
+ _clear_wsct_burst_range();
+
+ _clear_tsct_busid_enable();
+ _clear_ttype_high_priority_ext();
+ _clear_ttype_busid_ext();
+ _clear_ttype_chn_rank_sel();
+ _clear_ttype_burst_range();
+ reserve_wsct_setting = 0;
+
+
+
+ emi_TP_busfiltr_enable = 0;
+
+ high_priority_filter = 0x0;
+ rwtype = BM_BOTH_READ_WRITE;
+ dramc_pdir_enable = 1;
+
+
+ msel_enable = 0;
+ msel_group1 = BM_MASTER_ALL;
+ msel_group2 = BM_MASTER_ALL;
+ msel_group3 = BM_MASTER_ALL;
+
+
+ bw_limiter_enable = BM_BW_LIMITER_ENABLE;
+ ttype1_16_en = BM_TTYPE1_16_DISABLE;
+ ttype17_21_en = BM_TTYPE17_21_DISABLE;
+
+}
+
+static ssize_t clear_setting_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ if (value == 1)
+ _clear_setting();
+
+ return n;
+}
+
+static struct kobj_attribute clear_setting_attr = __ATTR_WO(clear_setting); // OK
+static struct kobj_attribute msel_group_ext_attr = __ATTR(msel_group_ext, 0664, msel_group_ext_show, msel_group_ext_store); //OK
+static struct kobj_attribute wsct_rw_attr = __ATTR(wsct_rw, 0664, wsct_rw_show, wsct_rw_store);
+static struct kobj_attribute wsct_high_priority_enable_attr = __ATTR(wsct_high_priority_enable, 0664, wsct_high_priority_enable_show, wsct_high_priority_enable_store);
+static struct kobj_attribute wsct_busid_attr = __ATTR(wsct_busid, 0664, wsct_busid_show, wsct_busid_store);
+static struct kobj_attribute wsct_chn_rank_sel_attr = __ATTR(wsct_chn_rank_sel, 0664, wsct_chn_rank_sel_show, wsct_chn_rank_sel_store);
+static struct kobj_attribute wsct_burst_range_attr = __ATTR(wsct_burst_range, 0664, wsct_burst_range_show, wsct_burst_range_store);
+static struct kobj_attribute tsct_busid_enable_attr = __ATTR(tsct_busid_enable, 0664, tsct_busid_enable_show, tsct_busid_enable_store);
+static struct kobj_attribute ttype_high_priority_ext_attr = __ATTR(ttype_high_priority_ext, 0664, ttype_high_priority_ext_show, ttype_high_priority_ext_store);
+static struct kobj_attribute ttype_busid_ext_attr = __ATTR(ttype_busid_ext, 0664, ttype_busid_ext_show, ttype_busid_ext_store);
+static struct kobj_attribute ttype_chn_rank_sel_attr = __ATTR(ttype_chn_rank_sel, 0664, ttype_chn_rank_sel_show, ttype_chn_rank_sel_store);
+static struct kobj_attribute ttype_burst_range_attr = __ATTR(ttype_burst_range, 0664, ttype_burst_range_show, ttype_burst_range_store);
+
+
+
+
+
+
+/**/
+#define KOBJ_ATTR_ITEM_SERIAL_FNODE(nr) \
+ do { \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _master); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _nbeat); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _nbyte); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _burst); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _busid); \
+ KOBJ_ATTR_ITEM(ttype ## nr ## _rw); \
+ } while (0)
+
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(high_priority_filter); \
+ KOBJ_ATTR_ITEM(emi_TP_busfiltr_enable); \
+ KOBJ_ATTR_ITEM(msel_enable); \
+ KOBJ_ATTR_ITEM(msel_group1); \
+ KOBJ_ATTR_ITEM(msel_group2); \
+ KOBJ_ATTR_ITEM(msel_group3); \
+ KOBJ_ATTR_ITEM(rwtype); \
+ KOBJ_ATTR_ITEM(ttype17_21_en); \
+ KOBJ_ATTR_ITEM(ttype1_16_en); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(1); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(2); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(3); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(4); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(5); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(6); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(7); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(8); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(9); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(10); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(11); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(12); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(13); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(14); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(15); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(16); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(17); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(18); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(19); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(20); \
+ KOBJ_ATTR_ITEM_SERIAL_FNODE(21); \
+ KOBJ_ATTR_ITEM(bw_limiter_enable); \
+ KOBJ_ATTR_ITEM(dramc_pdir_enable); \
+ KOBJ_ATTR_ITEM(clear_setting);\
+ KOBJ_ATTR_ITEM(msel_group_ext);\
+ KOBJ_ATTR_ITEM(wsct_rw);\
+ KOBJ_ATTR_ITEM(wsct_high_priority_enable);\
+ KOBJ_ATTR_ITEM(wsct_busid);\
+ KOBJ_ATTR_ITEM(wsct_chn_rank_sel);\
+ KOBJ_ATTR_ITEM(wsct_burst_range);\
+ KOBJ_ATTR_ITEM(tsct_busid_enable);\
+ KOBJ_ATTR_ITEM(ttype_high_priority_ext);\
+ KOBJ_ATTR_ITEM(ttype_busid_ext);\
+ KOBJ_ATTR_ITEM(ttype_chn_rank_sel);\
+ KOBJ_ATTR_ITEM(ttype_burst_range);\
+ KOBJ_ATTR_ITEM(reserve_wsct_setting);\
+ } while (0)
+
+
+
+/*======================================================================*/
+/* EMI Operations */
+/*======================================================================*/
+static void emi_init(void)
+{
+ unsigned int bmrw0_val, bmrw1_val, i;
+ /*unsigned int msel_group_val[4];*/
+
+ /*save origianl EMI config*/
+ MET_BM_SaveCfg();
+
+ /* get dram channel number */
+ dram_chann_num = MET_EMI_GetDramChannNum(0);
+
+ /* Init. EMI bus monitor */
+ MET_BM_SetReadWriteType(rwtype);
+
+ /*handle the ori */
+
+ if (ttype1_16_en != BM_TTYPE1_16_ENABLE) {
+ MET_BM_SetLatencyCounter(1); /*enable latency count*/
+ }
+ else {
+ MET_BM_SetLatencyCounter(0); /*disable latency count*/
+
+ for (i = 1; i <= 16; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+ }
+ }
+
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+ for (i = 17; i <= 21; i++) {
+ MET_BM_SetMonitorCounter(i,
+ ttype_master_val[i - 1],
+ ttype_nbeat_val[i - 1] |
+ ttype_nbyte_val[i - 1] |
+ ttype_burst_val[i - 1]);
+ }
+ }
+
+ PR_BOOTMSG("[%s]reserve_wsct_setting=%d\n",__func__,reserve_wsct_setting);
+
+ if (reserve_wsct_setting == 0) {
+ /* wsct 0 : total-all*/
+ msel_group_ext_val[0] = BM_MASTER_ALL;
+ wsct_rw_val[0] = BM_WSCT_RW_RWBOTH;
+ WSCT_HPRI_DIS[0] = 1;
+ WSCT_HPRI_SEL[0] = 0xF;
+ wsct_busid_val[0] = 0xFFFFF;
+ wsct_idMask_val[0] = 0xFFFF;
+ wsct_chn_rank_sel_val[0] = 0xF;
+ wsct_byte_bnd_dis[0] = 1;
+
+ /* wsct 4 : total-ultra*/
+ msel_group_ext_val[4] = BM_MASTER_ALL;
+ wsct_rw_val[4] = BM_WSCT_RW_RWBOTH;
+ WSCT_HPRI_DIS[4] = 0;
+ WSCT_HPRI_SEL[4] = 0x8; /* ultra */
+ wsct_busid_val[4] = 0xFFFFF;
+ wsct_idMask_val[4] = 0xFFFF;
+ wsct_chn_rank_sel_val[4] = 0xF;
+ wsct_byte_bnd_dis[4] = 1;
+
+ /* wsct 5 : total-pre_ultra*/
+ msel_group_ext_val[5] = BM_MASTER_ALL;
+ wsct_rw_val[5] = BM_WSCT_RW_RWBOTH;
+ WSCT_HPRI_DIS[5] = 0;
+ WSCT_HPRI_SEL[5] = 0x4; /* pre_ultra */
+ wsct_busid_val[5] = 0xFFFFF;
+ wsct_idMask_val[5] = 0xFFFF;
+ wsct_chn_rank_sel_val[5] = 0xF;
+ wsct_byte_bnd_dis[5] = 1;
+ }
+
+ if (msel_enable) {
+ /* if ole file node set, use the value */
+ if ( msel_group1 != BM_MASTER_ALL )
+ msel_group_ext_val[1] = msel_group1;
+
+ if ( msel_group2 != BM_MASTER_ALL )
+ msel_group_ext_val[2] = msel_group2;
+
+ if ( msel_group3 != BM_MASTER_ALL )
+ msel_group_ext_val[3] = msel_group3;
+
+ } else {
+ for ( i=1; i<=3; i++) {
+ msel_group_ext_val[i] = BM_MASTER_ALL;
+ }
+ }
+
+ MET_BM_SetWSCT_master_rw(msel_group_ext_val, wsct_rw_val);
+ MET_BM_SetWSCT_high_priority(WSCT_HPRI_DIS, WSCT_HPRI_SEL);
+ MET_BM_SetWSCT_busid_idmask(wsct_busid_val, wsct_idMask_val);
+ MET_BM_SetWSCT_chn_rank_sel(wsct_chn_rank_sel_val);
+ MET_BM_SetWSCT_burst_range(wsct_byte_bnd_dis, wsct_byte_low_bnd_val, wsct_byte_up_bnd_val);
+ MET_BM_SetTSCT_busid_enable(tsct_busid_enable_val);
+
+ MET_BM_SetTtype_high_priority_sel(high_priority_filter, TTYPE_HPRI_SEL);
+ MET_BM_SetTtype_busid_idmask(ttype_busid_val, ttype_idMask_val, ttype1_16_en, ttype17_21_en);
+ MET_BM_SetTtype_chn_rank_sel(ttype_chn_rank_sel_val);
+ MET_BM_SetTtype_burst_range(ttype_byte_bnd_dis, ttype_byte_low_bnd_val, ttype_byte_up_bnd_val);
+
+
+ bmrw0_val = 0;
+ for (i = 0; i < 16; i++)
+ bmrw0_val |= (ttype_rw_val[i] << (i * 2));
+
+ bmrw1_val = 0;
+ for (i = 16; i < 21; i++)
+ bmrw1_val |= (ttype_rw_val[i] << ((i-16) * 2));
+
+ MET_BM_SetTtypeCounterRW(bmrw0_val, bmrw1_val);
+
+}
+
+
+static void emi_uninit(void)
+{
+ MET_BM_RestoreCfg();
+}
+
+
+static inline int do_emi(void)
+{
+ return met_sspm_emi.mode;
+}
+
+
+
+
+
+
+
+/*======================================================================*/
+/* MET Device Operations */
+/*======================================================================*/
+static int emi_inited;
+
+static int met_emi_create(struct kobject *parent)
+{
+ int ret = 0;
+ int i;
+
+ for (i = 0; i < 21; i++) {
+ ttype_master_val[i] = BM_MASTER_M0;
+ ttype_nbeat_val[i] = BM_TRANS_TYPE_1BEAT;
+ ttype_nbyte_val[i] = BM_TRANS_TYPE_8Byte;
+ ttype_burst_val[i] = BM_TRANS_TYPE_BURST_INCR;
+ ttype_busid_val[i] = 0xfffff; /*default disable ttype bus sel if busid > 0xff_ff */
+ ttype_rw_val[i] = BM_TRANS_RW_DEFAULT;
+ }
+
+ _clear_msel_group_ext();
+ _clear_wsct_rw();
+ _clear_wsct_high_priority_enable();
+ _clear_wsct_busid();
+ _clear_wsct_chn_rank_sel();
+ _clear_wsct_burst_range();
+
+ _clear_tsct_busid_enable();
+ _clear_ttype_high_priority_ext();
+ _clear_ttype_high_priority_ext();
+ _clear_ttype_busid_ext();
+ _clear_ttype_chn_rank_sel();
+ _clear_ttype_burst_range();
+
+ reserve_wsct_setting = 0;
+
+
+ ret = MET_BM_Init();
+ if (ret != 0) {
+ pr_notice("MET_BM_Init failed!!!\n");
+ ret = 0; /* will retry later */
+ } else {
+ emi_inited = 1;
+ }
+
+ kobj_emi = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+ do { \
+ ret = sysfs_create_file(kobj_emi, &attr_name ## _attr.attr); \
+ if (ret != 0) { \
+ pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+ } while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+ return ret;
+}
+
+
+static void met_emi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_emi, &attr_name##_attr.attr)
+ if (kobj_emi != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_emi = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+
+ if (emi_inited)
+ MET_BM_DeInit();
+}
+
+
+
+static void met_emi_resume(void)
+{
+ if (!do_emi())
+ return;
+
+ emi_init();
+}
+
+
+static const char help[] = " --emi monitor EMI banwidth\n";
+static int emi_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+
+static int emi_print_header(char *buf, int len)
+{
+
+ if( (strlen(header_str) - output_str_len) > PAGE_SIZE ){
+ char output_buf[PAGE_SIZE/4];
+
+ strncpy(output_buf, header_str+output_str_len, (PAGE_SIZE/4) -1);
+ output_buf[(PAGE_SIZE/4) - 1] = '\0';
+
+ len = snprintf(buf, PAGE_SIZE, "%s", output_buf);
+ output_str_len += len;
+ met_sspm_emi.header_read_again = 1;
+
+ PR_BOOTMSG("EMI header read again!\n");
+ }
+ else{
+ len = snprintf(buf, PAGE_SIZE, "%s\n", header_str+output_str_len);
+
+ /* reset state */
+ met_sspm_emi.header_read_again = 0;
+ output_header_len = 0;
+ output_str_len = 0;
+ }
+
+
+ return len;
+}
+
+
+#define TTYPE_NAME_STR_LEN 64
+/* static char ttype_name[21][TTYPE_NAME_STR_LEN]; */
+
+static int emi_create_header(char *buf, int buf_len)
+{
+ int ret = 0;
+/* int ret_m[21]; */
+ int i = 0;
+
+#if 1 /* move to AP side print header */
+/*#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT*/
+ unsigned int dram_data_rate_MHz;
+ unsigned int DRAM_TYPE;
+ unsigned int base_clock_rate;
+#endif
+
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_wsct_amount: %d\n",WSCT_AMOUNT);
+
+ /* master selection header */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_msel: %x,%x,%x\n",
+ msel_group_ext_val[1] & BM_MASTER_ALL,
+ msel_group_ext_val[2] & BM_MASTER_ALL,
+ msel_group_ext_val[3] & BM_MASTER_ALL);
+
+ /*Ttype RW type header*/
+ PR_BOOTMSG("rwtype=%d\n",rwtype);
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_rw_cfg: ");
+ if (rwtype == BM_READ_ONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "R");
+ else if (rwtype == BM_WRITE_ONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "W");
+ else
+ ret += snprintf(buf + ret, buf_len - ret, "BOTH");
+
+ for (i = 0; i < 21; i++) {
+ if (ttype_rw_val[i] == BM_TRANS_RW_DEFAULT)
+ ret += snprintf(buf + ret, buf_len - ret, ",DEFAULT");
+ else if (ttype_rw_val[i] == BM_TRANS_RW_READONLY)
+ ret += snprintf(buf + ret, buf_len - ret, ",R");
+ else if (ttype_rw_val[i] == BM_TRANS_RW_WRITEONLY)
+ ret += snprintf(buf + ret, buf_len - ret, ",W");
+ else /*BM_TRANS_RW_RWBOTH*/
+ ret += snprintf(buf + ret, buf_len - ret, ",BOTH");
+ }
+ ret += snprintf(buf + ret, buf_len - ret, "\n");
+
+ /*ultra header*/
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_ultra_filter: %x\n", high_priority_filter);
+
+ /* ttype header */
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+ int i = 0;
+ int j = 0;
+
+ /* ttype master list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_master_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_master_list_item); j++) {
+ if (ttype_master_val[i] == ttype_master_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%s,", ttype_master_list_item[j].val);
+ }
+ }
+ }
+ /* remove the last comma */
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype busid list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_busid_list: ");
+ for (i = 0; i < 21; i++)
+ ret += snprintf(buf + ret, buf_len - ret, "%x,", ttype_busid_val[i]);
+
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype nbeat list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_nbeat_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_nbeat_list_item); j++) {
+ if (ttype_nbeat_val[i] == ttype_nbeat_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,", ttype_nbeat_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype nbyte list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_nbyte_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_nbyte_list_item); j++) {
+ if (ttype_nbyte_val[i] == ttype_nbyte_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,", ttype_nbyte_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /* ttype burst list */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_burst_list: ");
+ for (i = 0; i < 21; i++) {
+ for (j = 0; j < ARRAY_SIZE(ttype_burst_list_item); j++) {
+ if (ttype_burst_val[i] == ttype_burst_list_item[j].key) {
+ ret += snprintf(buf + ret, buf_len - ret, "%s,", ttype_burst_list_item[j].val);
+ }
+ }
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ }
+ /* ttype enable */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_ttype_enable: %d,%d\n",ttype1_16_en, ttype17_21_en);
+
+
+#if 1 /*SEDA 3.5*/
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_msel_ext: %x,%x,%x\n",
+ msel_group_ext_val[0] & BM_MASTER_ALL,
+ msel_group_ext_val[4] & BM_MASTER_ALL,
+ msel_group_ext_val[5] & BM_MASTER_ALL);
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_rw: ");
+
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ if (wsct_rw_val[i] == BM_WSCT_RW_RWBOTH)
+ ret += snprintf(buf + ret, buf_len - ret, "RW,");
+ else if (wsct_rw_val[i] == BM_WSCT_RW_READONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "R,");
+ else if (wsct_rw_val[i] == BM_WSCT_RW_WRITEONLY)
+ ret += snprintf(buf + ret, buf_len - ret, "W,");
+ else /*disable*/
+ ret += snprintf(buf + ret, buf_len - ret, "NONE,");
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_HPRI_DIS: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",WSCT_HPRI_DIS[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_HPRI_SEL: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",WSCT_HPRI_SEL[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_busid: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_busid_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_emi_wsct_idMask: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_idMask_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_chn_rank_sel: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_chn_rank_sel_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_byte_bnd_dis: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",wsct_byte_bnd_dis[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_byte_low_bnd: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_byte_low_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: wsct_byte_up_bnd: ");
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",wsct_byte_up_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: tsct_busid_enable: ");
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",tsct_busid_enable_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ /***************************** ttype ****************************************/
+ if (ttype17_21_en == BM_TTYPE17_21_ENABLE) {
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: TTYPE_HPRI_SEL: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",TTYPE_HPRI_SEL[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_idMask: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_idMask_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_chn_rank_sel: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_chn_rank_sel_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_byte_bnd_dis: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%d,",ttype_byte_bnd_dis[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_byte_low_bnd_val: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_byte_low_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ttype_byte_up_bnd_val: ");
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ ret += snprintf(buf + ret, buf_len - ret, "%x,",ttype_byte_up_bnd_val[i]);
+ }
+ snprintf(buf + ret -1, buf_len - ret + 1, "\n");
+ }
+#endif
+
+#ifdef EMI_NUM
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: EMI_NUM: %d\n", EMI_NUM);
+#endif
+ /*IP version*/
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: DRAMC_VER: %d\n", DRAMC_VER);
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: EMI_VER: %d.%d\n", EMI_VER_MAJOR, EMI_VER_MINOR);
+
+#if 1 /* SEDA3.5 header print move to AP side */
+/*#ifndef CONFIG_MTK_TINYSYS_SSPM_SUPPORT*/
+ dram_chann_num = MET_EMI_GetDramChannNum(0);
+ /* met_dram_chann_num_header
+ * channel number
+ * LP4: 2, LP3: 1
+ */
+
+ /*
+ * the ddr type define :
+ * enum DDRTYPE {
+ * TYPE_DDR1 = 1,
+ * TYPE_LPDDR2,
+ * TYPE_LPDDR3,
+ * TYPE_PCDDR3,
+ * TYPE_LPDDR4,
+ * TYPE_LPDDR4X,
+ * TYPE_LPDDR4P
+ * };
+ */
+ if (!get_cur_ddr_ratio_symbol){
+ PR_BOOTMSG("[%s][%d]get_cur_ddr_ratio_symbol = NULL , use the TYPE_LPDDR4 setting\n", __func__, __LINE__);
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ##_EMI_warning: get_cur_ddr_ratio_symbol = NULL , use the TYPE_LPDDR4 setting\n");
+ }
+
+ if (mtk_dramc_get_ddr_type_symbol) {
+ DRAM_TYPE = mtk_dramc_get_ddr_type_symbol();
+
+ base_clock_rate = MET_EMI_Get_BaseClock_Rate();
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_type: %d\n", DRAM_TYPE);
+
+ if ((DRAM_TYPE == 5) || (DRAM_TYPE == 6) || (DRAM_TYPE == 7))
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, base_clock_rate,
+ DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+ else
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, base_clock_rate,
+ DRAM_IO_BUS_WIDTH_LP3, DRAM_DATARATE);
+ } else {
+ METERROR("[%s][%d]mtk_dramc_get_ddr_type_symbol = NULL , use the TYPE_LPDDR4 setting\n", __func__, __LINE__);
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ##_EMI_warning: mtk_dramc_get_ddr_type_symbol = NULL , use the TYPE_LPDDR4 setting\n");
+
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_dram_chann_num_header: %d,%d,%d,%d\n",
+ dram_chann_num, DDR_RATIO_DEFAULT,
+ DRAM_IO_BUS_WIDTH_LP4, DRAM_DATARATE);
+ }
+
+
+
+ /* met_emi_clockrate */
+ if (mtk_dramc_get_data_rate_symbol) {
+ dram_data_rate_MHz = mtk_dramc_get_data_rate_symbol();
+ } else {
+ METERROR("mtk_dramc_get_data_rate_symbol = NULL\n");
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: ##_EMI_warning: mtk_dramc_get_data_rate_symbol = NULL\n");
+ dram_data_rate_MHz = DRAM_FREQ_DEFAULT;
+ }
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_dram_clockrate: %d\n",
+ dram_data_rate_MHz);
+
+ /* 1 : by ondiemet, 0: by pure linux */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: ##_emi_use_ondiemet: 1,%X\n",
+ get_sspm_support_feature());
+
+ /*dram bank num*/
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_dram_rank_num_header: %u,%u\n", MET_EMI_GetDramRankNum(0),
+ MET_EMI_GetDramRankNum(0));
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_emi_header: TS0,TS1,GP0_WSCT,GP1_WSCT,GP2_WSCT,GP3_WSCT,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "M0_LATENCY,M1_LATENCY,M2_LATENCY,M3_LATENCY,M4_LATENCY,M5_LATENCY,M6_LATENCY,M7_LATENCY,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "M0_TRANS,M1_TRANS,M2_TRANS,M3_TRANS,M4_TRANS,M5_TRANS,M6_TRANS,M7_TRANS,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "BACT,BSCT,BCNT,WACT,DCM_CTRL,TACT,");
+
+ for (i = 0; i < dram_chann_num; i++) {
+ if (i != 0)
+ ret += snprintf(buf + ret, buf_len - ret,
+ ",");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "PageHit_%d,PageMiss_%d,InterBank_%d,Idle_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "mr4_%d,refresh_pop_%d,freerun_26m_%d,", i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "read_bytes_%d,write_bytes_%d", i, i);
+ }
+ ret += snprintf(buf + ret, buf_len - ret, "\n");
+
+ /*TSCT header*/
+ if (emi_tsct_enable == 1) {
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: ms_emi_tsct_header: ms_emi_tsct,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "tsct1,tsct2,tsct3\n");
+ }
+
+ /*MDCT header*/
+ if (emi_mdct_enable == 1) {
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: ms_emi_mdct_header: ms_emi_mdct,");
+ ret += snprintf(buf + ret, buf_len - ret,
+ "RD_ULTRA,RD_MDMCU\n");
+ }
+
+
+
+ /* met_bw_rgtor_header */
+ ret += snprintf(buf + ret, buf_len - ret, "met-info [000] 0.0: met_bw_rgtor_unit_header: %x\n", MET_EMI_Get_CONH_2ND(0));
+
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_bw_rglr_header: metadata\n");
+
+
+ /* DRAM DVFS header */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: DRAM_DVFS_header: datarate(MHz)\n");
+
+ /*PDIR met_dramc_header*/
+ if (dramc_pdir_enable == 1 && DRAMC_VER >= 2 ) {
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: met_dramc_header: ");
+ for (i = 0; i < dram_chann_num; i++) {
+ if (i != 0)
+ ret += snprintf(buf + ret, buf_len - ret,
+ ",");
+ ret += snprintf(buf + ret, buf_len - ret, "freerun_26m_%d,", i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "rk0_pre_sb_%d,rk0_pre_pd_%d,rk0_act_sb_%d,rk0_act_pd_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "rk1_pre_sb_%d,rk1_pre_pd_%d,rk1_act_sb_%d,rk1_act_pd_%d,", i, i, i, i);
+ ret += snprintf(buf + ret, buf_len - ret,
+ "rk2_pre_sb_%d,rk2_pre_pd_%d,rk2_act_sb_%d,rk2_act_pd_%d", i, i, i, i);
+ }
+ ret += snprintf(buf + ret, buf_len - ret, "\n");
+ }
+
+ /* DRS header */
+ ret += snprintf(buf + ret, buf_len - ret,
+ "met-info [000] 0.0: emi_drs_header: ch0_RANK1_GP(%%),ch0_RANK1_SF(%%),ch0_ALL_SF(%%),ch1_RANK1_GP(%%),ch1_RANK1_SF(%%),ch1_ALL_SF(%%)\n");
+#endif
+
+ met_sspm_emi.header_read_again = 0;
+ output_header_len = 0;
+ output_str_len = 0;
+
+ return ret;
+}
+
+
+static int ondiemet_emi_print_header(char *buf, int len)
+{
+ return emi_print_header(buf, len);
+}
+
+
+
+static void MET_BM_IPI_REGISTER_CB(void)
+{
+ int ret, i;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_REGISTER_CB;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+
+static void MET_BM_IPI_configs(void)
+{
+ int ret, i;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ for (i = 0; i < 4; i++)
+ ipi_buf[i] = 0;
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | (MID_EMI << MID_BIT_SHIFT) | MET_ARGU | SET_EBM_CONFIGS1;
+ ipi_buf[2] = EMI_VER_MAJOR << 24 | EMI_VER_MINOR << 16 | DRAMC_VER << 8 | 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+
+static void ondiemet_emi_start(void)
+{
+ MET_BM_IPI_REGISTER_CB();
+ if (!emi_inited) {
+ if (MET_BM_Init() != 0) {
+ met_sspm_emi.mode = 0;
+ pr_notice("MET_BM_Init failed!!!\n");
+ return;
+ }
+ emi_inited = 1;
+ }
+ MET_BM_IPI_configs();
+
+ if (do_emi())
+ emi_init();
+
+ ondiemet_module[ONDIEMET_SSPM] |= ID_EMI;
+
+ emi_create_header(header_str, MAX_HEADER_LEN);
+}
+
+static void ondiemet_emi_stop(void)
+{
+ if (!emi_inited)
+ return;
+
+ if (do_emi())
+ emi_uninit();
+}
+
+
+
+struct metdevice met_sspm_emi = {
+ .name = "emi",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_emi_create,
+ .delete_subfs = met_emi_delete,
+ .resume = met_emi_resume,
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ .ondiemet_start = ondiemet_emi_start,
+ .ondiemet_stop = ondiemet_emi_stop,
+ .ondiemet_print_help = emi_print_help,
+ .ondiemet_print_header = ondiemet_emi_print_header,
+#endif
+#endif
+ .ondiemet_mode = 1,
+};
+EXPORT_SYMBOL(met_sspm_emi);
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3_6/mtk_emi_bm.c b/src/devtools/met_drv_v2/common/emi/SEDA3_6/mtk_emi_bm.c
new file mode 100644
index 0000000..2485377
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3_6/mtk_emi_bm.c
@@ -0,0 +1,926 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/io.h>
+
+#ifdef USE_KERNEL_SYNC_WRITE_H
+#include <mt-plat/sync_write.h>
+#else
+#include "sync_write.h"
+#endif
+
+#ifdef USE_KERNEL_MTK_IO_H
+#include <mt-plat/mtk_io.h>
+#else
+#include "mtk_io.h"
+#endif
+
+#include "mtk_typedefs.h"
+#include "core_plf_init.h"
+#include "mtk_emi_bm.h"
+#include "met_reg_addr.h"
+
+#include "met_drv.h"
+#include "interface.h"
+
+#undef DEBUG
+#undef debug_reg
+#ifdef debug_reg
+static inline unsigned int emi_readl(void __iomem *padr)
+{
+ unsigned int tmp;
+
+ tmp = readl(padr);
+ MET_TRACE("[MET_EMI] RD_Reg: %p: %08x\n", padr, tmp);
+ return tmp;
+}
+
+static inline void __emi_reg_sync_writel(unsigned int data, void __iomem *padr)
+{
+ unsigned int tmp;
+
+ mt_reg_sync_writel(data, padr);
+ tmp = readl(padr);
+ MET_TRACE("[MET_EMI] WR_Reg: %p: %08x, %08x\n", padr, data, tmp);
+}
+
+#define emi_reg_sync_writel(data, adr) __emi_reg_sync_writel(data, IOMEM(adr))
+
+#else
+#define emi_readl readl
+#define emi_reg_sync_writel mt_reg_sync_writel
+#endif
+
+#define MASK_MASTER 0xFF
+#define MASK_TRANS_TYPE 0xFF
+
+/* static int dram_chann_num; */
+static void __iomem *BaseAddrEMI[EMI_NUM_MAX];
+/* static void __iomem *BaseAddrCHN_EMI[2]; */
+
+/* static int dramc0_dcm_enable;
+static int dramc1_dcm_enable; */
+
+#define CH0_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[0]) + 0x284)
+#define CH1_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[1]) + 0x284)
+#define CH2_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[2]) + 0x284)
+#define CH3_MISC_CG_CTRL0 (((unsigned long) BaseAddrDDRPHY_AO[3]) + 0x284)
+
+
+const unsigned int emi_config[] = {
+ EMI_BMEN,
+ EMI_MSEL,
+ EMI_MSEL2,
+ EMI_MSEL3,
+ EMI_MSEL4,
+ EMI_MSEL5,
+ EMI_MSEL6,
+ EMI_MSEL7,
+ EMI_MSEL8,
+ EMI_MSEL9,
+ EMI_MSEL10,
+ EMI_BMID0,
+ EMI_BMID1,
+ EMI_BMID2,
+ EMI_BMID3,
+ EMI_BMID4,
+ EMI_BMID5,
+ EMI_BMID6,
+ EMI_BMID7,
+ EMI_BMID8,
+ EMI_BMID9,
+ EMI_BMID10,
+ EMI_BMEN1,
+ EMI_BMEN2,
+ EMI_BMRW0,
+ EMI_BMRW1,
+ EMI_DBWA,
+ EMI_DBWB,
+ EMI_DBWC,
+ EMI_DBWD,
+ EMI_DBWE,
+ EMI_DBWF,
+ EMI_DBWI,
+ EMI_DBWJ,
+ EMI_DBWK,
+ EMI_DBWA_2ND,
+ EMI_DBWB_2ND,
+ EMI_DBWC_2ND,
+ EMI_DBWD_2ND,
+ EMI_DBWE_2ND,
+ EMI_DBWF_2ND,
+ EMI_TTYPE1_CONA,
+ EMI_TTYPE1_CONB,
+ EMI_TTYPE2_CONA,
+ EMI_TTYPE2_CONB,
+ EMI_TTYPE3_CONA,
+ EMI_TTYPE3_CONB,
+ EMI_TTYPE4_CONA,
+ EMI_TTYPE4_CONB,
+ EMI_TTYPE5_CONA,
+ EMI_TTYPE5_CONB,
+ EMI_TTYPE6_CONA,
+ EMI_TTYPE6_CONB,
+ EMI_TTYPE7_CONA,
+ EMI_TTYPE7_CONB,
+ EMI_TTYPE8_CONA,
+ EMI_TTYPE8_CONB,
+ EMI_TTYPE9_CONA,
+ EMI_TTYPE9_CONB,
+ EMI_TTYPE10_CONA,
+ EMI_TTYPE10_CONB,
+ EMI_TTYPE11_CONA,
+ EMI_TTYPE11_CONB,
+ EMI_TTYPE12_CONA,
+ EMI_TTYPE12_CONB,
+ EMI_TTYPE13_CONA,
+ EMI_TTYPE13_CONB,
+ EMI_TTYPE14_CONA,
+ EMI_TTYPE14_CONB,
+ EMI_TTYPE15_CONA,
+ EMI_TTYPE15_CONB,
+ EMI_TTYPE16_CONA,
+ EMI_TTYPE16_CONB,
+ EMI_TTYPE17_CONA,
+ EMI_TTYPE17_CONB,
+ EMI_TTYPE18_CONA,
+ EMI_TTYPE18_CONB,
+ EMI_TTYPE19_CONA,
+ EMI_TTYPE19_CONB,
+ EMI_TTYPE20_CONA,
+ EMI_TTYPE20_CONB,
+ EMI_TTYPE21_CONA,
+ EMI_TTYPE21_CONB
+};
+#define EMI_CONFIG_MX_NR (sizeof(emi_config)/sizeof(unsigned int))
+static unsigned int emi_config_val[EMI_NUM][EMI_CONFIG_MX_NR];
+
+
+
+static inline void MET_REG_BCLR(unsigned long reg, u32 shift)
+{
+ unsigned int read_val = 0;
+
+ read_val = emi_readl(IOMEM(reg));
+ emi_reg_sync_writel(read_val & (~((1 << shift) & 0xFFFFFFFF)), reg);
+}
+
+
+int MET_BM_Init(void)
+{
+ /*emi*/
+ /*int idx;*/
+ unsigned int emi_no;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ BaseAddrEMI[emi_no] = 0;
+ }
+
+ if( EMI_NUM == 1 )
+ {
+ BaseAddrEMI[0] = ioremap(EMI_REG_BASE, EMI_REG_SIZE);
+ }
+ else {
+ /*EMI num == 2*/
+ BaseAddrEMI[0] = ioremap(EMI_REG_BASE, EMI_REG_SIZE);
+ BaseAddrEMI[1] = ioremap(SUB_EMI_REG_BASE, EMI_REG_SIZE);
+ }
+
+ /*check the ioremap sucess or not*/
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ if (BaseAddrEMI[emi_no] == 0)
+ {
+ METERROR("BaseAddrEMI[%d] ioremap fail\n",emi_no);
+ PR_BOOTMSG_ONCE("BaseAddrEMI[%d] ioremap fail\n",emi_no);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+
+void MET_BM_DeInit(void)
+{
+
+ /*iounmap*/
+ if( EMI_NUM == 1 )
+ {
+ if (BaseAddrEMI[0])
+ iounmap(BaseAddrEMI[0]);
+
+ BaseAddrEMI[0] = NULL;
+ }
+ else {
+ /*EMI num == 2*/
+ if (BaseAddrEMI[0])
+ iounmap(BaseAddrEMI[0]);
+
+ BaseAddrEMI[0] = NULL;
+
+ if (BaseAddrEMI[1])
+ iounmap(BaseAddrEMI[1]);
+
+ BaseAddrEMI[1] = NULL;
+ }
+}
+
+
+void MET_BM_SaveCfg(void)
+{
+ int i,emi_no;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++){
+ for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+ emi_config_val[emi_no][i] = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + emi_config[i]));
+ }
+}
+
+
+void MET_BM_RestoreCfg(void)
+{
+ int i,emi_no;
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++){
+ for (i = 0; i < EMI_CONFIG_MX_NR; i++)
+ emi_reg_sync_writel(emi_config_val[emi_no][i], (unsigned long)BaseAddrEMI[emi_no] + emi_config[i]);
+ }
+}
+
+
+void MET_BM_SetReadWriteType(const unsigned int ReadWriteType)
+{
+ /*
+ * ReadWriteType: 00/11 --> both R/W
+ * 01 --> only R
+ * 10 --> only W
+ */
+ volatile unsigned int value;
+ unsigned int emi_no;
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN));
+ emi_reg_sync_writel((value & 0xFFFFFFCF) | (ReadWriteType << 4), (unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN);
+ }
+}
+
+
+
+
+int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+ const unsigned int master, const unsigned int trans_type)
+{
+ unsigned int value, addr;
+ const unsigned int iMask = (MASK_TRANS_TYPE << 8) | MASK_MASTER;
+ unsigned int emi_no;
+
+ if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+ return BM_ERR_WRONG_REQ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ if (counter_num == 1) {
+ addr = EMI_BMEN;
+ value = (emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr)) & ~(iMask << 16)) |
+ ((trans_type & MASK_TRANS_TYPE) << 24) | ((master & MASK_MASTER) << 16);
+ } else {
+ addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+ /* clear master and transaction type fields */
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+ /* set master and transaction type fields */
+ value |= (((trans_type & MASK_TRANS_TYPE) << 8) |
+ (master & MASK_MASTER)) << ((counter_num % 2) * 16);
+ }
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val)
+{
+
+ volatile unsigned int value_origin;
+ unsigned int emi_no;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ value_origin = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMRW0));
+ MET_TRACE("[MET_EMI_settype1] value_origin: %x\n", value_origin);
+ if (value_origin != bmrw0_val) {
+ emi_reg_sync_writel(bmrw0_val, (unsigned long)BaseAddrEMI[emi_no] + EMI_BMRW0);
+ MET_TRACE("[MET_EMI_settype1] bmrw0_val: %x, value_origin: %x\n", bmrw0_val,
+ value_origin);
+ }
+
+
+ value_origin = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMRW1));
+ MET_TRACE("[MET_EMI_settype2] value_origin: %x\n", value_origin);
+ if (value_origin != bmrw1_val) {
+ emi_reg_sync_writel(bmrw1_val, (unsigned long)BaseAddrEMI[emi_no] + EMI_BMRW1);
+ MET_TRACE("[MET_EMI_settype2] bmrw0_val: %x, value_origin: %x\n", bmrw1_val,
+ value_origin);
+
+ }
+ }
+ return BM_REQ_OK;
+}
+
+/*not use after SEDA 3.5*/
+int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable)
+{
+ volatile unsigned int value;
+ unsigned int emi_no;
+
+ if (counter_num > 3)
+ return BM_ERR_WRONG_REQ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ value =
+ ((emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN2)) & (~(1 << (28 + counter_num)))) |
+ (enable << (28 + counter_num)));
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN2);
+ }
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master)
+{
+ volatile unsigned int value, addr;
+ const unsigned int iMask = 0x7F;
+ unsigned int emi_no;
+
+ if (counter_num < 1 || counter_num > BM_COUNTER_MAX)
+ return BM_ERR_WRONG_REQ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ if (counter_num == 1) {
+ addr = EMI_BMEN;
+ value =
+ (emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr)) & ~(iMask << 16)) | ((master & iMask) << 16);
+ } else {
+ addr = (counter_num <= 3) ? EMI_MSEL : (EMI_MSEL2 + (counter_num / 2 - 2) * 8);
+
+ /* clear master and transaction type fields */
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr)) & ~(iMask << ((counter_num % 2) * 16));
+
+ /* set master and transaction type fields */
+ value |= ((master & iMask) << ((counter_num % 2) * 16));
+ }
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID_En(const unsigned int counter_num,
+ const unsigned int enable)
+{
+ volatile unsigned int value;
+ unsigned int emi_no;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+ return BM_ERR_WRONG_REQ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ if (enable == 0) {
+ /* clear EMI ID selection Enabling SEL_ID_EN */
+ value = (emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN2))
+ & ~(1 << (counter_num - 1)));
+ } else {
+ /* enable EMI ID selection Enabling SEL_ID_EN */
+ value = (emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN2))
+ | (1 << (counter_num - 1)));
+ }
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN2);
+ }
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetbusID(const unsigned int counter_num,
+ const unsigned int id)
+{
+ volatile unsigned int value, addr, shift_num;
+ unsigned int emi_no;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX))
+ return BM_ERR_WRONG_REQ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ /* offset of EMI_BMIDx register */
+ addr = EMI_BMID0 + (counter_num - 1) / 2 * 4;
+ shift_num = ((counter_num - 1) % 2) * 16;
+ /* clear SELx_ID field */
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr)) & ~(EMI_BMID_MASK << shift_num);
+
+ /* set SELx_ID field */
+ if (id <= 0xffff) /*bigger then 0xff_ff : no select busid in master, reset busid as 0*/
+ value |= id << shift_num;
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable)
+{
+ volatile unsigned int value;
+ unsigned int emi_no;
+
+ if ((counter_num < 1 || counter_num > BM_COUNTER_MAX) || (enable > 1))
+ return BM_ERR_WRONG_REQ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ value = (emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN1))
+ & ~(1 << (counter_num - 1)))
+ | (enable << (counter_num - 1));
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN1);
+ }
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetLatencyCounter(unsigned int enable)
+{
+ volatile unsigned int value;
+ unsigned int emi_no;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN2)) & ~(0x3 << 24);
+ /*
+ * emi_ttype1 -- emi_ttype8 change as total latencies
+ * for m0 -- m7,
+ * and emi_ttype9 -- emi_ttype16 change as total transaction counts
+ * for m0 -- m7
+ */
+ if (enable == 1)
+ value |= (0x2 << 24);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + EMI_BMEN2);
+ }
+ return BM_REQ_OK;
+}
+
+
+
+
+
+
+
+
+int MET_BM_SetEmiDcm(const unsigned int setting)
+{
+ volatile unsigned int value;
+ unsigned int emi_no;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_CONM));
+ emi_reg_sync_writel((value & 0x00FFFFFF) | (setting << 24), (unsigned long)BaseAddrEMI[emi_no] + EMI_CONM);
+ }
+ return BM_REQ_OK;
+}
+
+
+
+
+unsigned int MET_EMI_GetDramChannNum(unsigned int emi_no)
+{
+ int num = -1;
+
+ if (BaseAddrEMI[emi_no]) {
+ num = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_CONA));
+ num = ((num >> 8) & 0x0000003);
+ } else {
+ return 1;
+ }
+
+ if (num == M0_DOUBLE_HALF_BW_1CH)
+ return 1;
+ else if (num == M0_DOUBLE_HALF_BW_2CH)
+ return 2;
+ else if (num == M0_DOUBLE_HALF_BW_4CH)
+ return 4;
+ else /* default return single channel */
+ return 1;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum(unsigned int emi_no)
+{
+ int dual_rank = 0;
+
+ if (BaseAddrEMI[emi_no]) {
+ dual_rank = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_CONA));
+ dual_rank = ((dual_rank >> 17) & RANK_MASK);
+ } else {
+ return DUAL_RANK;
+ }
+
+ if (dual_rank == DISABLE_DUAL_RANK_MODE)
+ return ONE_RANK;
+ else /* default return dual rank */
+ return DUAL_RANK;
+}
+
+
+unsigned int MET_EMI_GetDramRankNum_CHN1(unsigned int emi_no)
+{
+ int dual_rank = 0;
+
+ if (BaseAddrEMI[emi_no]) {
+ dual_rank = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_CONA));
+ dual_rank = ((dual_rank >> 16) & RANK_MASK);
+ } else {
+ return DUAL_RANK;
+ }
+
+ if (dual_rank == DISABLE_DUAL_RANK_MODE)
+ return ONE_RANK;
+ else /* default return dual rank */
+ return DUAL_RANK;
+}
+
+
+
+unsigned int MET_EMI_Get_BaseClock_Rate(void)
+{
+ unsigned int DRAM_TYPE;
+
+ if (get_cur_ddr_ratio_symbol)
+ return get_cur_ddr_ratio_symbol();
+ else {
+
+ if (mtk_dramc_get_ddr_type_symbol) {
+ DRAM_TYPE = mtk_dramc_get_ddr_type_symbol();
+
+ if ((DRAM_TYPE == 5) || (DRAM_TYPE == 6) || (DRAM_TYPE == 7))
+ return DRAM_EMI_BASECLOCK_RATE_LP4;
+ else
+ return DRAM_EMI_BASECLOCK_RATE_LP3;
+
+ } else {
+ return DRAM_EMI_BASECLOCK_RATE_LP4;
+ }
+ }
+}
+
+/* For SEDA3.5 wsct setting*/
+/* EMI_DBWX[15:8], X=A~F (SEL_MASTER) */
+/* RW: EMI_DBWX[1:0], X=A~F */
+int MET_BM_SetWSCT_master_rw(unsigned int *master , unsigned int *rw)
+{
+ volatile unsigned int value, addr;
+ int i;
+ unsigned int emi_no;
+
+ const unsigned int Mask_master = 0xFF;
+ const unsigned int offset_master = 8;
+
+ const unsigned int Mask_rw = 0x3;
+ const unsigned int offset_rw = 0;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i=0; i<WSCT_AMOUNT; i++) {
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_master << offset_master)) | ((*(master+i) & Mask_master) << offset_master);
+ value = (value & ~(Mask_rw << offset_rw)) | ((*(rw+i) & Mask_rw) << offset_rw);
+
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ }
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetWSCT_high_priority(unsigned int *disable, unsigned int *select)
+{
+ volatile unsigned int value, addr;
+ int i;
+ unsigned int emi_no;
+
+ const unsigned int Mask_disable = 0x1;
+ const unsigned int offset_disable = 2;
+
+ const unsigned int Mask_select = 0xF;
+ const unsigned int offset_select = 28;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+ value = (value & ~(Mask_disable << offset_disable)) | ((*(disable+i) & Mask_disable) << offset_disable);
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+
+ /* ultra level setting */
+ addr = EMI_DBWA_2ND + i*4;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+ value = (value & ~(Mask_select << offset_select)) | ((*(select+i) & Mask_select) << offset_select);
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ }
+ return BM_REQ_OK;
+}
+
+/* busid enbale: EMI_DBWX[3], X=A~F */
+/* busid sel: EMI_DBWX[28:16], X=A~F (SEL_ID_TMP) */
+/* busid mask : EMI_DBWY[12:0] 或 EMI_DBWY[28:16], Y=I~K (SEL_ID_MSK) */
+int MET_BM_SetWSCT_busid_idmask(unsigned int *busid, unsigned int *idMask)
+{
+ volatile unsigned int value, addr;
+ volatile unsigned int enable_tmp, busid_tmp, idmask_tmp;
+ int i;
+ unsigned int emi_no;
+
+ const unsigned int Mask_busid = 0xFFFF;
+ const unsigned int offset_busid = 16;
+
+ const unsigned int Mask_enable = 0x1;
+ const unsigned int offset_enable = 3;
+
+ const unsigned int Mask_idMask = 0xFFFF;
+ const unsigned int offset_idMask_even = 0;
+ const unsigned int offset_idMask_odd = 16;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i=0;i<WSCT_AMOUNT;i++) {
+
+ /*enable, SEL_ID_TMP*/
+ if (*(busid+i)>0xffff) {
+ enable_tmp = 0;
+ busid_tmp = 0xFFFF;
+ idmask_tmp = 0xFFFF;
+ }
+ else {
+ enable_tmp = 1;
+ busid_tmp = *(busid+i) & Mask_busid;
+ idmask_tmp = *(idMask+i) & Mask_idMask;
+ }
+
+
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_busid << offset_busid)) | (busid_tmp << offset_busid);
+ value = (value & ~(Mask_enable << offset_enable)) | (enable_tmp << offset_enable);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+
+ /*SEL_ID_MSK*/
+ addr = EMI_DBWI + (i/2)*4;
+
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ if (i%2==0)
+ value = (value & ~(Mask_idMask << offset_idMask_even)) | (idmask_tmp << offset_idMask_even);
+ else
+ value = (value & ~(Mask_idMask << offset_idMask_odd)) | (idmask_tmp << offset_idMask_odd);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ }
+
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetWSCT_chn_rank_sel(unsigned int *chn_rank_sel)
+{
+ volatile unsigned int value, addr;
+ int i;
+ unsigned int emi_no;
+
+ const unsigned int Mask = 0xF;
+ const unsigned int offset = 12;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i=0;i<WSCT_AMOUNT;i++) {
+ addr = EMI_DBWA_2ND + i*4;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask << offset)) | ((*(chn_rank_sel+i) & Mask) << offset);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ }
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetWSCT_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd)
+{
+ volatile unsigned int value, addr;
+ int i;
+ unsigned int emi_no;
+
+ const unsigned int Mask_dis = 0x1, Mask_low_bnd = 0x1FF, Mask_up_bnd = 0x1FF;
+ const unsigned int offset_dis = 4, offset_low_bnd = 16 , offset_up_bnd = 0 ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i=0;i<WSCT_AMOUNT;i++) {
+
+ addr = EMI_DBWA + i*4;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_dis << offset_dis)) | ((*(bnd_dis+i) & Mask_dis) << offset_dis);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+
+
+ addr = EMI_DBWA_2ND + i*4;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_low_bnd << offset_low_bnd)) | ((*(low_bnd+i) & Mask_low_bnd) << offset_low_bnd);
+ value = (value & ~(Mask_up_bnd << offset_up_bnd)) | ((*(up_bnd+i) & Mask_up_bnd) << offset_up_bnd);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ }
+ return BM_REQ_OK;
+
+}
+
+int MET_BM_SetTSCT_busid_enable(unsigned int *enable)
+{
+ //MET_BM_Set_WsctTsct_id_sel
+
+ int i;
+
+ for (i=0;i<TSCT_AMOUNT;i++) {
+ MET_BM_Set_WsctTsct_id_sel(i, *(enable+i));
+ }
+
+ return BM_REQ_OK;
+}
+
+//use the origin together, MET_BM_SetUltraHighFilter()
+/* EMI_TTYPEN_CONA [23:20], N=1~21 (HPRI_SEL) */
+int MET_BM_SetTtype_high_priority_sel(unsigned int _high_priority_filter, unsigned int *select)
+{
+ int i;
+ volatile unsigned int enable;
+ volatile unsigned int value, addr;
+ unsigned int emi_no;
+
+ const unsigned int Mask_sel = 0xF;
+ const unsigned int offset_sel = 20;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i = 0; i < BM_COUNTER_MAX; i++) {
+ if ((_high_priority_filter & (1 << i)) == 0){
+ enable = 0;
+ }
+ else {
+ enable = 1;
+ }
+
+ MET_BM_SetUltraHighFilter(i + 1, enable);
+
+ /* ultra level select */
+ addr = EMI_TTYPE1_CONA + i*8;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_sel << offset_sel)) | ((*(select+i) & Mask_sel) << offset_sel);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+
+ }
+ }
+ return BM_REQ_OK;
+}
+
+
+//always call this API to init the reg
+//related API, MET_BM_SetbusID, MET_BM_SetbusID_En
+int MET_BM_SetTtype_busid_idmask(unsigned int *busid, unsigned int *idMask, int _ttype1_16_en, int _ttype17_21_en)
+{
+ int i;
+ volatile unsigned int value, addr;
+ unsigned int emi_no;
+
+ const unsigned int Mask_idMask = 0x1FFF;
+ const unsigned int offset_idMask = 0;
+
+ if (_ttype1_16_en != BM_TTYPE1_16_ENABLE) {
+ /* mask set 0x1FFF , busid set disable*/
+ for (i = 1; i <= 16; i++) {
+ *(busid + i - 1) = 0xfffff;
+ *(idMask + i - 1) = 0x1FFF;
+ }
+ }
+
+ if (_ttype17_21_en != BM_TTYPE17_21_ENABLE) {
+ for (i = 17; i <= 21; i++) {
+ *(busid + i - 1) = 0xfffff;
+ *(idMask + i - 1) = 0x1FFF;
+ }
+ }
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i = 1; i <= BM_COUNTER_MAX; i++) {
+ MET_BM_SetbusID(i, *(busid + i - 1));
+ MET_BM_SetbusID_En(i, ( *(busid + i - 1) > 0xffff) ? 0 : 1);
+
+ /* set idMask */
+ addr = EMI_TTYPE1_CONA + (i-1)*8;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_idMask << offset_idMask)) | ((*(idMask+i-1) & Mask_idMask) << offset_idMask);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+
+ }
+ }
+ return BM_REQ_OK;
+}
+
+
+int MET_BM_SetTtype_chn_rank_sel(unsigned int *chn_rank_sel)
+{
+ volatile unsigned int value, addr;
+ int i;
+ unsigned int emi_no;
+
+ const unsigned int Mask = 0xF;
+ const unsigned int offset = 16;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+ addr = EMI_TTYPE1_CONA + i*8;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask << offset)) | ((*(chn_rank_sel+i) & Mask) << offset);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ }
+ return BM_REQ_OK;
+}
+
+int MET_BM_SetTtype_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd)
+{
+ volatile unsigned int value, addr;
+ int i;
+ unsigned int emi_no;
+
+ const unsigned int Mask_dis = 0x1, Mask_low_bnd = 0x1FF, Mask_up_bnd = 0x1FF;
+ const unsigned int offset_dis = 24, offset_low_bnd = 16 , offset_up_bnd = 0 ;
+
+ for(emi_no=0; emi_no<EMI_NUM ;emi_no++)
+ {
+ for (i=0;i<BM_COUNTER_MAX;i++) {
+
+ /* set dis bit */
+ addr = EMI_TTYPE1_CONA + i*8;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_dis << offset_dis)) | ((*(bnd_dis+i) & Mask_dis) << offset_dis);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+
+
+ addr = EMI_TTYPE1_CONB + i*8;
+ value = emi_readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + addr));
+
+ value = (value & ~(Mask_low_bnd << offset_low_bnd)) | ((*(low_bnd+i) & Mask_low_bnd) << offset_low_bnd);
+ value = (value & ~(Mask_up_bnd << offset_up_bnd)) | ((*(up_bnd+i) & Mask_up_bnd) << offset_up_bnd);
+
+ emi_reg_sync_writel(value, (unsigned long)BaseAddrEMI[emi_no] + addr);
+ }
+ }
+ return BM_REQ_OK;
+}
+
+unsigned int MET_EMI_Get_CONH_2ND(unsigned int emi_no)
+{
+ return readl(IOMEM((unsigned long)BaseAddrEMI[emi_no] + EMI_CONH_2ND));
+}
diff --git a/src/devtools/met_drv_v2/common/emi/SEDA3_6/mtk_emi_bm.h b/src/devtools/met_drv_v2/common/emi/SEDA3_6/mtk_emi_bm.h
new file mode 100644
index 0000000..fd6372e
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/emi/SEDA3_6/mtk_emi_bm.h
@@ -0,0 +1,302 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#ifndef __MT_MET_EMI_BM_H__
+#define __MT_MET_EMI_BM_H__
+
+#define EMI_VER_MAJOR 3
+#define EMI_VER_MINOR 6
+
+#define EMI_NUM_MAX 2
+#define EMI_NUM 2
+
+#define FILE_NODE_DATA_LEN 512
+#define WSCT_AMOUNT 6
+#define TSCT_AMOUNT 3
+
+
+#define DRAM_EMI_BASECLOCK_RATE_LP4 4
+#define DRAM_EMI_BASECLOCK_RATE_LP3 2
+
+#define DRAM_IO_BUS_WIDTH_LP4 16
+#define DRAM_IO_BUS_WIDTH_LP3 32
+
+#define DRAM_DATARATE 2
+
+#define DRAM_FREQ_DEFAULT 3733
+#define DDR_RATIO_DEFAULT 8
+#define DRAM_TYPE_DEFAULT 3
+
+/*#define ADDR_EMI ((unsigned long)BaseAddrEMI)*/
+
+#define BM_MASTER_M0 (0x01)
+#define BM_MASTER_M1 (0x02)
+#define BM_MASTER_M2 (0x04)
+#define BM_MASTER_M3 (0x08)
+#define BM_MASTER_M4 (0x10)
+#define BM_MASTER_M5 (0x20)
+#define BM_MASTER_M6 (0x40)
+#define BM_MASTER_M7 (0x80)
+#define BM_MASTER_ALL (0xFF)
+
+
+enum BM_RW_Type {
+ BM_BOTH_READ_WRITE,
+ BM_READ_ONLY,
+ BM_WRITE_ONLY
+};
+
+enum {
+ BM_TRANS_TYPE_1BEAT = 0x0,
+ BM_TRANS_TYPE_2BEAT,
+ BM_TRANS_TYPE_3BEAT,
+ BM_TRANS_TYPE_4BEAT,
+ BM_TRANS_TYPE_5BEAT,
+ BM_TRANS_TYPE_6BEAT,
+ BM_TRANS_TYPE_7BEAT,
+ BM_TRANS_TYPE_8BEAT,
+ BM_TRANS_TYPE_9BEAT,
+ BM_TRANS_TYPE_10BEAT,
+ BM_TRANS_TYPE_11BEAT,
+ BM_TRANS_TYPE_12BEAT,
+ BM_TRANS_TYPE_13BEAT,
+ BM_TRANS_TYPE_14BEAT,
+ BM_TRANS_TYPE_15BEAT,
+ BM_TRANS_TYPE_16BEAT,
+ BM_TRANS_TYPE_1Byte = 0 << 4,
+ BM_TRANS_TYPE_2Byte = 1 << 4,
+ BM_TRANS_TYPE_4Byte = 2 << 4,
+ BM_TRANS_TYPE_8Byte = 3 << 4,
+ BM_TRANS_TYPE_16Byte = 4 << 4,
+ BM_TRANS_TYPE_32Byte = 5 << 4,
+ BM_TRANS_TYPE_BURST_WRAP = 0 << 7,
+ BM_TRANS_TYPE_BURST_INCR = 1 << 7
+};
+
+enum {
+ BM_TRANS_RW_DEFAULT = 0x0,
+ BM_TRANS_RW_READONLY,
+ BM_TRANS_RW_WRITEONLY,
+ BM_TRANS_RW_RWBOTH
+};
+
+enum {
+ BM_WSCT_RW_DISABLE = 0x0,
+ BM_WSCT_RW_READONLY,
+ BM_WSCT_RW_WRITEONLY,
+ BM_WSCT_RW_RWBOTH
+};
+
+/*coda busid 12bit, but HW support 16 bit*/
+#define EMI_BMID_MASK (0xFFFF)
+#define BM_COUNTER_MAX (21)
+
+enum {
+ BUS_MON_EN_SHIFT = 0,
+ BUS_MON_PAUSE_SHIFT = 1,
+ BUS_MON_IDLE_SHIFT = 3,
+ BC_OVERRUN_SHIFT = 8,
+ DRAMC_CG_SHIFT = 9,
+};
+
+#define BM_REQ_OK (0)
+#define BM_ERR_WRONG_REQ (-1)
+#define BM_ERR_OVERRUN (-2)
+
+#define BM_WSCT_TSCT_IDSEL_ENABLE (0)
+#define BM_WSCT_TSCT_IDSEL_DISABLE (-1)
+#define BM_TTYPE1_16_ENABLE (0)
+#define BM_TTYPE1_16_DISABLE (-1)
+#define BM_TTYPE17_21_ENABLE (0)
+#define BM_TTYPE17_21_DISABLE (-1)
+#define BM_BW_LIMITER_ENABLE (0)
+#define BM_BW_LIMITER_DISABLE (-1)
+
+#define M0_DOUBLE_HALF_BW_1CH (0x0)
+#define M0_DOUBLE_HALF_BW_2CH (0x1)
+#define M0_DOUBLE_HALF_BW_4CH (0x2)
+
+/* EMI Rank configuration */
+enum {
+ DISABLE_DUAL_RANK_MODE = 0,
+ ENABLE_DUAL_RANK_MODE,
+};
+
+#define RANK_MASK 0x1
+#define ONE_RANK 1
+#define DUAL_RANK 2
+
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+enum BM_EMI_IPI_Type {
+ SET_BASE_EMI = 0x0,
+ SET_EBM_CONFIGS1 = 0x7,
+ SET_EBM_CONFIGS2 = 0x8,
+ SET_REGISTER_CB = 0x9,
+};
+#endif
+#endif
+
+
+#define EMI_OFF 0x0000
+#define EMI_CONA (0x000-EMI_OFF)
+#define EMI_CONH (0x038-EMI_OFF)
+#define EMI_CONH_2ND (0x03C-EMI_OFF)
+#define EMI_CONM (0x060-EMI_OFF)
+#define EMI_CONO (0x070-EMI_OFF)
+
+#define EMI_MDCT (0x078 - EMI_OFF)
+#define EMI_MDCT_2ND (0x07C - EMI_OFF)
+
+#define EMI_ARBA (0x100 - EMI_OFF)
+#define EMI_ARBB (0x108 - EMI_OFF)
+#define EMI_ARBC (0x110 - EMI_OFF)
+#define EMI_ARBD (0x118 - EMI_OFF)
+#define EMI_ARBE (0x120 - EMI_OFF)
+#define EMI_ARBF (0x128 - EMI_OFF)
+#define EMI_ARBG (0x130 - EMI_OFF)
+#define EMI_ARBG_2ND (0x134 - EMI_OFF)
+#define EMI_ARBH (0x138 - EMI_OFF)
+
+
+#define EMI_BMEN (0x400-EMI_OFF)
+#define EMI_MSEL (0x440 - EMI_OFF)
+#define EMI_MSEL2 (0x468 - EMI_OFF)
+#define EMI_MSEL3 (0x470 - EMI_OFF)
+#define EMI_MSEL4 (0x478 - EMI_OFF)
+#define EMI_MSEL5 (0x480 - EMI_OFF)
+#define EMI_MSEL6 (0x488 - EMI_OFF)
+#define EMI_MSEL7 (0x490 - EMI_OFF)
+#define EMI_MSEL8 (0x498 - EMI_OFF)
+#define EMI_MSEL9 (0x4A0 - EMI_OFF)
+#define EMI_MSEL10 (0x4A8 - EMI_OFF)
+
+#define EMI_BMID0 (0x4B0 - EMI_OFF)
+#define EMI_BMID1 (0x4B4 - EMI_OFF)
+#define EMI_BMID2 (0x4B8 - EMI_OFF)
+#define EMI_BMID3 (0x4BC - EMI_OFF)
+#define EMI_BMID4 (0x4C0 - EMI_OFF)
+#define EMI_BMID5 (0x4C4 - EMI_OFF)
+#define EMI_BMID6 (0x4C8 - EMI_OFF)
+#define EMI_BMID7 (0x4CC - EMI_OFF)
+#define EMI_BMID8 (0x4D0 - EMI_OFF)
+#define EMI_BMID9 (0x4D4 - EMI_OFF)
+#define EMI_BMID10 (0x4D8 - EMI_OFF)
+
+#define EMI_BMEN1 (0x4E0 - EMI_OFF)
+#define EMI_BMEN2 (0x4E8 - EMI_OFF)
+#define EMI_BMRW0 (0x4F8 - EMI_OFF)
+#define EMI_BMRW1 (0x4FC - EMI_OFF)
+
+
+/* SEDA 3.5 New! reg*/
+/* For WSCT setting*/
+#define EMI_DBWA (0xF00 - EMI_OFF)
+#define EMI_DBWB (0xF04 - EMI_OFF)
+#define EMI_DBWC (0xF08 - EMI_OFF)
+#define EMI_DBWD (0xF0C - EMI_OFF)
+#define EMI_DBWE (0xF10 - EMI_OFF)
+#define EMI_DBWF (0xF14 - EMI_OFF)
+
+
+#define EMI_DBWA_2ND (0xF2C - EMI_OFF)
+#define EMI_DBWB_2ND (0xF30 - EMI_OFF)
+#define EMI_DBWC_2ND (0xF34 - EMI_OFF)
+#define EMI_DBWD_2ND (0xF38 - EMI_OFF)
+#define EMI_DBWE_2ND (0xF3C - EMI_OFF)
+#define EMI_DBWF_2ND (0xF40 - EMI_OFF)
+
+#define EMI_DBWI (0xF20 - EMI_OFF) /* SEL_ID_MSK*/
+#define EMI_DBWJ (0xF24 - EMI_OFF)
+#define EMI_DBWK (0xF28 - EMI_OFF)
+
+/* For Ttype setting */
+#define EMI_TTYPE1_CONA (0xF50 - EMI_OFF)
+#define EMI_TTYPE1_CONB (0xF54 - EMI_OFF)
+#define EMI_TTYPE2_CONA (0xF58 - EMI_OFF)
+#define EMI_TTYPE2_CONB (0xF5C - EMI_OFF)
+#define EMI_TTYPE3_CONA (0xF60 - EMI_OFF)
+#define EMI_TTYPE3_CONB (0xF64 - EMI_OFF)
+#define EMI_TTYPE4_CONA (0xF68 - EMI_OFF)
+#define EMI_TTYPE4_CONB (0xF6C - EMI_OFF)
+#define EMI_TTYPE5_CONA (0xF70 - EMI_OFF)
+#define EMI_TTYPE5_CONB (0xF74 - EMI_OFF)
+#define EMI_TTYPE6_CONA (0xF78 - EMI_OFF)
+#define EMI_TTYPE6_CONB (0xF7C - EMI_OFF)
+#define EMI_TTYPE7_CONA (0xF80 - EMI_OFF)
+#define EMI_TTYPE7_CONB (0xF84 - EMI_OFF)
+#define EMI_TTYPE8_CONA (0xF88 - EMI_OFF)
+#define EMI_TTYPE8_CONB (0xF8C - EMI_OFF)
+#define EMI_TTYPE9_CONA (0xF90 - EMI_OFF)
+#define EMI_TTYPE9_CONB (0xF94 - EMI_OFF)
+#define EMI_TTYPE10_CONA (0xF98 - EMI_OFF)
+#define EMI_TTYPE10_CONB (0xF9C - EMI_OFF)
+#define EMI_TTYPE11_CONA (0xFA0 - EMI_OFF)
+#define EMI_TTYPE11_CONB (0xFA4 - EMI_OFF)
+#define EMI_TTYPE12_CONA (0xFA8 - EMI_OFF)
+#define EMI_TTYPE12_CONB (0xFAC - EMI_OFF)
+#define EMI_TTYPE13_CONA (0xFB0 - EMI_OFF)
+#define EMI_TTYPE13_CONB (0xFB4 - EMI_OFF)
+#define EMI_TTYPE14_CONA (0xFB8 - EMI_OFF)
+#define EMI_TTYPE14_CONB (0xFBC - EMI_OFF)
+#define EMI_TTYPE15_CONA (0xFC0 - EMI_OFF)
+#define EMI_TTYPE15_CONB (0xFC4 - EMI_OFF)
+#define EMI_TTYPE16_CONA (0xFC8 - EMI_OFF)
+#define EMI_TTYPE16_CONB (0xFCC - EMI_OFF)
+#define EMI_TTYPE17_CONA (0xFD0 - EMI_OFF)
+#define EMI_TTYPE17_CONB (0xFD4 - EMI_OFF)
+#define EMI_TTYPE18_CONA (0xFD8 - EMI_OFF)
+#define EMI_TTYPE18_CONB (0xFDC - EMI_OFF)
+#define EMI_TTYPE19_CONA (0xFE0 - EMI_OFF)
+#define EMI_TTYPE19_CONB (0xFE4 - EMI_OFF)
+#define EMI_TTYPE20_CONA (0xFE8 - EMI_OFF)
+#define EMI_TTYPE20_CONB (0xFEC - EMI_OFF)
+#define EMI_TTYPE21_CONA (0xFF0 - EMI_OFF)
+#define EMI_TTYPE21_CONB (0xFF4 - EMI_OFF)
+
+
+
+extern int MET_BM_Init(void);
+extern void MET_BM_DeInit(void);
+extern void MET_BM_SaveCfg(void);
+extern void MET_BM_RestoreCfg(void);
+
+
+
+extern int MET_BM_SetMonitorCounter(const unsigned int counter_num,
+ const unsigned int master, const unsigned int trans_type);
+extern int MET_BM_SetTtypeCounterRW(unsigned int bmrw0_val, unsigned int bmrw1_val);
+extern int MET_BM_Set_WsctTsct_id_sel(unsigned int counter_num, unsigned int enable);
+extern int MET_BM_SetMaster(const unsigned int counter_num, const unsigned int master);
+extern int MET_BM_SetbusID_En(const unsigned int counter_num,
+ const unsigned int enable);
+extern int MET_BM_SetbusID(const unsigned int counter_num,
+ const unsigned int id);
+extern int MET_BM_SetUltraHighFilter(const unsigned int counter_num, const unsigned int enable);
+extern int MET_BM_SetLatencyCounter(unsigned int enable);
+extern void MET_BM_SetReadWriteType(const unsigned int ReadWriteType);
+
+extern unsigned int MET_EMI_GetDramRankNum(unsigned int emi_no);
+extern unsigned int MET_EMI_GetDramRankNum_CHN1(unsigned int emi_no);
+
+
+unsigned int MET_EMI_GetDramChannNum(unsigned int emi_no);
+unsigned int MET_EMI_Get_CONH_2ND(unsigned int emi_no);
+
+/* SEDA 3.5 NEW */
+extern int MET_BM_SetWSCT_master_rw(unsigned int *master , unsigned int *rw);
+extern int MET_BM_SetWSCT_high_priority(unsigned int *disable, unsigned int *select);
+extern int MET_BM_SetWSCT_busid_idmask(unsigned int *busid, unsigned int *idMask);
+extern int MET_BM_SetWSCT_chn_rank_sel(unsigned int *chn_rank_sel);
+extern int MET_BM_SetWSCT_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd);
+extern int MET_BM_SetTSCT_busid_enable(unsigned int *enable);
+extern int MET_BM_SetTtype_high_priority_sel(unsigned int _high_priority_filter, unsigned int *select);
+extern int MET_BM_SetTtype_busid_idmask(unsigned int *busid, unsigned int *idMask, int _ttype1_16_en, int _ttype17_21_en);
+extern int MET_BM_SetTtype_chn_rank_sel(unsigned int *chn_rank_sel);
+extern int MET_BM_SetTtype_burst_range(unsigned int *bnd_dis, unsigned int *low_bnd, unsigned int *up_bnd);
+extern unsigned int MET_EMI_Get_BaseClock_Rate(void);
+
+#endif /* !__MT_MET_EMI_BM_H__ */
diff --git a/src/devtools/met_drv_v2/common/interface.c b/src/devtools/met_drv_v2/common/interface.c
new file mode 100644
index 0000000..2df9127
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/interface.c
@@ -0,0 +1,1529 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/sched/clock.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/miscdevice.h>
+#include <linux/kallsyms.h>
+#include <linux/syscore_ops.h>
+#include <linux/dma-mapping.h>
+#include <linux/of.h>
+#include "interface.h"
+#include "sampler.h"
+#include "util.h"
+
+#include "ondiemet.h"
+
+#include "met_drv.h"
+#include "met_tag.h"
+#include "met_kernel_symbol.h"
+#include "met_power.h"
+#include "met_api.h"
+#include "version.h"
+
+extern int enable_met_backlight_tag(void);
+extern int output_met_backlight_tag(int level);
+
+static int run = -1;
+static int sample_rate = 1000; /* Default: 1000 Hz */
+static int met_suspend_compensation_mode;
+static int met_suspend_compensation_flag;
+
+/*
+ * met_cpu_pmu_method:
+ * 0: MET pmu driver
+ * 1: perf APIs
+ */
+unsigned int met_cpu_pmu_method = 1;
+/*
+ * controls whether re-configuring pmu events after leaving cpu off state
+ */
+unsigned int met_cpu_pm_pmu_reconfig = 1;
+
+int met_hrtimer_expire; /* in ns */
+int met_timer_expire; /* in jiffies */
+unsigned int ctrl_flags;
+int met_mode;
+EXPORT_SYMBOL(met_mode);
+
+DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_nmi);
+EXPORT_SYMBOL(met_strbuf_nmi);
+
+DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_irq);
+EXPORT_SYMBOL(met_strbuf_irq);
+
+DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_sirq);
+EXPORT_SYMBOL(met_strbuf_sirq);
+
+DEFINE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf);
+EXPORT_SYMBOL(met_strbuf);
+
+static void calc_timer_value(int rate)
+{
+ sample_rate = rate;
+
+ if (rate == 0) {
+ met_hrtimer_expire = 0;
+ met_timer_expire = 0;
+ return;
+ }
+
+ met_hrtimer_expire = 1000000000 / rate;
+
+ /* Case 1: hrtimer < 1 OS tick, met_timer_expire = 1 OS tick */
+ if (rate > HZ)
+ met_timer_expire = 1;
+ /* Case 2: hrtimer > 1 OS tick, met_timer_expire is hrtimer + 1 OS tick */
+ else
+ met_timer_expire = (HZ / rate) + 1;
+
+ /* pr_debug("JBK HZ=%d, met_hrtimer_expire=%d ns, met_timer_expire=%d ticks\n", */
+ /* HZ, met_hrtimer_expire, met_timer_expire); */
+}
+
+int met_parse_num(const char *str, unsigned int *value, int len)
+{
+ int ret;
+
+ if (len <= 0)
+ return -1;
+
+ if ((len > 2) &&
+ ((str[0] == '0') &&
+ ((str[1] == 'x') || (str[1] == 'X')))) {
+ ret = kstrtoint(str, 16, value);
+ } else {
+ ret = kstrtoint(str, 10, value);
+ }
+
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
+void met_set_suspend_notify(int flag)
+{
+ if (met_suspend_compensation_mode == 1)
+ met_suspend_compensation_flag = flag;
+ else
+ met_suspend_compensation_flag = 0;
+}
+
+LIST_HEAD(met_list);
+static struct kobject *kobj_misc;
+static struct kobject *kobj_pmu;
+static struct kobject *kobj_bus;
+
+static ssize_t ver_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(ver, 0444, ver_show, NULL);
+
+static ssize_t plf_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(plf, 0444, plf_show, NULL);
+
+static ssize_t chip_id_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(chip_id, 0444, chip_id_show, NULL);
+
+static ssize_t core_topology_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(core_topology, 0444, core_topology_show, NULL);
+
+static ssize_t devices_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(devices, 0444, devices_show, NULL);
+
+static ssize_t ctrl_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(ctrl, 0664, ctrl_show, ctrl_store);
+
+static ssize_t spr_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t spr_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(sample_rate, 0664, spr_show, spr_store);
+
+static ssize_t run_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t run_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(run, 0664, run_show, run_store);
+
+static ssize_t ksym_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t ksym_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(ksym, 0664, ksym_show, ksym_store);
+
+static ssize_t cpu_pmu_method_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t cpu_pmu_method_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(cpu_pmu_method, 0664, cpu_pmu_method_show, cpu_pmu_method_store);
+
+static ssize_t cpu_pm_pmu_reconfig_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t cpu_pm_pmu_reconfig_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count);
+static DEVICE_ATTR(cpu_pm_pmu_reconfig,
+ 0664,
+ cpu_pm_pmu_reconfig_show,
+ cpu_pm_pmu_reconfig_store);
+
+#ifdef PR_CPU_NOTIFY
+int met_cpu_notify;
+static ssize_t cpu_notify_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t cpu_notify_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(cpu_notify, 0664, cpu_notify_show, cpu_notify_store);
+#endif
+
+#if IS_ENABLED(CONFIG_CPU_FREQ)
+static ssize_t dvfs_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t dvfs_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(dvfs, 0664, dvfs_show, dvfs_store);
+#endif
+
+static ssize_t suspend_compensation_enable_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t suspend_compensation_enable_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count);
+static DEVICE_ATTR(suspend_compensation_enable, 0664, suspend_compensation_enable_show,
+ suspend_compensation_enable_store);
+
+static ssize_t suspend_compensation_flag_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(suspend_compensation_flag, 0444, suspend_compensation_flag_show, NULL);
+
+static ssize_t ipi_test_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count);
+static DEVICE_ATTR(ipi_test, 0220, NULL, ipi_test_store);
+
+static const struct file_operations met_file_ops = {
+ .owner = THIS_MODULE
+};
+
+struct miscdevice met_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "met",
+ .mode = 0664,
+ .fops = &met_file_ops
+};
+EXPORT_SYMBOL(met_device);
+
+static int met_run(void)
+{
+ sampler_start();
+#ifdef MET_USER_EVENT_SUPPORT
+ bltab.flag &= (~MET_CLASS_ALL);
+#endif
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ ondiemet_start();
+#endif
+#endif
+
+ return 0;
+}
+
+static void met_stop(void)
+{
+#ifdef MET_USER_EVENT_SUPPORT
+ bltab.flag |= MET_CLASS_ALL;
+#endif
+ sampler_stop();
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ /* the met.ko will be use by script "cat ...", release it */
+ if ((ondiemet_module[ONDIEMET_SSPM] == 0) || (sspm_buffer_size == -1))
+ ondiemet_log_manager_stop();
+ ondiemet_stop();
+ ondiemet_extract();
+#endif
+#endif
+}
+
+static ssize_t ver_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%s\n", MET_BACKEND_VERSION);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t devices_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int len, total_len = 0;
+ struct metdevice *c = NULL;
+
+ mutex_lock(&dev->mutex);
+ list_for_each_entry(c, &met_list, list) {
+ len = 0;
+ if (c->type == MET_TYPE_PMU)
+ len = snprintf(buf, PAGE_SIZE - total_len, "pmu/%s:0\n", c->name);
+ else if (c->type == MET_TYPE_BUS)
+ len = snprintf(buf, PAGE_SIZE - total_len, "bus/%s:0\n", c->name);
+ else if (c->type == MET_TYPE_MISC)
+ len = snprintf(buf, PAGE_SIZE - total_len, "misc/%s:0\n", c->name);
+
+ if (c->ondiemet_mode == 0) {
+ if (c->process_argument)
+ buf[len - 2]++;
+ } else if (c->ondiemet_mode == 1) {
+ if (c->ondiemet_process_argument)
+ buf[len - 2]++;
+ } else if (c->ondiemet_mode == 2) {
+ if (c->process_argument)
+ buf[len - 2]++;
+ if (c->ondiemet_process_argument)
+ buf[len - 2]++;
+ }
+
+ buf += len;
+ total_len += len;
+ }
+
+ mutex_unlock(&dev->mutex);
+ return total_len;
+}
+
+static char met_platform[16] = "none";
+static ssize_t plf_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%s\n", met_platform);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static unsigned int met_chip_id = 0;
+static ssize_t chip_id_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "0x%08X\n", met_chip_id);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static char met_topology[64] = "none";
+static ssize_t core_topology_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%s\n", met_topology);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t ctrl_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", ctrl_flags);
+}
+
+static ssize_t ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned int value = 0;
+
+ if (met_parse_num(buf, &value, count) < 0)
+ return -EINVAL;
+
+ ctrl_flags = value;
+ return count;
+}
+
+static ssize_t cpu_pmu_method_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", met_cpu_pmu_method);
+}
+
+static ssize_t cpu_pmu_method_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ unsigned int value = 0;
+
+ if (met_parse_num(buf, &value, count) < 0)
+ return -EINVAL;
+
+ met_cpu_pmu_method = value;
+ return count;
+}
+
+static ssize_t cpu_pm_pmu_reconfig_show(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", met_cpu_pm_pmu_reconfig);
+}
+
+static ssize_t cpu_pm_pmu_reconfig_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ unsigned int value = 0;
+
+ if (met_parse_num(buf, &value, count) < 0)
+ return -EINVAL;
+
+ met_cpu_pm_pmu_reconfig = value;
+ return count;
+}
+
+static void _test_trace_ipi_raise(void *info)
+{
+ unsigned int *cpu = (unsigned int *)info;
+
+ if (met_export_api_symbol->met_arch_send_call_function_single_ipi)
+ met_export_api_symbol->met_arch_send_call_function_single_ipi(*cpu);
+}
+
+
+static ssize_t ipi_test_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int this_cpu = smp_processor_id();
+ unsigned int cpu = 0;
+ unsigned int value = 0;
+
+ if (met_parse_num(buf, &value, count) < 0)
+ return -EINVAL;
+
+ cpu = value;
+ if (cpu == this_cpu)
+ _test_trace_ipi_raise(&cpu);
+ else {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ _test_trace_ipi_raise, &cpu, 1);
+ }
+
+ return count;
+}
+
+
+#if defined(MET_BOOT_MSG)
+char met_boot_msg_tmp[256];
+char met_boot_msg[PAGE_SIZE];
+int met_boot_msg_idx;
+
+int pr_bootmsg(int str_len, char *str)
+{
+ if (met_boot_msg_idx+str_len+1 > PAGE_SIZE)
+ return -1;
+ memcpy(met_boot_msg+met_boot_msg_idx, str, str_len);
+ met_boot_msg_idx += str_len;
+ return 0;
+}
+
+static ssize_t bootmsg_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%s\n", met_boot_msg);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static DEVICE_ATTR_RO(bootmsg);
+EXPORT_SYMBOL(met_boot_msg_tmp);
+EXPORT_SYMBOL(pr_bootmsg);
+#endif
+
+static ssize_t spr_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sample_rate);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t spr_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int value;
+ struct metdevice *c = NULL;
+
+ mutex_lock(&dev->mutex);
+
+ if ((run == 1) || (count == 0) || (buf == NULL)) {
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+ if (kstrtoint(buf, 0, &value) != 0) {
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+
+ if ((value < 0) || (value > 10000)) {
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+
+ calc_timer_value(value);
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->polling_interval > 0)
+ c->polling_count_reload = ((c->polling_interval * sample_rate) - 1) / 1000;
+ else
+ c->polling_count_reload = 0;
+ }
+
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
+static ssize_t run_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", run);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t run_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ int value;
+
+ mutex_lock(&dev->mutex);
+
+ if ((count == 0) || (buf == NULL)) {
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+ if (kstrtoint(buf, 0, &value) != 0) {
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+
+ switch (value) {
+ case 1:
+ if (run != 1) {
+ run = 1;
+ met_run();
+ }
+ break;
+ case 0:
+ if (run != 0) {
+ if (run == 1) {
+ met_stop();
+#ifdef MET_USER_EVENT_SUPPORT
+#ifdef CONFIG_MET_MODULE
+ met_save_dump_buffer_real("/data/trace.dump");
+#else
+ met_save_dump_buffer("/data/trace.dump");
+#endif
+#endif
+ run = 0;
+ } else
+ /* run == -1 */
+ run = 0;
+ }
+ break;
+ case -1:
+ if (run != -1) {
+ if (run == 1)
+ met_stop();
+
+ run = -1;
+ }
+ break;
+ default:
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
+static unsigned int met_ksym_addr;
+static char met_func_name[512];
+static ssize_t ksym_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+ int len = 0;
+ int idx = 0;
+
+ mutex_lock(&dev->mutex);
+ if (met_ksym_addr != 0)
+ len = sprint_symbol_no_offset(met_func_name, met_ksym_addr);
+ if (len != 0) {
+ for (idx = 0; idx < 512; idx++)
+ if (met_func_name[idx] == ' ')
+ met_func_name[idx] = '\0';
+ i = snprintf(buf, PAGE_SIZE, "%s\n", met_func_name);
+ } else
+ i = snprintf(buf, PAGE_SIZE, "ksymlookup fail(%x)\n", met_ksym_addr);
+
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t ksym_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ mutex_lock(&dev->mutex);
+
+ if ((count == 0) || (buf == NULL)) {
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+ if (kstrtoint(buf, 16, &met_ksym_addr) != 0) {
+ mutex_unlock(&dev->mutex);
+ return -EINVAL;
+ }
+
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
+#if defined(PR_CPU_NOTIFY)
+static ssize_t cpu_notify_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", met_cpu_notify);
+ return i;
+}
+
+static ssize_t cpu_notify_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ if ((count == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &met_cpu_notify) != 0)
+ return -EINVAL;
+
+ return count;
+}
+#endif
+
+#if IS_ENABLED(CONFIG_CPU_FREQ)
+static ssize_t dvfs_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", 0);
+ return i;
+}
+
+static ssize_t dvfs_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ return count;
+}
+#endif
+
+static ssize_t suspend_compensation_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret;
+
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", met_suspend_compensation_mode);
+
+ return ret;
+}
+
+static ssize_t suspend_compensation_enable_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int value;
+
+ if ((count == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+ met_suspend_compensation_mode = value;
+
+ return count;
+}
+
+static ssize_t suspend_compensation_flag_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ret;
+
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", met_suspend_compensation_flag);
+
+ return ret;
+}
+
+static ssize_t hash_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ return 0;
+}
+
+static ssize_t hash_store(struct device *dev, struct device_attribute *attr, const char *buf,
+ size_t count)
+{
+ return 0;
+}
+
+static DEVICE_ATTR(hash, 0664, hash_show, hash_store);
+
+static ssize_t mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->mode);
+}
+
+static ssize_t mode_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
+ size_t n)
+{
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (kstrtoint(buf, 0, &(c->mode)) != 0)
+ return -EINVAL;
+
+ return n;
+}
+
+static struct kobj_attribute mode_attr = __ATTR(mode, 0664, mode_show, mode_store);
+
+static ssize_t ondiemet_mode_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->ondiemet_mode);
+}
+
+static ssize_t ondiemet_mode_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
+ size_t n)
+{
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (kstrtoint(buf, 0, &(c->ondiemet_mode)) != 0)
+ return -EINVAL;
+
+ return n;
+}
+
+static struct kobj_attribute ondiemet_mode_attr = __ATTR(ondiemet_mode, 0664, ondiemet_mode_show, ondiemet_mode_store);
+
+static ssize_t polling_interval_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int interval = 1;
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (c->polling_interval)
+ interval = c->polling_interval;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", interval);
+}
+
+static ssize_t polling_interval_store(struct kobject *kobj, struct kobj_attribute *attr,
+ const char *buf, size_t n)
+{
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (kstrtoint(buf, 0, &(c->polling_interval)) != 0)
+ return -EINVAL;
+
+ if (c->polling_interval > 0)
+ c->polling_count_reload = ((c->polling_interval * sample_rate) - 1) / 1000;
+ else
+ c->polling_count_reload = 0;
+
+ return n;
+}
+
+static struct kobj_attribute polling_interval_attr =
+__ATTR(polling_ms, 0664, polling_interval_show, polling_interval_store);
+
+static ssize_t header_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct metdevice *c = NULL;
+ ssize_t count = 0;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (c->ondiemet_mode == 0) {
+ if ((c->mode) && (c->print_header))
+ return c->print_header(buf, PAGE_SIZE);
+ } else if (c->ondiemet_mode == 1) {
+ if ((c->mode) && (c->ondiemet_print_header))
+ return c->ondiemet_print_header(buf, PAGE_SIZE);
+ } else if (c->ondiemet_mode == 2) {
+ if ((c->mode) && (c->print_header))
+ count = c->print_header(buf, PAGE_SIZE);
+ if (count < PAGE_SIZE) {
+ if ((c->mode) && (c->ondiemet_print_header))
+ count += c->ondiemet_print_header(buf+count, PAGE_SIZE - count);
+ }
+ return count;
+ }
+
+ return 0;
+}
+
+static struct kobj_attribute header_attr = __ATTR(header, 0444, header_show, NULL);
+
+static ssize_t help_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct metdevice *c = NULL;
+ ssize_t count = 0;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (c->ondiemet_mode == 0) {
+ if (c->print_help)
+ return c->print_help(buf, PAGE_SIZE);
+ } else if (c->ondiemet_mode == 1) {
+ if (c->ondiemet_print_help)
+ return c->ondiemet_print_help(buf, PAGE_SIZE);
+ } else if (c->ondiemet_mode == 2) {
+ if (c->print_help)
+ count = c->print_help(buf, PAGE_SIZE);
+ if (count < PAGE_SIZE) {
+ if (c->ondiemet_print_help)
+ count += c->ondiemet_print_help(buf+count, PAGE_SIZE - count);
+ }
+ return count;
+ }
+
+ return 0;
+}
+
+static struct kobj_attribute help_attr = __ATTR(help, 0444, help_show, NULL);
+
+static int argu_status = -1;
+static ssize_t argu_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
+ size_t n)
+{
+ int ret = 0;
+ struct metdevice *c = NULL;
+
+ argu_status = -1;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (c->ondiemet_mode == 0) {
+ if (c->process_argument)
+ ret = c->process_argument(buf, (int)n);
+ } else if (c->ondiemet_mode == 1) {
+ if (c->ondiemet_process_argument)
+ ret = c->ondiemet_process_argument(buf, (int)n);
+ } else if (c->ondiemet_mode == 2) {
+ if (c->process_argument)
+ ret = c->process_argument(buf, (int)n);
+ if (c->ondiemet_process_argument)
+ ret = c->ondiemet_process_argument(buf, (int)n);
+ }
+
+ if (ret != 0)
+ return -EINVAL;
+
+ argu_status = 0;
+ return n;
+}
+
+static ssize_t argu_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", argu_status);
+}
+
+static struct kobj_attribute argu_attr = __ATTR(argu, 0664, argu_show, argu_store);
+
+static ssize_t reset_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ int ret = 0;
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ if (c->ondiemet_mode == 0) {
+ if (c->reset)
+ ret = c->reset();
+ else
+ c->mode = 0;
+ } else if (c->ondiemet_mode == 1) {
+ if (c->ondiemet_reset)
+ ret = c->ondiemet_reset();
+ } else if (c->ondiemet_mode == 2) {
+ if (c->reset)
+ ret = c->reset();
+ else
+ c->mode = 0;
+ if (c->ondiemet_reset)
+ ret = c->ondiemet_reset();
+ }
+
+ if (ret != 0)
+ return -EINVAL;
+
+ return n;
+}
+
+static struct kobj_attribute reset_attr = __ATTR(reset, 0220, NULL, reset_store);
+
+static ssize_t header_read_again_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->kobj == kobj)
+ break;
+ }
+ if (c == NULL)
+ return -ENOENT;
+
+ return snprintf(buf, PAGE_SIZE, "%d\n", c->header_read_again);
+}
+
+static struct kobj_attribute header_read_again_attr = __ATTR(header_read_again, 0664, header_read_again_show, NULL);
+
+
+int met_register(struct metdevice *met)
+{
+ int ret, cpu;
+ struct metdevice *c;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (!strcmp(c->name, met->name))
+ return -EEXIST;
+ }
+
+ PR_BOOTMSG("met_register %s ...\n", met->name);
+
+ INIT_LIST_HEAD(&met->list);
+
+ /* Allocate timer count for per CPU */
+ met->polling_count = alloc_percpu(int);
+ if (met->polling_count == NULL)
+ return -EINVAL;
+
+ for_each_possible_cpu(cpu)
+ *(per_cpu_ptr(met->polling_count, cpu)) = 0;
+
+ if (met->polling_interval > 0) {
+ ret = ((met->polling_interval * sample_rate) - 1) / 1000;
+ met->polling_count_reload = ret;
+ } else
+ met->polling_count_reload = 0;
+
+ met->kobj = NULL;
+
+ if (met->type == MET_TYPE_BUS)
+ met->kobj = kobject_create_and_add(met->name, kobj_bus);
+ else if (met->type == MET_TYPE_PMU)
+ met->kobj = kobject_create_and_add(met->name, kobj_pmu);
+ else if (met->type == MET_TYPE_MISC)
+ met->kobj = kobject_create_and_add(met->name, kobj_misc);
+ else {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ if (met->kobj == NULL) {
+ ret = -EINVAL;
+ goto err_out;
+ }
+
+ if (met->create_subfs) {
+ ret = met->create_subfs(met->kobj);
+ if (ret)
+ goto err_out;
+ }
+
+ ret = sysfs_create_file(met->kobj, &mode_attr.attr);
+ if (ret)
+ goto err_out;
+
+
+ ret = sysfs_create_file(met->kobj, &ondiemet_mode_attr.attr);
+ if (ret)
+ goto err_out;
+
+ ret = sysfs_create_file(met->kobj, &polling_interval_attr.attr);
+ if (ret)
+ goto err_out;
+
+ ret = sysfs_create_file(met->kobj, &header_read_again_attr.attr);
+ if (ret)
+ goto err_out;
+
+ if (met->print_header || met->ondiemet_print_header) {
+ ret = sysfs_create_file(met->kobj, &header_attr.attr);
+ if (ret)
+ goto err_out;
+ }
+
+ if (met->print_help || met->ondiemet_print_help) {
+ ret = sysfs_create_file(met->kobj, &help_attr.attr);
+ if (ret)
+ goto err_out;
+ }
+
+ if (met->process_argument || met->ondiemet_process_argument) {
+ ret = sysfs_create_file(met->kobj, &argu_attr.attr);
+ if (ret)
+ goto err_out;
+ }
+
+ if (met->reset) {
+ ret = sysfs_create_file(met->kobj, &reset_attr.attr);
+ if (ret)
+ goto err_out;
+ }
+
+ spin_lock_init(&met->my_lock);
+
+ list_add(&met->list, &met_list);
+ return 0;
+
+ err_out:
+
+ if (met->polling_count)
+ free_percpu(met->polling_count);
+
+ if (met->kobj) {
+ kobject_del(met->kobj);
+ kobject_put(met->kobj);
+ met->kobj = NULL;
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(met_register);
+
+int met_deregister(struct metdevice *met)
+{
+ struct metdevice *c = NULL;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c == met)
+ break;
+ }
+ if (c != met)
+ return -ENOENT;
+
+ if (met->print_header || met->ondiemet_print_header)
+ sysfs_remove_file(met->kobj, &header_attr.attr);
+
+ if (met->print_help || met->ondiemet_print_help)
+ sysfs_remove_file(met->kobj, &help_attr.attr);
+
+ if (met->process_argument || met->ondiemet_process_argument)
+ sysfs_remove_file(met->kobj, &argu_attr.attr);
+
+ sysfs_remove_file(met->kobj, &reset_attr.attr);
+ sysfs_remove_file(met->kobj, &header_read_again_attr.attr);
+ sysfs_remove_file(met->kobj, &polling_interval_attr.attr);
+ sysfs_remove_file(met->kobj, &mode_attr.attr);
+ sysfs_remove_file(met->kobj, &ondiemet_mode_attr.attr);
+
+ if (met->delete_subfs)
+ met->delete_subfs();
+
+ kobject_del(met->kobj);
+ kobject_put(met->kobj);
+ met->kobj = NULL;
+
+ if (met->polling_count)
+ free_percpu(met->polling_count);
+
+ list_del(&met->list);
+ return 0;
+}
+EXPORT_SYMBOL(met_deregister);
+
+int met_set_platform(const char *plf_name, int flag)
+{
+ strncpy(met_platform, plf_name, sizeof(met_platform) - 1);
+#if 0
+ int ret;
+
+ if (flag) {
+ ret = device_create_file(met_device.this_device, &dev_attr_plf);
+ if (ret != 0) {
+ pr_debug("can not create device file: plf\n");
+ return ret;
+ }
+ strncpy(met_platform, plf_name, sizeof(met_platform) - 1);
+ } else
+ device_remove_file(met_device.this_device, &dev_attr_plf);
+
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(met_set_platform);
+
+char *met_get_platform(void)
+{
+ return met_platform;
+}
+EXPORT_SYMBOL(met_get_platform);
+
+int met_set_chip_id(const unsigned int chip_id)
+{
+ met_chip_id = chip_id;
+
+ return 0;
+}
+EXPORT_SYMBOL(met_set_chip_id);
+
+const unsigned int met_get_chip_id(void)
+{
+ return met_chip_id;
+}
+EXPORT_SYMBOL(met_get_chip_id);
+
+unsigned int met_get_chipid_from_atag(void)
+{
+ struct device_node *chosen_node;
+ struct tag_chipid *chip_id;
+ int len;
+
+ chosen_node = of_find_node_by_path("/chosen");
+ if (!chosen_node)
+ chosen_node = of_find_node_by_path("/chosen@0");
+
+ if (chosen_node) {
+ chip_id = (struct tag_chipid*) of_get_property(chosen_node, "atag,chipid", &len);
+ if (chip_id == NULL) {
+ PR_BOOTMSG("Warning: could not found atag,chipid in chosen\n");
+ return -1;
+ }
+ } else {
+ PR_BOOTMSG("Warning: chosen node not found in device tree\n");
+ return -1;
+ }
+
+ return chip_id->hw_code;
+}
+
+int met_set_topology(const char *topology_name, int flag)
+{
+ strncpy(met_topology, topology_name, sizeof(met_topology) - 1);
+#if 0
+ int ret;
+
+ if (flag) {
+ ret = device_create_file(met_device.this_device, &dev_attr_core_topology);
+ if (ret != 0) {
+ pr_debug("can not create device file: topology\n");
+ return ret;
+ }
+ strncpy(met_topology, topology_name, sizeof(met_topology) - 1);
+ } else {
+ device_remove_file(met_device.this_device, &dev_attr_core_topology);
+ }
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(met_set_topology);
+
+#include "met_struct.h"
+
+void force_sample(void *unused)
+{
+ int cpu;
+ unsigned long long stamp;
+ struct metdevice *c;
+ struct met_cpu_struct *met_cpu_ptr;
+
+ if ((run != 1) || (sample_rate == 0))
+ return;
+
+ /* to avoid met tag is coming after __met_hrtimer_stop and before run=-1 */
+ met_cpu_ptr = this_cpu_ptr(&met_cpu);
+ if (met_cpu_ptr->work_enabled == 0)
+ return;
+
+ cpu = smp_processor_id();
+
+ stamp = cpu_clock(cpu);
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->ondiemet_mode == 0) {
+ if ((c->mode != 0) && (c->tagged_polling != NULL))
+ c->tagged_polling(stamp, 0);
+ } else if (c->ondiemet_mode == 1) {
+ if ((c->mode != 0) && (c->ondiemet_tagged_polling != NULL))
+ c->ondiemet_tagged_polling(stamp, 0);
+ } else if (c->ondiemet_mode == 2) {
+ if ((c->mode != 0) && (c->tagged_polling != NULL))
+ c->tagged_polling(stamp, 0);
+ if ((c->mode != 0) && (c->ondiemet_tagged_polling != NULL))
+ c->ondiemet_tagged_polling(stamp, 0);
+ }
+ }
+}
+
+#define MET_SUSPEND_HAND
+#ifdef MET_SUSPEND_HAND
+static struct syscore_ops met_hrtimer_ops = {
+ .suspend = met_hrtimer_suspend,
+ .resume = met_hrtimer_resume,
+};
+#endif
+
+int fs_reg(int met_minor)
+{
+ int ret = -1;
+
+ ctrl_flags = 0;
+ met_mode = 0;
+
+#ifdef MET_SUSPEND_HAND
+ /* suspend/resume function handle register */
+ register_syscore_ops(&met_hrtimer_ops);
+#endif
+
+ calc_timer_value(sample_rate);
+
+ if ( met_minor != -1)
+ met_device.minor = met_minor;
+ ret = misc_register(&met_device);
+ if (ret != 0) {
+ pr_debug("misc register failed, minor = %d \n", met_device.minor);
+ return ret;
+ }
+
+ /* dma map config */
+ /* arch_setup_dma_ops(met_device.this_device, 0, 0, NULL, false); */
+ if (met_export_api_symbol->met_arch_setup_dma_ops)
+ met_export_api_symbol->met_arch_setup_dma_ops(met_device.this_device);
+
+ ret = device_create_file(met_device.this_device, &dev_attr_ksym);
+ if (ret != 0) {
+ pr_debug("can not create device file: ksym\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_run);
+ if (ret != 0) {
+ pr_debug("can not create device file: run\n");
+ return ret;
+ }
+
+#if defined(PR_CPU_NOTIFY)
+ ret = device_create_file(met_device.this_device, &dev_attr_cpu_notify);
+ if (ret != 0) {
+ pr_debug("can not create device file: cpu_notify\n");
+ return ret;
+ }
+#endif
+
+#if IS_ENABLED(CONFIG_CPU_FREQ)
+ ret = device_create_file(met_device.this_device, &dev_attr_dvfs);
+ if (ret != 0) {
+ pr_debug("can not create device file: dvfs\n");
+ return ret;
+ }
+#endif
+
+ ret = device_create_file(met_device.this_device, &dev_attr_suspend_compensation_enable);
+ if (ret != 0) {
+ pr_debug("can not create device file: suspend_compensation_enable\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_suspend_compensation_flag);
+ if (ret != 0) {
+ pr_debug("can not create device file: suspend_compensation_enable\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_ver);
+ if (ret != 0) {
+ pr_debug("can not create device file: ver\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_devices);
+ if (ret != 0) {
+ pr_debug("can not create device file: devices\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_ctrl);
+ if (ret != 0) {
+ pr_debug("can not create device file: ctrl\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_cpu_pmu_method);
+ if (ret != 0) {
+ pr_debug("can not create device file: cpu_pmu_method\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_cpu_pm_pmu_reconfig);
+ if (ret != 0) {
+ pr_debug("can not create device file: cpu_pm_pmu_reconfig\n");
+ return ret;
+ }
+
+#if defined(MET_BOOT_MSG)
+ ret = device_create_file(met_device.this_device, &dev_attr_bootmsg);
+ if (ret != 0) {
+ pr_debug("can not create device file: bootmsg\n");
+ return ret;
+ }
+#endif
+
+ ret = device_create_file(met_device.this_device, &dev_attr_sample_rate);
+ if (ret != 0) {
+ pr_debug("can not create device file: sample_rate\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_core_topology);
+ if (ret != 0) {
+ pr_debug("can not create device file: topology\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_plf);
+ if (ret != 0) {
+ pr_debug("can not create device file: plf\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_chip_id);
+ if (ret != 0) {
+ pr_debug("can not create device file: chip_id\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_hash);
+ if (ret != 0) {
+ pr_debug("can not create device file: hash\n");
+ return ret;
+ }
+
+ ret = device_create_file(met_device.this_device, &dev_attr_ipi_test);
+ if (ret != 0) {
+ pr_debug("can not create device file: ipi_test\n");
+ return ret;
+ }
+
+ kobj_misc = kobject_create_and_add("misc", &met_device.this_device->kobj);
+ if (kobj_misc == NULL) {
+ pr_debug("can not create kobject: kobj_misc\n");
+ return -1;
+ }
+
+ kobj_pmu = kobject_create_and_add("pmu", &met_device.this_device->kobj);
+ if (kobj_pmu == NULL) {
+ pr_debug("can not create kobject: kobj_pmu\n");
+ return -1;
+ }
+
+ kobj_bus = kobject_create_and_add("bus", &met_device.this_device->kobj);
+ if (kobj_bus == NULL) {
+ pr_debug("can not create kobject: kobj_bus\n");
+ return -1;
+ }
+
+ met_register(&met_cookie);
+ met_register(&met_cpupmu);
+ met_register(&met_memstat);
+ met_register(&met_switch);
+ met_register_api_symbol->met_sched_switch = met_sched_switch;
+#ifdef MET_EVENT_POWER_SUPPORT
+ met_register(&met_trace_event);
+ met_register_api_symbol->met_pm_qos_update_request = pm_qos_update_request;
+ met_register_api_symbol->met_pm_qos_update_target = pm_qos_update_target;
+#endif
+
+ met_register(&met_dummy_header);
+#ifdef FEATURE_CPU_EB_NUM
+#if FEATURE_CPU_EB_NUM
+ met_register(&met_cpu_eb);
+#endif
+#endif
+
+#ifdef MET_USER_EVENT_SUPPORT
+ tag_reg((struct file_operations * const) met_device.fops, &met_device.this_device->kobj);
+#endif
+
+ met_register(&met_stat);
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ ondiemet_log_manager_init(met_device.this_device);
+ ondiemet_attr_init(met_device.this_device);
+#endif
+#endif
+
+ return 0;
+}
+
+void fs_unreg(void)
+{
+ if (run == 1)
+ met_stop();
+
+ run = -1;
+
+ met_deregister(&met_stat);
+
+#ifdef MET_USER_EVENT_SUPPORT
+ tag_unreg();
+#endif
+
+#ifdef FEATURE_CPU_EB_NUM
+#if FEATURE_CPU_EB_NUM
+ met_deregister(&met_cpu_eb);
+#endif
+#endif
+
+ met_deregister(&met_dummy_header);
+#ifdef MET_EVENT_POWER_SUPPORT
+ met_deregister(&met_trace_event);
+ met_register_api_symbol->met_pm_qos_update_request = NULL;
+ met_register_api_symbol->met_pm_qos_update_target = NULL;
+#endif
+ met_deregister(&met_switch);
+ met_deregister(&met_memstat);
+ met_deregister(&met_cpupmu);
+ met_deregister(&met_cookie);
+
+ met_register_api_symbol->met_sched_switch = NULL;
+
+ kobject_del(kobj_misc);
+ kobject_put(kobj_misc);
+ kobj_misc = NULL;
+ kobject_del(kobj_pmu);
+ kobject_put(kobj_pmu);
+ kobj_pmu = NULL;
+ kobject_del(kobj_bus);
+ kobject_put(kobj_bus);
+ kobj_bus = NULL;
+
+ device_remove_file(met_device.this_device, &dev_attr_ksym);
+
+ device_remove_file(met_device.this_device, &dev_attr_run);
+#ifdef PR_CPU_NOTIFY
+ device_remove_file(met_device.this_device, &dev_attr_cpu_notify);
+#endif
+#if IS_ENABLED(CONFIG_CPU_FREQ)
+ device_remove_file(met_device.this_device, &dev_attr_dvfs);
+#endif
+ device_remove_file(met_device.this_device, &dev_attr_suspend_compensation_enable);
+ device_remove_file(met_device.this_device, &dev_attr_suspend_compensation_flag);
+
+ device_remove_file(met_device.this_device, &dev_attr_ver);
+ device_remove_file(met_device.this_device, &dev_attr_devices);
+ device_remove_file(met_device.this_device, &dev_attr_sample_rate);
+
+ device_remove_file(met_device.this_device, &dev_attr_ctrl);
+ device_remove_file(met_device.this_device, &dev_attr_cpu_pmu_method);
+ device_remove_file(met_device.this_device, &dev_attr_cpu_pm_pmu_reconfig);
+
+ device_remove_file(met_device.this_device, &dev_attr_core_topology);
+ device_remove_file(met_device.this_device, &dev_attr_plf);
+ device_remove_file(met_device.this_device, &dev_attr_chip_id);
+ device_remove_file(met_device.this_device, &dev_attr_hash);
+ device_remove_file(met_device.this_device, &dev_attr_ipi_test);
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+ ondiemet_log_manager_uninit(met_device.this_device);
+ ondiemet_attr_uninit(met_device.this_device);
+#endif
+#endif
+
+ misc_deregister(&met_device);
+#ifdef MET_SUSPEND_HAND
+ /* suspend/resume function handle register */
+ unregister_syscore_ops(&met_hrtimer_ops);
+#endif
+}
+
+unsigned int get_ctrl_flags(void)
+{
+ return ctrl_flags;
+}
diff --git a/src/devtools/met_drv_v2/common/interface.h b/src/devtools/met_drv_v2/common/interface.h
new file mode 100644
index 0000000..dad0dce
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/interface.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __INTERFACE_H__
+#define __INTERFACE_H__
+
+#include <linux/fs.h>
+
+struct tag_chipid {
+ u32 size;
+ u32 hw_code;
+ u32 hw_subcode;
+ u32 hw_ver;
+ u32 sw_ver;
+};
+extern unsigned int met_get_chipid_from_atag(void);
+
+#ifdef MET_USER_EVENT_SUPPORT
+extern int tag_reg(struct file_operations *const fops, struct kobject *kobj);
+extern int tag_unreg(void);
+#include "met_drv.h"
+#include "met_tag.h"
+extern struct bltable_t bltab;
+#endif
+
+extern struct metdevice met_stat;
+extern struct metdevice met_cpupmu;
+extern struct metdevice met_cookie;
+extern struct metdevice met_memstat;
+extern struct metdevice met_switch;
+extern struct metdevice met_trace_event;
+extern struct metdevice met_dummy_header;
+extern struct metdevice met_backlight;
+extern struct metdevice met_cpu_eb;
+
+/* This variable will decide which method to access the CPU PMU counter */
+/* 0: access registers directly */
+/* others: via Linux perf driver */
+extern unsigned int met_cpu_pmu_method;
+
+/*
+ * controls whether re-configuring pmu events after leaving cpu off state
+ */
+extern unsigned int met_cpu_pm_pmu_reconfig;
+
+extern int met_parse_num(const char *str, unsigned int *value, int len);
+extern void met_set_suspend_notify(int flag);
+
+#define PR_CPU_NOTIFY
+#if defined(PR_CPU_NOTIFY)
+extern int met_cpu_notify;
+#endif
+
+//#undef MET_BOOT_MSG
+#define MET_BOOT_MSG
+#if defined(MET_BOOT_MSG)
+extern char met_boot_msg_tmp[256];
+extern int pr_bootmsg(int str_len, char *str);
+#define PR_BOOTMSG(fmt, args...) { \
+ int str_len = snprintf(met_boot_msg_tmp, sizeof(met_boot_msg_tmp), \
+ fmt, ##args); \
+ pr_bootmsg(str_len, met_boot_msg_tmp); }
+#define PR_BOOTMSG_ONCE(fmt, args...) { \
+ static int once; \
+ if (!once) { \
+ int str_len = snprintf(met_boot_msg_tmp, \
+ sizeof(met_boot_msg_tmp), \
+ fmt, ##args); \
+ pr_bootmsg(str_len, met_boot_msg_tmp); \
+ once = 1; \
+ } }
+#else
+#define pr_bootmsg(str_len, str)
+#define PR_BOOTMSG(fmt, args...)
+#define PR_BOOTMSG_ONCE(fmt, args...)
+#endif
+
+#endif /* __INTERFACE_H__ */
diff --git a/src/devtools/met_drv_v2/common/mem_stat.c b/src/devtools/met_drv_v2/common/mem_stat.c
new file mode 100644
index 0000000..8542b46
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mem_stat.c
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+
+#include "met_drv.h"
+#include "mem_stat.h"
+#include "trace.h"
+
+
+/* define MEMSTAT_DEBUG */
+#ifdef MEMSTAT_DEBUG
+#define debug_memstat(fmt, arg...) pr_debug(fmt, ##arg)
+#else
+#define debug_memstat(fmt, arg...) do {} while (0)
+#endif
+
+struct metdevice met_memstat;
+
+unsigned int phy_memstat_mask;
+unsigned int vir_memstat_mask;
+
+#define MAX_PHY_MEMSTAT_EVENT_AMOUNT 6
+#define MAX_VIR_MEMSTAT_EVENT_AMOUNT 6
+
+struct mem_event phy_memstat_table[] = {
+ {FREE_MEM, "free_mem", "Free Memory"}
+};
+
+#define PHY_MEMSTAT_TABLE_SIZE (sizeof(phy_memstat_table) / sizeof(struct mem_event))
+
+struct mem_event vir_memstat_table[] = {
+ {FILE_PAGES, "file_pages", "File Pages"},
+ {FILE_DIRTY, "file_dirty", "FD APP->FS(KB)"},
+ {NUM_DIRTIED, "num_dirtied", "Num Dirtied"},
+ {WRITE_BACK, "write_back", "WB. FS->Block IO(KB)"},
+ {NUM_WRITTEN, "num_written", "Num Written"},
+ {PG_FAULT_CNT, "pg_fault_cnt", "Page Fault Count"}
+};
+
+#define VIR_MEMSTAT_TABLE_SIZE (sizeof(vir_memstat_table) / sizeof(struct mem_event))
+
+int vm_event_counters_enable;
+unsigned long *vm_status;
+static struct delayed_work dwork;
+
+noinline void memstat(unsigned int cnt, unsigned int *value)
+{
+ MET_GENERAL_PRINT(MET_TRACE, cnt, value);
+}
+
+static int get_phy_memstat(unsigned int *value)
+{
+ int i, cnt = 0;
+ struct sysinfo info;
+
+#define K(x) ((x) << (PAGE_SHIFT - 10))
+
+ si_meminfo(&info);
+
+ for (i = 0; i < MAX_PHY_MEMSTAT_EVENT_AMOUNT; i++) {
+ if (phy_memstat_mask & (1 << i)) {
+ switch (i) {
+ case FREE_MEM:
+ value[cnt] = K(info.freeram);
+ break;
+ }
+
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+
+static int get_vir_memstat(unsigned int *value)
+{
+ int i, cnt = 0;
+
+ for (i = 0; i < NR_VM_ZONE_STAT_ITEMS; i++)
+ vm_status[i] = global_zone_page_state(i);
+
+ all_vm_events(vm_status + NR_VM_ZONE_STAT_ITEMS);
+
+ for (i = 0; i < MAX_VIR_MEMSTAT_EVENT_AMOUNT; i++) {
+ if (vir_memstat_mask & (1 << i)) {
+ switch (i) {
+ case FILE_PAGES:
+ value[cnt] = vm_status[NR_FILE_PAGES] << (PAGE_SHIFT - 10);
+ break;
+ case FILE_DIRTY:
+ value[cnt] = vm_status[NR_FILE_DIRTY] << (PAGE_SHIFT - 10);
+ break;
+ case NUM_DIRTIED:
+ value[cnt] = vm_status[NR_DIRTIED] << (PAGE_SHIFT - 10);
+ break;
+ case WRITE_BACK:
+ value[cnt] = vm_status[NR_WRITEBACK] << (PAGE_SHIFT - 10);
+ break;
+ case NUM_WRITTEN:
+ value[cnt] = vm_status[NR_WRITTEN] << (PAGE_SHIFT - 10);
+ break;
+ case PG_FAULT_CNT:
+ value[cnt] = vm_status[NR_VM_ZONE_STAT_ITEMS + PGFAULT];
+ break;
+ }
+
+ cnt++;
+ }
+ }
+
+ return cnt;
+}
+
+static void wq_get_memstat(struct work_struct *work)
+{
+ int total_event_amount = 0, phy_event_amount = 0;
+ unsigned int stat_val[MAX_PHY_MEMSTAT_EVENT_AMOUNT + MAX_VIR_MEMSTAT_EVENT_AMOUNT];
+
+ memset(stat_val, 0, sizeof(unsigned int) * (MAX_PHY_MEMSTAT_EVENT_AMOUNT + MAX_VIR_MEMSTAT_EVENT_AMOUNT));
+ total_event_amount = phy_event_amount = get_phy_memstat(stat_val);
+
+ if (vm_event_counters_enable)
+ total_event_amount += get_vir_memstat(&(stat_val[phy_event_amount]));
+
+ if (total_event_amount <= (MAX_PHY_MEMSTAT_EVENT_AMOUNT + MAX_VIR_MEMSTAT_EVENT_AMOUNT))
+ memstat(total_event_amount-1, stat_val);
+}
+
+void met_memstat_polling(unsigned long long stamp, int cpu)
+{
+ schedule_delayed_work(&dwork, 0);
+}
+
+static void met_memstat_start(void)
+{
+ int stat_items_size = 0;
+
+ stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long);
+
+#if IS_ENABLED(CONFIG_VM_EVENT_COUNTERS)
+ stat_items_size += sizeof(struct vm_event_state);
+#endif
+
+ vm_status = kmalloc(stat_items_size, GFP_KERNEL);
+ if (vm_status == NULL)
+ return;
+ INIT_DELAYED_WORK(&dwork, wq_get_memstat);
+}
+
+static void met_memstat_stop(void)
+{
+ kfree(vm_status);
+ cancel_delayed_work_sync(&dwork);
+}
+
+static const char help[] =
+" --memstat=[phy_mem_stat|vir_mem_stat]:event_name enable sampling physical & virtual memory status\n";
+
+static int met_memstat_print_help(char *buf, int len)
+{
+ int i, l;
+
+ l = snprintf(buf, PAGE_SIZE, help);
+
+ for (i = 0; i < PHY_MEMSTAT_TABLE_SIZE; i++)
+ l += snprintf(buf + l, PAGE_SIZE - l, " --memstat=phy_mem_stat:%s\n",
+ phy_memstat_table[i].name);
+
+#if IS_ENABLED(CONFIG_VM_EVENT_COUNTERS)
+ for (i = 0; i < VIR_MEMSTAT_TABLE_SIZE; i++)
+ l += snprintf(buf + l, PAGE_SIZE - l, " --memstat=vir_mem_stat:%s\n",
+ vir_memstat_table[i].name);
+#endif
+
+ return l;
+}
+
+static const char header[] = "met-info [000] 0.0: ms_ud_sys_header: memstat,";
+
+
+static int met_memstat_print_header(char *buf, int len)
+{
+ int i, l;
+ int event_amount = 0;
+
+ l = snprintf(buf, PAGE_SIZE, header);
+
+ for (i = 0; i < MAX_PHY_MEMSTAT_EVENT_AMOUNT; i++) {
+ if ((phy_memstat_mask & (1 << i)) && (i < PHY_MEMSTAT_TABLE_SIZE)) {
+ l += snprintf(buf + l, PAGE_SIZE - l, phy_memstat_table[i].header_name);
+ l += snprintf(buf + l, PAGE_SIZE - l, ",");
+ event_amount++;
+ }
+ }
+
+#if IS_ENABLED(CONFIG_VM_EVENT_COUNTERS)
+ for (i = 0; i < MAX_VIR_MEMSTAT_EVENT_AMOUNT; i++) {
+ if ((vir_memstat_mask & (1 << i)) && (i < VIR_MEMSTAT_TABLE_SIZE)) {
+ l += snprintf(buf + l, PAGE_SIZE - l, vir_memstat_table[i].header_name);
+ l += snprintf(buf + l, PAGE_SIZE - l, ",");
+ event_amount++;
+ }
+ }
+#endif
+
+ for (i = 0; i < event_amount; i++) {
+ l += snprintf(buf + l, PAGE_SIZE - l, "x");
+ l += snprintf(buf + l, PAGE_SIZE - l, ",");
+ }
+
+ phy_memstat_mask = 0;
+ vir_memstat_mask = 0;
+
+ l += snprintf(buf + l, PAGE_SIZE - l, "\n");
+
+ return l;
+}
+
+static int met_memstat_process_argument(const char *arg, int len)
+{
+ int i, found_event = 0;
+ char choice[16], event[32];
+ char *pch;
+ int str_len;
+
+
+#if IS_ENABLED(CONFIG_VM_EVENT_COUNTERS)
+ vm_event_counters_enable = 1;
+#endif
+
+ pch = strchr(arg, ':');
+ if (pch == NULL)
+ goto error;
+
+ memset(choice, 0, sizeof(choice));
+ memset(event, 0, sizeof(event));
+
+ str_len = (int)(pch - arg);
+ if (str_len >= 16)
+ goto error;
+ memcpy(choice, arg, str_len);
+
+ if (len - (str_len + 1) >= 32)
+ goto error;
+ memcpy(event, arg + str_len + 1, len - (str_len + 1));
+
+ if (strncmp(choice, "phy_mem_stat", 12) == 0) {
+ for (i = 0; i < PHY_MEMSTAT_TABLE_SIZE; i++) {
+ if (strncmp(event, phy_memstat_table[i].name, MAX_EVENT_NAME_LEN) == 0) {
+ phy_memstat_mask |= (1 << phy_memstat_table[i].id);
+ found_event = 1;
+
+ break;
+ }
+ }
+ } else if (strncmp(choice, "vir_mem_stat", 12) == 0) {
+ if (!vm_event_counters_enable) {
+ pr_debug("[%s] %d: CONFIG_VM_EVENT_COUNTERS is not configured\n", __func__,
+ __LINE__);
+ goto error;
+ }
+
+ for (i = 0; i < VIR_MEMSTAT_TABLE_SIZE; i++) {
+ if (strncmp(event, vir_memstat_table[i].name, MAX_EVENT_NAME_LEN) == 0) {
+ vir_memstat_mask |= (1 << vir_memstat_table[i].id);
+ found_event = 1;
+
+ break;
+ }
+ }
+ } else {
+ pr_debug("[%s] %d: only support phy_mem_stat & vir_mem_stat keyword\n", __func__,
+ __LINE__);
+ goto error;
+ }
+
+ if (!found_event) {
+ pr_debug("[%s] %d: input event name error\n", __func__, __LINE__);
+ goto error;
+ }
+
+ met_memstat.mode = 1;
+ return 0;
+
+error:
+ met_memstat.mode = 0;
+ return -EINVAL;
+}
+
+struct metdevice met_memstat = {
+ .name = "memstat",
+ .type = MET_TYPE_PMU,
+ .cpu_related = 0,
+ .start = met_memstat_start,
+ .stop = met_memstat_stop,
+ .polling_interval = 1,
+ .timed_polling = met_memstat_polling,
+ .tagged_polling = met_memstat_polling,
+ .print_help = met_memstat_print_help,
+ .print_header = met_memstat_print_header,
+ .process_argument = met_memstat_process_argument
+};
diff --git a/src/devtools/met_drv_v2/common/mem_stat.h b/src/devtools/met_drv_v2/common/mem_stat.h
new file mode 100644
index 0000000..6e5738a
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mem_stat.h
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MEM_STAT_H__
+#define __MEM_STAT_H__
+
+#define MAX_EVENT_NAME_LEN 32
+
+enum phy_mem_event_id {
+ FREE_MEM = 0
+};
+
+enum vir_mem_event_id {
+ FILE_PAGES = 0,
+ FILE_DIRTY,
+ NUM_DIRTIED,
+ WRITE_BACK,
+ NUM_WRITTEN,
+ PG_FAULT_CNT
+};
+
+struct mem_event {
+ int id;
+ char name[32];
+ char header_name[32];
+};
+
+#endif
diff --git a/src/devtools/met_drv_v2/common/met_backlight.c b/src/devtools/met_drv_v2/common/met_backlight.c
new file mode 100644
index 0000000..dbb2752
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_backlight.c
@@ -0,0 +1,140 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#if IS_ENABLED(CONFIG_LEDS_MTK_DISP)
+#include "mtk_leds_drv.h"
+#include "leds-mtk-disp.h"
+#elif IS_ENABLED(CONFIG_LEDS_MTK_PWM)
+#include <mtk_leds_drv.h>
+#include <leds-mtk-pwm.h>
+#endif
+
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+static int met_backlight_enable;
+static DEFINE_SPINLOCK(met_backlight_lock);
+static struct kobject *kobj_met_backlight;
+
+static ssize_t bl_tag_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+static ssize_t bl_tag_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n);
+static struct kobj_attribute bl_tag_enable_attr =
+__ATTR(backlight_tag_enable, 0664, bl_tag_enable_show, bl_tag_enable_store);
+
+#if IS_ENABLED(CONFIG_LEDS_MTK_DISP) || IS_ENABLED(CONFIG_LEDS_MTK_PWM)
+static int led_brightness_changed_event(struct notifier_block *nb,
+ unsigned long event, void *v)
+{
+ struct led_conf_info *led_conf;
+
+ led_conf = (struct led_conf_info *)v;
+
+ switch (event) {
+ case 1:
+ output_met_backlight_tag_real(led_conf->cdev.brightness);
+ break;
+ default:
+ break;
+ }
+
+ return NOTIFY_DONE;
+}
+
+static struct notifier_block leds_change_notifier = {
+ .notifier_call = led_brightness_changed_event,
+};
+#endif
+
+int enable_met_backlight_tag_real(void)
+{
+ return met_backlight_enable;
+}
+
+int output_met_backlight_tag_real(int level)
+{
+ int ret;
+ unsigned long flags;
+
+ spin_lock_irqsave(&met_backlight_lock, flags);
+#ifdef CONFIG_MET_MODULE
+ ret = met_tag_oneshot_real(33880, "_MM_BL_", level);
+#else
+ ret = met_tag_oneshot(33880, "_MM_BL_", level);
+#endif
+ spin_unlock_irqrestore(&met_backlight_lock, flags);
+
+ return ret;
+}
+
+static ssize_t bl_tag_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int ret;
+
+ ret = snprintf(buf, PAGE_SIZE, "%d\n", met_backlight_enable);
+
+ return ret;
+}
+
+static ssize_t bl_tag_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+#if IS_ENABLED(CONFIG_LEDS_MTK_DISP) || IS_ENABLED(CONFIG_LEDS_MTK_PWM)
+ if (value == 1) {
+ mtk_leds_register_notifier(&leds_change_notifier);
+ } else if (value == 0) {
+ mtk_leds_unregister_notifier(&leds_change_notifier);
+ }
+#endif
+ met_backlight_enable = value;
+
+ return n;
+}
+
+static int met_backlight_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ kobj_met_backlight = parent;
+
+ ret = sysfs_create_file(kobj_met_backlight, &bl_tag_enable_attr.attr);
+ if (ret != 0) {
+ pr_debug("Failed to create montype0 in sysfs\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void met_backlight_delete(void)
+{
+ sysfs_remove_file(kobj_met_backlight, &bl_tag_enable_attr.attr);
+ kobj_met_backlight = NULL;
+}
+
+struct metdevice met_backlight = {
+ .name = "backlight",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_backlight_create,
+ .delete_subfs = met_backlight_delete,
+ .cpu_related = 0,
+};
+EXPORT_SYMBOL(met_backlight);
diff --git a/src/devtools/met_drv_v2/common/met_drv.h b/src/devtools/met_drv_v2/common/met_drv.h
new file mode 100644
index 0000000..f6c63ac
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_drv.h
@@ -0,0 +1,271 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef MET_DRV
+#define MET_DRV
+
+#include <linux/version.h>
+#include <linux/preempt.h>
+#include <linux/device.h>
+#include <linux/percpu.h>
+#include <linux/hardirq.h>
+#include <linux/clk.h>
+
+extern int met_mode;
+extern int core_plf_init(void);
+extern void core_plf_exit(void);
+
+#define MET_MODE_TRACE_CMD_OFFSET (1)
+#define MET_MODE_TRACE_CMD (1<<MET_MODE_TRACE_CMD_OFFSET)
+
+#ifdef CONFIG_MET_MODULE
+#define my_preempt_enable() preempt_enable()
+#else
+#define my_preempt_enable() preempt_enable_no_resched()
+#endif
+
+#define MET_STRBUF_SIZE 1024
+DECLARE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_nmi);
+DECLARE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_irq);
+DECLARE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf_sirq);
+DECLARE_PER_CPU(char[MET_STRBUF_SIZE], met_strbuf);
+
+#if IS_ENABLED(CONFIG_TRACING)
+#define TRACE_PUTS(p) \
+ do { \
+ trace_puts(p);; \
+ } while (0)
+#else
+#define TRACE_PUTS(p) do {} while (0)
+#endif
+
+#define GET_MET_TRACE_BUFFER_ENTER_CRITICAL() \
+ ({ \
+ char *pmet_strbuf; \
+ preempt_disable(); \
+ if (in_nmi()) \
+ pmet_strbuf = per_cpu(met_strbuf_nmi, smp_processor_id()); \
+ else if (in_irq()) \
+ pmet_strbuf = per_cpu(met_strbuf_irq, smp_processor_id()); \
+ else if (in_softirq()) \
+ pmet_strbuf = per_cpu(met_strbuf_sirq, smp_processor_id()); \
+ else \
+ pmet_strbuf = per_cpu(met_strbuf, smp_processor_id()); \
+ pmet_strbuf;\
+ })
+
+#define PUT_MET_TRACE_BUFFER_EXIT_CRITICAL(pmet_strbuf) \
+ do {\
+ if (pmet_strbuf)\
+ TRACE_PUTS(pmet_strbuf); \
+ my_preempt_enable(); \
+ } while (0)
+
+#define MET_TRACE(FORMAT, args...) \
+ do { \
+ char *pmet_strbuf; \
+ preempt_disable(); \
+ if (in_nmi()) \
+ pmet_strbuf = per_cpu(met_strbuf_nmi, smp_processor_id()); \
+ else if (in_irq()) \
+ pmet_strbuf = per_cpu(met_strbuf_irq, smp_processor_id()); \
+ else if (in_softirq()) \
+ pmet_strbuf = per_cpu(met_strbuf_sirq, smp_processor_id()); \
+ else \
+ pmet_strbuf = per_cpu(met_strbuf, smp_processor_id()); \
+ if (met_mode & MET_MODE_TRACE_CMD) \
+ snprintf(pmet_strbuf, MET_STRBUF_SIZE, "%s: " FORMAT, __func__, ##args); \
+ else \
+ snprintf(pmet_strbuf, MET_STRBUF_SIZE, FORMAT, ##args); \
+ TRACE_PUTS(pmet_strbuf); \
+ my_preempt_enable(); \
+ } while (0)
+
+/*
+ * SOB: start of buf
+ * EOB: end of buf
+ */
+#define MET_TRACE_GETBUF(pSOB, pEOB) \
+ ({ \
+ preempt_disable(); \
+ if (in_nmi()) \
+ *pSOB = per_cpu(met_strbuf_nmi, smp_processor_id()); \
+ else if (in_irq()) \
+ *pSOB = per_cpu(met_strbuf_irq, smp_processor_id()); \
+ else if (in_softirq()) \
+ *pSOB = per_cpu(met_strbuf_sirq, smp_processor_id()); \
+ else \
+ *pSOB = per_cpu(met_strbuf, smp_processor_id()); \
+ *pEOB = *pSOB; \
+ if (met_mode & MET_MODE_TRACE_CMD) \
+ *pEOB += snprintf(*pEOB, MET_STRBUF_SIZE, "%s: ", __func__); \
+ })
+
+extern int __trace_puts(unsigned long ip, const char *str, int size);
+#define MET_TRACE_PUTBUF(SOB, EOB) \
+ ({ \
+ __trace_puts(_THIS_IP_, (SOB), (uintptr_t)((EOB)-(SOB))); \
+ my_preempt_enable(); \
+ })
+
+#define MET_FTRACE_DUMP(TRACE_NAME, args...) \
+ do { \
+ trace_##TRACE_NAME(args);; \
+ } while (0)
+
+
+#define MET_TYPE_PMU 1
+#define MET_TYPE_BUS 2
+#define MET_TYPE_MISC 3
+
+enum met_action {
+ MET_CPU_ONLINE,
+ MET_CPU_OFFLINE,
+
+ NR_MET_ACTION,
+};
+
+struct metdevice {
+ struct list_head list;
+ int type;
+ const char *name;
+ struct module *owner;
+ struct kobject *kobj;
+
+ int (*create_subfs)(struct kobject *parent);
+ void (*delete_subfs)(void);
+ int mode;
+ int ondiemet_mode; /* new for ondiemet; 1: call ondiemet functions */
+ int cpu_related;
+ int polling_interval;
+ int polling_count_reload;
+ int __percpu *polling_count;
+ int header_read_again; /*for header size > 1 page */
+ void (*start)(void);
+ void (*uniq_start)(void);
+ void (*stop)(void);
+ void (*uniq_stop)(void);
+ int (*reset)(void);
+ void (*timed_polling)(unsigned long long stamp, int cpu);
+ void (*tagged_polling)(unsigned long long stamp, int cpu);
+ int (*print_help)(char *buf, int len);
+ int (*print_header)(char *buf, int len);
+ int (*process_argument)(const char *arg, int len);
+ void (*cpu_state_notify)(long cpu, unsigned long action);
+
+ void (*ondiemet_start)(void);
+ void (*uniq_ondiemet_start)(void);
+ void (*ondiemet_stop)(void);
+ void (*uniq_ondiemet_stop)(void);
+ int (*ondiemet_reset)(void);
+ int (*ondiemet_print_help)(char *buf, int len);
+ int (*ondiemet_print_header)(char *buf, int len);
+ int (*ondiemet_process_argument)(const char *arg, int len);
+ void (*ondiemet_timed_polling)(unsigned long long stamp, int cpu);
+ void (*ondiemet_tagged_polling)(unsigned long long stamp, int cpu);
+
+ struct list_head exlist; /* for linked list before register */
+ void (*suspend)(void);
+ void (*resume)(void);
+
+ unsigned long long prev_stamp;
+ spinlock_t my_lock;
+ void *reversed1;
+};
+
+int met_register(struct metdevice *met);
+int met_deregister(struct metdevice *met);
+int met_set_platform(const char *plf_name, int flag);
+int met_set_chip_id(const unsigned int chip_id);
+int met_set_topology(const char *topology_name, int flag);
+int met_devlink_add(struct metdevice *met);
+int met_devlink_del(struct metdevice *met);
+int met_devlink_register_all(void);
+int met_devlink_deregister_all(void);
+
+int fs_reg(int met_minor);
+void fs_unreg(void);
+
+/******************************************************************************
+ * Tracepoints
+ ******************************************************************************/
+#define MET_DEFINE_PROBE(probe_name, proto) \
+ static void probe_##probe_name(void *data, PARAMS(proto))
+#define MET_REGISTER_TRACE(probe_name) \
+ register_trace_##probe_name(probe_##probe_name, NULL)
+#define MET_UNREGISTER_TRACE(probe_name) \
+ unregister_trace_##probe_name(probe_##probe_name, NULL)
+
+
+/* ====================== Tagging API ================================ */
+
+#define MAX_EVENT_CLASS 31
+#define MAX_TAGNAME_LEN 128
+#define MET_CLASS_ALL 0x80000000
+
+/* IOCTL commands of MET tagging */
+struct mtag_cmd_t {
+ unsigned int class_id;
+ unsigned int value;
+ unsigned int slen;
+ char tname[MAX_TAGNAME_LEN];
+ void *data;
+ unsigned int size;
+};
+
+#define TYPE_START 1
+#define TYPE_END 2
+#define TYPE_ONESHOT 3
+#define TYPE_ENABLE 4
+#define TYPE_DISABLE 5
+#define TYPE_REC_SET 6
+#define TYPE_DUMP 7
+#define TYPE_DUMP_SIZE 8
+#define TYPE_DUMP_SAVE 9
+#define TYPE_USRDATA 10
+#define TYPE_DUMP_AGAIN 11
+#define TYPE_ASYNC_START 12
+#define TYPE_ASYNC_END 13
+#define TYPE_MET_SUSPEND 15
+#define TYPE_MET_RESUME 16
+
+/* Use 'm' as magic number */
+#define MTAG_IOC_MAGIC 'm'
+/* Please use a different 8-bit number in your code */
+#define MTAG_CMD_START _IOW(MTAG_IOC_MAGIC, TYPE_START, struct mtag_cmd_t)
+#define MTAG_CMD_END _IOW(MTAG_IOC_MAGIC, TYPE_END, struct mtag_cmd_t)
+#define MTAG_CMD_ONESHOT _IOW(MTAG_IOC_MAGIC, TYPE_ONESHOT, struct mtag_cmd_t)
+#define MTAG_CMD_ENABLE _IOW(MTAG_IOC_MAGIC, TYPE_ENABLE, int)
+#define MTAG_CMD_DISABLE _IOW(MTAG_IOC_MAGIC, TYPE_DISABLE, int)
+#define MTAG_CMD_REC_SET _IOW(MTAG_IOC_MAGIC, TYPE_REC_SET, int)
+#define MTAG_CMD_DUMP _IOW(MTAG_IOC_MAGIC, TYPE_DUMP, struct mtag_cmd_t)
+#define MTAG_CMD_DUMP_SIZE _IOWR(MTAG_IOC_MAGIC, TYPE_DUMP_SIZE, int)
+#define MTAG_CMD_DUMP_SAVE _IOW(MTAG_IOC_MAGIC, TYPE_DUMP_SAVE, struct mtag_cmd_t)
+#define MTAG_CMD_USRDATA _IOW(MTAG_IOC_MAGIC, TYPE_USRDATA, struct mtag_cmd_t)
+#define MTAG_CMD_DUMP_AGAIN _IOW(MTAG_IOC_MAGIC, TYPE_DUMP_AGAIN, void *)
+#define MTAG_CMD_ASYNC_START _IOW(MTAG_IOC_MAGIC, TYPE_ASYNC_START, struct mtag_cmd_t)
+#define MTAG_CMD_ASYNC_END _IOW(MTAG_IOC_MAGIC, TYPE_ASYNC_END, struct mtag_cmd_t)
+
+/* include file */
+extern int met_tag_start_real(unsigned int class_id, const char *name);
+extern int met_tag_end_real(unsigned int class_id, const char *name);
+extern int met_tag_async_start_real(unsigned int class_id, const char *name, unsigned int cookie);
+extern int met_tag_async_end_real(unsigned int class_id, const char *name, unsigned int cookie);
+extern int met_tag_oneshot_real(unsigned int class_id, const char *name, unsigned int value);
+extern int met_tag_userdata_real(char *pData);
+extern int met_tag_dump_real(unsigned int class_id, const char *name, void *data, unsigned int length);
+extern int met_tag_disable_real(unsigned int class_id);
+extern int met_tag_enable_real(unsigned int class_id);
+extern int met_set_dump_buffer_real(int size);
+extern int met_save_dump_buffer_real(const char *pathname);
+extern int met_save_log_real(const char *pathname);
+extern int met_show_bw_limiter_real(void);
+extern int met_reg_bw_limiter_real(void *fp);
+extern int met_show_clk_tree_real(const char *name, unsigned int addr, unsigned int status);
+extern int met_reg_clk_tree_real(void *fp);
+extern int enable_met_backlight_tag_real(void);
+extern int output_met_backlight_tag_real(int level);
+
+#endif /* MET_DRV */
diff --git a/src/devtools/met_drv_v2/common/met_kernel_symbol.h b/src/devtools/met_drv_v2/common/met_kernel_symbol.h
new file mode 100644
index 0000000..11e2dc2
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_kernel_symbol.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef MET_KERNEL_SYMBOL
+#define MET_KERNEL_SYMBOL
+
+/*lookup symbol*/
+#include <asm/cpu.h>
+#include <linux/kallsyms.h>
+#include <linux/perf_event.h>
+#include <linux/kthread.h>
+
+#include "met_api.h"
+
+#define _MET_SYMBOL_GET(_func_name_) ({\
+ int ret = 0; \
+ do { \
+ _func_name_##_symbol = (void *)symbol_get(_func_name_); \
+ if (_func_name_##_symbol == NULL) { \
+ pr_debug("MET ext. symbol : %s is not found!\n", #_func_name_); \
+ PR_BOOTMSG_ONCE("MET ext. symbol : %s is not found!\n", #_func_name_); \
+ ret = -1; \
+ } \
+ } while (0); \
+ ret; \
+ })
+
+#define _MET_SYMBOL_PUT(_func_name_) { \
+ if (_func_name_##_symbol) { \
+ symbol_put(_func_name_); \
+ _func_name_##_symbol = NULL; \
+ } \
+ }
+
+extern struct met_register_tbl *met_register_api_symbol;
+extern struct met_export_tbl *met_export_api_symbol;
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#ifdef SSPM_VERSION_V2
+#include "sspm/ondiemet_sspm.h"
+extern struct mtk_ipi_device sspm_ipidev;
+extern struct mtk_ipi_device *sspm_ipidev_symbol;
+#endif
+#endif
+#endif
+
+extern unsigned int mt_get_chip_id(void);
+extern unsigned int (*mt_get_chip_id_symbol)(void);
+
+#endif /* MET_KERNEL_SYMBOL */
diff --git a/src/devtools/met_drv_v2/common/met_main.c b/src/devtools/met_drv_v2/common/met_main.c
new file mode 100644
index 0000000..1a60c27
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_main.c
@@ -0,0 +1,361 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/hrtimer.h>
+#include <linux/cpu.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/profile.h>
+#include <linux/dcache.h>
+#include <linux/types.h>
+#include <linux/dcookies.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+/* #include <mt-plat/mtk_chip.h> */
+
+#include <asm/irq_regs.h>
+
+#include "met_struct.h"
+#include "met_drv.h"
+#include "met_kernel_symbol.h"
+#include "interface.h"
+#include <linux/of.h>
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#if defined(SSPM_VERSION_V2)
+#include "sspm_ipi_id.h" /* for sspm_ipidev */
+#endif
+#endif
+#endif
+
+extern struct device_node *of_root;
+static const char *platform_name;
+
+struct cpu_type_name {
+ char full_name[32];
+ char abbr_name[8];
+};
+
+static struct cpu_type_name met_known_cpu_type[] = {
+ {"arm,cortex-a53", "CA53"},
+ {"arm,cortex-a55", "CA55"},
+ {"arm,cortex-a72", "CA72"},
+ {"arm,cortex-a73", "CA73"},
+ {"arm,cortex-a75", "CA75"},
+ {"arm,cortex-a76", "CA76"},
+};
+#define MET_KNOWN_CPU_TYPE_COUNT \
+ (sizeof(met_known_cpu_type)/sizeof(struct cpu_type_name))
+
+static char met_cpu_topology[64];
+
+struct met_register_tbl *met_register_api_symbol;
+EXPORT_SYMBOL(met_register_api_symbol);
+struct met_export_tbl *met_export_api_symbol;
+EXPORT_SYMBOL(met_export_api_symbol);
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#if defined(SSPM_VERSION_V2)
+struct mtk_ipi_device *sspm_ipidev_symbol = NULL;
+#endif
+#endif
+#endif
+
+unsigned int (*mt_get_chip_id_symbol)(void);
+
+static int met_minor = -1;
+module_param(met_minor, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+
+#ifdef MTK_PLATFORM
+#define _SHOW_MTK_PLATFORM(X) #X
+#define SHOW_MTK_PLATFORM(X) _SHOW_MTK_PLATFORM(X)
+#endif
+
+static int is_platform_name_valid(const char * buf)
+{
+ int len = strlen(buf);
+ int i;
+
+ for (i=0; i<len; i++) {
+ if ((buf[i] == 'm' && buf[i+1] == 't')
+ || (buf[i] == 'M' && buf[i+1] == 'T')
+ || (buf[i] == 'M' && buf[i+1] == 't')
+ || (buf[i] == 'm' && buf[i+1] == 'T')) {
+ return i;
+ }
+ }
+ return -1;
+}
+
+#if 0
+const char *met_get_platform_name(void)
+{
+ const char default_platform_name[7] = "mtxxxx";
+ int found = -1;
+
+ found = is_platform_name_valid(platform_name);
+
+ if(found < 0){
+#ifdef MTK_PLATFORM
+ const char buf[7] = SHOW_MTK_PLATFORM(MTK_PLATFORM);
+ found = is_platform_name_valid(buf);
+ if ( !(found < 0) )
+ platform_name = buf;
+ else
+#endif
+ platform_name = default_platform_name;
+ }
+
+ strncpy(&buf_tmp[2], &platform_name[found+2], 4);
+ return platform_name;
+}
+EXPORT_SYMBOL(met_get_platform_name);
+#endif
+
+static void get_cpu_type_name(const char *compatible, char *cpu_type)
+{
+ int i;
+
+ for (i = 0; i < MET_KNOWN_CPU_TYPE_COUNT; i++) {
+ if (!strncmp(compatible, met_known_cpu_type[i].full_name,
+ strlen(met_known_cpu_type[i].full_name)))
+ strncpy(cpu_type, met_known_cpu_type[i].abbr_name,
+ strlen(met_known_cpu_type[i].abbr_name) + 1);
+ }
+}
+
+static void met_set_cpu_topology(int core_id, int cluster_core_num)
+{
+ int i, buf_len = strlen(met_cpu_topology);
+ struct device_node *node = NULL;
+ const char *prev_cptb = NULL;
+ const char *cptb;
+ char cpu_type[16];
+
+ for (i = 0; i < cluster_core_num; i++) {
+ node = of_get_cpu_node(core_id + i, NULL);
+ if (node) {
+ cptb = of_get_property(node, "compatible", NULL);
+ if (cptb) {
+ get_cpu_type_name(cptb, cpu_type);
+ if (prev_cptb == NULL)
+ /* first write: write core_type & core_number */
+ buf_len += snprintf(met_cpu_topology + buf_len,
+ sizeof(met_cpu_topology) - buf_len,
+ "%s:%d", cpu_type, core_id + i);
+ else if (!strncmp(prev_cptb, cptb, strlen(prev_cptb)))
+ /* cpu type is the same with before */
+ /* write core_number */
+ buf_len += snprintf(met_cpu_topology + buf_len,
+ sizeof(met_cpu_topology) - buf_len,
+ ",%d", core_id + i);
+ else
+ /* cpu type is different with before */
+ /* write core_type & core_number */
+ buf_len += snprintf(met_cpu_topology + buf_len,
+ sizeof(met_cpu_topology) - buf_len,
+ "|%s:%d", cpu_type, core_id + i);
+
+ prev_cptb = cptb;
+ }
+ }
+ }
+}
+
+static int met_create_cpu_topology(void)
+{
+ int i, j, len;
+ struct device_node *node = NULL, *core_node = NULL;
+ int start_core_id = 0;
+ int cluster_num = 0, cluster_core_num = 0;
+ char cluster_name[16], core_name[16];
+
+ node = of_find_node_by_name(NULL, "cpu-map");
+ if (!node)
+ node = of_find_node_by_name(NULL, "virtual-cpu-map");
+
+ if (node) {
+ cluster_num = of_get_child_count(node);
+ of_node_put(node);
+
+ for (i = 0; i < cluster_num; i++) {
+ snprintf(cluster_name, sizeof(cluster_name), "cluster%d", i);
+ node = of_find_node_by_name(NULL, cluster_name);
+ if (node) {
+
+ j = 0;
+ cluster_core_num = 0;
+ do {
+ snprintf(core_name, sizeof(core_name), "core%d", j);
+ core_node = of_get_child_by_name(node, core_name);
+ if (core_node) {
+ cluster_core_num++;
+ of_node_put(core_node);
+ }
+ j++;
+ } while (core_node);
+ of_node_put(node);
+
+ /* "|" use to separate different cluster */
+ if (i > 0) {
+ len = strlen(met_cpu_topology);
+ snprintf(met_cpu_topology + len, sizeof(met_cpu_topology) - len, "|");
+ }
+
+ met_set_cpu_topology(start_core_id, cluster_core_num);
+ start_core_id = cluster_core_num;
+ }
+ }
+ }
+
+ return strlen(met_cpu_topology);
+}
+
+static int met_kernel_symbol_get(void)
+{
+ int ret = 0;
+
+ ret += _MET_SYMBOL_GET(met_register_api);
+ ret += _MET_SYMBOL_GET(met_export_api);
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#if defined(SSPM_VERSION_V2)
+ ret += _MET_SYMBOL_GET(sspm_ipidev);
+#endif
+#endif
+#endif
+ return ret;
+}
+
+static void met_kernel_symbol_put(void)
+{
+ _MET_SYMBOL_PUT(met_register_api);
+ _MET_SYMBOL_PUT(met_export_api);
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT)
+#if defined(ONDIEMET_SUPPORT) || defined(TINYSYS_SSPM_SUPPORT)
+#ifdef SSPM_VERSION_V2
+ _MET_SYMBOL_PUT(sspm_ipidev);
+#endif
+#endif
+#endif
+}
+
+DEFINE_PER_CPU(struct met_cpu_struct, met_cpu);
+
+static int __init met_drv_init(void)
+{
+ int cpu;
+ int ret;
+ int cpu_topology_len;
+ struct met_cpu_struct *met_cpu_ptr;
+ unsigned int chip_id;
+
+ for_each_possible_cpu(cpu) {
+ met_cpu_ptr = &per_cpu(met_cpu, cpu);
+ /* snprintf(&(met_cpu_ptr->name[0]), sizeof(met_cpu_ptr->name), "met%02d", cpu); */
+ met_cpu_ptr->cpu = cpu;
+ }
+
+ ret = met_kernel_symbol_get();
+ if (ret) {
+ pr_notice("[MET] met_kernel_symbol_get fail, ret = %d\n", ret);
+ return ret;
+ }
+
+ ret = fs_reg(met_minor);
+ if (ret) {
+ pr_notice("[MET] met fs_reg fail, ret = %d\n", ret);
+ return ret;
+ }
+
+ if (of_root){
+ /*
+ mt6765.dts
+ model = "MT6765";
+ compatible = "mediatek,MT6765";
+ interrupt-parent = <&sysirq>;
+ */
+ if (of_root->properties) {
+ of_property_read_string(of_root, "compatible", &platform_name);
+ PR_BOOTMSG("dts property compatible=%s\n", platform_name);
+ }
+ }
+ if (platform_name) {
+ char buf[7];
+ int found = -1;
+
+ found = is_platform_name_valid(platform_name);
+
+ if ( !(found < 0) ) {
+ memset(buf, 0x0, 7);
+ buf[0] = 'm';
+ buf[1] = 't';
+ strncpy(&buf[2], &platform_name[found+2], 4);
+ met_set_platform(buf, 1);
+ PR_BOOTMSG("Get platform info from dts, platform_name=%s\n", buf);
+ } else {
+#ifdef MTK_PLATFORM
+ memset(buf, 0x0, 7);
+ strcpy(buf, SHOW_MTK_PLATFORM(MTK_PLATFORM));
+ found = is_platform_name_valid((const char *)buf);
+ if( !(found < 0) ){
+ PR_BOOTMSG("Get platform info from met_drv Kbuild, platform_name=%s\n", buf);
+ met_set_platform(buf, 1);
+ }
+ else
+#endif
+ {
+ PR_BOOTMSG("Can not get platform info from dts nor met_drv Kbuild, set platform_name=mtxxxx\n");
+ met_set_platform("mtxxxx", 1);
+ }
+ }
+ }
+
+ /* get the chip id */
+ _MET_SYMBOL_GET(mt_get_chip_id);
+ if (mt_get_chip_id_symbol != NULL)
+ met_set_chip_id(mt_get_chip_id_symbol());
+ else {
+ chip_id = met_get_chipid_from_atag();
+ if (((int) chip_id) < 0) {
+ PR_BOOTMSG("Can not get chip id info, set chip_id=0x0\n");
+ } else
+ met_set_chip_id(chip_id);
+ }
+
+ cpu_topology_len = met_create_cpu_topology();
+ if (cpu_topology_len)
+ met_set_topology(met_cpu_topology, 1);
+
+#ifdef MET_PLF_USE
+ core_plf_init();
+#endif
+ return 0;
+}
+
+static void __exit met_drv_exit(void)
+{
+#ifdef MET_PLF_USE
+ core_plf_exit();
+#endif
+ fs_unreg();
+
+ met_kernel_symbol_put();
+ _MET_SYMBOL_PUT(mt_get_chip_id);
+}
+module_init(met_drv_init);
+module_exit(met_drv_exit);
+
+MODULE_AUTHOR("DT_DM5");
+MODULE_DESCRIPTION("MET_CORE");
+MODULE_LICENSE("GPL");
diff --git a/src/devtools/met_drv_v2/common/met_power.h b/src/devtools/met_drv_v2/common/met_power.h
new file mode 100644
index 0000000..8a6290c
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_power.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef MET_POWER
+#define MET_POWER
+
+enum {
+ _PM_QOS_RESERVED = 0,
+ _PM_QOS_CPU_DMA_LATENCY,
+ _PM_QOS_NETWORK_LATENCY,
+ _PM_QOS_NETWORK_THROUGHPUT,
+ _PM_QOS_MEMORY_BANDWIDTH,
+
+ _PM_QOS_CPU_MEMORY_BANDWIDTH,
+ _PM_QOS_GPU_MEMORY_BANDWIDTH,
+ _PM_QOS_MM_MEMORY_BANDWIDTH,
+ _PM_QOS_OTHER_MEMORY_BANDWIDTH,
+ _PM_QOS_MM0_BANDWIDTH_LIMITER,
+ _PM_QOS_MM1_BANDWIDTH_LIMITER,
+
+ _PM_QOS_DDR_OPP,
+ _PM_QOS_VCORE_OPP,
+ _PM_QOS_SCP_VCORE_REQUEST,
+ _PM_QOS_POWER_MODEL_DDR_REQUEST,
+ _PM_QOS_POWER_MODEL_VCORE_REQUEST,
+ _PM_QOS_VCORE_DVFS_FORCE_OPP,
+
+ _PM_QOS_DISP_FREQ,
+ _PM_QOS_MDP_FREQ,
+ _PM_QOS_VDEC_FREQ,
+ _PM_QOS_VENC_FREQ,
+ _PM_QOS_IMG_FREQ,
+ _PM_QOS_CAM_FREQ,
+ _PM_QOS_VVPU_OPP,
+ _PM_QOS_VMDLA_OPP,
+ _PM_QOS_ISP_HRT_BANDWIDTH,
+ _PM_QOS_APU_MEMORY_BANDWIDTH,
+ /* insert new class ID */
+ _PM_QOS_NUM_CLASSES,
+};
+/* Action requested to pm_qos_update_target */
+enum _pm_qos_req_action {
+ _PM_QOS_ADD_REQ, /* Add a new request */
+ _PM_QOS_UPDATE_REQ, /* Update an existing request */
+ _PM_QOS_REMOVE_REQ /* Remove an existing request */
+};
+
+extern void pm_qos_update_request(int pm_qos_class, s32 value);
+extern void pm_qos_update_target(unsigned int action, int prev_value, int curr_value);
+
+#endif /* MET_DRV */
+
diff --git a/src/devtools/met_drv_v2/common/met_ptpod.c b/src/devtools/met_drv_v2/common/met_ptpod.c
new file mode 100644
index 0000000..0d8631d
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_ptpod.c
@@ -0,0 +1,356 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/fs.h>
+
+#include "met_drv.h"
+#include "trace.h"
+#include "core_plf_init.h"
+#include "core_plf_trace.h"
+
+static unsigned int MT_GPU_DVFS_IDX = NR_MT_CPU_DVFS;
+static unsigned int g_u4GPUVolt;
+static unsigned int g_u4Volt[NR_MT_CPU_DVFS + 1];
+
+/* g_ap_ptpod: cpu volt from ap or sspm setting
+ * if 1: cpu volt from ap
+ * if 0: cpu volt from sspm */
+static unsigned int g_ap_ptpod;
+
+/* gpu_volt_enable:
+ * if 1: enable gpu volt to output
+ * if 0: disable gpu volt to output */
+static unsigned int gpu_volt_enable = 1;
+
+/* get_volt_by_wq:
+ * if 1: get cpu/gpu volt by workqueue
+ * if 0: get cpu/gpu volt in irq */
+static unsigned int get_volt_by_wq;
+
+static int ptpod_started;
+static struct kobject *kobj_ptpod;
+static struct delayed_work get_volt_dwork;
+
+noinline void ms_ptpod(void)
+{
+ char *SOB, *EOB;
+
+ if (g_ap_ptpod) {
+ MET_TRACE_GETBUF(&SOB, &EOB);
+
+ if (gpu_volt_enable) {
+ g_u4Volt[MT_GPU_DVFS_IDX] = g_u4GPUVolt;
+ EOB = ms_formatD_EOL(EOB, ARRAY_SIZE(g_u4Volt), g_u4Volt);
+ } else
+ EOB = ms_formatD_EOL(EOB, ARRAY_SIZE(g_u4Volt) - 1, g_u4Volt);
+
+ MET_TRACE_PUTBUF(SOB, EOB);
+ } else {
+ if (gpu_volt_enable) {
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatD_EOL(EOB, 1, &g_u4GPUVolt);
+ MET_TRACE_PUTBUF(SOB, EOB);
+ }
+ }
+}
+
+#if 0
+static void ptpod_cpu_voltSampler(enum mt_cpu_dvfs_id id, unsigned int volt)
+{
+ switch (id) {
+ case MT_CPU_DVFS_LL:
+ g_u4CPUVolt_LL = volt;
+ break;
+ case MT_CPU_DVFS_L:
+ g_u4CPUVolt_L = volt;
+ break;
+ case MT_CPU_DVFS_CCI:
+ g_u4CPUVolt_CCI = volt;
+ break;
+ default:
+ return;
+ }
+ ptpod();
+}
+#endif
+
+#if 0
+static void ptpod_gpu_voltSampler(unsigned int a_u4Volt)
+{
+ g_u4GPUVolt = (a_u4Volt+50)/100;
+
+ if (ptpod_started)
+ ptpod();
+}
+#endif
+
+#define PTPOD_CONF_SHOW_IMPLEMENT(var) \
+ do { \
+ int i; \
+ i = snprintf(buf, PAGE_SIZE, "%d\n", var); \
+ return i; \
+ } while (0)
+
+#define PTPOD_CONF_STORE_IMPLEMENT(var) \
+ do { \
+ int value; \
+ if ((n == 0) || (buf == NULL)) \
+ return -EINVAL; \
+ if (kstrtoint(buf, 0, &value) != 0) \
+ return -EINVAL; \
+ if (value == 1) \
+ var = 1; \
+ else \
+ var = 0; \
+ return n; \
+ } while (0)
+
+
+static ssize_t ap_ptpod_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ PTPOD_CONF_SHOW_IMPLEMENT(g_ap_ptpod);
+}
+
+static ssize_t ap_ptpod_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ PTPOD_CONF_STORE_IMPLEMENT(g_ap_ptpod);
+}
+
+static ssize_t gpu_volt_enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ PTPOD_CONF_SHOW_IMPLEMENT(gpu_volt_enable);
+}
+
+static ssize_t gpu_volt_enable_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ PTPOD_CONF_STORE_IMPLEMENT(gpu_volt_enable);
+}
+
+static ssize_t get_volt_by_wq_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ PTPOD_CONF_SHOW_IMPLEMENT(get_volt_by_wq);
+}
+
+static ssize_t get_volt_by_wq_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ PTPOD_CONF_STORE_IMPLEMENT(get_volt_by_wq);
+}
+
+static struct kobj_attribute ap_ptpod_enable_attr = __ATTR(ap_ptpod_enable, 0664, ap_ptpod_enable_show, ap_ptpod_enable_store);
+static struct kobj_attribute gpu_volt_enable_attr = __ATTR(gpu_volt_enable, 0664, gpu_volt_enable_show, gpu_volt_enable_store);
+static struct kobj_attribute get_volt_by_wq_attr = __ATTR(get_volt_by_wq, 0664, get_volt_by_wq_show, get_volt_by_wq_store);
+
+/* create ptpod related kobj node */
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(ap_ptpod_enable); \
+ KOBJ_ATTR_ITEM(gpu_volt_enable); \
+ KOBJ_ATTR_ITEM(get_volt_by_wq); \
+ } while (0)
+
+static int ptpod_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ kobj_ptpod = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+ do { \
+ ret = sysfs_create_file(kobj_ptpod, &attr_name ## _attr.attr); \
+ if (ret != 0) { \
+ pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+ } while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+ return 0;
+}
+
+static void ptpod_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_ptpod, &attr_name ## _attr.attr)
+
+ if (kobj_ptpod != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_ptpod = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+}
+
+static void update_volt_value(void)
+{
+ int i;
+
+ if (g_ap_ptpod && mt_cpufreq_get_cur_volt_symbol) {
+ /*
+ g_u4CPUVolt_LL = mt_cpufreq_get_cur_volt_symbol(MT_CPU_DVFS_LL)/100;
+ g_u4CPUVolt_L = mt_cpufreq_get_cur_volt_symbol(MT_CPU_DVFS_L)/100;
+ g_u4CPUVolt_CCI = mt_cpufreq_get_cur_volt_symbol(MT_CPU_DVFS_CCI)/100;
+ */
+ for (i = 0; i < NR_MT_CPU_DVFS; i++)
+ g_u4Volt[i] = mt_cpufreq_get_cur_volt_symbol(i) / 100;
+ }
+
+ if (gpu_volt_enable) {
+ if (mt_gpufreq_get_cur_volt_symbol)
+ g_u4GPUVolt = ((mt_gpufreq_get_cur_volt_symbol() + 50) / 100);
+ }
+}
+
+static void get_volt_notify(unsigned long long stamp, int cpu)
+{
+ schedule_delayed_work(&get_volt_dwork, 0);
+}
+
+static void met_ptpod_polling_by_wq(struct work_struct *work)
+{
+ update_volt_value();
+
+ ms_ptpod();
+}
+
+static void met_ptpod_polling(unsigned long long stamp, int cpu)
+{
+ update_volt_value();
+
+ ms_ptpod();
+}
+
+/*
+ * Called from "met-cmd --start"
+ */
+static void ptpod_start(void)
+{
+#if 0
+ met_gpufreq_setvolt_registerCB(ptpod_gpu_voltSampler, kFOR_MET_PTPOD_USE);
+#endif
+
+ if (get_volt_by_wq) {
+ met_ptpod.timed_polling = get_volt_notify;
+
+ INIT_DELAYED_WORK(&get_volt_dwork, met_ptpod_polling_by_wq);
+ } else
+ met_ptpod.timed_polling = met_ptpod_polling;
+
+ update_volt_value();
+
+ ms_ptpod();
+
+#if 0
+ /* register callback */
+ if (mt_cpufreq_setvolt_registerCB_symbol)
+ mt_cpufreq_setvolt_registerCB_symbol(ptpod_cpu_voltSampler);
+#endif
+
+ ptpod_started = 1;
+}
+
+/*
+ * Called from "met-cmd --stop"
+ */
+static void ptpod_stop(void)
+{
+ ptpod_started = 0;
+
+#if 0
+ /* unregister callback */
+ if (mt_cpufreq_setvolt_registerCB_symbol)
+ mt_cpufreq_setvolt_registerCB_symbol(NULL);
+#endif
+
+ if (get_volt_by_wq)
+ cancel_delayed_work_sync(&get_volt_dwork);
+
+ update_volt_value();
+
+ ms_ptpod();
+
+#if 0
+ met_gpufreq_setvolt_registerCB(NULL, kFOR_MET_PTPOD_USE);
+#endif
+}
+
+static char help[] =
+ " --ptpod Measure CPU/GPU voltage\n";
+static int ptpod_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+/*
+ * It will be called back when run "met-cmd --extract" and mode is 1
+ */
+static int ptpod_print_header(char *buf, int len)
+{
+ int str_len = 0;
+
+ if (g_ap_ptpod) {
+ int i;
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_header: ");
+
+ for (i = 0; i < NR_MT_CPU_DVFS; i++)
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "CPUVolt_%d,", i);
+
+ if (gpu_volt_enable)
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "GPUVolt,");
+
+ buf[str_len-1] = '\n';
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_version: ap\n");
+ } else {
+ if (gpu_volt_enable) {
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_header: ");
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len, "GPUVolt\n");
+ }
+
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_version: sspm\n");
+ }
+
+ if (gpu_volt_enable)
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_gpu_volt_enable: YES\n");
+ else
+ str_len += snprintf(buf + str_len, PAGE_SIZE - str_len,
+ "met-info [000] 0.0: met_ptpod_gpu_volt_enable: NO\n");
+
+ return str_len;
+}
+
+struct metdevice met_ptpod = {
+ .name = "ptpod",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_PMU,
+ .cpu_related = 0,
+ .create_subfs = ptpod_create,
+ .delete_subfs = ptpod_delete,
+ .start = ptpod_start,
+ .stop = ptpod_stop,
+ .timed_polling = met_ptpod_polling,
+ .print_help = ptpod_print_help,
+ .print_header = ptpod_print_header,
+};
+EXPORT_SYMBOL(met_ptpod);
diff --git a/src/devtools/met_drv_v2/common/met_struct.h b/src/devtools/met_drv_v2/common/met_struct.h
new file mode 100644
index 0000000..ee63a8e
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_struct.h
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _MET_STRUCT_H_
+#define _MET_STRUCT_H_
+
+#include <linux/hrtimer.h>
+
+struct met_cpu_struct {
+ struct hrtimer hrtimer;
+ struct delayed_work dwork;
+/* struct kmem_cache *cachep; */
+/* struct list_head sample_head; */
+/* spinlock_t list_lock; */
+/* struct mutex list_sync_lock; */
+ int work_enabled;
+ int cpu;
+ int hrtimer_online_check;
+/* char name[16]; */
+};
+
+DECLARE_PER_CPU(struct met_cpu_struct, met_cpu);
+
+#endif /* _MET_STRUCT_H_ */
diff --git a/src/devtools/met_drv_v2/common/met_tag.h b/src/devtools/met_drv_v2/common/met_tag.h
new file mode 100644
index 0000000..d13cd46
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_tag.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MET_TAG_EX_H__
+#define __MET_TAG_EX_H__
+
+#ifdef BUILD_WITH_MET
+void force_sample(void *unused);
+#else
+#include <linux/string.h>
+#endif
+
+/* Black List Table */
+struct bltable_t {
+ struct mutex mlock;
+ /* flag - Bit31: Global ON/OFF; Bit0~30: ON/OF slot map of class_id */
+ unsigned int flag;
+ int class_id[MAX_EVENT_CLASS];
+};
+
+extern void met_sched_switch(struct task_struct *prev, struct task_struct *next);
+
+extern int tracing_mark_write(int type, unsigned int class_id,
+ const char *name, unsigned int value,
+ unsigned int value2, unsigned int value3);
+
+#endif /* __MET_TAG_EX_H__ */
diff --git a/src/devtools/met_drv_v2/common/met_tag_ex.c b/src/devtools/met_drv_v2/common/met_tag_ex.c
new file mode 100644
index 0000000..f22bbee
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_tag_ex.c
@@ -0,0 +1,607 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#define BUILD_WITH_MET
+
+#ifdef MET_USER_EVENT_SUPPORT
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+/* #include <asm/uaccess.h> */
+#include <linux/uaccess.h>
+
+#include "met_drv.h"
+#include "met_tag.h"
+#include "interface.h"
+#include "switch.h"
+
+struct bltable_t bltab;
+
+static int dump_buffer_size;
+static int dump_data_size;
+static int dump_overrun;
+static int dump_overrun_size;
+static int dump_seq_no;
+static void *dump_buffer;
+
+#define OPFLAG_OVERWRITE 0x1
+static unsigned int options_flag;
+
+#define DEVICE_NAME "met_tag"
+
+/* #define ERRF_ENABLE */
+/* #define DEBF_ENABLE */
+
+#ifdef ERRF_ENABLE
+#define MSG_ERR "Error:["DEVICE_NAME"]"
+#define ERRF(args...) pr_debug(MSG_ERR args)
+#else
+#define ERRF(args...)
+#endif
+
+#ifdef DEBF_ENABLE
+#define MSG_IFO "Info :["DEVICE_NAME"]"
+#define DEBF(args...) pr_debug(MSG_IFO args)
+#else
+#define DEBF(args...)
+#endif
+
+static int is_enabled(unsigned int class_id)
+{
+ int i;
+
+ if (bltab.flag == 0)
+ return 1;
+ if (bltab.flag & MET_CLASS_ALL)
+ return 0;
+
+ for (i = 0; i < MAX_EVENT_CLASS; i++) {
+ if ((bltab.flag & (1 << i)) && (bltab.class_id[i] == class_id))
+ return 0;
+ }
+
+ return 1;
+}
+
+noinline int tracing_mark_write(int type, unsigned int class_id,
+ const char *name, unsigned int value,
+ unsigned int value2, unsigned int value3)
+{
+ if (type == TYPE_MET_SUSPEND) {
+ MET_TRACE("C|0|MET_SUSPEND|1");
+ return 0;
+ }
+ if (type == TYPE_MET_RESUME) {
+ MET_TRACE("C|0|MET_SUSPEND|0");
+ return 0;
+ }
+ if (!is_enabled(class_id))
+ return 0;
+ switch (type) {
+ case TYPE_START:
+ MET_TRACE("B|%d|%s\n", class_id, name);
+ break;
+ case TYPE_END:
+ MET_TRACE("E|%s\n", name);
+ break;
+ case TYPE_ONESHOT:
+ MET_TRACE("C|%d|%s|%d\n", class_id, name, value);
+ break;
+ case TYPE_ASYNC_START:
+ MET_TRACE("S|%d|%s|%d\n", class_id, name, value);
+ break;
+ case TYPE_ASYNC_END:
+ MET_TRACE("F|%d|%s|%d\n", class_id, name, value);
+ break;
+ case TYPE_DUMP:
+ MET_TRACE("D|%d|%s|%d|%d|%d\n", class_id, name, value, value2, value3);
+ break;
+ default:
+ return -1;
+ }
+ return 0;
+}
+
+int met_tag_init(void)
+{
+ memset(&bltab, 0, sizeof(struct bltable_t));
+ bltab.flag = MET_CLASS_ALL;
+ mutex_init(&bltab.mlock);
+ return 0;
+}
+
+int met_tag_uninit(void)
+{
+ met_set_dump_buffer_real(0);
+ return 0;
+}
+
+int met_tag_start_real(unsigned int class_id, const char *name)
+{
+ int ret;
+
+ ret = tracing_mark_write(TYPE_START, class_id, name, 0, 0, 0);
+#if 0
+ if ((met_switch.mode & MT_SWITCH_TAGPOLLING)) {
+ /* tag polling only enable when MT_SWITCH_TAGPOLLING is config */
+ force_sample(NULL);
+ }
+#endif
+ return ret;
+}
+EXPORT_SYMBOL(met_tag_start_real);
+
+int met_tag_end_real(unsigned int class_id, const char *name)
+{
+ int ret;
+#if 0
+ if ((met_switch.mode & MT_SWITCH_TAGPOLLING)) {
+ /* tag polling only enable when MT_SWITCH_TAGPOLLING is config */
+ force_sample(NULL);
+ }
+#endif
+ ret = tracing_mark_write(TYPE_END, class_id, name, 0, 0, 0);
+
+ return ret;
+}
+EXPORT_SYMBOL(met_tag_end_real);
+
+int met_tag_async_start_real(unsigned int class_id, const char *name, unsigned int cookie)
+{
+ int ret;
+
+ ret = tracing_mark_write(TYPE_ASYNC_START, class_id, name, cookie, 0, 0);
+#if 0
+ if ((met_switch.mode & MT_SWITCH_TAGPOLLING)) {
+ /* tag polling only enable when MT_SWITCH_TAGPOLLING is config */
+ force_sample(NULL);
+ }
+#endif
+ return ret;
+}
+
+int met_tag_async_end_real(unsigned int class_id, const char *name, unsigned int cookie)
+{
+ int ret;
+
+#if 0
+ if ((met_switch.mode & MT_SWITCH_TAGPOLLING)) {
+ /* tag polling only enable when MT_SWITCH_TAGPOLLING is config */
+ force_sample(NULL);
+ }
+#endif
+ ret = tracing_mark_write(TYPE_ASYNC_END, class_id, name, cookie, 0, 0);
+ return ret;
+}
+
+int met_tag_oneshot_real(unsigned int class_id, const char *name, unsigned int value)
+{
+ int ret;
+
+ ret = tracing_mark_write(TYPE_ONESHOT, class_id, name, value, 0, 0);
+#if 0
+ if ((met_switch.mode & MT_SWITCH_TAGPOLLING)) {
+ /* tag polling only enable when MT_SWITCH_TAGPOLLING is config */
+ force_sample(NULL);
+ }
+#endif
+ return ret;
+}
+EXPORT_SYMBOL(met_tag_oneshot_real);
+
+int met_tag_userdata_real(char *pData)
+{
+ MET_TRACE("%s\n", pData);
+ return 0;
+}
+
+int met_tag_dump_real(unsigned int class_id, const char *name, void *data, unsigned int length)
+{
+ int ret;
+
+ if ((dump_data_size + length + sizeof(int)) > dump_buffer_size) {
+ if (options_flag & OPFLAG_OVERWRITE) {
+ dump_overrun_size = dump_data_size;
+ dump_overrun++;
+ memcpy(dump_buffer, &dump_seq_no, sizeof(int));
+ memcpy(dump_buffer + sizeof(int), data, length);
+ ret = tracing_mark_write(TYPE_DUMP, class_id, name,
+ dump_seq_no++, 0, length + sizeof(int));
+ dump_data_size = length + sizeof(int);
+ } else {
+ ret = tracing_mark_write(TYPE_DUMP, class_id, name, dump_seq_no++, 0, 0);
+ }
+ } else {
+ memcpy(dump_buffer + dump_data_size, &dump_seq_no, sizeof(int));
+ memcpy(dump_buffer + dump_data_size + sizeof(int), data, length);
+ ret = tracing_mark_write(TYPE_DUMP, class_id, name,
+ dump_seq_no++, dump_data_size, length + sizeof(int));
+ dump_data_size += length + sizeof(int);
+ }
+ return ret;
+}
+
+int met_tag_disable_real(unsigned int class_id)
+{
+ int i;
+
+ mutex_lock(&bltab.mlock);
+
+ if (class_id == MET_CLASS_ALL) {
+ bltab.flag |= MET_CLASS_ALL;
+ mutex_unlock(&bltab.mlock);
+ return 0;
+ }
+
+ for (i = 0; i < MAX_EVENT_CLASS; i++) {
+ if ((bltab.flag & (1 << i)) == 0) {
+ bltab.class_id[i] = class_id;
+ bltab.flag |= (1 << i);
+ mutex_unlock(&bltab.mlock);
+ return 0;
+ }
+ }
+
+ mutex_unlock(&bltab.mlock);
+ return -1;
+}
+
+int met_tag_enable_real(unsigned int class_id)
+{
+ int i;
+
+ mutex_lock(&bltab.mlock);
+
+ if (class_id == MET_CLASS_ALL) {
+ bltab.flag &= (~MET_CLASS_ALL);
+ mutex_unlock(&bltab.mlock);
+ return 0;
+ }
+
+ for (i = 0; i < MAX_EVENT_CLASS; i++) {
+ if ((bltab.flag & (1 << i)) && (bltab.class_id[i] == class_id)) {
+ bltab.flag &= (~(1 << i));
+ bltab.class_id[i] = 0;
+ mutex_unlock(&bltab.mlock);
+ return 0;
+ }
+ }
+
+ mutex_unlock(&bltab.mlock);
+ return -1;
+}
+
+int met_set_dump_buffer_real(int size)
+{
+ if (dump_buffer_size && dump_buffer) {
+ free_pages((unsigned long)dump_buffer, get_order(dump_buffer_size));
+ dump_data_size = 0;
+ dump_overrun = 0;
+ dump_overrun_size = 0;
+ dump_seq_no = 0;
+ dump_buffer_size = 0;
+ }
+ /* size is 0 means free dump buffer */
+ if (size == 0)
+ return 0;
+
+ if (size < 0)
+ return -1;
+
+ size = (size + (PAGE_SIZE - 1)) & (~(PAGE_SIZE - 1));
+ dump_buffer = (void *)__get_free_pages(GFP_KERNEL, get_order(size));
+ if (dump_buffer == NULL) {
+ ERRF("can not allocate buffer to copy\n");
+ return -ENOMEM;
+ }
+
+ dump_buffer_size = size;
+ return dump_buffer_size;
+}
+
+int met_save_dump_buffer_real(const char *pathname)
+{
+ int size, ret = 0;
+ struct file *outfp = NULL;
+ mm_segment_t oldfs;
+
+ if (dump_data_size == 0)
+ return 0;
+
+ if (dump_data_size < 0 || dump_overrun_size < 0)
+ return -1;
+
+ if (dump_buffer == NULL || dump_buffer_size <= 0)
+ return -1;
+
+ if (dump_overrun)
+ size = dump_overrun_size;
+ else
+ size = dump_data_size;
+
+ if (size >= dump_buffer_size)
+ return -1;
+
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ outfp = filp_open(pathname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
+ if (unlikely(outfp == NULL)) {
+ ERRF("can not open saved file for write\n");
+ return -EIO;
+ }
+
+ ret = vfs_write(outfp, dump_buffer, size, &(outfp->f_pos));
+ if (ret < 0)
+ ERRF("can not write to dump file\n");
+ else {
+ dump_data_size = 0;
+ dump_overrun = 0;
+ dump_overrun_size = 0;
+ dump_seq_no = 0;
+ }
+
+ set_fs(oldfs);
+
+ if (outfp != NULL)
+ filp_close(outfp, NULL);
+
+ return 0;
+}
+
+int met_save_log_real(const char *pathname)
+{
+ int len, ret = 0;
+ struct file *infp = NULL;
+ struct file *outfp = NULL;
+ void *ptr = NULL;
+ mm_segment_t oldfs;
+
+ infp = filp_open("/sys/kernel/debug/tracing/trace", O_RDONLY, 0);
+ if (unlikely(infp == NULL)) {
+ ERRF("can not open trace file for read\n");
+ ret = -1;
+ goto save_out;
+ }
+
+ outfp = filp_open(pathname, O_WRONLY | O_TRUNC | O_CREAT, 0664);
+ if (unlikely(outfp == NULL)) {
+ ERRF("can not open saved file for write\n");
+ ret = -2;
+ goto save_out;
+ }
+
+ ptr = (void *)__get_free_pages(GFP_KERNEL, 2);
+ if (ptr == NULL) {
+ ERRF("can not allocate buffer to copy\n");
+ ret = -3;
+ goto save_out;
+ }
+
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+
+ while (1) {
+ len = vfs_read(infp, ptr, PAGE_SIZE << 2, &(infp->f_pos));
+ if (len < 0) {
+ ERRF("can not read from trace file\n");
+ ret = -3;
+ break;
+ } else if (len == 0) {
+ break;
+ }
+
+ ret = vfs_write(outfp, ptr, len, &(outfp->f_pos));
+ if (ret < 0) {
+ ERRF("can not write to saved file\n");
+ break;
+ }
+ }
+
+ set_fs(oldfs);
+
+save_out:
+ if (ptr != NULL)
+ free_pages((unsigned long)ptr, 2);
+ if (infp != NULL)
+ filp_close(infp, NULL);
+ if (outfp != NULL)
+ filp_close(outfp, NULL);
+
+ return ret;
+}
+
+#ifdef BUILD_WITH_MET
+#include <linux/module.h>
+#include <linux/uaccess.h>
+/* =========================================================================== */
+/* misc file nodes */
+/* =========================================================================== */
+static ssize_t enable_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int i;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", (bltab.flag >> 31) ? 0 : 1);
+ return i;
+}
+
+static ssize_t enable_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
+ size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ mutex_lock(&bltab.mlock);
+
+ if (value == 1)
+ bltab.flag &= (~MET_CLASS_ALL);
+ else
+ bltab.flag |= MET_CLASS_ALL;
+
+ mutex_unlock(&bltab.mlock);
+
+ return n;
+}
+
+static struct kobject *kobj_tag;
+static struct kobj_attribute enable_attr = __ATTR(enable, 0664, enable_show, enable_store);
+
+static ssize_t dump_buffer_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int i, size;
+
+ if (dump_overrun)
+ size = dump_overrun_size;
+ else
+ size = dump_data_size;
+
+ i = snprintf(buf, PAGE_SIZE, "Buffer Size (KB)=%d\nData Size (KB)=%d\nOverrun=%d\n",
+ dump_buffer_size >> 10, size >> 10, dump_overrun);
+ return i;
+}
+
+static ssize_t dump_buffer_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
+ size_t n)
+{
+ int ret, value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ ret = met_set_dump_buffer_real(value << 10);
+
+ if (ret < 0)
+ return ret;
+
+ return n;
+}
+
+static struct kobj_attribute dump_buffer_attr =
+__ATTR(dump_buffer_kb, 0664, dump_buffer_show, dump_buffer_store);
+
+static ssize_t options_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int i = 0;
+
+ buf[0] = 0;
+
+ if (options_flag == 0) {
+ strncat(buf, "none\n", PAGE_SIZE - 1 - i);
+ i += 5;
+ }
+
+ if (options_flag & OPFLAG_OVERWRITE) {
+ strncat(buf, "overwrite\n", PAGE_SIZE - 1 - i);
+ i += 10;
+ }
+
+ return i;
+}
+
+static ssize_t options_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf,
+ size_t n)
+{
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if ((n == 1) && (buf[0] == 0xA)) {
+ options_flag = 0;
+ return n;
+ }
+
+ if (strncmp(buf, "overwrite", 9) == 0)
+ options_flag |= OPFLAG_OVERWRITE;
+ else
+ return -EINVAL;
+
+ return n;
+}
+
+static struct kobj_attribute options_attr = __ATTR(options, 0664, options_show, options_store);
+
+int tag_reg(struct file_operations *const fops, struct kobject *kobj)
+{
+ int ret;
+
+ kobj_tag = kobject_create_and_add("tag", kobj);
+ if (kobj_tag == NULL) {
+ ERRF("can not create kobject: kobj_bus\n");
+ return -1;
+ }
+
+ ret = sysfs_create_file(kobj_tag, &enable_attr.attr);
+ if (ret != 0) {
+ ERRF("Failed to create enable in sysfs\n");
+ kobject_del(kobj_tag);
+ kobject_put(kobj_tag);
+ kobj_tag = NULL;
+ return ret;
+ }
+
+ ret = sysfs_create_file(kobj_tag, &dump_buffer_attr.attr);
+ if (ret != 0) {
+ ERRF("Failed to create dump_buffer in sysfs\n");
+ sysfs_remove_file(kobj_tag, &enable_attr.attr);
+ kobject_del(kobj_tag);
+ kobject_put(kobj_tag);
+ kobj_tag = NULL;
+ return ret;
+ }
+
+ ret = sysfs_create_file(kobj_tag, &options_attr.attr);
+ if (ret != 0) {
+ ERRF("Failed to create options in sysfs\n");
+ sysfs_remove_file(kobj_tag, &enable_attr.attr);
+ sysfs_remove_file(kobj_tag, &dump_buffer_attr.attr);
+ kobject_del(kobj_tag);
+ kobject_put(kobj_tag);
+ kobj_tag = NULL;
+ return ret;
+ }
+
+ met_tag_init();
+
+ return 0;
+}
+
+int tag_unreg(void)
+{
+ met_tag_uninit();
+ sysfs_remove_file(kobj_tag, &enable_attr.attr);
+ sysfs_remove_file(kobj_tag, &dump_buffer_attr.attr);
+ sysfs_remove_file(kobj_tag, &options_attr.attr);
+ kobject_del(kobj_tag);
+ kobject_put(kobj_tag);
+ kobj_tag = NULL;
+
+ return 0;
+}
+
+#endif /* BUILD_WITH_MET */
+
+#else /* not MET_USER_EVENT_SUPPORT */
+
+#ifdef BUILD_WITH_MET
+int tag_reg(void *p, void *q)
+{
+ return 0;
+}
+
+int tag_unreg(void)
+{
+ return 0;
+}
+#endif
+
+#endif /* MET_USER_EVENT_SUPPORT */
diff --git a/src/devtools/met_drv_v2/common/met_vcoredvfs.c b/src/devtools/met_drv_v2/common/met_vcoredvfs.c
new file mode 100644
index 0000000..7901ecc
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_vcoredvfs.c
@@ -0,0 +1,306 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+
+#include <dvfsrc-exp.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "core_plf_init.h"
+#include "core_plf_trace.h"
+
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+
+/* Global variables */
+struct metdevice met_vcoredvfs;
+int polling_mode = 1;
+
+/* external symbols */
+#define DEFAULT_INFO_NUM 3
+#define DEFAULT_SRC_NUM 1
+
+char *default_info_name[DEFAULT_INFO_NUM] = {
+ "OPP",
+ "VOLT",
+ "FREQ"
+};
+
+char *default_src_name[DEFAULT_SRC_NUM] = {
+ "MD2SPM"
+};
+
+unsigned int opp_info[DEFAULT_INFO_NUM];
+unsigned int src_req[DEFAULT_SRC_NUM];
+
+static int met_vcorefs_get_num_opp(void)
+{
+ if (vcorefs_get_num_opp_symbol)
+ return vcorefs_get_num_opp_symbol();
+ else
+ return 0;
+}
+
+static int met_vcorefs_get_opp_info_num(void)
+{
+ if (vcorefs_get_opp_info_num_symbol)
+ return vcorefs_get_opp_info_num_symbol();
+ else
+ return DEFAULT_INFO_NUM;
+}
+
+
+static int met_vcorefs_get_src_req_num(void)
+{
+ if (vcorefs_get_src_req_num_symbol)
+ return vcorefs_get_src_req_num_symbol();
+ else
+ return DEFAULT_SRC_NUM;
+}
+
+
+static char **met_vcorefs_get_opp_info_name(void)
+{
+ if (vcorefs_get_opp_info_name_symbol)
+ return vcorefs_get_opp_info_name_symbol();
+ else
+ return default_info_name;
+}
+
+static char **met_vcorefs_get_src_req_name(void)
+{
+ if (vcorefs_get_src_req_name_symbol)
+ return vcorefs_get_src_req_name_symbol();
+ else
+ return default_src_name;
+}
+
+static unsigned int *met_vcorefs_get_opp_info(void)
+{
+ if (vcorefs_get_opp_info_symbol)
+ return vcorefs_get_opp_info_symbol();
+
+ return opp_info;
+}
+
+static unsigned int *met_vcorefs_get_src_req(void)
+{
+ if (vcorefs_get_src_req_symbol)
+ return vcorefs_get_src_req_symbol();
+
+ return src_req;
+}
+
+
+/*======================================================================*/
+/* File Node definitions */
+/*======================================================================*/
+
+static struct kobject *kobj_met_vcoredvfs;
+
+static ssize_t vcorefs_polling_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+static ssize_t vcorefs_polling_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n);
+static struct kobj_attribute vcorefs_polling_attr =
+__ATTR(vcorefs_polling, 0664, vcorefs_polling_show, vcorefs_polling_store);
+
+/*======================================================================*/
+/* Utilities */
+/*======================================================================*/
+
+static inline int do_vcoredvfs(void)
+{
+ return met_vcoredvfs.mode;
+}
+
+/*======================================================================*/
+/* Data Output */
+/*======================================================================*/
+
+noinline void vcorefs(unsigned char cnt, unsigned int *value)
+{
+ char *SOB, *EOB;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH_EOL(EOB, cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void vcorefs_kicker(unsigned char cnt, int *value)
+{
+ char *SOB, *EOB;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH_EOL(EOB, cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void ms_vcorefs(unsigned char cnt, unsigned int *value)
+{
+ char *SOB, *EOB;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH_EOL(EOB, cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+/*======================================================================*/
+/* Callback functions */
+/*======================================================================*/
+void vcoredvfs_irq(int opp)
+{
+ int num;
+ unsigned int *out;
+
+ num = met_vcorefs_get_opp_info_num();
+ out = met_vcorefs_get_opp_info();
+
+ vcorefs(num, out);
+}
+
+/*======================================================================*/
+/* File Node Operations */
+/*======================================================================*/
+static ssize_t vcorefs_polling_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", polling_mode);
+}
+
+static ssize_t vcorefs_polling_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+ polling_mode = value;
+
+ return n;
+}
+
+/*======================================================================*/
+/* MET Device Operations */
+/*======================================================================*/
+static int met_vcoredvfs_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ kobj_met_vcoredvfs = parent;
+
+ ret = sysfs_create_file(kobj_met_vcoredvfs, &vcorefs_polling_attr.attr);
+ if (ret != 0) {
+ pr_debug("Failed to create vcoredvfs in sysfs\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void met_vcoredvfs_delete(void)
+{
+ sysfs_remove_file(kobj_met_vcoredvfs, &vcorefs_polling_attr.attr);
+}
+
+static void met_vcoredvfs_start(void)
+{
+ vcoredvfs_irq(-1);
+}
+
+static void met_vcoredvfs_stop(void)
+{
+ vcoredvfs_irq(-1);
+}
+
+static void met_vcoredvfs_polling(unsigned long long stamp, int cpu)
+{
+ int num;
+ unsigned int *out;
+
+ if (!do_vcoredvfs())
+ return;
+
+ /* vcorefs opp information */
+ if (polling_mode)
+ vcoredvfs_irq(-1);
+
+ /* vcorefs source request */
+ num = met_vcorefs_get_src_req_num();
+ out = met_vcorefs_get_src_req();
+
+ ms_vcorefs(num, out);
+}
+
+static const char help[] =
+ " --vcoredvfs monitor VCORE DVFS\n";
+static int vcoredvfs_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static const char header_dvfs[] = "met-info [000] 0.0: met_vcorefs_header:";
+
+static const char header_ms_dvfs[] = "met-info [000] 0.0: ms_vcorefs_header:";
+
+static int vcoredvfs_print_header(char *buf, int len)
+{
+ int ret = 0;
+ int idx = 0;
+ int num = 0;
+ char **header;
+
+ ret = snprintf(buf, PAGE_SIZE, "met-info [000] 0.0: met_vcorefs_cfg: NUM_OPP:%d\n", met_vcorefs_get_num_opp());
+
+ /* opp information */
+ num = met_vcorefs_get_opp_info_num();
+ header = met_vcorefs_get_opp_info_name();
+
+ ret += snprintf(buf + ret, PAGE_SIZE, header_dvfs);
+ for (idx = 0; idx < num; idx++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", header[idx]);
+ buf[strlen(buf)-1] = '\n';
+
+ /* source requests */
+ num = met_vcorefs_get_src_req_num();
+ header = met_vcorefs_get_src_req_name();
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, header_ms_dvfs);
+ for (idx = 0; idx < num; idx++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", header[idx]);
+ buf[strlen(buf)-1] = '\n';
+
+ met_vcoredvfs.mode = 0;
+
+ return ret;
+}
+
+struct metdevice met_vcoredvfs = {
+ .name = "vcoredvfs",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_vcoredvfs_create,
+ .delete_subfs = met_vcoredvfs_delete,
+ .cpu_related = 0,
+ .start = met_vcoredvfs_start,
+ .stop = met_vcoredvfs_stop,
+ .polling_interval = 1, /* ms */
+ .timed_polling = met_vcoredvfs_polling,
+ .print_help = vcoredvfs_print_help,
+ .print_header = vcoredvfs_print_header,
+};
diff --git a/src/devtools/met_drv_v2/common/met_vcoredvfs_44.c b/src/devtools/met_drv_v2/common/met_vcoredvfs_44.c
new file mode 100644
index 0000000..2e22bce
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_vcoredvfs_44.c
@@ -0,0 +1,365 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2018 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+
+#include <mtk_vcorefs_governor.h>
+#include <mtk_spm_vcore_dvfs.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+
+#include "core_plf_init.h"
+#include "core_plf_trace.h"
+
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+
+/* Global variables */
+struct metdevice met_vcoredvfs;
+int polling_mode = 1;
+
+/* external symbols */
+#define DEFAULT_INFO_NUM 3
+#define DEFAULT_SRC_NUM 1
+
+char *default_info_name[DEFAULT_INFO_NUM] = {
+ "OPP",
+ "VOLT",
+ "FREQ"
+};
+
+char *default_src_name[DEFAULT_SRC_NUM] = {
+ "MD2SPM"
+};
+
+unsigned int opp_info[DEFAULT_INFO_NUM];
+unsigned int src_req[DEFAULT_SRC_NUM];
+
+static char *met_governor_get_kicker_name(int id)
+{
+ if (governor_get_kicker_name_symbol)
+ return governor_get_kicker_name_symbol(id);
+ else
+ return "KIR_UNKNOWN";
+}
+
+static int met_vcorefs_get_num_opp(void)
+{
+ if (vcorefs_get_num_opp_symbol)
+ return vcorefs_get_num_opp_symbol();
+ else
+ return 0;
+}
+
+static int met_vcorefs_get_opp_info_num(void)
+{
+ if (vcorefs_get_opp_info_num_symbol)
+ return vcorefs_get_opp_info_num_symbol();
+ else
+ return DEFAULT_INFO_NUM;
+}
+
+static char **met_vcorefs_get_opp_info_name(void)
+{
+ if (vcorefs_get_opp_info_name_symbol)
+ return vcorefs_get_opp_info_name_symbol();
+ else
+ return default_info_name;
+}
+
+static char **met_vcorefs_get_src_req_name(void)
+{
+ if (vcorefs_get_src_req_name_symbol)
+ return vcorefs_get_src_req_name_symbol();
+ else
+ return default_src_name;
+}
+
+static int met_vcorefs_get_src_req_num(void)
+{
+ if (vcorefs_get_src_req_num_symbol)
+ return vcorefs_get_src_req_num_symbol();
+ else
+ return DEFAULT_SRC_NUM;
+}
+
+static unsigned int *met_vcorefs_get_opp_info(void)
+{
+ int count = 0;
+
+ if (vcorefs_get_opp_info_symbol)
+ return vcorefs_get_opp_info_symbol();
+
+ if (vcorefs_get_hw_opp_symbol)
+ opp_info[count++] = vcorefs_get_hw_opp_symbol();
+ if (vcorefs_get_curr_vcore_symbol)
+ opp_info[count++] = vcorefs_get_curr_vcore_symbol(); /* uV */
+ if (vcorefs_get_curr_ddr_symbol)
+ opp_info[count++] = vcorefs_get_curr_ddr_symbol(); /* kHz */
+
+ return opp_info;
+}
+
+static unsigned int *met_vcorefs_get_src_req(void)
+{
+ if (vcorefs_get_src_req_symbol)
+ return vcorefs_get_src_req_symbol();
+
+ if (spm_vcorefs_get_MD_status_symbol)
+ src_req[0] = spm_vcorefs_get_MD_status_symbol();
+ return src_req;
+}
+
+
+/*======================================================================*/
+/* File Node definitions */
+/*======================================================================*/
+
+static struct kobject *kobj_met_vcoredvfs;
+
+static ssize_t vcorefs_polling_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf);
+static ssize_t vcorefs_polling_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n);
+static struct kobj_attribute vcorefs_polling_attr =
+__ATTR(vcorefs_polling, 0664, vcorefs_polling_show, vcorefs_polling_store);
+
+/*======================================================================*/
+/* Utilities */
+/*======================================================================*/
+
+static inline int do_vcoredvfs(void)
+{
+ return met_vcoredvfs.mode;
+}
+
+/*======================================================================*/
+/* Data Output */
+/*======================================================================*/
+
+noinline void vcorefs(unsigned char cnt, unsigned int *value)
+{
+ char *SOB, *EOB;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH_EOL(EOB, cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void vcorefs_kicker(unsigned char cnt, int *value)
+{
+ char *SOB, *EOB;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH_EOL(EOB, cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void ms_vcorefs(unsigned char cnt, unsigned int *value)
+{
+ char *SOB, *EOB;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH_EOL(EOB, cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+/*======================================================================*/
+/* Callback functions */
+/*======================================================================*/
+void sw_kicker_req(enum dvfs_kicker kicker, enum dvfs_opp opp)
+{
+ if (!do_vcoredvfs())
+ return;
+
+ if (kicker_table_symbol)
+ vcorefs_kicker(NUM_KICKER, kicker_table_symbol);
+}
+
+void vcoredvfs_irq(int opp)
+{
+ int num;
+ unsigned int *out;
+
+ num = met_vcorefs_get_opp_info_num();
+ out = met_vcorefs_get_opp_info();
+
+ vcorefs(num, out);
+}
+
+/*======================================================================*/
+/* File Node Operations */
+/*======================================================================*/
+static ssize_t vcorefs_polling_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", polling_mode);
+}
+
+static ssize_t vcorefs_polling_store(struct kobject *kobj,
+ struct kobj_attribute *attr, const char *buf, size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+ polling_mode = value;
+
+ return n;
+}
+
+/*======================================================================*/
+/* MET Device Operations */
+/*======================================================================*/
+static int met_vcoredvfs_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ kobj_met_vcoredvfs = parent;
+
+ ret = sysfs_create_file(kobj_met_vcoredvfs, &vcorefs_polling_attr.attr);
+ if (ret != 0) {
+ pr_debug("Failed to create vcoredvfs in sysfs\n");
+ return ret;
+ }
+
+ return ret;
+}
+
+static void met_vcoredvfs_delete(void)
+{
+ sysfs_remove_file(kobj_met_vcoredvfs, &vcorefs_polling_attr.attr);
+}
+
+static void met_vcoredvfs_start(void)
+{
+ if (kicker_table_symbol)
+ vcorefs_kicker(NUM_KICKER, kicker_table_symbol);
+
+ vcoredvfs_irq(-1);
+
+ if (!polling_mode && spm_vcorefs_register_handler_symbol)
+ spm_vcorefs_register_handler_symbol(vcoredvfs_irq);
+
+ if (vcorefs_register_req_notify_symbol)
+ vcorefs_register_req_notify_symbol(sw_kicker_req);
+ else
+ MET_TRACE("vcorefs_register_req_notify not exist!\n");
+
+ if (!polling_mode && vcorefs_enable_debug_isr_symbol)
+ vcorefs_enable_debug_isr_symbol(true);
+}
+
+static void met_vcoredvfs_stop(void)
+{
+ if (!polling_mode && vcorefs_enable_debug_isr_symbol)
+ vcorefs_enable_debug_isr_symbol(false);
+
+ if (vcorefs_register_req_notify_symbol)
+ vcorefs_register_req_notify_symbol(NULL);
+
+ if (spm_vcorefs_register_handler_symbol)
+ spm_vcorefs_register_handler_symbol(NULL);
+
+ if (kicker_table_symbol)
+ vcorefs_kicker(NUM_KICKER, kicker_table_symbol);
+ vcoredvfs_irq(-1);
+}
+
+static void met_vcoredvfs_polling(unsigned long long stamp, int cpu)
+{
+ int num;
+ unsigned int *out;
+
+ if (!do_vcoredvfs())
+ return;
+
+ /* vcorefs opp information */
+ if (polling_mode)
+ vcoredvfs_irq(-1);
+
+ /* vcorefs source request */
+ num = met_vcorefs_get_src_req_num();
+ out = met_vcorefs_get_src_req();
+
+ ms_vcorefs(num, out);
+}
+
+static const char help[] =
+ " --vcoredvfs monitor VCORE DVFS\n";
+static int vcoredvfs_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static const char header_dvfs[] = "met-info [000] 0.0: met_vcorefs_header:";
+
+static const char header_kicker[] = "met-info [000] 0.0: met_vcorefs_kicker_header:";
+
+static const char header_ms_dvfs[] = "met-info [000] 0.0: ms_vcorefs_header:";
+
+static int vcoredvfs_print_header(char *buf, int len)
+{
+ int ret;
+ int idx, num;
+ char **header;
+
+ ret = snprintf(buf, PAGE_SIZE, "met-info [000] 0.0: met_vcorefs_cfg: NUM_OPP:%d\n", met_vcorefs_get_num_opp());
+
+ /* opp information */
+ num = met_vcorefs_get_opp_info_num();
+ header = met_vcorefs_get_opp_info_name();
+
+ ret += snprintf(buf + ret, PAGE_SIZE, header_dvfs);
+ for (idx = 0; idx < num; idx++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", header[idx]);
+ buf[strlen(buf)-1] = '\n';
+
+ /* sw kickers */
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s", header_kicker);
+ for (idx = 0; idx < NUM_KICKER; idx++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", met_governor_get_kicker_name(idx));
+ buf[strlen(buf)-1] = '\n';
+
+ /* source requests */
+ num = met_vcorefs_get_src_req_num();
+ header = met_vcorefs_get_src_req_name();
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, header_ms_dvfs);
+ for (idx = 0; idx < num; idx++)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "%s,", header[idx]);
+ buf[strlen(buf)-1] = '\n';
+
+ met_vcoredvfs.mode = 0;
+
+ return ret;
+}
+
+struct metdevice met_vcoredvfs = {
+ .name = "vcoredvfs",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_vcoredvfs_create,
+ .delete_subfs = met_vcoredvfs_delete,
+ .cpu_related = 0,
+ .start = met_vcoredvfs_start,
+ .stop = met_vcoredvfs_stop,
+ .polling_interval = 1, /* ms */
+ .timed_polling = met_vcoredvfs_polling,
+ .print_help = vcoredvfs_print_help,
+ .print_header = vcoredvfs_print_header,
+};
diff --git a/src/devtools/met_drv_v2/common/met_wall_time.c b/src/devtools/met_drv_v2/common/met_wall_time.c
new file mode 100644
index 0000000..4150a47
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/met_wall_time.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/sched/clock.h>
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <asm/div64.h>
+#include <linux/types.h>
+#include <linux/kallsyms.h>
+#include <linux/ktime.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+#include "trace.h"
+#include "interface.h"
+#include "met_kernel_symbol.h"
+
+#define MODE_CUSOM_CLKSRC 2
+struct metdevice met_wall_time;
+
+/** */
+/* How to add a new clocksource: */
+/* */
+/* 1. add constant for new clocksource in #define-macro */
+/* 2. declare new weakref function */
+/* 3. implement handler functions: */
+/* (1) clksrc_attr_t::*ready: */
+/* check if ... */
+/* (i) clocksource correctly working */
+/* (ii) weakref function is not null */
+/* (2) clksrc_attr_t::*get_cnt: read clocksource from weakref function */
+/* 4. place attrs of new clocksource into clksrc_attr_tb */
+/* 5. update DEFAULT_CLKSRC_STR */
+/* 6. update help message */
+/** */
+
+#define __SYS_TIMER 0x0
+#define __GPT1 0x1
+#define __GPT2 0x2
+#define __GPT3 0x3
+#define __GPT4 0x4
+#define __GPT5 0x5
+#define __GPT6 0x6
+
+#define DEFAULT_CLKSRC_STR "SYS_TIMER"
+
+extern ktime_t ktime_get(void);
+
+int __sys_timer_get_cnt(u8 clksrc, u64 *cycles)
+{
+ if (met_export_api_symbol->met_arch_counter_get_cntvct)
+ *cycles = met_export_api_symbol->met_arch_counter_get_cntvct();
+ return 0;
+}
+
+
+struct clksrc_attr_t {
+ u8 clksrc;
+ const char *clksrc_str;
+ /* checks if clksrc/get_cnt function is working/available */
+ int (*clksrc_ready)(u8 clksrc);
+ int (*clksrc_get_cnt)(u8 clksrc, u64 *cycles);
+};
+
+struct clksrc_attr_t clksrc_attr_tb[] = {
+ {__SYS_TIMER, "SYS_TIMER", NULL, __sys_timer_get_cnt},
+ /* {__GPT1, "GPT1", __gpt_timer_ready, __gpt_timer_get_cnt}, */
+ /* {__GPT2, "GPT2", __gpt_timer_ready, __gpt_timer_get_cnt}, */
+ /* {__GPT3, "GPT3", __gpt_timer_ready, __gpt_timer_get_cnt}, */
+ /* {__GPT4, "GPT4", __gpt_timer_ready, __gpt_timer_get_cnt}, */
+ /* {__GPT5, "GPT5", __gpt_timer_ready, __gpt_timer_get_cnt}, */
+ /* {__GPT6, "GPT6", __gpt_timer_ready, __gpt_timer_get_cnt}, */
+};
+
+static const struct clksrc_attr_t *lookup_clksrc_attr_tb(const char *clksrc_str, int len);
+static const struct clksrc_attr_t *wall_time_attr;
+
+/* definitions for auto-sampling of working freq. of clocksource */
+/* maximum tolerable error percentage(%) of sampled clock freq */
+#define FREQ_ERR_PERCENT 3
+
+/* expected working freq. of clocksources */
+static const u32 freq_level[] = { 32768, 13000000, 26000000 };
+
+static u32 lookup_freq_level(u32 freq);
+
+/* flag indicating whether sampling is on-going */
+static u32 do_sample;
+static u32 freq;
+static u64 start_us_ts;
+static u64 start_wall_time;
+/* end definitions for sampling of freq. */
+
+static void wall_time_start(void)
+{
+ if (met_wall_time.mode != MODE_CUSOM_CLKSRC) {
+ wall_time_attr = lookup_clksrc_attr_tb(DEFAULT_CLKSRC_STR,
+ strlen(DEFAULT_CLKSRC_STR));
+ }
+
+ freq = 0;
+ do_sample = 1;
+
+ if (wall_time_attr) {
+
+ /* XXX: always use CPU 0 */
+ start_us_ts = cpu_clock(0);
+ wall_time_attr->clksrc_get_cnt(wall_time_attr->clksrc, &start_wall_time);
+
+ /* us_ts = ap_ts/1000; */
+ do_div(start_us_ts, 1000);
+ }
+}
+
+noinline void met_mono_time(void)
+{
+ /* mono time vs local time */
+ u64 cur_local_ns = sched_clock();
+ ktime_t cur_mono_ts = ktime_get();
+
+ MET_TRACE("TS.APTS=%llu TS.MONO=%llu\n", (unsigned long long)cur_local_ns,
+ (unsigned long long)ktime_to_ns(cur_mono_ts));
+}
+
+noinline void met_ap_wall_time(unsigned long long ts, int cpu)
+{
+ u64 ap_ts;
+ u64 us_ts;
+ u64 sec;
+ u64 usec;
+ u64 cycles;
+ u64 f;
+
+ if (wall_time_attr) {
+
+ wall_time_attr->clksrc_get_cnt(wall_time_attr->clksrc, &cycles);
+ ap_ts = cpu_clock(cpu);
+
+ us_ts = ap_ts;
+ do_div(us_ts, 1000); /* us_ts = ap_ts/1000; */
+
+ sec = us_ts;
+ usec = do_div(sec, 1000000); /* sec = us_ts/1000000; usec = us_ts%1000000; */
+ MET_TRACE("TS.APTS=%llu.%06llu WCLK=%llu\n", (unsigned long long)sec,
+ (unsigned long long)usec, (unsigned long long)cycles);
+
+ // print local time vs mono time for gpu time shift
+ met_mono_time();
+
+ if (do_sample) {
+
+ do_sample = 0;
+
+ f = (cycles - start_wall_time) * 1000000;
+ do_div(f, us_ts - start_us_ts);
+
+ /* don't worry about the u64 -> u32 assignment, */
+ /* sampled wall-clock freq is expected to be below 2^32-1 */
+ freq = lookup_freq_level(f);
+
+ /* debug message */
+ /* MET_TRACE("wall_time debug: result: %u," */
+ /* "start cycle: %llu, end cycle: %llu, cycle diff: %llu," */
+ /* "start us: %llu, end us: %llu, us diff: %llu", */
+ /* f, */
+ /* start_wall_time, cycles, cycles - start_wall_time, */
+ /* start_us_ts, us_ts, us_ts - start_us_ts); */
+
+ if (freq != 0)
+ met_tag_oneshot_real(33880, "_WCLK_FREQ_", freq);
+ }
+ }
+}
+
+static const char help[] =
+" --wall_time output wall-clock syncing info in system timer\n";
+/* " --wall_time=SYS_TIMER|GPT[1-6] output wall-clock syncing info in custom clocksource\n"; */
+
+static int wall_time_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static const char *header =
+"met-info [000] 0.0: WCLK: %d\n"
+"met-info [000] 0.0: clocksource: %s\n";
+
+static int wall_time_print_header(char *buf, int len)
+{
+ return snprintf(buf, len, header,
+ freq == 0 ? -1 : freq,
+ wall_time_attr ? wall_time_attr->clksrc_str : "NONE");
+}
+
+static int wall_time_process_argument(const char *arg, int len)
+{
+ /* reset wall-time clocksource */
+ wall_time_attr = lookup_clksrc_attr_tb(arg, len);
+
+ if (!wall_time_attr) {
+ met_wall_time.mode = 0;
+ return -1;
+ }
+
+ met_wall_time.mode = MODE_CUSOM_CLKSRC;
+ return 0;
+}
+
+static const struct clksrc_attr_t *lookup_clksrc_attr_tb(const char *clksrc_str, int len)
+{
+ int i;
+ const struct clksrc_attr_t *attr;
+ int tb_nmemb = sizeof(clksrc_attr_tb) / sizeof(*clksrc_attr_tb);
+
+ for (i = 0; i < tb_nmemb; i++) {
+
+ attr = clksrc_attr_tb + i;
+
+ if (strlen(attr->clksrc_str) == len &&
+ strncmp(clksrc_str, attr->clksrc_str, len) == 0) {
+ return attr;
+ }
+ }
+
+ return NULL;
+}
+
+static u32 lookup_freq_level(u32 freq)
+{
+
+ int ii;
+ int freq_nmemb = sizeof(freq_level) / sizeof(*freq_level);
+ u32 fdiff;
+
+ for (ii = 0; ii < freq_nmemb; ii++) {
+ fdiff = freq_level[ii] > freq ? freq_level[ii] - freq : freq - freq_level[ii];
+ if (fdiff < freq_level[ii] * FREQ_ERR_PERCENT / 100)
+ return freq_level[ii];
+ }
+
+ return 0;
+}
+
+struct metdevice met_wall_time = {
+ .name = "wall_time",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .start = wall_time_start,
+ .polling_interval = 1000,
+ .timed_polling = met_ap_wall_time,
+ .print_help = wall_time_print_help,
+ .print_header = wall_time_print_header,
+ .process_argument = wall_time_process_argument,
+};
+EXPORT_SYMBOL(met_wall_time);
diff --git a/src/devtools/met_drv_v2/common/mips_pmu_hw.c b/src/devtools/met_drv_v2/common/mips_pmu_hw.c
new file mode 100644
index 0000000..1246d26
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mips_pmu_hw.c
@@ -0,0 +1,430 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <asm/system.h>
+#include <linux/smp.h>
+
+#include "cpu_pmu.h"
+#include "mips_pmu_name.h"
+
+struct chip_pmu {
+ enum cpu_type_enum type;
+ struct pmu_desc **desc;
+ void *refptr;
+ const char *cpu_name;
+ unsigned int pmu_desc_size;
+ unsigned int max_hw_events;
+ unsigned int max_reg_count;
+};
+
+struct pmu_desc *mips_pmu_desc[MIPS_MAX_HWEVENTS];
+
+static struct chip_pmu chips[] = {
+ {CPU_1004K, mips_pmu_desc, (void *)mips_1004k_pmu_desc, "MIPS_1004K",
+ MIPS_1004K_PMU_DESC_SIZE, MIPS_1004K_PMU_DESC_COUNT, PMU_1004K_MAX_HW_REGS},
+};
+
+static struct chip_pmu chip_unknown = { CPU_UNKNOWN, NULL, NULL, "Unknown CPU", 0, 0, 0 };
+
+#define CHIP_PMU_COUNT (sizeof(chips) / sizeof(struct chip_pmu))
+static struct chip_pmu *chip;
+#define M_CONFIG1_PC (1 << 4)
+
+#define M_PERFCTL_EXL (1 << 0)
+#define M_PERFCTL_KERNEL (1 << 1)
+#define M_PERFCTL_SUPERVISOR (1 << 2)
+#define M_PERFCTL_USER (1 << 3)
+#define M_PERFCTL_INTERRUPT_ENABLE (1 << 4)
+#define M_PERFCTL_EVENT(event) (((event) & 0x3ff) << 5)
+#define M_PERFCTL_VPEID(vpe) ((vpe) << 16)
+
+#if IS_ENABLED(CONFIG_CPU_BMIPS5000)
+#define M_PERFCTL_MT_EN(filter) 0
+#else /* !CONFIG_CPU_BMIPS5000 */
+#define M_PERFCTL_MT_EN(filter) ((filter) << 20)
+#endif /* CONFIG_CPU_BMIPS5000 */
+
+#define M_TC_EN_ALL M_PERFCTL_MT_EN(0)
+#define M_TC_EN_VPE M_PERFCTL_MT_EN(1)
+#define M_TC_EN_TC M_PERFCTL_MT_EN(2)
+#define M_PERFCTL_TCID(tcid) ((tcid) << 22)
+#define M_PERFCTL_WIDE (1 << 30)
+#define M_PERFCTL_MORE (1 << 31)
+#define M_PERFCTL_TC (1 << 30)
+
+#define M_PERFCTL_COUNT_EVENT_WHENEVER (M_PERFCTL_EXL | \
+ M_PERFCTL_KERNEL | \
+ M_PERFCTL_USER | \
+ M_PERFCTL_SUPERVISOR | \
+ M_PERFCTL_INTERRUPT_ENABLE)
+
+#if IS_ENABLED(CONFIG_MIPS_MT_SMP)
+#define M_PERFCTL_CONFIG_MASK 0x3fff801f
+#else
+#define M_PERFCTL_CONFIG_MASK 0x1f
+#endif
+#define M_PERFCTL_EVENT_MASK 0xfe0
+
+#define vpe_id() 0
+
+/* To get current TCID*/
+#define read_c0_tcbind() __read_32bit_c0_register($2, 2)
+
+struct cpu_hw_events {
+ unsigned int config_base[MIPS_MAX_HWEVENTS];
+ unsigned int saved_ctrl[MIPS_MAX_HWEVENTS];
+};
+
+DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
+ .config_base = {
+ 0, 0, 0, 0}, .saved_ctrl = {
+0, 0, 0, 0},};
+
+static enum cpu_type_enum mips_get_ic(void)
+{
+ unsigned int value = current_cpu_type();
+
+ /* pr_debug("ic value: %X\n", value); */
+ return value;
+}
+
+static int __n_counters(void)
+{
+ if (!(read_c0_config1() & M_CONFIG1_PC))
+ return 0;
+ if (!(read_c0_perfctrl0() & M_PERFCTL_MORE))
+ return 1;
+ if (!(read_c0_perfctrl1() & M_PERFCTL_MORE))
+ return 2;
+ if (!(read_c0_perfctrl2() & M_PERFCTL_MORE))
+ return 3;
+
+ return 4;
+}
+
+static int n_counters(void)
+{
+ int counters;
+
+ switch (current_cpu_type()) {
+ case CPU_R10000:
+ counters = 2;
+ break;
+ case CPU_R12000:
+ case CPU_R14000:
+ counters = 4;
+ break;
+ default:
+ counters = __n_counters();
+ break;
+ }
+
+ return counters;
+}
+
+static int mips_pmu_hw_get_counters(void)
+{
+ int count = n_counters();
+
+ /* pr_debug("pmu hw event nr: %d\n", count); */
+ return count;
+}
+
+static unsigned int mipsxx_pmu_swizzle_perf_idx(unsigned int idx)
+{
+ if (vpe_id() == 1)
+ idx = (idx + 2) & 3;
+ return idx;
+}
+
+static void mipsxx_pmu_write_counter(unsigned int idx, u64 val)
+{
+ idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
+ switch (idx) {
+ case 0:
+ write_c0_perfcntr0(val);
+ return;
+ case 1:
+ write_c0_perfcntr1(val);
+ return;
+ case 2:
+ write_c0_perfcntr2(val);
+ return;
+ case 3:
+ write_c0_perfcntr3(val);
+ return;
+ }
+}
+
+static u64 mipsxx_pmu_read_counter(unsigned int idx)
+{
+ idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
+ switch (idx) {
+ case 0:
+ /*
+ * The counters are unsigned, we must cast to truncate
+ * off the high bits.
+ */
+ return (u32) read_c0_perfcntr0();
+ case 1:
+ return (u32) read_c0_perfcntr1();
+ case 2:
+ return (u32) read_c0_perfcntr2();
+ case 3:
+ return (u32) read_c0_perfcntr3();
+ default:
+ WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
+ return 0;
+ }
+}
+
+
+static unsigned int mipsxx_pmu_read_control(unsigned int idx)
+{
+ idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
+ switch (idx) {
+ case 0:
+ return read_c0_perfctrl0();
+ case 1:
+ return read_c0_perfctrl1();
+ case 2:
+ return read_c0_perfctrl2();
+ case 3:
+ return read_c0_perfctrl3();
+ default:
+ WARN_ONCE(1, "Invalid performance counter number (%d)\n", idx);
+ return 0;
+ }
+}
+
+static void mipsxx_pmu_write_control(unsigned int idx, unsigned int val)
+{
+ idx = mipsxx_pmu_swizzle_perf_idx(idx);
+
+ switch (idx) {
+ case 0:
+ write_c0_perfctrl0(val);
+ return;
+ case 1:
+ write_c0_perfctrl1(val);
+ return;
+ case 2:
+ write_c0_perfctrl2(val);
+ return;
+ case 3:
+ write_c0_perfctrl3(val);
+ return;
+ }
+}
+
+static int mipsxx_pmu_get_vpeid(void)
+{
+ return read_c0_tcbind() & 0xF;
+}
+
+static void mipsxx_pmu_reset_counters(int idx)
+{
+ switch (idx) {
+ case 3:
+ mipsxx_pmu_write_control(3, 0);
+ mipsxx_pmu_write_counter(3, 0);
+ break;
+ case 2:
+ mipsxx_pmu_write_control(2, 0);
+ mipsxx_pmu_write_counter(2, 0);
+ break;
+ case 1:
+ mipsxx_pmu_write_control(1, 0);
+ mipsxx_pmu_write_counter(1, 0);
+ break;
+ case 0:
+ mipsxx_pmu_write_control(0, 0);
+ mipsxx_pmu_write_counter(0, 0);
+ break;
+ }
+}
+
+static void mipsxx_pmu_enable_event(int idx, int event)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ unsigned long flags;
+
+ WARN_ON(idx < 0 || idx >= chip->max_hw_events);
+ cpuc->saved_ctrl[idx] = M_PERFCTL_EVENT(event & 0xff) |
+ M_PERFCTL_VPEID(mipsxx_pmu_get_vpeid()) |
+ (cpuc->config_base[idx] & M_PERFCTL_CONFIG_MASK);
+#if IS_ENABLED(CONFIG_CPU_BMIPS5000)
+ /* if (IS_ENABLED(CONFIG_CPU_BMIPS5000)) */
+ /* enable the counter for the calling thread */
+ cpuc->saved_ctrl[idx] |= (1 << (12 + vpe_id())) | M_PERFCTL_TC;
+#endif
+ /*
+ * To enable pmu count
+ */
+ local_irq_save(flags);
+ mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
+ local_irq_restore(flags);
+}
+
+static void mipsxx_pmu_disable_event(int idx)
+{
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+ unsigned long flags;
+
+ /* WARN_ON(idx < 0 || idx >= mipspmu.num_counters); */
+ WARN_ON(idx < 0 || idx >= chip->max_hw_events);
+
+ local_irq_save(flags);
+ cpuc->saved_ctrl[idx] = mipsxx_pmu_read_control(idx) & ~M_PERFCTL_COUNT_EVENT_WHENEVER;
+ mipsxx_pmu_write_control(idx, cpuc->saved_ctrl[idx]);
+ local_irq_restore(flags);
+}
+
+static int mips_pmu_hw_get_event_desc(int idx, int event, char *event_desc)
+{
+ int i;
+
+ if (event_desc == NULL) {
+ pr_debug("event_desc is NULL\n");
+ return -1;
+ }
+
+ for (i = 0; i < chip->max_reg_count; i++) {
+ if (chip->desc[idx][i].event == event) {
+ strncpy(event_desc, chip->desc[idx][i].name, MXSIZE_PMU_DESC - 1);
+ break;
+ }
+ }
+ if (i == chip->max_reg_count)
+ return -1;
+
+ return 0;
+}
+
+
+static int mips_pmu_hw_check_event(struct met_pmu *pmu, int idx, int event)
+{
+ int i;
+
+ /* to check index over run */
+ if (!chip)
+ return -1;
+
+ if (idx >= chip->max_hw_events)
+ return -1;
+
+ for (i = 0; i < chip->max_reg_count; i++) {
+ if (chip->desc[idx][i].event == event)
+ break;
+ }
+ if (i == chip->max_reg_count)
+ return -1;
+
+ return 0;
+}
+
+static void mips_pmu_hw_start(struct met_pmu *pmu, int count)
+{
+ int i;
+ int generic = count - 1;
+ struct cpu_hw_events *cpuc = this_cpu_ptr(&cpu_hw_events);
+
+ /* pr_debug("hw_start generic: %d\n", generic); */
+ for (i = 0; i < generic; i++) {
+ /* init config */
+ cpuc->config_base[i] = 0;
+ cpuc->config_base[i] |= M_TC_EN_VPE;
+ cpuc->config_base[i] |= M_PERFCTL_USER;
+ cpuc->config_base[i] |= M_PERFCTL_KERNEL;
+ cpuc->config_base[i] |= M_PERFCTL_EXL;
+ cpuc->config_base[i] |= M_PERFCTL_SUPERVISOR;
+ cpuc->config_base[i] &= M_PERFCTL_CONFIG_MASK;
+ /**/ mipsxx_pmu_reset_counters(i);
+ if (pmu[i].mode == MODE_POLLING)
+ mipsxx_pmu_enable_event(i, pmu[i].event);
+ }
+ if (pmu[count - 1].mode == MODE_POLLING)
+ pr_debug("%s %d BUG!!! index over run!!\n", __func__, __LINE__);
+}
+
+static void mips_pmu_hw_stop(int count)
+{
+ int idx = 0;
+ int generic = count - 1;
+ /* pr_debug("reset %d\n", generic); */
+ for (idx = 0; idx < generic; idx++) {
+ mipsxx_pmu_reset_counters(idx);
+ mipsxx_pmu_disable_event(idx);
+ }
+}
+
+
+static unsigned int mips_pmu_hw_polling(struct met_pmu *pmu, int count, unsigned int *pmu_value)
+{
+ int i, cnt = 0;
+ int generic = count - 1;
+
+ for (i = 0; i < generic; i++) {
+ if (pmu[i].mode == MODE_POLLING) {
+ pmu_value[cnt] = mipsxx_pmu_read_counter(i);
+ cnt++;
+ mipsxx_pmu_reset_counters(i);
+ mipsxx_pmu_enable_event(i, pmu[i].event);
+ }
+ }
+ if (pmu[count - 1].mode == MODE_POLLING) {
+ pr_debug("%s %d BUG!!! index over run!!\n", __func__, __LINE__);
+ pmu_value[cnt] = 0xFFFF;
+ cnt++;
+ }
+
+ return cnt;
+}
+
+
+
+struct cpu_pmu_hw mips_pmu = {
+ .name = "mips_pmu",
+ .get_event_desc = mips_pmu_hw_get_event_desc,
+ .check_event = mips_pmu_hw_check_event,
+ .start = mips_pmu_hw_start,
+ .stop = mips_pmu_hw_stop,
+ .polling = mips_pmu_hw_polling,
+};
+
+struct cpu_pmu_hw *cpu_pmu_hw_init(void)
+{
+ int i = 0;
+ enum cpu_type_enum type;
+ int pmu_hw_count = 0;
+
+ type = mips_get_ic();
+
+ if (CPU_UNKNOWN == type || CPU_LAST == type) {
+ chip = &chip_unknown;
+ return NULL;
+ }
+ for (i = 0; i < CHIP_PMU_COUNT; i++) {
+ if (chips[i].type == type) {
+ chip = &(chips[i]);
+ break;
+ }
+ }
+ if (i == CHIP_PMU_COUNT) {
+ chip = &chip_unknown;
+ return NULL;
+ }
+
+ pmu_hw_count = mips_pmu_hw_get_counters();
+ for (i = 0; i < pmu_hw_count; i++)
+ chip->desc[i] = chip->refptr + (chip->pmu_desc_size * i);
+
+ mips_pmu.nr_cnt = pmu_hw_count + 1;
+ mips_pmu.cpu_name = chip->cpu_name;
+ return &mips_pmu;
+}
diff --git a/src/devtools/met_drv_v2/common/mips_pmu_name.h b/src/devtools/met_drv_v2/common/mips_pmu_name.h
new file mode 100644
index 0000000..9feef56
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mips_pmu_name.h
@@ -0,0 +1,164 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _MIPS_PMU_NAME_H_
+#define _MIPS_PMU_NAME_H_
+
+/* MIPS 1004K */
+#define MIPS_MAX_HWEVENTS (4)
+
+#define PMU_1004K_MAX_HW_REGS (128)
+struct pmu_desc mips_1004k_pmu_desc[][PMU_1004K_MAX_HW_REGS] = {
+ /* COUNT 0 */
+ {
+ {0, "CPU_CYCLES"},
+ {1, "CPU_INST"},
+ {2, "BRANCH_INSNS"},
+ {3, "JR_31_INSNS"},
+ {4, "JR_NON_31_INSNS"},
+ {5, "ITLB_ACCESSES"},
+ {6, "DTLB_ACCESSES"},
+ {7, "JTLB_INSN_ACCESSES"},
+ {8, "JTLB_DATA_ACCESSES"},
+ {9, "ICACHE_ACCESSES"},
+ {10, "DCACHE_ACCESSES"},
+ {11, "DCACHE_MISSES"},
+ {12, "RESERVED"},
+ {13, "STORE_MISS_INSNS"},
+ {14, "INTEGER_INSNS"},
+ {15, "LOAD_INSNS"},
+ {16, "J_JAL_INSNS"},
+ {17, "NO_OPS_INSNS"},
+ {18, "ALL_STALLS"},
+ {19, "SC_INSNS"},
+ {20, "PREFETCH_INSNS"},
+ {21, "L2_CACHE_WRITEBACKS"},
+ {22, "L2_CACHE_MISSES"},
+ {23, "EXCEPTIONS_TAKEN"},
+ {24, "CACHE_FIXUP_CYCLES"},
+ {25, "IFU_STALLS"},
+ {26, "DSP_INSNS"},
+ {27, "RESERVED"},
+ {28, "POLICY_EVENTS"},
+ {29, "ISPRAM_EVENTS"},
+ {30, "COREEXTEND_EVENTS"},
+ {31, "YIELD_EVENTS"},
+ {32, "ITC_LOADS"},
+ {33, "UNCACHED_LOAD_INSNS"},
+ {34, "FORK_INSNS"},
+ {35, "CP2_ARITH_INSNS"},
+ {36, "INTERVENTION_STALLS"},
+ {37, "ICACHE_MISS_STALLS"},
+ {38, "RESERVED"},
+ {39, "DCACHE_MISS_CYCLES"},
+ {40, "UNCACHED_STALLS"},
+ {41, "MDU_STALLS"},
+ {42, "CP2_STALLS"},
+ {43, "ISPRAM_STALLS"},
+ {44, "CACHE_INSN_STALLS"},
+ {45, "LOAD_USE_STALLS"},
+ {46, "INTERLOCK_STALLS"},
+ {47, "RELAX_STALLS"},
+ {48, "IFU_FB_FULL_REFETCHES"},
+ {49, "EJTAG_INSN_TRIGGERS"},
+ {50, "FSB_LESS_25_FULL"},
+ {51, "FSB_OVER_50_FULL"},
+ {52, "LDQ_LESS_25_FULL"},
+ {53, "LDQ_OVER_50_FULL"},
+ {54, "WBB_LESS_25_FULL"},
+ {55, "WBB_OVER_50_FULL"},
+ {56, "INTERVENTION_HIT_COUNT"},
+ {57, "INVALIDATE_INTERVENTION_COUNT"},
+ {58, "EVICTION_COUNT"},
+ {59, "MESI_INVAL_COUNT"},
+ {60, "MESI_MODIFIED_COUNT"},
+ {61, "SELF_INTERVENTION_LATENCY"},
+ {62, "READ_RESPONSE_LATENCY"},
+ {63, "RESERVED"},
+ {64, "SI_PCEVENT1"},
+ {65, "SI_PCEVENT3"},
+ {66, "SI_PCEVENT5"},
+ {67, "SI_PCEVENT7"},
+ {-1, "RESERVED"},
+ /* 68 - 127 for Reserved */
+ },
+ /* COUNT 1 */
+ {
+ {0, "CPU_CYCLES"},
+ {1, "CPU_INST"},
+ {2, "MISPREDICTED_BRANCH_INSNS"},
+ {3, "JR_31_MISPREDICTIONS"},
+ {4, "JR_31_NO_PREDICTIONS"},
+ {5, "ITLB_MISSES"},
+ {6, "DTLB_MISSES"},
+ {7, "JTLB_INSN_MISSES"},
+ {8, "JTLB_DATA_MISSES"},
+ {9, "ICACHE_MISSES"},
+ {10, "DCACHE_WRITEBACKS"},
+ {11, "DCACHE_MISSES"},
+ {12, "RESERVED"},
+ {13, "LOAD_MISS_INSNS"},
+ {14, "FPU_INSNS"},
+ {15, "STORE_INSNS"},
+ {16, "MIPS16_INSNS"},
+ {17, "INT_MUL_DIV_INSNS"},
+ {18, "REPLAYED_INSNS"},
+ {19, "SC_INSNS_FAILED"},
+ {20, "CACHE_HIT_PREFETCH_INSNS"},
+ {21, "L2_CACHE_ACCESSES"},
+ {22, "L2_CACHE_SINGLE_BIT_ERRORS"},
+ {23, "SINGLE_THREADED_CYCLES"},
+ {24, "REFETCHED_INSNS"},
+ {25, "ALU_STALLS"},
+ {26, "ALU_DSP_SATURATION_INSNS"},
+ {27, "MDU_DSP_SATURATION_INSNS"},
+ {28, "CP2_EVENTS"},
+ {29, "DSPRAM_EVENTS"},
+ {30, "RESERVED"},
+ {31, "ITC_EVENT"},
+ {33, "UNCACHED_STORE_INSNS"},
+ {34, "YIELD_IN_COMP"},
+ {35, "CP2_TO_FROM_INSNS"},
+ {36, "INTERVENTION_MISS_STALLS"},
+ {37, "DCACHE_MISS_STALLS"},
+ {38, "RESERVED"},
+ /* 38 was listed in OPROFILE web page, but not listed 1004k mips spec */
+ /* {38, "FSB_INDEX_CONFLICT_STALLS"}, */
+ {39, "L2_CACHE_MISS_CYCLES"},
+ {40, "ITC_STALLS"},
+ {41, "FPU_STALLS"},
+ {42, "COREEXTEND_STALLS"},
+ {43, "DSPRAM_STALLS"},
+ {45, "ALU_TO_AGEN_STALLS"},
+ {46, "MISPREDICTION_STALLS"},
+ {47, "RESERVED"},
+ {48, "FB_ENTRY_ALLOCATED_CYCLES"},
+ {49, "EJTAG_DATA_TRIGGERS"},
+ {50, "FSB_25_50_FULL"},
+ {51, "FSB_FULL_STALLS"},
+ {52, "LDQ_25_50_FULL"},
+ {53, "LDQ_FULL_STALLS"},
+ {54, "WBB_25_50_FULL"},
+ {55, "WBB_FULL_STALLS"},
+ {56, "INTERVENTION_COUNT"},
+ {57, "INVALID_INTERVENT_HIT_CNT"},
+ {58, "WRITEBACK_COUNT"},
+ {59, "MESI_EXCLUSIVE_COUNT"},
+ {60, "MESI_SHARED_COUNT"},
+ {61, "SELF_INTERVENTION_COUNT"},
+ {62, "READ_RESPONSE_COUNT"},
+ {63, "RESERVED"},
+ {64, "SI_PCEVENT0"},
+ {65, "SI_PCEVENT2"},
+ {66, "SI_PCEVENT4"},
+ {67, "SI_PCEVENT6"},
+ {-1, "RESERVED"},
+ },
+};
+
+#define MIPS_1004K_PMU_DESC_SIZE (sizeof(mips_1004k_pmu_desc[0]))
+#define MIPS_1004K_PMU_DESC_COUNT (sizeof(mips_1004k_pmu_desc) / MIPS_1004K_PMU_DESC_SIZE)
+
+#endif /* _V8_PMU_NAME_H_ */
diff --git a/src/devtools/met_drv_v2/common/mtk_gpu_metmonitor.c b/src/devtools/met_drv_v2/common/mtk_gpu_metmonitor.c
new file mode 100644
index 0000000..39d4653
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mtk_gpu_metmonitor.c
@@ -0,0 +1,879 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <asm/page.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/syscalls.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+#include <linux/io.h>
+#include <linux/hrtimer.h>
+
+#include "met_drv.h"
+#include "trace.h"
+#include "interface.h"
+
+#include "mtk_gpu_metmonitor.h"
+#include "core_plf_init.h"
+#include "core_plf_trace.h"
+
+
+/*
+ * define if the hal implementation might re-schedule, cannot run inside softirq
+ * undefine this is better for sampling jitter if HAL support it
+ */
+#undef GPU_HAL_RUN_PREMPTIBLE
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+static struct delayed_work gpu_dwork;
+static struct delayed_work gpu_pwr_dwork;
+#endif
+
+/* the mt_gpufreq_get_thermal_limit_freq use mutex_lock to do its job */
+/* so, change the gpu-dvfs implementation to dwork */
+static struct delayed_work gpu_dvfs_dwork;
+
+/*
+ * GPU monitor HAL comes from alps\mediatek\kernel\include\linux\mtk_gpu_utility.h
+ *
+ * mtk_get_gpu_memory_usage(unsigned int* pMemUsage) in unit of bytes
+ *
+ * mtk_get_gpu_xxx_loading are in unit of %
+*/
+
+enum MET_GPU_PROFILE_INDEX {
+ eMET_GPU_LOADING = 0,
+ eMET_GPU_BLOCK_LOADING, /* 1 */
+ eMET_GPU_IDLE_LOADING, /* 2 */
+ eMET_GPU_PROFILE_CNT
+};
+
+static unsigned long g_u4AvailableInfo;
+
+static unsigned int output_header_pmu_len;
+static unsigned int output_pmu_str_len;
+
+noinline void GPU_Loading(unsigned char cnt, unsigned int *value)
+{
+ switch (cnt) {
+ case 1:
+ MET_TRACE("%u\n", value[0]);
+ break;
+ case 2:
+ MET_TRACE("%u,%u\n", value[0], value[1]);
+ break;
+ case 3:
+ MET_TRACE("%u,%u,%u\n", value[0], value[1], value[2]);
+ break;
+ case 4:
+ MET_TRACE("%u,%u,%u,%u\n", value[0], value[1], value[2], value[3]);
+ break;
+ default:
+ break;
+ }
+
+}
+
+noinline void GPU_Sub_Loading(unsigned int loading)
+{
+ MET_TRACE("%u\n", loading);
+}
+
+noinline void GPU_3D_Fences_Count(int count)
+{
+ MET_TRACE("%d\n", count);
+}
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+static void gpu_GPULoading(struct work_struct *work)
+{
+ unsigned int pu4Value[eMET_GPU_PROFILE_CNT];
+ unsigned long u4Index = 0;
+ unsigned int loading = 0;
+ int count = 0;
+
+ memset(pu4Value, 0x00, eMET_GPU_PROFILE_CNT);
+ if ((1 << eMET_GPU_LOADING) & g_u4AvailableInfo) {
+ if (mtk_get_gpu_loading_symbol && mtk_get_gpu_loading_symbol(&pu4Value[u4Index]))
+ u4Index += 1;
+ }
+
+ if ((1 << eMET_GPU_BLOCK_LOADING) & g_u4AvailableInfo) {
+ if (mtk_get_gpu_block_symbol && mtk_get_gpu_block_symbol(&pu4Value[u4Index]))
+ u4Index += 1;
+ }
+
+ if ((1 << eMET_GPU_IDLE_LOADING) & g_u4AvailableInfo) {
+ if (mtk_get_gpu_idle_symbol && mtk_get_gpu_idle_symbol(&pu4Value[u4Index]))
+ u4Index += 1;
+ }
+
+ if (g_u4AvailableInfo)
+ GPU_Loading(u4Index, pu4Value);
+
+ if (mtk_get_gpu_sub_loading_symbol && mtk_get_gpu_sub_loading_symbol(&loading))
+ GPU_Sub_Loading(loading);
+
+ if (mtk_get_3D_fences_count_symbol && mtk_get_3D_fences_count_symbol(&count))
+ GPU_3D_Fences_Count(count);
+}
+#else
+static void gpu_GPULoading(unsigned long long stamp, int cpu)
+{
+ unsigned int pu4Value[eMET_GPU_PROFILE_CNT];
+ unsigned long u4Index = 0;
+ unsigned int loading = 0;
+ int count = 0;
+
+ memset(pu4Value, 0x00, eMET_GPU_PROFILE_CNT);
+ if ((1 << eMET_GPU_LOADING) & g_u4AvailableInfo) {
+ if (mtk_get_gpu_loading_symbol) {
+ mtk_get_gpu_loading_symbol(&pu4Value[u4Index]);
+ u4Index += 1;
+ }
+ }
+
+ if ((1 << eMET_GPU_BLOCK_LOADING) & g_u4AvailableInfo) {
+ if (mtk_get_gpu_block_symbol) {
+ mtk_get_gpu_block_symbol(&pu4Value[u4Index]);
+ u4Index += 1;
+ }
+ }
+
+ if ((1 << eMET_GPU_IDLE_LOADING) & g_u4AvailableInfo) {
+ if (mtk_get_gpu_idle_symbol) {
+ mtk_get_gpu_idle_symbol(&pu4Value[u4Index]);
+ u4Index += 1;
+ }
+ }
+
+ if (g_u4AvailableInfo)
+ GPU_Loading(u4Index, pu4Value);
+
+ if (mtk_get_gpu_sub_loading_symbol) {
+ mtk_get_gpu_sub_loading_symbol(&loading);
+ GPU_Sub_Loading(loading);
+ }
+
+ if (mtk_get_3D_fences_count_symbol) {
+ mtk_get_3D_fences_count_symbol(&count);
+ GPU_3D_Fences_Count(count);
+ }
+}
+#endif
+
+static void gpu_monitor_start(void)
+{
+ if (mtk_get_gpu_loading_symbol)
+ g_u4AvailableInfo |= (1 << eMET_GPU_LOADING);
+ if (mtk_get_gpu_block_symbol)
+ g_u4AvailableInfo |= (1 << eMET_GPU_BLOCK_LOADING);
+ if (mtk_get_gpu_idle_symbol)
+ g_u4AvailableInfo |= (1 << eMET_GPU_IDLE_LOADING);
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ INIT_DELAYED_WORK(&gpu_dwork, gpu_GPULoading);
+#endif
+}
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+static void gpu_monitor_stop(void)
+{
+ cancel_delayed_work_sync(&gpu_dwork);
+}
+
+static void GPULoadingNotify(unsigned long long stamp, int cpu)
+{
+ schedule_delayed_work(&gpu_dwork, 0);
+}
+#endif
+
+static char help[] =
+ " --gpu monitor gpu status\n";
+static int gpu_status_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static char g_pComGPUStatusHeader[] =
+ "met-info [000] 0.0: met_gpu_loading_header: ";
+static int gpu_status_print_header(char *buf, int len)
+{
+ int ret = 0;
+
+ ret = snprintf(buf, PAGE_SIZE, "%s", g_pComGPUStatusHeader);
+
+ if ((1 << eMET_GPU_LOADING) & g_u4AvailableInfo)
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%s", "Loading,");
+
+ if ((1 << eMET_GPU_BLOCK_LOADING) & g_u4AvailableInfo)
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%s", "Blcok,");
+
+ if ((1 << eMET_GPU_IDLE_LOADING) & g_u4AvailableInfo)
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%s", "Idle");
+
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%s", "\n");
+
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ "met-info [000] 0.0: met_gpu_sub_loading_header: Loading\n");
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ "met-info [000] 0.0: met_gpu_3d_fences_count_header: Count\n");
+
+ return ret;
+}
+
+struct metdevice met_gpu = {
+ .name = "gpu",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .start = gpu_monitor_start,
+ .mode = 0,
+ .polling_interval = 1, /* ms */
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ .timed_polling = GPULoadingNotify,
+ .stop = gpu_monitor_stop,
+#else
+ .timed_polling = gpu_GPULoading,
+#endif
+ .print_help = gpu_status_print_help,
+ .print_header = gpu_status_print_header,
+};
+
+/*
+ * GPU DVFS Monitor
+ */
+#define MTK_GPU_DVFS_TYPE_ITEM(type) #type,
+static char *gpu_dvfs_type_name[] = MTK_GPU_DVFS_TYPE_LIST;
+#undef MTK_GPU_DVFS_TYPE_ITEM
+
+static enum MTK_GPU_DVFS_TYPE gpu_dvfs_type_prev;
+static unsigned long gpu_dvfs_type_freq_prev;
+static unsigned int gpu_dvfs_type_freq[ARRAY_SIZE(gpu_dvfs_type_name)];
+
+noinline void GPU_DVFS(unsigned int Freq, unsigned int ThermalLimit,
+ unsigned long CustomBoost, unsigned long CustomUpbound)
+{
+ MET_TRACE("%u,%u,%lu,%lu\n", Freq, ThermalLimit, CustomBoost, CustomUpbound);
+}
+
+noinline void GPU_DVFS_TYPE(void)
+{
+ char *SOB, *EOB;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatD_EOL(EOB, ARRAY_SIZE(gpu_dvfs_type_freq), gpu_dvfs_type_freq);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+noinline void GPU_DVFS_VSYNC(unsigned long freq)
+{
+ MET_TRACE("%lu\n", freq);
+}
+
+noinline void GPU_VSYNC_OFFSET_STATUS(unsigned int event_status, unsigned int debug_status)
+{
+ MET_TRACE("%u,%u\n", event_status, debug_status);
+}
+
+static void gpu_dvfs(void)
+{
+ unsigned int freq = 0;
+ unsigned int ThermalLimit = 0;
+ enum MTK_GPU_DVFS_TYPE peType;
+ unsigned long pulFreq = 0;
+ unsigned long CustomBoost = 0;
+ unsigned long CustomUpbound = 0;
+ unsigned int event_status = 0;
+ unsigned int debug_status = 0;
+
+ freq = mt_gpufreq_get_cur_freq_symbol ? mt_gpufreq_get_cur_freq_symbol() : 0;
+ ThermalLimit = mt_gpufreq_get_thermal_limit_freq_symbol ? mt_gpufreq_get_thermal_limit_freq_symbol() : 0;
+ if (mtk_get_custom_boost_gpu_freq_symbol)
+ mtk_get_custom_boost_gpu_freq_symbol(&CustomBoost);
+ if (mtk_get_custom_upbound_gpu_freq_symbol)
+ mtk_get_custom_upbound_gpu_freq_symbol(&CustomUpbound);
+ GPU_DVFS(freq, ThermalLimit, CustomBoost, CustomUpbound);
+
+ /* gpu dvfs type */
+ if (mtk_get_gpu_dvfs_from_symbol && mtk_get_gpu_dvfs_from_symbol(&peType, &pulFreq)) {
+ if (gpu_dvfs_type_prev != peType || gpu_dvfs_type_freq_prev != pulFreq) {
+ gpu_dvfs_type_freq[gpu_dvfs_type_prev] = 0;
+ gpu_dvfs_type_prev = peType;
+ gpu_dvfs_type_freq_prev = pulFreq;
+ gpu_dvfs_type_freq[gpu_dvfs_type_prev] = gpu_dvfs_type_freq_prev;
+ GPU_DVFS_TYPE();
+ }
+ }
+
+ if (mtk_get_vsync_based_target_freq_symbol && mtk_get_vsync_based_target_freq_symbol(&pulFreq))
+ GPU_DVFS_VSYNC(pulFreq);
+
+ if (mtk_get_vsync_offset_event_status_symbol && mtk_get_vsync_offset_debug_status_symbol) {
+ if (mtk_get_vsync_offset_event_status_symbol(&event_status)
+ && mtk_get_vsync_offset_debug_status_symbol(&debug_status)) {
+ GPU_VSYNC_OFFSET_STATUS(event_status, debug_status);
+ }
+ }
+}
+
+static void gpu_dvfs_work(struct work_struct *work)
+{
+ gpu_dvfs();
+}
+
+static void gpu_dvfs_monitor_start(void)
+{
+ gpu_dvfs();
+ INIT_DELAYED_WORK(&gpu_dvfs_dwork, gpu_dvfs_work);
+}
+
+static void gpu_dvfs_monitor_stop(void)
+{
+ cancel_delayed_work_sync(&gpu_dvfs_dwork);
+ gpu_dvfs();
+
+ /* reset status */
+ gpu_dvfs_type_prev = 0;
+ gpu_dvfs_type_freq_prev = 0;
+}
+
+static void gpu_dvfs_monitor_polling(unsigned long long stamp, int cpu)
+{
+ schedule_delayed_work(&gpu_dvfs_dwork, 0);
+}
+
+static int gpu_dvfs_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE,
+ " --gpu-dvfs monitor gpu freq\n");
+}
+
+static int gpu_dvfs_print_header(char *buf, int len)
+{
+ int ret = 0;
+ int i = 0;
+
+ ret = snprintf(buf, PAGE_SIZE,
+ "met-info [000] 0.0: met_gpu_dvfs_header: ");
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ "Freq(kHz),ThermalLimit(kHz),CustomBoost,CustomUpbound\n");
+
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ "met-info [000] 0.0: met_gpu_dvfs_type_header: %s", gpu_dvfs_type_name[0]);
+ for (i = 1; i < ARRAY_SIZE(gpu_dvfs_type_name); i++)
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, ",%s", gpu_dvfs_type_name[i]);
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%s", "\n");
+
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ "met-info [000] 0.0: met_gpu_dvfs_vsync_header: VSYNC Based Freq\n");
+ ret += snprintf(buf+ret, PAGE_SIZE-ret,
+ "met-info [000] 0.0: met_gpu_vsync_offset_status_header: Event Status,Debug Status\n");
+
+ return ret;
+}
+
+struct metdevice met_gpudvfs = {
+ .name = "gpu-dvfs",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .start = gpu_dvfs_monitor_start,
+ .stop = gpu_dvfs_monitor_stop,
+ .polling_interval = 1, /* ms */
+ .timed_polling = gpu_dvfs_monitor_polling,
+ .print_help = gpu_dvfs_print_help,
+ .print_header = gpu_dvfs_print_header,
+ .ondiemet_mode = 0,
+};
+
+/*
+ * GPU MEM monitor
+ */
+static unsigned long g_u4MemProfileIsOn;
+
+static void gpu_mem_monitor_start(void)
+{
+ if (!mtk_get_gpu_memory_usage_symbol)
+ return;
+
+#if 0
+ if (mtk_get_gpu_memory_usage_symbol(&u4Value))
+ g_u4MemProfileIsOn = 1;
+#endif
+ g_u4MemProfileIsOn = 1;
+}
+
+noinline void GPU_MEM(unsigned long long stamp, int cpu)
+{
+ unsigned int u4Value = 0;
+
+ if (!mtk_get_gpu_memory_usage_symbol)
+ return;
+
+ if (g_u4MemProfileIsOn == 1) {
+ mtk_get_gpu_memory_usage_symbol(&u4Value);
+ MET_TRACE("%d\n", u4Value);
+ }
+}
+
+static void gpu_mem_monitor_stop(void)
+{
+ g_u4MemProfileIsOn = 0;
+}
+
+static char help_mem[] =
+ " --gpu-mem monitor gpu memory status\n";
+static int gpu_mem_status_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help_mem);
+}
+
+static char g_pComGPUMemHeader[] =
+ "met-info [000] 0.0: met_gpu_mem_header: Usage\n";
+static int gpu_mem_status_print_header(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, g_pComGPUMemHeader);
+}
+
+struct metdevice met_gpumem = {
+ .name = "gpu-mem",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .start = gpu_mem_monitor_start,
+ .stop = gpu_mem_monitor_stop,
+ .mode = 0,
+ .polling_interval = 1, /* ms */
+ .timed_polling = GPU_MEM,
+ .print_help = gpu_mem_status_print_help,
+ .print_header = gpu_mem_status_print_header,
+};
+
+/*
+ * GPU power monitor
+ */
+static unsigned long g_u4PowerProfileIsOn;
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+noinline void GPU_Power(struct work_struct *work)
+{
+ unsigned int u4Value = 0;
+
+ if (!mtk_get_gpu_power_loading_symbol)
+ return;
+
+ mtk_get_gpu_power_loading_symbol(&u4Value);
+ MET_TRACE("%d\n", u4Value);
+}
+
+static void GPU_PowerNotify(unsigned long long stamp, int cpu)
+{
+ if (g_u4PowerProfileIsOn == 1)
+ schedule_delayed_work(&gpu_pwr_dwork, 0);
+}
+#else
+noinline void GPU_Power(unsigned long long stamp, int cpu)
+{
+ unsigned int u4Value = 0;
+
+ if (!mtk_get_gpu_power_loading_symbol)
+ return;
+
+ if (g_u4PowerProfileIsOn == 1) {
+ mtk_get_gpu_power_loading_symbol(&u4Value);
+ MET_TRACE("%d\n", u4Value);
+ }
+}
+#endif
+
+static void gpu_Power_monitor_start(void)
+{
+ if (!mtk_get_gpu_power_loading_symbol)
+ return;
+
+#if 0
+ if (mtk_get_gpu_power_loading_symbol(&u4Value))
+ g_u4PowerProfileIsOn = 1;
+#endif
+ g_u4PowerProfileIsOn = 1;
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ INIT_DELAYED_WORK(&gpu_pwr_dwork, GPU_Power);
+#endif
+}
+
+static void gpu_Power_monitor_stop(void)
+{
+ g_u4PowerProfileIsOn = 0;
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ cancel_delayed_work_sync(&gpu_pwr_dwork);
+#endif
+}
+
+static char help_pwr[] =
+ " --gpu-pwr monitor gpu power status\n";
+static int gpu_Power_status_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help_pwr);
+}
+
+static char g_pComGPUPowerHeader[] =
+ "met-info [000] 0.0: met_gpu_power_header: Loading\n";
+static int gpu_Power_status_print_header(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, g_pComGPUPowerHeader);
+}
+
+struct metdevice met_gpupwr = {
+ .name = "gpu-pwr",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .start = gpu_Power_monitor_start,
+ .stop = gpu_Power_monitor_stop,
+ .mode = 0,
+ .polling_interval = 1, /* ms */
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ .timed_polling = GPU_PowerNotify,
+#else
+ .timed_polling = GPU_Power,
+#endif
+ .print_help = gpu_Power_status_print_help,
+ .print_header = gpu_Power_status_print_header,
+};
+
+
+/*
+ * GPU PMU
+ */
+#define UNUSE_ARG(arg) ((void)arg)
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+static struct delayed_work gpu_pmu_dwork;
+#endif
+
+#define MAX_PMU_STR_LEN (1024 * 5)
+
+static const char help_pmu[] = " --gpu-pmu monitor gpu pmu status";
+static const char header_pmu[] = "met-info [000] 0.0: met_gpu_pmu_header: ";
+static char pmu_str[MAX_PMU_STR_LEN];
+static int pmu_cnt;
+static int gpu_pwr_status = 1;
+static struct GPU_PMU *pmu_list;
+
+
+noinline void GPU_PMU_RAW(
+ unsigned long long stamp,
+ int cpu)
+{
+ bool ret;
+ int i = 0;
+ char *SOB, *EOB;
+ unsigned int value[pmu_cnt];
+
+ if (stamp == 0 && cpu == 0) {
+ for (i = 0; i < pmu_cnt; i++)
+ value[i] = 0;
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH(EOB, pmu_cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+ return;
+ }
+
+ if (mtk_get_gpu_pmu_swapnreset_symbol) {
+ ret = mtk_get_gpu_pmu_swapnreset_symbol(pmu_list, pmu_cnt);
+ if (ret) {
+ for (i = 0; i < pmu_cnt; i++) {
+ if (pmu_list[i].overflow)
+ pmu_list[i].value = 0xFFFFFFFF;
+ value[i] = pmu_list[i].value;
+ }
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH(EOB, pmu_cnt, value);
+ MET_TRACE_PUTBUF(SOB, EOB);
+ }
+ }
+}
+
+static int create_gpu_pmu_list(void)
+{
+ int ret = 0;
+ int len = 0;
+ int i = 0;
+
+ if (mtk_get_gpu_pmu_init_symbol) {
+ ret = mtk_get_gpu_pmu_init_symbol(NULL, 0, &pmu_cnt);
+ if (pmu_cnt == 0 || ret == 0)
+ return 0;
+ } else
+ return 0;
+
+ pmu_list = kmalloc_array(pmu_cnt, sizeof(struct GPU_PMU), GFP_KERNEL);
+ if (pmu_list) {
+ memset(pmu_list, 0x00, sizeof(struct GPU_PMU)*pmu_cnt);
+ ret = mtk_get_gpu_pmu_init_symbol(pmu_list, pmu_cnt, NULL);
+
+ memset(pmu_str, 0x00, MAX_PMU_STR_LEN);
+ len = snprintf(pmu_str, MAX_PMU_STR_LEN, "%s", pmu_list[0].name);
+ for (i = 1; i < pmu_cnt; i++)
+ len += snprintf(pmu_str + len, MAX_PMU_STR_LEN - len, ",%s", pmu_list[i].name);
+
+ /*
+ * dummy read in order to reset GPU PMU counter
+ */
+ if (mtk_get_gpu_pmu_swapnreset_symbol)
+ mtk_get_gpu_pmu_swapnreset_symbol(pmu_list, pmu_cnt);
+ }
+
+ /* init state */
+ met_gpu_pmu.header_read_again = 0;
+ output_header_pmu_len = 0;
+ output_pmu_str_len = 0;
+
+ return ret;
+}
+
+static void delete_gpu_pmu_list(void)
+{
+ kfree(pmu_list);
+ pmu_list = NULL;
+ pmu_cnt = 0;
+}
+
+static void gpu_pwr_status_cb(int on)
+{
+ MET_TRACE("on = %d\n", on);
+
+ if (on == 1) {
+ /*
+ * dummy read in order to reset GPU PMU counter
+ */
+ if (mtk_get_gpu_pmu_swapnreset_symbol)
+ mtk_get_gpu_pmu_swapnreset_symbol(pmu_list, pmu_cnt);
+
+ } else {
+ GPU_PMU_RAW(1, 0);
+ GPU_PMU_RAW(0, 0);
+ }
+
+ gpu_pwr_status = on;
+}
+
+static void gpu_pmu_monitor_start(void)
+{
+ int ret;
+
+ ret = create_gpu_pmu_list();
+ if (ret == 0)
+ return;
+
+ if (mtk_register_gpu_power_change_symbol)
+ mtk_register_gpu_power_change_symbol("met_gpu", gpu_pwr_status_cb);
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ INIT_DELAYED_WORK(&gpu_pmu_dwork, GPU_PMU_RAW);
+#endif
+}
+
+static void gpu_pmu_monitor_stop(void)
+{
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ cancel_delayed_work_sync(&gpu_pmu_dwork);
+#endif
+
+ if (mtk_unregister_gpu_power_change_symbol)
+ mtk_unregister_gpu_power_change_symbol("met_gpu");
+ delete_gpu_pmu_list();
+
+#if 1
+ /* stop polling counter */
+ if (mtk_get_gpu_pmu_swapnreset_stop_symbol)
+ mtk_get_gpu_pmu_swapnreset_stop_symbol();
+ /* release resource */
+ if (mtk_get_gpu_pmu_deinit_symbol)
+ mtk_get_gpu_pmu_deinit_symbol();
+#endif
+}
+
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+static void gpu_pmu_timed_polling_notify(
+ unsigned long long stamp,
+ int cpu)
+{
+ UNUSE_ARG(stamp);
+ UNUSE_ARG(cpu);
+
+ if (gpu_pwr_status == 1)
+ schedule_delayed_work(&gpu_pmu_dwork, 0);
+}
+#else
+static void gpu_pmu_timed_polling(
+ unsigned long long stamp,
+ int cpu)
+{
+ UNUSE_ARG(stamp);
+ UNUSE_ARG(cpu);
+
+ if (gpu_pwr_status == 1)
+ GPU_PMU_RAW(stamp, cpu);
+}
+#endif
+
+static int gpu_pmu_print_help(
+ char *buf,
+ int len)
+{
+ UNUSE_ARG(len);
+ return snprintf(buf, PAGE_SIZE, "%s\n", help_pmu);
+}
+
+static int gpu_pmu_print_header(
+ char *buf,
+ int len)
+{
+ if(output_header_pmu_len == 0){
+ len = snprintf(buf, PAGE_SIZE, "%s", header_pmu);
+ met_gpu_pmu.header_read_again = 1;
+ output_header_pmu_len = len;
+ }
+ else{
+ if( (strlen(pmu_str) - output_pmu_str_len) > PAGE_SIZE ){
+ char output_buf[PAGE_SIZE/4];
+
+ strncpy(output_buf, pmu_str+output_pmu_str_len, PAGE_SIZE/4);
+ len = snprintf(buf, PAGE_SIZE, "%s", output_buf);
+ output_pmu_str_len += len;
+ }
+ else{
+ len = snprintf(buf, PAGE_SIZE, "%s\n", pmu_str+output_pmu_str_len);
+
+ /* reset state */
+ met_gpu_pmu.header_read_again = 0;
+ output_header_pmu_len = 0;
+ output_pmu_str_len = 0;
+ }
+ }
+
+ return len;
+}
+
+struct metdevice met_gpu_pmu = {
+ .name = "gpu-pmu",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_PMU,
+ .cpu_related = 0,
+ .start = gpu_pmu_monitor_start,
+ .stop = gpu_pmu_monitor_stop,
+ .mode = 0,
+ .polling_interval = 1, /* ms */
+#ifdef GPU_HAL_RUN_PREMPTIBLE
+ .timed_polling = gpu_pmu_timed_polling_notify,
+#else
+ .timed_polling = gpu_pmu_timed_polling,
+#endif
+ .print_help = gpu_pmu_print_help,
+ .print_header = gpu_pmu_print_header,
+};
+
+/*
+ * GPU stall counters
+ */
+#ifdef MET_GPU_STALL_MONITOR
+static void __iomem *io_addr_gpu_stall;
+
+static int gpu_stall_create_subfs(struct kobject *parent)
+{
+ io_addr_gpu_stall = ioremap(IO_ADDR_GPU_STALL, IO_SIZE_GPU_STALL);
+ if (!io_addr_gpu_stall) {
+ PR_BOOTMSG("Failed to init GPU stall counters!!\n");
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static void gpu_stall_delete_subfs(void)
+{
+ if (io_addr_gpu_stall) {
+ iounmap(io_addr_gpu_stall);
+ io_addr_gpu_stall = NULL;
+ }
+}
+
+static void gpu_stall_start(void)
+{
+#ifdef GPU_STALL_CNT_SINGLE
+ unsigned int value = 0x00000001;
+#else
+ unsigned int value = 0x00010001;
+#endif
+ writel(value, io_addr_gpu_stall+OFFSET_STALL_GPU_M0_CHECK);
+ writel(value, io_addr_gpu_stall+OFFSET_STALL_GPU_M1_CHECK);
+ writel(value, io_addr_gpu_stall+OFFSET_STALL_GPU_M0_EMI_CHECK);
+ writel(value, io_addr_gpu_stall+OFFSET_STALL_GPU_M1_EMI_CHECK);
+}
+
+static void gpu_stall_stop(void)
+{
+ writel(0x00000000, io_addr_gpu_stall+OFFSET_STALL_GPU_M0_CHECK);
+ writel(0x00000000, io_addr_gpu_stall+OFFSET_STALL_GPU_M1_CHECK);
+ writel(0x00000000, io_addr_gpu_stall+OFFSET_STALL_GPU_M0_EMI_CHECK);
+ writel(0x00000000, io_addr_gpu_stall+OFFSET_STALL_GPU_M1_EMI_CHECK);
+}
+
+noinline void GPU_STALL_RAW(void)
+{
+ unsigned int stall_counters[4];
+ char *SOB, *EOB;
+
+ stall_counters[0] = (unsigned int)readl(io_addr_gpu_stall+OFFSET_STALL_GPU_M0_CHECK);
+ stall_counters[1] = (unsigned int)readl(io_addr_gpu_stall+OFFSET_STALL_GPU_M1_CHECK);
+ stall_counters[2] = (unsigned int)readl(io_addr_gpu_stall+OFFSET_STALL_GPU_M0_EMI_CHECK);
+ stall_counters[3] = (unsigned int)readl(io_addr_gpu_stall+OFFSET_STALL_GPU_M1_EMI_CHECK);
+
+ MET_TRACE_GETBUF(&SOB, &EOB);
+ EOB = ms_formatH(EOB, ARRAY_SIZE(stall_counters), stall_counters);
+ MET_TRACE_PUTBUF(SOB, EOB);
+}
+
+static void gpu_stall_timed_polling(unsigned long long stamp, int cpu)
+{
+ GPU_STALL_RAW();
+}
+
+#ifdef GPU_STALL_CNT_SINGLE
+static char g_pComGPUStallHeader[] =
+ "met-info [000] 0.0: met_gpu_stall_header: M0_WR,M0_RD,M1_WR,M1_RD\n";
+#else
+static char g_pComGPUStallHeader[] =
+ "met-info [000] 0.0: met_gpu_stall_header: M0_STATUS_1,M1_STATUS_1,M0_STATUS_2,M1_STATUS_2\n";
+#endif
+static int gpu_stall_print_header(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, g_pComGPUStallHeader);
+}
+
+struct metdevice met_gpu_stall = {
+ .name = "gpu-stall",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .create_subfs = gpu_stall_create_subfs,
+ .delete_subfs = gpu_stall_delete_subfs,
+ .start = gpu_stall_start,
+ .stop = gpu_stall_stop,
+ .mode = 0,
+ .polling_interval = 1, /* ms */
+ .timed_polling = gpu_stall_timed_polling,
+ .print_header = gpu_stall_print_header,
+};
+#endif /* MET_GPU_STALL_MONITOR */
diff --git a/src/devtools/met_drv_v2/common/mtk_gpu_metmonitor.h b/src/devtools/met_drv_v2/common/mtk_gpu_metmonitor.h
new file mode 100644
index 0000000..3163d23
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mtk_gpu_metmonitor.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _MT_GPU_METMONITOR_H_
+
+#define _MT_GPU_METMONITOR_H_
+
+#endif /* _MT_GPU_METMONITOR_H_ */
diff --git a/src/devtools/met_drv_v2/common/mtk_io.h b/src/devtools/met_drv_v2/common/mtk_io.h
new file mode 100644
index 0000000..860c3d6
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mtk_io.h
@@ -0,0 +1,15 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2017 MediaTek Inc.
+ */
+
+#ifndef __MT_IO_H__
+#define __MT_IO_H__
+
+/* only for arm64 */
+#if IS_ENABLED(CONFIG_ARM64)
+#define IOMEM(a) ((void __force __iomem *)((a)))
+#endif
+
+#endif /* !__MT_IO_H__ */
+
diff --git a/src/devtools/met_drv_v2/common/mtk_typedefs.h b/src/devtools/met_drv_v2/common/mtk_typedefs.h
new file mode 100644
index 0000000..c9a593f
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/mtk_typedefs.h
@@ -0,0 +1,310 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _MT_TYPEDEFS_H__
+
+/*
+ * KOBJ ATTR Manipulations Macros
+ */
+
+#define KOBJ_ITEM_LIST(args...) args
+
+/*
+ * Declaring KOBJ attributes
+ */
+#define DECLARE_KOBJ_ATTR(attr_name) \
+ static struct kobj_attribute attr_name##_attr = \
+ __ATTR(attr_name, 0664, attr_name##_show, attr_name##_store)
+
+#define DECLARE_KOBJ_ATTR_RO(attr_name) \
+ static struct kobj_attribute attr_name##_attr = \
+ __ATTR_RO(attr_name)
+
+/*
+ * Declaring KOBJ attributes with integer variable
+ */
+/* normal version */
+#define DECLARE_KOBJ_ATTR_SHOW_INT(attr_name, var_name) \
+ static ssize_t attr_name##_show( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+ { \
+ return snprintf(buf, PAGE_SIZE, "%d\n", var_name); \
+ }
+#define DECLARE_KOBJ_ATTR_STORE_INT(attr_name, var_name) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ int val = 0; \
+ if (kstrtoint(buf, 0, &val) != 0) { \
+ return -EINVAL; \
+ } \
+ var_name = val; \
+ return n; \
+ }
+#define DECLARE_KOBJ_ATTR_INT(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_SHOW_INT(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_STORE_INT(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR(attr_name)
+#define DECLARE_KOBJ_ATTR_RO_INT(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_SHOW_INT(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_RO(attr_name)
+
+/* cond-check version */
+#define DECLARE_KOBJ_ATTR_STORE_INT_CHECK(attr_name, var_name, cond) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ int var_name##temp = var_name; \
+ if (kstrtoint(buf, 0, &var_name) != 0) { \
+ var_name = var_name##temp; \
+ return -EINVAL; \
+ } \
+ if (cond) { \
+ return n; \
+ } else { \
+ var_name = var_name##temp; \
+ return -EINVAL; \
+ } \
+ }
+/* Note: the name of val in cond can NOT be the same as var_name */
+#define DECLARE_KOBJ_ATTR_INT_CHECK(attr_name, var_name, cond) \
+ DECLARE_KOBJ_ATTR_SHOW_INT(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_STORE_INT_CHECK(attr_name, var_name, cond) \
+ DECLARE_KOBJ_ATTR(attr_name)
+
+/* helper procedure version */
+#define DECLARE_KOBJ_ATTR_SHOW_INT_PROC(attr_name, var_name, func) \
+ static ssize_t attr_name##_show( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+ { \
+ return func(kobj, attr, buf, var_name); \
+ }
+#define DECLARE_KOBJ_ATTR_STORE_INT_PROC(attr_name, var_name, func) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ return func(kobj, attr, buf, n, &(var_name)); \
+ }
+#define DECLARE_KOBJ_ATTR_INT_PROC(attr_name, var_name, show, store) \
+ DECLARE_KOBJ_ATTR_SHOW_INT_PROC(attr_name, var_name, show) \
+ DECLARE_KOBJ_ATTR_STORE_INT_PROC(attr_name, var_name, store) \
+ DECLARE_KOBJ_ATTR(attr_name)
+
+/*
+ * Declaring KOBJ attributes with integer(hex) variable
+ */
+/* normal version */
+#define DECLARE_KOBJ_ATTR_SHOW_HEX(attr_name, var_name) \
+ static ssize_t attr_name##_show( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+ { \
+ return snprintf(buf, PAGE_SIZE, "%x\n", var_name); \
+ }
+#define DECLARE_KOBJ_ATTR_STORE_HEX(attr_name, var_name) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ unsigned int val = 0; \
+ if (kstrtouint(buf, 0, &val) != 0) { \
+ return -EINVAL; \
+ } \
+ var_name = val; \
+ return n; \
+ }
+#define DECLARE_KOBJ_ATTR_HEX(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_SHOW_HEX(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_STORE_HEX(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR(attr_name)
+#define DECLARE_KOBJ_ATTR_RO_HEX(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_SHOW_HEX(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_RO(attr_name)
+
+/* cond-check version */
+#define DECLARE_KOBJ_ATTR_STORE_HEX_CHECK(attr_name, var_name, cond) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ unsigned int var_name##temp = var_name; \
+ if (kstrtouint(buf, 0, &var_name) != 0) { \
+ var_name = var_name##temp; \
+ return -EINVAL; \
+ } \
+ if (cond) { \
+ return n; \
+ } else { \
+ var_name = var_name##temp; \
+ return -EINVAL; \
+ } \
+ }
+/* Note: the name of val in cond can NOT be the same as var_name */
+#define DECLARE_KOBJ_ATTR_HEX_CHECK(attr_name, var_name, cond) \
+ DECLARE_KOBJ_ATTR_SHOW_HEX(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_STORE_HEX_CHECK(attr_name, var_name, cond) \
+ DECLARE_KOBJ_ATTR(attr_name)
+
+/* helper procedure version */
+#define DECLARE_KOBJ_ATTR_SHOW_HEX_PROC(attr_name, var_name, func) \
+ static ssize_t attr_name##_show( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+ { \
+ return func(kobj, attr, buf, var_name); \
+ }
+#define DECLARE_KOBJ_ATTR_STORE_HEX_PROC(attr_name, var_name, func) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ return func(kobj, attr, buf, n, &(var_name)); \
+ }
+#define DECLARE_KOBJ_ATTR_HEX_PROC(attr_name, var_name, show, store) \
+ DECLARE_KOBJ_ATTR_SHOW_HEX_PROC(attr_name, var_name, show) \
+ DECLARE_KOBJ_ATTR_STORE_HEX_PROC(attr_name, var_name, store) \
+ DECLARE_KOBJ_ATTR(attr_name)
+
+/*
+ * Declaring KOBJ attributes with string variable
+ */
+#define DECLARE_KOBJ_ATTR_SHOW_STR(attr_name, var_name) \
+ static ssize_t attr_name##_show( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+ { \
+ return snprintf(buf, PAGE_SIZE, "%s", var_name); \
+ }
+
+#define DECLARE_KOBJ_ATTR_RO_STR(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_SHOW_STR(attr_name, var_name) \
+ DECLARE_KOBJ_ATTR_RO(attr_name)
+
+/*
+ * Declaring KOBJ attributes with integer list variable
+ */
+#define DECLARE_KOBJ_ATTR_INT_LIST_ITEM(list_name, list) \
+ static struct list_name##_list_item_t { \
+ int key; \
+ int val; \
+ } const list_name##_list_item[] = { list }
+#define DECLARE_KOBJ_ATTR_SHOW_INT_LIST(attr_name, var_name, list_name) \
+ static ssize_t attr_name##_show( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(list_name##_list_item); i++) { \
+ if (var_name == list_name##_list_item[i].key) { \
+ return snprintf(buf, \
+ PAGE_SIZE, \
+ "%d\n", \
+ list_name##_list_item[i].val); \
+ } \
+ } \
+ return snprintf(buf, PAGE_SIZE, "%d\n", -1); \
+ }
+#define DECLARE_KOBJ_ATTR_STORE_INT_LIST(attr_name, var_name, list_name) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ int value; \
+ int i; \
+ if (kstrtoint(buf, 10, &value) != 0) \
+ return -EINVAL; \
+ for (i = 0; i < ARRAY_SIZE(list_name##_list_item); i++) { \
+ if (value == list_name##_list_item[i].val) { \
+ var_name = list_name##_list_item[i].key; \
+ return n; \
+ } \
+ } \
+ return -EINVAL; \
+ }
+#define DECLARE_KOBJ_ATTR_INT_LIST(attr_name, var_name, list_name) \
+ DECLARE_KOBJ_ATTR_SHOW_INT_LIST(attr_name, var_name, list_name) \
+ DECLARE_KOBJ_ATTR_STORE_INT_LIST(attr_name, var_name, list_name) \
+ DECLARE_KOBJ_ATTR(attr_name)
+
+/*
+ * Declaring KOBJ attributes with string list variable
+ */
+#define DECLARE_KOBJ_ATTR_STR_LIST_ITEM(list_name, list) \
+ static struct list_name##_list_item_t { \
+ int key; \
+ char *val; \
+ } const list_name##_list_item[] = { list }
+#define DECLARE_KOBJ_ATTR_SHOW_STR_LIST(attr_name, var_name, list_name) \
+ static ssize_t attr_name##_show( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ char *buf) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(list_name##_list_item); i++) { \
+ if (var_name == list_name##_list_item[i].key) { \
+ return snprintf(buf, \
+ PAGE_SIZE, \
+ "%s\n", \
+ list_name##_list_item[i].val); \
+ } \
+ } \
+ return snprintf(buf, PAGE_SIZE, "%s\n", "ERR"); \
+ }
+#define DECLARE_KOBJ_ATTR_STORE_STR_LIST(attr_name, var_name, list_name) \
+ static ssize_t attr_name##_store( \
+ struct kobject *kobj, \
+ struct kobj_attribute *attr, \
+ const char *buf, \
+ size_t n) \
+ { \
+ int i; \
+ for (i = 0; i < ARRAY_SIZE(list_name##_list_item); i++) { \
+ if (strncasecmp(buf, \
+ list_name##_list_item[i].val, \
+ strlen(list_name##_list_item[i].val)) == 0) { \
+ var_name = list_name##_list_item[i].key; \
+ return n; \
+ } \
+ } \
+ return -EINVAL; \
+ }
+#define DECLARE_KOBJ_ATTR_STR_LIST(attr_name, var_name, list_name) \
+ DECLARE_KOBJ_ATTR_SHOW_STR_LIST(attr_name, var_name, list_name) \
+ DECLARE_KOBJ_ATTR_STORE_STR_LIST(attr_name, var_name, list_name) \
+ DECLARE_KOBJ_ATTR(attr_name)
+
+/*
+ * MET Debug Message
+ */
+#define METINFO(format, ...) pr_debug("[MET]%s: "format, __func__, ##__VA_ARGS__)
+#define METERROR(format, ...) pr_debug("[MET][ERR]%s: "format, __func__, ##__VA_ARGS__)
+
+#endif /* _MT_TYPEDEFS_H__ */
diff --git a/src/devtools/met_drv_v2/common/ondiemet.c b/src/devtools/met_drv_v2/common/ondiemet.c
new file mode 100644
index 0000000..206b981
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/ondiemet.c
@@ -0,0 +1,84 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "ondiemet.h"
+
+/* record enabled modules */
+unsigned int ondiemet_module[ONDIEMET_NUM];
+EXPORT_SYMBOL(ondiemet_module);
+
+void (*scp_start[ONDIEMET_NUM]) (void) = {
+sspm_start, NULL, NULL};
+
+void (*scp_stop[ONDIEMET_NUM]) (void) = {
+sspm_stop, NULL, NULL};
+
+void (*scp_extract[ONDIEMET_NUM]) (void) = {
+sspm_extract, NULL, NULL};
+
+/* record which MCU is started to generate data */
+int ondiemet_module_started[ONDIEMET_NUM];
+
+int ondiemet_attr_init(struct device *dev)
+{
+ int ret;
+
+ ret = sspm_attr_init(dev);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm related\n");
+ return ret;
+ }
+
+ return 0;
+
+}
+
+int ondiemet_attr_uninit(struct device *dev)
+{
+ int ret;
+
+ ret = sspm_attr_uninit(dev);
+ if (ret != 0) {
+ pr_debug("can not delete device file: sspm related\n");
+ return ret;
+ }
+
+ return 0;
+
+}
+
+void ondiemet_start(void)
+{
+ int i;
+
+ for (i = 0; i < ONDIEMET_NUM; i++) {
+ if (ondiemet_module[i] != 0) {
+ ondiemet_module_started[i] = 1;
+ (*scp_start[i]) ();
+ }
+ }
+}
+
+void ondiemet_stop(void)
+{
+ int i;
+
+ for (i = 0; i < ONDIEMET_NUM; i++) {
+ if (ondiemet_module[i] != 0) {
+ (*scp_stop[i]) ();
+ ondiemet_module_started[i] = 0;
+ }
+ }
+}
+
+void ondiemet_extract(void)
+{
+ int i;
+
+ for (i = 0; i < ONDIEMET_NUM; i++) {
+ if (ondiemet_module[i] != 0)
+ (*scp_extract[i]) ();
+ }
+}
diff --git a/src/devtools/met_drv_v2/common/ondiemet.h b/src/devtools/met_drv_v2/common/ondiemet.h
new file mode 100644
index 0000000..57c82e1
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/ondiemet.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __ONDIEMET_H
+#define __ONDIEMET_H
+
+#include "ondiemet_log.h"
+
+extern void ondiemet_extract(void);
+extern void ondiemet_stop(void);
+extern void ondiemet_start(void);
+
+#define ONDIEMET_SSPM 0
+#define ONDIEMET_NUM 3 /* total number of supported */
+extern unsigned int ondiemet_module[];
+extern void sspm_start(void);
+extern void sspm_stop(void);
+extern void sspm_extract(void);
+extern int sspm_attr_init(struct device *dev);
+extern int sspm_attr_uninit(struct device *dev);
+
+extern int ondiemet_attr_init(struct device *dev);
+extern int ondiemet_attr_uninit(struct device *dev);
+
+extern int sspm_buffer_size;
+
+#endif /* __ONDIEMET_H */
diff --git a/src/devtools/met_drv_v2/common/ondiemet_log.c b/src/devtools/met_drv_v2/common/ondiemet_log.c
new file mode 100644
index 0000000..85514ea
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/ondiemet_log.c
@@ -0,0 +1,540 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/completion.h>
+
+#include "ondiemet_log.h"
+#include "interface.h"
+
+#define ONDIEMET_LOG_REQ 1
+/* TODO: abandon this constatnt */
+#define ONDIEMET_LOG_STOP 2
+
+#define PID_NONE (-1)
+
+#define ONDIEMET_LOG_STOP_MODE 0
+#define ONDIEMET_LOG_RUN_MODE 1
+#define ONDIEMET_LOG_DEBUG_MODE 2
+
+static int ondiemet_trace_run;
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+static struct dentry *dbgfs_met_dir;
+#else
+static struct proc_dir_entry *procfs_met_dir;
+#endif
+
+struct mutex lock_tracef;
+struct ondiemet_log_req_q_t {
+ struct list_head listq;
+ struct mutex lockq;
+ /* struct semaphore new_evt_sema; */
+ struct completion new_evt_comp;
+ int closeq_flag;
+} ondiemet_log_req_q;
+
+struct ondiemet_log_req {
+ struct list_head list;
+ int cmd_type;
+ const char *src;
+ size_t num;
+
+ void (*on_fini_cb)(const void *p);
+ const void *param;
+};
+
+#define __ondiemet_log_req_init(req, cmd, s, n, pf, p) \
+ do { \
+ INIT_LIST_HEAD(&req->list); \
+ req->cmd_type = cmd; \
+ req->src = s; \
+ req->num = n; \
+ req->on_fini_cb = pf; \
+ req->param = p; \
+ } while (0)
+
+#define __ondiemet_log_req_fini(req) \
+ do { \
+ if (req->on_fini_cb) \
+ req->on_fini_cb(req->param); \
+ kfree(req); \
+ } while (0)
+
+static void __ondiemet_log_req_q_init(struct ondiemet_log_req_q_t *q)
+{
+ INIT_LIST_HEAD(&q->listq);
+ mutex_init(&q->lockq);
+ /* sema_init(&q->new_evt_sema, 0); */
+ init_completion(&q->new_evt_comp);
+ q->closeq_flag = 1;
+}
+
+/* undequeue is seen as a roll-back operation, so it can be done even when the queue is closed */
+static void __ondiemet_log_req_undeq(struct ondiemet_log_req *req)
+{
+ mutex_lock(&ondiemet_log_req_q.lockq);
+ list_add(&req->list, &ondiemet_log_req_q.listq);
+ mutex_unlock(&ondiemet_log_req_q.lockq);
+
+ /* up(&ondiemet_log_req_q.new_evt_sema); */
+ complete(&ondiemet_log_req_q.new_evt_comp);
+}
+
+static int __ondiemet_log_req_enq(struct ondiemet_log_req *req)
+{
+ mutex_lock(&ondiemet_log_req_q.lockq);
+ if (ondiemet_log_req_q.closeq_flag) {
+ mutex_unlock(&ondiemet_log_req_q.lockq);
+ return -EBUSY;
+ }
+
+ list_add_tail(&req->list, &ondiemet_log_req_q.listq);
+ if (req->cmd_type == ONDIEMET_LOG_STOP)
+ ondiemet_log_req_q.closeq_flag = 1;
+ mutex_unlock(&ondiemet_log_req_q.lockq);
+
+ /* up(&ondiemet_log_req_q.new_evt_sema); */
+ complete(&ondiemet_log_req_q.new_evt_comp);
+
+ return 0;
+}
+
+int ondiemet_log_req_enq(const char *src, size_t num, void (*on_fini_cb)(const void *p), const void *param)
+{
+ struct ondiemet_log_req *req = kmalloc(sizeof(*req), GFP_KERNEL);
+
+ __ondiemet_log_req_init(req, ONDIEMET_LOG_REQ, src, num, on_fini_cb, param);
+ return __ondiemet_log_req_enq(req);
+}
+
+/*int down_freezable_interruptible(struct semaphore *sem) */
+int down_freezable_interruptible(struct completion *comp)
+{
+
+ int ret;
+
+ freezer_do_not_count();
+ /* ret = down_interruptible(sem); */
+ ret = wait_for_completion_interruptible(comp);
+ freezer_count();
+
+ return ret;
+}
+
+struct ondiemet_log_req *__ondiemet_log_req_deq(void)
+{
+ struct ondiemet_log_req *ret_req;
+
+ /*if (down_freezable_interruptible(&ondiemet_log_req_q.new_evt_sema))*/
+ if (down_freezable_interruptible(&ondiemet_log_req_q.new_evt_comp))
+ return NULL;
+
+ mutex_lock(&ondiemet_log_req_q.lockq);
+ ret_req = list_entry(ondiemet_log_req_q.listq.next, struct ondiemet_log_req, list);
+ list_del_init(&ret_req->list);
+ mutex_unlock(&ondiemet_log_req_q.lockq);
+
+ return ret_req;
+}
+
+void __ondiemet_log_req_open(void)
+{
+ mutex_lock(&ondiemet_log_req_q.lockq);
+ ondiemet_log_req_q.closeq_flag = 0;
+ mutex_unlock(&ondiemet_log_req_q.lockq);
+}
+
+int __ondiemet_log_req_closed(void)
+{
+ int ret;
+
+ mutex_lock(&ondiemet_log_req_q.lockq);
+ ret = ondiemet_log_req_q.closeq_flag && list_empty(&ondiemet_log_req_q.listq);
+ mutex_unlock(&ondiemet_log_req_q.lockq);
+
+ return ret;
+}
+
+int __ondiemet_log_req_working(void)
+{
+ int ret;
+
+ mutex_lock(&ondiemet_log_req_q.lockq);
+ ret = !ondiemet_log_req_q.closeq_flag;
+ mutex_unlock(&ondiemet_log_req_q.lockq);
+
+ return ret;
+}
+
+static void *__ondiemet_trace_seq_next(struct seq_file *seqf, loff_t *offset)
+{
+ struct ondiemet_log_req *next_req;
+
+ if (ondiemet_trace_run == ONDIEMET_LOG_DEBUG_MODE)
+ pr_debug("[met] __ondiemet_trace_seq_next: pid: %d\n", current->pid);
+
+ if (__ondiemet_log_req_closed())
+ return NULL;
+
+ next_req = __ondiemet_log_req_deq();
+
+ if (next_req == NULL)
+ return NULL;
+
+ if (next_req->cmd_type == ONDIEMET_LOG_STOP) {
+ __ondiemet_log_req_fini(next_req);
+ return NULL;
+ }
+
+ return (void *) next_req;
+}
+
+struct mutex lock_trace_owner_pid;
+pid_t trace_owner_pid = PID_NONE;
+static void *ondiemet_trace_seq_start(struct seq_file *seqf, loff_t *offset)
+{
+ void *ret;
+
+ if (ondiemet_trace_run == ONDIEMET_LOG_DEBUG_MODE) {
+ pr_debug("[met] ondiemet_trace_seq_start: locked_pid: %d, pid: %d, offset: %llu\n",
+ trace_owner_pid, current->pid, *offset);
+ }
+
+ if (!mutex_trylock(&lock_tracef))
+ return NULL;
+
+ mutex_lock(&lock_trace_owner_pid);
+ trace_owner_pid = current->pid;
+ current->flags |= PF_NOFREEZE;
+ mutex_unlock(&lock_trace_owner_pid);
+
+ ret = __ondiemet_trace_seq_next(seqf, offset);
+
+ return ret;
+}
+
+static void *ondiemet_trace_seq_next(struct seq_file *seqf, void *p, loff_t *offset)
+{
+ if (ondiemet_trace_run == ONDIEMET_LOG_DEBUG_MODE)
+ pr_debug("[met] ondiemet_trace_seq_next: pid: %d\n", current->pid);
+
+ (*offset)++;
+ return __ondiemet_trace_seq_next(seqf, offset);
+}
+
+static int ondiemet_trace_seq_show(struct seq_file *seqf, void *p)
+{
+ struct ondiemet_log_req *req = (struct ondiemet_log_req *) p;
+ size_t l_sz;
+ size_t r_sz;
+ struct ondiemet_log_req *l_req;
+ struct ondiemet_log_req *r_req;
+ int ret;
+
+ if (ondiemet_trace_run == ONDIEMET_LOG_DEBUG_MODE)
+ pr_debug("[met] ondiemet_trace_seq_show: pid: %d\n", current->pid);
+
+ if (req->num >= seqf->size) {
+ l_req = kmalloc(sizeof(*req), GFP_KERNEL);
+ r_req = req;
+
+ l_sz = seqf->size >> 1;
+ r_sz = req->num - l_sz;
+ __ondiemet_log_req_init(l_req, ONDIEMET_LOG_REQ, req->src, l_sz, NULL, NULL);
+ __ondiemet_log_req_init(r_req, ONDIEMET_LOG_REQ, req->src + l_sz,
+ r_sz, req->on_fini_cb, req->param);
+
+ __ondiemet_log_req_undeq(r_req);
+ req = l_req;
+
+ if (ondiemet_trace_run == ONDIEMET_LOG_DEBUG_MODE)
+ pr_debug("[met] ondiemet_trace_seq_show: split request\n");
+ }
+
+ ret = seq_write(seqf, req->src, req->num);
+
+ if (ret) {
+ /* check if seq_file buffer overflows */
+ if (seqf->count == seqf->size) {
+ __ondiemet_log_req_undeq(req);
+ } else {
+ if (ondiemet_trace_run == ONDIEMET_LOG_DEBUG_MODE)
+ pr_debug("[met] ondiemet_trace_seq_show: reading trace record failed, some data may be lost or corrupted\n");
+ __ondiemet_log_req_fini(req);
+ }
+ return 0;
+ }
+
+ __ondiemet_log_req_fini(req);
+ return 0;
+}
+
+static void ondiemet_trace_seq_stop(struct seq_file *seqf, void *p)
+{
+ if (ondiemet_trace_run == ONDIEMET_LOG_DEBUG_MODE)
+ pr_debug("[met] ondiemet_trace_seq_stop: pid: %d\n", current->pid);
+
+ mutex_lock(&lock_trace_owner_pid);
+ if (current->pid == trace_owner_pid) {
+ trace_owner_pid = PID_NONE;
+ mutex_unlock(&lock_tracef);
+ }
+ mutex_unlock(&lock_trace_owner_pid);
+}
+
+static const struct seq_operations ondiemet_trace_seq_ops = {
+ .start = ondiemet_trace_seq_start,
+ .next = ondiemet_trace_seq_next,
+ .stop = ondiemet_trace_seq_stop,
+ .show = ondiemet_trace_seq_show
+};
+
+static int ondiemet_trace_open(struct inode *inode, struct file *fp)
+{
+ return seq_open(fp, &ondiemet_trace_seq_ops);
+}
+
+static const struct file_operations ondiemet_trace_fops = {
+ .owner = THIS_MODULE,
+ .open = ondiemet_trace_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+/*struct semaphore log_start_sema;*/
+struct completion log_start_comp;
+int ondiemet_log_manager_start(void)
+{
+ int ret;
+
+ /* TODO: choose a better return value */
+ if (__ondiemet_log_req_working())
+ return -EINVAL;
+
+ if (!__ondiemet_log_req_closed()) {
+ /*ret = down_killable(&log_start_sema);*/
+ ret = wait_for_completion_killable(&log_start_comp);
+ if (ret)
+ return ret;
+ }
+
+ __ondiemet_log_req_open();
+
+ return 0;
+}
+
+/*struct semaphore log_stop_sema;*/
+struct completion log_stop_comp;
+static void __log_stop_cb(const void *p)
+{
+ /* up(&log_start_sema); */
+ /* up(&log_stop_sema); */
+ complete(&log_start_comp);
+ complete(&log_stop_comp);
+}
+
+int ondiemet_log_manager_stop(void)
+{
+ int ret;
+ struct ondiemet_log_req *req;
+
+ /* TODO: choose a better return value */
+ if (__ondiemet_log_req_closed())
+ return -EINVAL;
+
+ req = kmalloc(sizeof(*req), GFP_KERNEL);
+
+ __ondiemet_log_req_init(req, ONDIEMET_LOG_STOP, NULL, 0, __log_stop_cb, NULL);
+ /*sema_init(&log_start_sema, 0); */
+ /*sema_init(&log_stop_sema, 0); */
+ init_completion(&log_start_comp);
+ init_completion(&log_stop_comp);
+
+ ret = __ondiemet_log_req_enq(req);
+ if (ret)
+ return ret;
+
+ /* XXX: blocking may be break by SIGKILL */
+ /*return down_killable(&log_stop_sema);*/
+ return wait_for_completion_killable(&log_stop_comp);
+}
+
+int ondiemet_parse_num(const char *str, unsigned int *value, int len)
+{
+ int ret;
+
+ if (len <= 0)
+ return -1;
+
+ if ((len > 2) &&
+ ((str[0] == '0') &&
+ ((str[1] == 'x') || (str[1] == 'X')))) {
+ ret = kstrtouint(str, 16, value);
+ } else {
+ ret = kstrtouint(str, 10, value);
+ }
+
+ if (ret != 0)
+ return -1;
+
+ return 0;
+}
+
+/* XXX: seq_file will output only when a page is filled */
+static ssize_t ondiemet_log_write_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *plog = NULL;
+
+ plog = kmalloc_array(count, sizeof(*plog), GFP_KERNEL);
+ if (!plog) {
+ /* TODO: use a better error code */
+ return -EINVAL;
+ }
+
+ memcpy(plog, buf, count);
+
+ mutex_lock(&dev->mutex);
+ ondiemet_log_req_enq(plog, strnlen(plog, count), kfree, plog);
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
+static DEVICE_ATTR(ondiemet_log_write, 0664, NULL, ondiemet_log_write_store);
+
+static ssize_t ondiemet_log_run_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int sz;
+
+ mutex_lock(&dev->mutex);
+ sz = snprintf(buf, PAGE_SIZE, "%d\n", ondiemet_trace_run);
+ mutex_unlock(&dev->mutex);
+ return sz;
+}
+
+static ssize_t ondiemet_log_run_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int ret;
+ int prev_run_state;
+
+ mutex_lock(&dev->mutex);
+
+ prev_run_state = ondiemet_trace_run;
+
+ if (kstrtoint(buf, 10, &ondiemet_trace_run) != 0)
+ return -EINVAL;
+
+ if (ondiemet_trace_run <= ONDIEMET_LOG_STOP_MODE) {
+ ondiemet_trace_run = ONDIEMET_LOG_STOP_MODE;
+ ondiemet_log_manager_stop();
+
+ if (prev_run_state == ONDIEMET_LOG_DEBUG_MODE)
+ device_remove_file(dev, &dev_attr_ondiemet_log_write);
+ } else if (ondiemet_trace_run == ONDIEMET_LOG_RUN_MODE) {
+ ondiemet_trace_run = ONDIEMET_LOG_RUN_MODE;
+ ondiemet_log_manager_start();
+
+ if (prev_run_state == ONDIEMET_LOG_DEBUG_MODE)
+ device_remove_file(dev, &dev_attr_ondiemet_log_write);
+ } else {
+ ondiemet_trace_run = ONDIEMET_LOG_DEBUG_MODE;
+ ondiemet_log_manager_start();
+
+ if (prev_run_state != ONDIEMET_LOG_DEBUG_MODE) {
+ ret = device_create_file(dev, &dev_attr_ondiemet_log_write);
+ if (ret != 0)
+ pr_debug("[met] can not create device node: ondiemet_log_write\n");
+ }
+ }
+
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
+static DEVICE_ATTR(ondiemet_log_run, 0660, ondiemet_log_run_show, ondiemet_log_run_store);
+
+int ondiemet_log_manager_init(struct device *dev)
+{
+ int ret;
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ struct dentry *d;
+#else
+ struct proc_dir_entry *d;
+#endif
+
+ mutex_init(&lock_tracef);
+
+ __ondiemet_log_req_q_init(&ondiemet_log_req_q);
+
+ /*sema_init(&log_start_sema, 0);*/
+ /*sema_init(&log_stop_sema, 0);*/
+ init_completion(&log_start_comp);
+ init_completion(&log_stop_comp);
+
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ dbgfs_met_dir = debugfs_create_dir("ondiemet", NULL);
+ if (!dbgfs_met_dir) {
+ PR_BOOTMSG("[met] can not create debugfs directory: ondiemet\n");
+ return -ENOMEM;
+ }
+#else
+ procfs_met_dir = proc_mkdir("ondiemet", NULL);
+ if (!procfs_met_dir) {
+ PR_BOOTMSG("[met] can not create proc directory: ondiemet\n");
+ return -ENOMEM;
+ }
+#endif
+
+ mutex_init(&lock_trace_owner_pid);
+
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ d = debugfs_create_file("trace", 0600, dbgfs_met_dir, NULL, &ondiemet_trace_fops);
+ if (!d) {
+ PR_BOOTMSG("[met] can not create devide node in debugfs: ondiemet_trace\n");
+ return -ENOMEM;
+ }
+#else
+ d = proc_create("trace", 0600, procfs_met_dir, &ondiemet_trace_fops);
+ if (!d) {
+ PR_BOOTMSG("[met] can not create devide node in procfs: ondiemet_trace\n");
+ return -ENOMEM;
+ }
+#endif
+
+ ondiemet_trace_run = __ondiemet_log_req_working();
+ ret = device_create_file(dev, &dev_attr_ondiemet_log_run);
+ if (ret != 0) {
+ pr_debug("[met] can not create device node: ondiemet_log_run\n");
+ return ret;
+ }
+
+ return 0;
+}
+
+int ondiemet_log_manager_uninit(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_ondiemet_log_run);
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ debugfs_remove_recursive(dbgfs_met_dir);
+#else
+ proc_remove(procfs_met_dir);
+#endif
+
+ return 0;
+}
diff --git a/src/devtools/met_drv_v2/common/ondiemet_log.h b/src/devtools/met_drv_v2/common/ondiemet_log.h
new file mode 100644
index 0000000..9d65b18
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/ondiemet_log.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _ONDIEMET_LOG_H_
+#define _ONDIEMET_LOG_H_
+
+#include <linux/device.h>
+
+int ondiemet_log_manager_init(struct device *dev);
+int ondiemet_log_manager_uninit(struct device *dev);
+int ondiemet_log_manager_start(void);
+/* Log manager can be reactivated by inserting new requests, i.e., calling ondiemet_log_req_enq() */
+int ondiemet_log_manager_stop(void);
+int ondiemet_log_req_enq(const char *src, size_t num, void (*on_fini_cb) (const void *p),
+ const void *param);
+
+#endif /* _ONDIEMET_LOG_H_ */
diff --git a/src/devtools/met_drv_v2/common/power.c b/src/devtools/met_drv_v2/common/power.c
new file mode 100644
index 0000000..0176a4d
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/power.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/cpufreq.h>
+#include <trace/events/power.h>
+
+#include "power.h"
+#include "met_drv.h"
+#include "met_kernel_symbol.h"
+
+noinline void cpu_frequency(unsigned int frequency, unsigned int cpu_id)
+{
+ if (met_export_api_symbol->met_cpu_frequency)
+ met_export_api_symbol->met_cpu_frequency(frequency, cpu_id);
+}
+
+void force_power_log(int cpu)
+{
+ struct cpufreq_policy *p;
+
+ if (cpu == POWER_LOG_ALL) {
+ for_each_possible_cpu(cpu) {
+ p = cpufreq_cpu_get(cpu);
+ if (p != NULL) {
+ cpu_frequency(p->cur, cpu);
+ cpufreq_cpu_put(p);
+ } else {
+ cpu_frequency(0, cpu);
+ }
+ }
+ } else {
+ p = cpufreq_cpu_get(cpu);
+ if (p != NULL) {
+ cpu_frequency(p->cur, cpu);
+ cpufreq_cpu_put(p);
+ } else {
+ cpu_frequency(0, cpu);
+ }
+ }
+}
+
+void force_power_log_val(unsigned int frequency, int cpu)
+{
+ cpu_frequency(frequency, cpu);
+}
diff --git a/src/devtools/met_drv_v2/common/power.h b/src/devtools/met_drv_v2/common/power.h
new file mode 100644
index 0000000..eceef6b
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/power.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _POWER_H_
+#define _POWER_H_
+
+#define POWER_LOG_ALL -1
+void force_power_log(int cpu);
+void force_power_log_val(unsigned int frequency, int cpu);
+
+#endif /* _POWER_H_ */
diff --git a/src/devtools/met_drv_v2/common/sampler.c b/src/devtools/met_drv_v2/common/sampler.c
new file mode 100644
index 0000000..a9fc9ff
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sampler.c
@@ -0,0 +1,718 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/sched/clock.h>
+#include <linux/kernel.h>
+#include <linux/cpuhotplug.h>
+#include <linux/cpu.h>
+#include <linux/sched.h>
+#include <linux/notifier.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#if 0 /* fix me later, no such file on current tree */
+#include <mach/mt_cpuxgpt.h>
+#endif
+#include <asm/arch_timer.h>
+
+#define MET_USER_EVENT_SUPPORT
+#include "interface.h"
+#include "sampler.h"
+#include "met_struct.h"
+#include "util.h"
+#include "switch.h"
+#include "trace.h"
+#include "met_drv.h"
+#include "met_tag.h" /* for tracing_mark_write */
+
+#include "cpu_pmu.h" /* for using kernel perf PMU driver */
+
+#include "met_kernel_symbol.h"
+
+#undef DEBUG_CPU_NOTIFY
+/* #define DEBUG_CPU_NOTIFY */
+#if defined(DEBUG_CPU_NOTIFY)
+#ifdef CONFIG_MET_MODULE
+#define dbg_met_tag_oneshot met_tag_oneshot_real
+#else
+#define dbg_met_tag_oneshot met_tag_oneshot
+#endif /* CONFIG_MET_MODULE */
+#else
+#define dbg_met_tag_oneshot(class_id, name, value) ({ 0; })
+#endif
+
+static int start;
+static unsigned int online_cpu_map;
+static int curr_polling_cpu;
+static int cpu_related_cnt;
+static int cpu_related_polling_hdlr_cnt;
+
+static int preferred_cpu_list[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+
+static int calc_preferred_polling_cpu(unsigned int cpu_map)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(preferred_cpu_list); i++) {
+ if (cpu_map & (1 << preferred_cpu_list[i]))
+ return preferred_cpu_list[i];
+ }
+
+ return -1;
+}
+
+static void wq_sync_buffer(struct work_struct *work)
+{
+ int cpu;
+ struct delayed_work *dw = container_of(work, struct delayed_work, work);
+ struct met_cpu_struct *met_cpu_ptr = container_of(dw, struct met_cpu_struct, dwork);
+
+ cpu = smp_processor_id();
+ if (met_cpu_ptr->cpu != cpu) {
+ /* panic("ERROR"); */
+ return;
+ }
+
+ /* sync_samples(cpu); */
+ /* don't re-add the work if we're shutting down */
+ if (met_cpu_ptr->work_enabled)
+ schedule_delayed_work(dw, DEFAULT_TIMER_EXPIRE);
+}
+
+static enum hrtimer_restart met_hrtimer_notify(struct hrtimer *hrtimer)
+{
+ int cpu;
+ int *count;
+ unsigned long long stamp;
+ struct met_cpu_struct *met_cpu_ptr = container_of(hrtimer, struct met_cpu_struct, hrtimer);
+ struct metdevice *c;
+#if defined(DEBUG_CPU_NOTIFY)
+ char msg[32];
+#endif
+
+ cpu = smp_processor_id();
+#if defined(DEBUG_CPU_NOTIFY)
+ {
+ char msg[32];
+
+ snprintf(msg, sizeof(msg), "met_hrtimer notify_%d", cpu);
+ dbg_met_tag_oneshot(0, msg, 1);
+ }
+#endif
+
+ if (met_cpu_ptr->cpu != cpu) {
+ /* panic("ERROR2"); */
+ dbg_met_tag_oneshot(0, msg, -3);
+ return HRTIMER_NORESTART;
+ }
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->ondiemet_mode == 0) {
+ if ((c->mode == 0) || (c->timed_polling == NULL))
+ continue;
+ } else if (c->ondiemet_mode == 1) {
+ if ((c->mode == 0) || (c->ondiemet_timed_polling == NULL))
+ continue;
+ } else if (c->ondiemet_mode == 2) {
+ if ((c->mode == 0) || ((c->timed_polling == NULL)
+ && (c->ondiemet_timed_polling == NULL)))
+ continue;
+ }
+
+ count = per_cpu_ptr(c->polling_count, cpu);
+ if ((*count) > 0) {
+ (*count)--;
+ continue;
+ }
+
+ *(count) = c->polling_count_reload;
+
+ stamp = cpu_clock(cpu);
+
+ if (c->cpu_related == 0) {
+ if (cpu == curr_polling_cpu) {
+ if (c->ondiemet_mode == 0) {
+ c->timed_polling(stamp, 0);
+ } else if (c->ondiemet_mode == 1) {
+ c->ondiemet_timed_polling(stamp, 0);
+ } else if (c->ondiemet_mode == 2) {
+ if (c->timed_polling)
+ c->timed_polling(stamp, 0);
+ if (c->ondiemet_timed_polling)
+ c->ondiemet_timed_polling(stamp, 0);
+ }
+ }
+ } else {
+ if (c->ondiemet_mode == 0) {
+ c->timed_polling(stamp, cpu);
+ } else if (c->ondiemet_mode == 1) {
+ c->ondiemet_timed_polling(stamp, cpu);
+ } else if (c->ondiemet_mode == 2) {
+ if (c->timed_polling)
+ c->timed_polling(stamp, 0);
+ if (c->ondiemet_timed_polling)
+ c->ondiemet_timed_polling(stamp, 0);
+ }
+ }
+ }
+
+ if (met_cpu_ptr->hrtimer_online_check) {
+ online_cpu_map |= (1 << cpu);
+ met_cpu_ptr->hrtimer_online_check = 0;
+ dbg_met_tag_oneshot(0, "met_online check done", cpu);
+ if (calc_preferred_polling_cpu(online_cpu_map) == cpu) {
+ curr_polling_cpu = cpu;
+ dbg_met_tag_oneshot(0, "met_curr polling cpu", cpu);
+ }
+ }
+
+ if (met_cpu_ptr->work_enabled) {
+ hrtimer_forward_now(hrtimer, ns_to_ktime(DEFAULT_HRTIMER_EXPIRE));
+ dbg_met_tag_oneshot(0, msg, 0);
+ return HRTIMER_RESTART;
+ }
+ dbg_met_tag_oneshot(0, msg, 0);
+ return HRTIMER_NORESTART;
+}
+
+static void __met_init_cpu_related_device(void *unused)
+{
+ struct metdevice *c;
+
+ list_for_each_entry(c, &met_list, list) {
+ *(this_cpu_ptr(c->polling_count)) = 0;
+ if (c->ondiemet_mode == 0) {
+ if ((c->cpu_related) && (c->mode) && (c->start))
+ c->start();
+ } else if (c->ondiemet_mode == 1) {
+ if (((c->cpu_related)) && (c->mode) && (c->ondiemet_start))
+ c->ondiemet_start();
+ } else if (c->ondiemet_mode == 2) {
+ if ((c->cpu_related) && (c->mode) && (c->start))
+ c->start();
+ if (((c->cpu_related)) && (c->mode) && (c->ondiemet_start))
+ c->ondiemet_start();
+ }
+ }
+}
+
+static void __met_hrtimer_register(void *unused)
+{
+ struct met_cpu_struct *met_cpu_ptr = NULL;
+ struct hrtimer *hrtimer = NULL;
+ /* struct delayed_work *dw; */
+ /*struct metdevice *c;*/
+
+ met_cpu_ptr = this_cpu_ptr(&met_cpu);
+#if defined(DEBUG_CPU_NOTIFY)
+ {
+ char msg[32];
+
+ snprintf(msg, sizeof(msg), "met_hrtimer status_%d", met_cpu_ptr->cpu);
+ dbg_met_tag_oneshot(0, msg, 1);
+ }
+#endif
+ /*
+ * do not open HRtimer when EVENT timer enable
+ */
+ if (!(met_switch.mode & MT_SWITCH_EVENT_TIMER)) {
+
+ hrtimer = &met_cpu_ptr->hrtimer;
+ hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ hrtimer->function = met_hrtimer_notify;
+
+ if (DEFAULT_HRTIMER_EXPIRE) {
+ met_cpu_ptr->work_enabled = 1;
+ /* schedule_delayed_work_on(smp_processor_id(), dw, DEFAULT_TIMER_EXPIRE); */
+ hrtimer_start(hrtimer, ns_to_ktime(DEFAULT_HRTIMER_EXPIRE),
+ HRTIMER_MODE_REL_PINNED);
+ }
+ }
+}
+
+static void __met_hrtimer_stop(void *unused)
+{
+ struct met_cpu_struct *met_cpu_ptr;
+ struct hrtimer *hrtimer;
+ /* struct delayed_work *dw; */
+ struct metdevice *c;
+
+ met_cpu_ptr = this_cpu_ptr(&met_cpu);
+#if defined(DEBUG_CPU_NOTIFY)
+ {
+ char msg[32];
+
+ snprintf(msg, sizeof(msg), "met_hrtimer status_%d", met_cpu_ptr->cpu);
+ dbg_met_tag_oneshot(0, msg, 0);
+ }
+#endif
+ /*
+ * do not open HRtimer when EVENT timer enable
+ */
+ if (!(met_switch.mode & MT_SWITCH_EVENT_TIMER)) {
+ hrtimer = &met_cpu_ptr->hrtimer;
+ /* dw = &met_cpu_ptr->dwork; */
+
+ met_cpu_ptr->work_enabled = 0;
+ hrtimer_cancel(hrtimer);
+
+ /* cancel_delayed_work_sync(dw); */
+ }
+ list_for_each_entry(c, &met_list, list) {
+ if (c->ondiemet_mode == 0) {
+ if ((c->cpu_related) && (c->mode) && (c->stop))
+ c->stop();
+ } else if (c->ondiemet_mode == 1) {
+ if ((c->cpu_related) && (c->mode) && (c->ondiemet_stop))
+ c->ondiemet_stop();
+ } else if (c->ondiemet_mode == 2) {
+ if ((c->cpu_related) && (c->mode) && (c->stop))
+ c->stop();
+ if ((c->cpu_related) && (c->mode) && (c->ondiemet_stop))
+ c->ondiemet_stop();
+ }
+ *(this_cpu_ptr(c->polling_count)) = 0;
+ }
+}
+
+static int met_pmu_cpu_notify(enum met_action action, unsigned int cpu)
+{
+ struct met_cpu_struct *met_cpu_ptr;
+ struct delayed_work *dw;
+ int preferred_polling_cpu;
+ struct metdevice *c;
+
+ if (start == 0)
+ return NOTIFY_OK;
+
+#if defined(DEBUG_CPU_NOTIFY)
+ {
+ char msg[32];
+
+ snprintf(msg, sizeof(msg), "met_cpu notify_%d", cpu);
+ dbg_met_tag_oneshot(0, msg, action);
+ }
+#elif defined(PR_CPU_NOTIFY)
+ {
+ char msg[32];
+
+ if (met_cpu_notify) {
+ snprintf(msg, sizeof(msg), "met_cpu notify_%d", cpu);
+ dbg_met_tag_oneshot(0, msg, action);
+ }
+ }
+#endif
+
+ if (cpu < 0 || cpu >= NR_CPUS)
+ return NOTIFY_OK;
+
+ switch (action) {
+ case MET_CPU_ONLINE:
+ met_cpu_ptr = &per_cpu(met_cpu, cpu);
+ met_cpu_ptr->hrtimer_online_check = 1;
+ dbg_met_tag_oneshot(0, "met_online check", cpu);
+
+ if (cpu_related_cnt == 0) {
+ /*pr_info("%s, %d: curr_polling_cpu is alive = %d\n",
+ * __func__, __LINE__, online_cpu_map & (1 << curr_polling_cpu));
+ */
+
+ online_cpu_map |= (1 << cpu);
+
+ /* check curr_polling_cpu is alive, if it is down,
+ * start current cpu hrtimer, and change it to be currr_pollling_cpu
+ */
+ if ((online_cpu_map & (1 << curr_polling_cpu)) == 0) {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_hrtimer_register, NULL, 1);
+ curr_polling_cpu = cpu;
+ }
+ } else {
+ if (cpu_related_polling_hdlr_cnt) {
+ if (met_export_api_symbol->met_smp_call_function_single) {
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_init_cpu_related_device, NULL, 1);
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_hrtimer_register, NULL, 1);
+ }
+ } else {
+ /*pr_info("%s, %d: curr_polling_cpu is alive = %d\n",
+ * __func__, __LINE__, online_cpu_map & (1 << curr_polling_cpu));
+ */
+
+ online_cpu_map |= (1 << cpu);
+
+ /* check curr_polling_cpu is alive, if it is down,
+ * start current cpu hrtimer, and change it to be currr_pollling_cpu
+ */
+ if ((online_cpu_map & (1 << curr_polling_cpu)) == 0) {
+ if (met_export_api_symbol->met_smp_call_function_single) {
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_init_cpu_related_device, NULL, 1);
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_hrtimer_register, NULL, 1);
+ }
+ curr_polling_cpu = cpu;
+ }
+ }
+ }
+
+#if IS_ENABLED(CONFIG_CPU_FREQ)
+ force_power_log(cpu);
+#endif
+ list_for_each_entry(c, &met_list, list) {
+ if (c->cpu_state_notify)
+ c->cpu_state_notify(cpu, action);
+ }
+ break;
+
+ case MET_CPU_OFFLINE:
+ list_for_each_entry(c, &met_list, list) {
+ if (c->cpu_state_notify)
+ c->cpu_state_notify(cpu, action);
+ }
+
+ online_cpu_map &= ~(1 << cpu);
+ dbg_met_tag_oneshot(0, "met_offline cpu", cpu);
+ if (cpu == curr_polling_cpu) {
+ /* pr_info("%s, %d: curr_polling_cpu %d is down\n",
+ * __func__, __LINE__, curr_polling_cpu);
+ */
+ preferred_polling_cpu = calc_preferred_polling_cpu(online_cpu_map);
+ /* pr_info("%s, %d: preferred_polling_cpu = %d\n",
+ * __func__, __LINE__, preferred_polling_cpu);
+ */
+ if (preferred_polling_cpu != -1) {
+ curr_polling_cpu = preferred_polling_cpu;
+ dbg_met_tag_oneshot(0, "met_curr polling cpu", curr_polling_cpu);
+
+ if (cpu_related_cnt == 0) {
+ /* pr_info("%s, %d: start cpu %d hrtimer start\n",
+ * __func__, __LINE__, curr_polling_cpu);
+ */
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(curr_polling_cpu,
+ __met_hrtimer_register, NULL, 1);
+ } else if (cpu_related_polling_hdlr_cnt == 0) {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(curr_polling_cpu,
+ __met_hrtimer_register, NULL, 1);
+ }
+ }
+ }
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_hrtimer_stop, NULL, 1);
+
+ met_cpu_ptr = &per_cpu(met_cpu, cpu);
+ dw = &met_cpu_ptr->dwork;
+ cancel_delayed_work_sync(dw);
+
+ /* sync_samples(cpu); */
+ break;
+ default:
+ list_for_each_entry(c, &met_list, list) {
+ if (c->cpu_state_notify)
+ c->cpu_state_notify(cpu, action);
+ }
+ }
+
+ return NOTIFY_OK;
+}
+
+static int _met_pmu_cpu_notify_online(unsigned int cpu)
+{
+ met_pmu_cpu_notify(MET_CPU_ONLINE, cpu);
+
+ return 0;
+}
+
+static int _met_pmu_cpu_notify_offline(unsigned int cpu)
+{
+ met_pmu_cpu_notify(MET_CPU_OFFLINE, cpu);
+
+ return 0;
+}
+
+int sampler_start(void)
+{
+ int ret, cpu;
+ struct met_cpu_struct *met_cpu_ptr;
+ struct metdevice *c;
+ int preferred_polling_cpu;
+
+ met_set_suspend_notify(0);
+
+#if IS_ENABLED(CONFIG_CPU_FREQ)
+ force_power_log(POWER_LOG_ALL);
+#endif
+
+ for_each_possible_cpu(cpu) {
+ met_cpu_ptr = &per_cpu(met_cpu, cpu);
+ met_cpu_ptr->work_enabled = 0;
+ met_cpu_ptr->hrtimer_online_check = 0;
+ hrtimer_init(&met_cpu_ptr->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ met_cpu_ptr->hrtimer.function = met_hrtimer_notify;
+ INIT_DELAYED_WORK(&met_cpu_ptr->dwork, wq_sync_buffer);
+ }
+
+ start = 0;
+ ret = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
+ "met:online",
+ _met_pmu_cpu_notify_online,
+ _met_pmu_cpu_notify_offline);
+
+ list_for_each_entry(c, &met_list, list) {
+
+ if (try_module_get(c->owner) == 0)
+ continue;
+
+ if ((c->mode) && (c->cpu_related == 1)) {
+ cpu_related_cnt = 1;
+
+ if (c->ondiemet_mode == 0) {
+ if (c->timed_polling)
+ cpu_related_polling_hdlr_cnt = 1;
+ } else if (c->ondiemet_mode == 1) {
+ if (c->ondiemet_timed_polling)
+ cpu_related_polling_hdlr_cnt = 1;
+ } else if (c->ondiemet_mode == 2) {
+ if (c->timed_polling || c->ondiemet_timed_polling)
+ cpu_related_polling_hdlr_cnt = 1;
+ }
+ }
+
+ if (c->ondiemet_mode == 0) {
+ if ((!(c->cpu_related)) && (c->mode) && (c->start))
+ c->start();
+ else if ((c->cpu_related) && (c->mode) && (c->uniq_start))
+ c->uniq_start();
+ } else if (c->ondiemet_mode == 1) {
+ if ((!(c->cpu_related)) && (c->mode) && (c->ondiemet_start))
+ c->ondiemet_start();
+ if ((c->cpu_related) && (c->mode) && (c->uniq_ondiemet_start))
+ c->uniq_ondiemet_start();
+ } else if (c->ondiemet_mode == 2) {
+ if ((!(c->cpu_related)) && (c->mode) && (c->start))
+ c->start();
+ else if ((c->cpu_related) && (c->mode) && (c->uniq_start))
+ c->uniq_start();
+
+ if ((!(c->cpu_related)) && (c->mode) && (c->ondiemet_start))
+ c->ondiemet_start();
+ else if ((c->cpu_related) && (c->mode) && (c->uniq_ondiemet_start))
+ c->uniq_ondiemet_start();
+ }
+ }
+
+ get_online_cpus();
+ online_cpu_map = 0;
+ for_each_online_cpu(cpu) {
+ online_cpu_map |= (1 << cpu);
+ }
+ dbg_met_tag_oneshot(0, "met_online cpu map", online_cpu_map);
+ preferred_polling_cpu = calc_preferred_polling_cpu(online_cpu_map);
+ if (preferred_polling_cpu != -1)
+ curr_polling_cpu = preferred_polling_cpu;
+ dbg_met_tag_oneshot(0, "met_curr polling cpu", curr_polling_cpu);
+ start = 1;
+
+ if (cpu_related_cnt == 0) {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(curr_polling_cpu,
+ __met_hrtimer_register, NULL, 1);
+ }
+ else {
+ //on_each_cpu(__met_hrtimer_start, NULL, 1);
+ for_each_online_cpu(cpu) {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_init_cpu_related_device, NULL, 1);
+ }
+
+ if (cpu_related_polling_hdlr_cnt) {
+ for_each_online_cpu(cpu) {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_hrtimer_register, NULL, 1);
+ }
+ } else {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(curr_polling_cpu,
+ __met_hrtimer_register, NULL, 1);
+ }
+ }
+ put_online_cpus();
+
+ return ret;
+}
+
+void sampler_stop(void)
+{
+ int cpu;
+ struct met_cpu_struct *met_cpu_ptr;
+ struct metdevice *c;
+ struct delayed_work *dw;
+
+
+ get_online_cpus();
+ //on_each_cpu(__met_hrtimer_stop, NULL, 1);
+ online_cpu_map = 0;
+ for_each_online_cpu(cpu) {
+ online_cpu_map |= (1 << cpu);
+ }
+
+ for_each_online_cpu(cpu) {
+ if (met_export_api_symbol->met_smp_call_function_single)
+ met_export_api_symbol->met_smp_call_function_single(cpu,
+ __met_hrtimer_stop, NULL, 1);
+ }
+
+ /* for_each_online_cpu(cpu) { */
+ for_each_possible_cpu(cpu) { /* Just for case */
+ met_cpu_ptr = &per_cpu(met_cpu, cpu);
+ dw = &met_cpu_ptr->dwork;
+ cancel_delayed_work_sync(dw);
+ /* sync_samples(cpu); */
+ }
+ start = 0;
+ put_online_cpus();
+
+ cpuhp_remove_state_nocalls(CPUHP_AP_ONLINE_DYN);
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->ondiemet_mode == 0) {
+ if ((!(c->cpu_related)) && (c->mode) && (c->stop))
+ c->stop();
+ else if ((c->cpu_related) && (c->mode) && (c->uniq_stop))
+ c->uniq_stop();
+ } else if (c->ondiemet_mode == 1) {
+ if ((!(c->cpu_related)) && (c->mode) && (c->ondiemet_stop))
+ c->ondiemet_stop();
+ else if ((c->cpu_related) && (c->mode) && (c->uniq_ondiemet_stop))
+ c->uniq_ondiemet_stop();
+ } else if (c->ondiemet_mode == 2) {
+ if ((!(c->cpu_related)) && (c->mode) && (c->stop))
+ c->stop();
+ else if ((c->cpu_related) && (c->mode) && (c->uniq_stop))
+ c->uniq_stop();
+
+ if ((!(c->cpu_related)) && (c->mode) && (c->ondiemet_stop))
+ c->ondiemet_stop();
+ else if ((c->cpu_related) && (c->mode) && (c->uniq_ondiemet_stop))
+ c->uniq_ondiemet_stop();
+ }
+ module_put(c->owner);
+ }
+
+ cpu_related_cnt = 0;
+ cpu_related_polling_hdlr_cnt = 0;
+}
+
+#if 0 /* cann't use static now */
+enum {
+ MET_SUSPEND = 1,
+ MET_RESUME = 2,
+};
+
+static noinline void tracing_mark_write(int op)
+{
+ switch (op) {
+ case MET_SUSPEND:
+ MET_TRACE("C|0|MET_SUSPEND|1");
+ break;
+ case MET_RESUME:
+ MET_TRACE("C|0|MET_SUSPEND|0");
+ break;
+ }
+}
+#endif
+
+int met_hrtimer_suspend(void)
+{
+ struct metdevice *c;
+
+ met_set_suspend_notify(1);
+ /* tracing_mark_write(MET_SUSPEND); */
+ tracing_mark_write(TYPE_MET_SUSPEND, 0, 0, 0, 0, 0);
+ if (start == 0)
+ return 0;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->suspend)
+ c->suspend();
+ }
+
+ /* get current COUNT */
+ MET_TRACE("TS: %llu GPT: %llX", sched_clock(), arch_counter_get_cntvct());
+ return 0;
+}
+
+void met_hrtimer_resume(void)
+{
+ struct metdevice *c;
+
+ /* get current COUNT */
+ MET_TRACE("TS: %llu GPT: %llX", sched_clock(), arch_counter_get_cntvct());
+
+ /* tracing_mark_write(MET_RESUME); */
+ tracing_mark_write(TYPE_MET_RESUME, 0, 0, 0, 0, 0);
+ if (start == 0)
+ return;
+
+ list_for_each_entry(c, &met_list, list) {
+ if (c->resume)
+ c->resume();
+ }
+}
+
+/*
+ * event timer:
+ * register IRQ, sched_switch event to monitor Polling count
+ * count can be printed at any live cpu.
+ */
+void met_event_timer_notify(void)
+{
+ unsigned long long stamp;
+ struct metdevice *c;
+ int cpu = -1;
+
+ if (start == 0)
+ return;
+
+ cpu = smp_processor_id();
+ list_for_each_entry(c, &met_list, list) {
+ stamp = local_clock();
+
+ if (c->prev_stamp == 0)
+ c->prev_stamp = stamp;
+
+ /* Critical Section Start */
+ /* try spinlock to prevent a event print twice between config time interval */
+ if (!spin_trylock(&(c->my_lock)))
+ continue;
+
+ /*
+ * DEFAULT_HRTIMER_EXPIRE (met_hrtimer_expire):
+ * sample_rate == 0 --> always print
+ * sample_rate == 1000 --> print interval larger than 1 ms
+ */
+ if (DEFAULT_HRTIMER_EXPIRE == 0 || (stamp - c->prev_stamp) < DEFAULT_HRTIMER_EXPIRE) {
+ spin_unlock(&(c->my_lock));
+ continue;
+ }
+
+ c->prev_stamp = stamp;
+ spin_unlock(&(c->my_lock));
+ /* Critical Section End */
+
+ if ((c->mode == 0) || (c->timed_polling == NULL))
+ continue;
+
+ stamp = local_clock();
+ c->timed_polling(stamp, cpu);
+ }
+}
+
diff --git a/src/devtools/met_drv_v2/common/sampler.h b/src/devtools/met_drv_v2/common/sampler.h
new file mode 100644
index 0000000..131203e
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sampler.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _SAMPLER_H_
+#define _SAMPLER_H_
+
+/*
+ * sampling rate: 1ms
+ * log generating rate: 10ms
+ */
+#if 0
+#define DEFAULT_TIMER_EXPIRE (HZ / 100)
+#define DEFAULT_HRTIMER_EXPIRE (TICK_NSEC / 10)
+#else
+extern int met_timer_expire; /* in jiffies */
+extern int met_hrtimer_expire; /* in us */
+#define DEFAULT_TIMER_EXPIRE (met_timer_expire)
+#define DEFAULT_HRTIMER_EXPIRE (met_hrtimer_expire)
+#endif
+/*
+ * sampling rate: 10ms
+ * log generating rate: 100ms
+ */
+/* #define DEFAULT_TIMER_EXPIRE (HZ / 10) */
+/* #define DEFAULT_HRTIMER_EXPIRE (TICK_NSEC / 1) */
+
+int met_hrtimer_start(void);
+void met_hrtimer_stop(void);
+int sampler_start(void);
+void sampler_stop(void);
+
+extern struct list_head met_list;
+extern void add_cookie(struct pt_regs *regs, int cpu);
+extern int met_hrtimer_suspend(void);
+extern void met_hrtimer_resume(void);
+extern void met_event_timer_notify(void);
+
+#if IS_ENABLED(CONFIG_CPU_FREQ)
+#include "power.h"
+#endif
+
+#endif /* _SAMPLER_H_ */
diff --git a/src/devtools/met_drv_v2/common/spmtwam/ap/met_spmtwam.c b/src/devtools/met_drv_v2/common/spmtwam/ap/met_spmtwam.c
new file mode 100644
index 0000000..ba6a8e6
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/spmtwam/ap/met_spmtwam.c
@@ -0,0 +1,682 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/fs.h>
+#include <linux/ctype.h>
+
+#include <mtk_spm.h>
+#include "met_drv.h"
+#include "trace.h"
+#include "core_plf_init.h"
+#include "interface.h"
+#include "met_spmtwam.h"
+
+/* #define SPM_TWAM_DEBUG */
+
+#define INFRA_FMEM_DCM_BASE 0x1020E000
+#define INFRA_FMEM_DCM_SIZE 0x1000
+#define FMEM_MUX_ADDR_OFFSET 0x200
+#define FMEM_MUX_VALUE 0x780
+#define TWAM_DBG_SIG_BASE 0x0D0A0000
+#define TWAM_DBG_SIG_SIZE 0x100
+#define TWAM_DBG_SIG_OFFSET 0x94
+
+
+struct metdevice met_spmtwam;
+static struct kobject *kobj_spmtwam;
+/* static void __iomem *fmem_dcm_base; */
+static void __iomem *twam_dbg_signal_base;
+static struct met_spmtwam_para spmtwam_para[MAX_EVENT_COUNT];
+
+#ifdef SPM_TWAM_DEBUG
+static unsigned int debug_signal_val;
+#endif
+
+static struct twam_sig twamsig;
+static struct twam_sig montype; /* b'00: rising, b'01: falling, b'10: high, b'11: low */
+static struct twam_sig dbgout;
+static int used_count;
+static int start;
+static bool twam_clock_mode = TWAM_SPEED_MODE; /* true:speed mode, false:normal mode */
+static unsigned int window_len = 1300000; /* 50 ms in 26 MHz */
+static unsigned int idle_sel;
+
+#define MONTYPE_SHOW_IMPLEMENT(num) \
+ do { \
+ int i; \
+ i = snprintf(buf, PAGE_SIZE, "%d\n", montype.sig ## num); \
+ return i; \
+ } while (0)
+
+#define MONTYPE_STORE_IMPLEMENT(num) \
+ do { \
+ int value; \
+ if ((n == 0) || (buf == NULL)) \
+ return -EINVAL; \
+ if (kstrtoint(buf, 10, &value) != 0) \
+ return -EINVAL; \
+ if (value < 0 || value > 3) \
+ return -EINVAL; \
+ montype.sig ## num= value; \
+ return n; \
+ } while (0)
+
+#define DBGOUT_SHOW_IMPLEMENT(num) \
+ do { \
+ int i; \
+ i = snprintf(buf, PAGE_SIZE, "%d\n", dbgout.sig ## num); \
+ return i; \
+ } while (0)
+
+#define DBGOUT_STORE_IMPLEMENT(num) \
+ do { \
+ int value; \
+ if ((n == 0) || (buf == NULL)) \
+ return -EINVAL; \
+ if (kstrtoint(buf, 10, &value) != 0) \
+ return -EINVAL; \
+ if (value < 0 || value > 127) \
+ return -EINVAL; \
+ dbgout.sig ## num = value; \
+ return n; \
+ } while (0)
+
+
+static ssize_t montype0_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(0);
+}
+
+static ssize_t montype0_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(0);
+}
+
+static ssize_t montype1_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(1);
+}
+
+static ssize_t montype1_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(1);
+}
+
+static ssize_t montype2_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(2);
+}
+
+static ssize_t montype2_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(2);
+}
+
+static ssize_t montype3_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(3);
+}
+
+static ssize_t montype3_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(3);
+}
+
+static ssize_t window_len_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int i;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", window_len);
+
+ return i;
+}
+
+static ssize_t window_len_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 10, &value) != 0)
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+ window_len = value;
+
+ return n;
+}
+
+static ssize_t dbgout0_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ DBGOUT_SHOW_IMPLEMENT(0);
+}
+
+static ssize_t dbgout0_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ DBGOUT_STORE_IMPLEMENT(0);
+}
+
+static ssize_t dbgout1_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ DBGOUT_SHOW_IMPLEMENT(1);
+}
+
+static ssize_t dbgout1_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ DBGOUT_STORE_IMPLEMENT(1);
+}
+
+static ssize_t dbgout2_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ DBGOUT_SHOW_IMPLEMENT(2);
+}
+
+static ssize_t dbgout2_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ DBGOUT_STORE_IMPLEMENT(2);
+}
+
+static ssize_t dbgout3_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ DBGOUT_SHOW_IMPLEMENT(3);
+}
+
+static ssize_t dbgout3_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ DBGOUT_STORE_IMPLEMENT(3);
+}
+
+#ifdef SPM_TWAM_DEBUG
+/* extern void *mt_spm_base_get(void); */
+static ssize_t debug_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int ret;
+
+ ret = snprintf(buf, PAGE_SIZE, "0x%x\n", debug_signal_val);
+ ret += snprintf(buf+ret, PAGE_SIZE-ret, "%d, %d, %d, %d\n",
+ twam_sig_size[0], twam_sig_size[1], twam_sig_size[2], twam_sig_size[3]);
+/* ret += snprintf(buf+ret, PAGE_SIZE-ret, "spm_base_addr: %p\n", mt_spm_base_get()); */
+
+ return ret;
+}
+static struct kobj_attribute debug_attr = __ATTR_RO(debug);
+#endif
+
+static struct kobj_attribute montype0_attr = __ATTR(montype0, 0664, montype0_show, montype0_store);
+static struct kobj_attribute montype1_attr = __ATTR(montype1, 0664, montype1_show, montype1_store);
+static struct kobj_attribute montype2_attr = __ATTR(montype2, 0664, montype2_show, montype2_store);
+static struct kobj_attribute montype3_attr = __ATTR(montype3, 0664, montype3_show, montype3_store);
+static struct kobj_attribute window_len_attr = __ATTR(window_len, 0664, window_len_show, window_len_store);
+static struct kobj_attribute dbgout0_attr = __ATTR(dbgout0, 0664, dbgout0_show, dbgout0_store);
+static struct kobj_attribute dbgout1_attr = __ATTR(dbgout1, 0664, dbgout1_show, dbgout1_store);
+static struct kobj_attribute dbgout2_attr = __ATTR(dbgout2, 0664, dbgout2_show, dbgout2_store);
+static struct kobj_attribute dbgout3_attr = __ATTR(dbgout3, 0664, dbgout3_show, dbgout3_store);
+
+
+/* create spmtwam related kobj node */
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(montype0); \
+ KOBJ_ATTR_ITEM(montype1); \
+ KOBJ_ATTR_ITEM(montype2); \
+ KOBJ_ATTR_ITEM(montype3); \
+ KOBJ_ATTR_ITEM(window_len); \
+ KOBJ_ATTR_ITEM(dbgout0); \
+ KOBJ_ATTR_ITEM(dbgout1); \
+ KOBJ_ATTR_ITEM(dbgout2); \
+ KOBJ_ATTR_ITEM(dbgout3); \
+ } while (0)
+
+static int met_spmtwam_create(struct kobject *parent)
+{
+ int ret = 0;
+
+ kobj_spmtwam = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+ do { \
+ ret = sysfs_create_file(kobj_spmtwam, &attr_name ## _attr.attr); \
+ if (ret != 0) { \
+ pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+ } while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+#ifdef SPM_TWAM_DEBUG
+ ret = sysfs_create_file(kobj_spmtwam, &debug_attr.attr);
+ if (ret != 0) {
+ pr_debug("Failed to create debug in sysfs\n");
+ return ret;
+ }
+#endif
+
+ /* init. */
+ montype.sig0 = 0x2;
+ montype.sig1 = 0x2;
+ montype.sig2 = 0x2;
+ montype.sig3 = 0x2;
+
+#if 0
+ dbgout.sig0 = 87;
+ dbgout.sig1 = 89;
+ dbgout.sig2 = 91;
+ dbgout.sig3 = 106;
+#endif
+
+ return ret;
+}
+
+static void met_spmtwam_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_spmtwam, &attr_name ## _attr.attr)
+
+ if (kobj_spmtwam != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_spmtwam = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+
+#ifdef SPM_TWAM_DEBUG
+ sysfs_remove_file(kobj_spmtwam, &debug_attr.attr);
+#endif
+}
+
+void ms_spmtwam(struct twam_sig *ts)
+{
+ switch (used_count) {
+ case 1:
+ MET_TRACE(MP_FMT1,
+ (ts->sig0));
+ break;
+ case 2:
+ MET_TRACE(MP_FMT2,
+ (ts->sig0),
+ (ts->sig1));
+ break;
+ case 3:
+ MET_TRACE(MP_FMT3,
+ (ts->sig0),
+ (ts->sig1),
+ (ts->sig2));
+ break;
+ case 4:
+ MET_TRACE(MP_FMT4,
+ (ts->sig0),
+ (ts->sig1),
+ (ts->sig2),
+ (ts->sig3));
+ break;
+ default:
+ MET_SPMTWAM_ERR("No assign profile event\n");
+ break;
+ }
+}
+
+static int reset_driver_stat(void)
+{
+ met_spmtwam.mode = 0;
+ used_count = 0;
+ start = 0;
+ return 0;
+}
+
+void spm_twam_enable_debug_out(struct twam_sig *sig, void *addr)
+{
+ int value = 0;
+
+ value |= ((1 << 31) | (sig->sig3 << 24) | (sig->sig2 << 16) | (sig->sig1 << 8) | (sig->sig0 << 0));
+
+#ifdef SPM_TWAM_DEBUG
+ debug_signal_val = value;
+#endif
+
+ writel(value, addr);
+}
+
+void spm_twam_disable_debug_out(void *addr)
+{
+ unsigned int value = 0;
+
+ value = readl(addr);
+ value &= (((unsigned int)(1 << 31)) - 1);
+
+#ifdef SPM_TWAM_DEBUG
+ debug_signal_val = value;
+#endif
+
+ writel(value, addr);
+}
+
+/*
+ * Called from "met-cmd --start"
+ */
+static void spmtwam_start(void)
+{
+ if (idle_sel == 3) {
+#if 0
+ /* swithc idle signal D id0 pimux to fmem */
+ if (fmem_dcm_base == NULL) {
+ fmem_dcm_base = ioremap_nocache(INFRA_FMEM_DCM_BASE, INFRA_FMEM_DCM_SIZE);
+ if (!fmem_dcm_base) {
+ pr_debug("fmem_dcm_base ioremap fail...");
+ return;
+ }
+
+ writel(FMEM_MUX_VALUE, (fmem_dcm_base + FMEM_MUX_ADDR_OFFSET));
+ }
+#endif
+ } else if (idle_sel == 2) {
+ /* debug signal mapping */
+ if (twam_dbg_signal_base == NULL) {
+ twam_dbg_signal_base = ioremap_nocache(TWAM_DBG_SIG_BASE, TWAM_DBG_SIG_SIZE);
+ if (!twam_dbg_signal_base) {
+ pr_debug("twam_dbg_signal_base ioremap fail...");
+ return;
+ }
+ }
+
+ spm_twam_enable_debug_out(&dbgout, (twam_dbg_signal_base + TWAM_DBG_SIG_OFFSET));
+ }
+
+ if (spm_twam_set_mon_type_symbol)
+ spm_twam_set_mon_type_symbol(&montype);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_set_mon_type_symbol is NULL\n");
+ return;
+ }
+
+ if (spm_twam_set_window_length_symbol)
+ spm_twam_set_window_length_symbol(window_len);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_set_window_length_symbol is NULL\n");
+ return;
+ }
+
+ if (spm_twam_set_idle_select_symbol)
+ spm_twam_set_idle_select_symbol(idle_sel);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_set_idle_select_symbol is NULL\n");
+ return;
+ }
+
+ if (spm_twam_register_handler_symbol)
+ spm_twam_register_handler_symbol(ms_spmtwam);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_register_handler_symbol is NULL\n");
+ return;
+ }
+
+ if (spm_twam_enable_monitor_symbol)
+ spm_twam_enable_monitor_symbol(&twamsig, twam_clock_mode);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_enable_monitor_symbol is NULL\n");
+ return;
+ }
+
+ start = 1;
+}
+
+/*
+ * Called from "met-cmd --stop"
+ */
+static void spmtwam_stop(void)
+{
+ if (idle_sel == 3) {
+#if 0
+ if (fmem_dcm_base)
+ iounmap(fmem_dcm_base);
+#endif
+ } else if (idle_sel == 2) {
+ spm_twam_disable_debug_out(twam_dbg_signal_base + TWAM_DBG_SIG_OFFSET);
+
+ if (twam_dbg_signal_base) {
+ iounmap(twam_dbg_signal_base);
+ twam_dbg_signal_base = NULL;
+ }
+ }
+
+ if (spm_twam_register_handler_symbol)
+ spm_twam_register_handler_symbol(NULL);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_register_handler_symbol is NULL\n");
+ return;
+ }
+
+ if (spm_twam_disable_monitor_symbol)
+ spm_twam_disable_monitor_symbol();
+ else {
+ MET_SPMTWAM_ERR("spm_twam_disable_monitor_symbol is NULL\n");
+ return;
+ }
+}
+
+static const char header[] = "met-info [000] 0.0: ms_spmtwam_header: ";
+
+/*
+ * It will be called back when run "met-cmd --extract" and mode is 1
+ */
+static int spmtwam_print_header(char *buf, int len)
+{
+ int i, total_size;
+ char idle_sig;
+ unsigned int event;
+
+ total_size = snprintf(buf, PAGE_SIZE, header);
+
+ for (i = 0; i < used_count; i++) {
+ idle_sig = spmtwam_para[i].idle_sig;
+ event = spmtwam_para[i].event;
+
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size,
+ "signal_%c_%02u,", idle_sig, event);
+ }
+
+ /* cut the last comma */
+ buf[total_size - 1] = '\n';
+
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size, "met-info [000] 0.0: spmtwam_clock_mode: %s\n",
+ twam_clock_mode == TWAM_SPEED_MODE ? "speed" : "normal");
+
+#ifdef SPMTWAM_SINGLE_IDLE_SIGNAL
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size, "met-info [000] 0.0: spmtwam_idle_signal_support: %s\n",
+ TWAM_SINGLE_IDLE_SIGNAL);
+#endif
+
+#ifdef SPMTWAM_MULTIPLE_IDLE_SIGNAL
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size, "met-info [000] 0.0: spmtwam_idle_signal_support: %s\n",
+ TWAM_MULTIPLE_IDLE_SIGNAL);
+#endif
+
+ reset_driver_stat();
+ return total_size;
+}
+
+static int assign_slot(char idle_sig, unsigned int event)
+{
+ int i;
+ int sig2int;
+
+ if (used_count == MAX_EVENT_COUNT) {
+ PR_BOOTMSG("%s exceed max used event count\n", MET_SPMTWAM_TAG);
+ return -1;
+ }
+
+ /* check duplicated */
+ for (i = 0; i < used_count; i++) {
+ if ((spmtwam_para[i].idle_sig == idle_sig) &&
+ (spmtwam_para[i].event == event)) {
+ PR_BOOTMSG("%s input duplicated event %u\n", MET_SPMTWAM_TAG, event);
+ return -2;
+ }
+ }
+
+ /* check idle_sig range in a~d or A~D */
+ if (tolower(idle_sig) < 'a' || tolower(idle_sig) > 'd') {
+ PR_BOOTMSG("%s input idle signal %c is not in a~d range\n",
+ MET_SPMTWAM_TAG, idle_sig);
+ return -3;
+ }
+
+ /* check event no */
+ if (event > MAX_TWAM_EVENT_COUNT) {
+ PR_BOOTMSG("%s input event %u exceed max twam event %u\n",
+ MET_SPMTWAM_TAG, event, MAX_TWAM_EVENT_COUNT);
+ return -4;
+ }
+
+#ifdef SPMTWAM_SINGLE_IDLE_SIGNAL
+ if (used_count > 0) {
+ for (i = 0; i < used_count; i++) {
+ if (idle_sig != spmtwam_para[i].idle_sig) {
+ PR_BOOTMSG("%s %c idle signal is defferent previous, only support one idle signal\n",
+ MET_SPMTWAM_TAG, idle_sig);
+ return -5;
+ }
+ }
+ }
+#endif
+
+ spmtwam_para[used_count].idle_sig = idle_sig;
+ spmtwam_para[used_count].event = event;
+
+ sig2int = (int) (tolower(idle_sig) - 'a');
+#ifdef SPMTWAM_SINGLE_IDLE_SIGNAL
+ idle_sel = sig2int;
+#endif
+
+ switch (used_count) {
+ case 0:
+ twamsig.sig0 = event;
+ break;
+ case 1:
+ twamsig.sig1 = event;
+ break;
+ case 2:
+ twamsig.sig2 = event;
+ break;
+ case 3:
+ twamsig.sig3 = event;
+ break;
+ }
+
+ used_count++;
+
+ return 0;
+}
+
+static char help[] =
+ " --spmtwam=clock:[speed|normal] default is normal\n"
+ " normal mode monitors 4 channels\n"
+ " speed mode monitors 4 channels\n"
+ " --spmtwam=signal:selx\n"
+ " signal= a ~ d for idle signal A~D select\n"
+ " selx= 0 ~ 31 for for channel event\n";
+
+/*
+ * Called from "met-cmd --help"
+ */
+static int spmtwam_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static int spmtwam_process_argument(const char *arg, int len)
+{
+ if (start == 1)
+ reset_driver_stat();
+
+ if (strncmp(arg, "clock:", 6) == 0) {
+ if (strncmp(&(arg[6]), "speed", 5) == 0) {
+ twam_clock_mode = TWAM_SPEED_MODE;
+ } else if (strncmp(&(arg[6]), "normal", 6) == 0) {
+ twam_clock_mode = TWAM_NORMAL_MODE;
+ } else {
+ PR_BOOTMSG("%s unknown clock mode\n", MET_SPMTWAM_TAG);
+
+ goto error;
+ }
+ } else {
+ char signal;
+ int event;
+ int ret;
+
+ if (len < 3) {
+ PR_BOOTMSG("%s input parameter is too short !!!\n", MET_SPMTWAM_TAG);
+ goto error;
+ }
+
+ /*
+ * parse arguments
+ */
+ ret = sscanf(arg, "%c:%u", &signal, &event);
+ if (ret < 2) {
+ PR_BOOTMSG("%s input parameter is wrong format !!!\n", MET_SPMTWAM_TAG);
+ goto error;
+ }
+
+ if (assign_slot(signal, event) < 0) {
+ goto error;
+ }
+ }
+
+ met_spmtwam.mode = 1;
+ return 0;
+
+error:
+ reset_driver_stat();
+ return -1;
+}
+
+struct metdevice met_spmtwam = {
+ .name = "spmtwam",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_spmtwam_create,
+ .delete_subfs = met_spmtwam_delete,
+ .cpu_related = 0,
+ .start = spmtwam_start,
+ .stop = spmtwam_stop,
+ .reset = reset_driver_stat,
+ .print_help = spmtwam_print_help,
+ .print_header = spmtwam_print_header,
+ .process_argument = spmtwam_process_argument
+};
+EXPORT_SYMBOL(met_spmtwam);
diff --git a/src/devtools/met_drv_v2/common/spmtwam/include/met_spmtwam.h b/src/devtools/met_drv_v2/common/spmtwam/include/met_spmtwam.h
new file mode 100644
index 0000000..def575a
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/spmtwam/include/met_spmtwam.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MET_SPMTWAM_H__
+#define __MET_SPMTWAM_H__
+
+#define MET_SPMTWAM_TAG "[met_spmtwam]"
+#define MET_SPMTWAM_ERR(format, ...) \
+ do { \
+ MET_TRACE(MET_SPMTWAM_TAG format, ##__VA_ARGS__); \
+ PR_BOOTMSG(MET_SPMTWAM_TAG format, ##__VA_ARGS__); \
+ } while (0)
+
+#define TWAM_ENABLE true
+#define TWAM_DISABLE false
+#define TWAM_SPEED_MODE true
+#define TWAM_NORMAL_MODE false
+#define TWAM_DEBUG_SIG_ENABLE 1
+#define TWAM_DEBUG_SIG_DISABLE 0
+#define TWAM_SINGLE_IDLE_SIGNAL "single"
+#define TWAM_MULTIPLE_IDLE_SIGNAL "multiple"
+
+struct met_spmtwam_para {
+ char idle_sig;
+ int event;
+};
+
+
+/* event counters by HW spec */
+#define MAX_EVENT_COUNT 4
+#define MAX_TWAM_EVENT_COUNT 32
+
+#endif
diff --git a/src/devtools/met_drv_v2/common/spmtwam/sspm/met_spmtwam.c b/src/devtools/met_drv_v2/common/spmtwam/sspm/met_spmtwam.c
new file mode 100644
index 0000000..bfe8d12
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/spmtwam/sspm/met_spmtwam.c
@@ -0,0 +1,469 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/fs.h>
+#include <linux/ctype.h>
+
+#include <mtk_spm.h>
+#include "met_drv.h"
+#include "trace.h"
+#include "core_plf_init.h"
+#include "interface.h"
+#include "met_spmtwam.h"
+
+
+struct metdevice met_spmtwam;
+static struct kobject *kobj_spmtwam;
+
+static struct twam_cfg twam_config;
+static struct met_spmtwam_para spmtwam_para[MAX_EVENT_COUNT];
+
+static unsigned int twam_dbg_enable = TWAM_DEBUG_SIG_DISABLE;
+static bool twam_clock_mode = TWAM_SPEED_MODE; /* true:speed mode, false:normal mode */
+static unsigned int window_len = 1300000; /* 50 ms in 26 MHz */
+
+static int used_count;
+static int start;
+
+
+#define MONTYPE_SHOW_IMPLEMENT(cfg) \
+ do { \
+ int i; \
+ i = snprintf(buf, PAGE_SIZE, "%d\n", cfg.monitor_type); \
+ return i; \
+ } while (0)
+
+#define MONTYPE_STORE_IMPLEMENT(cfg) \
+ do { \
+ int value; \
+ if ((n == 0) || (buf == NULL)) \
+ return -EINVAL; \
+ if (kstrtoint(buf, 10, &value) != 0) \
+ return -EINVAL; \
+ if (value < 0 || value > 3) \
+ return -EINVAL; \
+ cfg.monitor_type = value; \
+ return n; \
+ } while (0)
+
+static ssize_t montype0_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(twam_config.byte[0]);
+}
+
+static ssize_t montype0_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(twam_config.byte[0]);
+}
+
+static ssize_t montype1_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(twam_config.byte[1]);
+}
+
+static ssize_t montype1_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(twam_config.byte[1]);
+}
+
+static ssize_t montype2_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(twam_config.byte[2]);
+}
+
+static ssize_t montype2_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(twam_config.byte[2]);
+}
+
+static ssize_t montype3_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ MONTYPE_SHOW_IMPLEMENT(twam_config.byte[3]);
+}
+
+static ssize_t montype3_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ MONTYPE_STORE_IMPLEMENT(twam_config.byte[3]);
+}
+
+static ssize_t window_len_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ int i;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", window_len);
+
+ return i;
+}
+
+static ssize_t window_len_store(struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t n)
+{
+ int value;
+
+ if ((n == 0) || (buf == NULL))
+ return -EINVAL;
+
+ if (kstrtoint(buf, 10, &value) != 0)
+ return -EINVAL;
+
+ if (value < 0)
+ return -EINVAL;
+
+ window_len = value;
+
+ return n;
+}
+
+static struct kobj_attribute montype0_attr = __ATTR(montype0, 0664, montype0_show, montype0_store);
+static struct kobj_attribute montype1_attr = __ATTR(montype1, 0664, montype1_show, montype1_store);
+static struct kobj_attribute montype2_attr = __ATTR(montype2, 0664, montype2_show, montype2_store);
+static struct kobj_attribute montype3_attr = __ATTR(montype3, 0664, montype3_show, montype3_store);
+static struct kobj_attribute window_len_attr = __ATTR(window_len, 0664, window_len_show, window_len_store);
+
+
+/* create spmtwam related kobj node */
+#define KOBJ_ATTR_LIST \
+ do { \
+ KOBJ_ATTR_ITEM(montype0); \
+ KOBJ_ATTR_ITEM(montype1); \
+ KOBJ_ATTR_ITEM(montype2); \
+ KOBJ_ATTR_ITEM(montype3); \
+ KOBJ_ATTR_ITEM(window_len); \
+ } while (0)
+
+static int met_spmtwam_create(struct kobject *parent)
+{
+ int i;
+ int ret = 0;
+
+ kobj_spmtwam = parent;
+
+#define KOBJ_ATTR_ITEM(attr_name) \
+ do { \
+ ret = sysfs_create_file(kobj_spmtwam, &attr_name ## _attr.attr); \
+ if (ret != 0) { \
+ pr_notice("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+ } while (0)
+ KOBJ_ATTR_LIST;
+#undef KOBJ_ATTR_ITEM
+
+ /* init. */
+ for (i = 0; i < MAX_EVENT_COUNT; i++)
+ twam_config.byte[i].monitor_type = 0x2;
+
+ return ret;
+}
+
+static void met_spmtwam_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_spmtwam, &attr_name ## _attr.attr)
+
+ if (kobj_spmtwam != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_spmtwam = NULL;
+ }
+#undef KOBJ_ATTR_ITEM
+}
+
+void ms_spmtwam(struct twam_cfg *cfg, struct twam_select *twam_sel)
+{
+ switch (used_count) {
+ case 1:
+ MET_TRACE(MP_FMT1,
+ (cfg->byte[0].id));
+ break;
+ case 2:
+ MET_TRACE(MP_FMT2,
+ (cfg->byte[0].id),
+ (cfg->byte[1].id));
+ break;
+ case 3:
+ MET_TRACE(MP_FMT3,
+ (cfg->byte[0].id),
+ (cfg->byte[1].id),
+ (cfg->byte[2].id));
+ break;
+ case 4:
+ MET_TRACE(MP_FMT4,
+ (cfg->byte[0].id),
+ (cfg->byte[1].id),
+ (cfg->byte[2].id),
+ (cfg->byte[3].id));
+ break;
+ default:
+ MET_SPMTWAM_ERR("No assign profile event\n");
+ break;
+ }
+}
+
+static int reset_driver_stat(void)
+{
+ met_spmtwam.mode = 0;
+ used_count = 0;
+ start = 0;
+
+ return 0;
+}
+
+#if 0
+void sspm_twam_debug(void)
+{
+/*
+ PR_BOOTMSG("[MET_TWAM] byte0 idle=%d, event=%d, type=%d \n",twam_config.byte[0].signal,twam_config.byte[0].id,twam_config.byte[0].monitor_type);
+ PR_BOOTMSG("[MET_TWAM] byte1 idle=%d, event=%d, type=%d \n",twam_config.byte[1].signal,twam_config.byte[1].id,twam_config.byte[1].monitor_type);
+ PR_BOOTMSG("[MET_TWAM] byte2 idle=%d, event=%d, type=%d \n",twam_config.byte[2].signal,twam_config.byte[2].id,twam_config.byte[2].monitor_type);
+ PR_BOOTMSG("[MET_TWAM] byte3 idle=%d, event=%d, type=%d \n",twam_config.byte[3].signal,twam_config.byte[3].id,twam_config.byte[3].monitor_type);
+ PR_BOOTMSG("[MET_TWAM] twam_clock_mode=%d, window_len=%d \n",twam_clock_mode, window_len);
+*/
+}
+#endif
+
+/*
+ * Called from "met-cmd --start"
+ */
+static void spmtwam_start(void)
+{
+ if (spm_twam_met_enable_symbol) {
+ if (true == spm_twam_met_enable_symbol()) {
+ if (spm_twam_enable_monitor_symbol)
+ spm_twam_enable_monitor_symbol(TWAM_DISABLE, TWAM_DEBUG_SIG_DISABLE, NULL);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_enable_monitor_symbol is NULL\n");
+ return;
+ }
+ }
+ } else {
+ MET_SPMTWAM_ERR("spm_twam_met_enable_symbol is NULL\n");
+ return;
+ }
+
+ if (spm_twam_config_channel_symbol)
+ spm_twam_config_channel_symbol(&twam_config, twam_clock_mode, window_len);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_config_channel_symbol is NULL\n");
+ return;
+ }
+
+ if (spm_twam_enable_monitor_symbol) {
+ spm_twam_enable_monitor_symbol(TWAM_ENABLE, twam_dbg_enable, ms_spmtwam);
+ /* sspm_twam_debug(); */
+ } else {
+ MET_SPMTWAM_ERR("spm_twam_enable_monitor_symbol is NULL\n");
+ return;
+ }
+
+ start = 1;
+}
+
+/*
+ * Called from "met-cmd --stop"
+ */
+static void spmtwam_stop(void)
+{
+ if (spm_twam_enable_monitor_symbol)
+ spm_twam_enable_monitor_symbol(TWAM_DISABLE, TWAM_DEBUG_SIG_DISABLE, NULL);
+ else {
+ MET_SPMTWAM_ERR("spm_twam_enable_monitor_symbol is NULL\n");
+ return;
+ }
+}
+
+static const char header[] = "met-info [000] 0.0: ms_spmtwam_header: ";
+
+/*
+ * It will be called back when run "met-cmd --extract" and mode is 1
+ */
+static int spmtwam_print_header(char *buf, int len)
+{
+ int i, total_size;
+ char idle_sig;
+ unsigned int event;
+
+ total_size = snprintf(buf, PAGE_SIZE, header);
+
+ for (i = 0; i < used_count; i++) {
+ idle_sig = spmtwam_para[i].idle_sig;
+ event = spmtwam_para[i].event;
+
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size,
+ "signal_%c_%02u,", idle_sig, event);
+ }
+
+ /* cut the last comma */
+ buf[total_size - 1] = '\n';
+
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size, "met-info [000] 0.0: spmtwam_clock_mode: %s\n",
+ twam_clock_mode == TWAM_SPEED_MODE ? "speed" : "normal");
+
+#ifdef SPMTWAM_SINGLE_IDLE_SIGNAL
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size, "met-info [000] 0.0: spmtwam_idle_signal_support: %s\n",
+ TWAM_SINGLE_IDLE_SIGNAL);
+#endif
+
+#ifdef SPMTWAM_MULTIPLE_IDLE_SIGNAL
+ total_size += snprintf(buf + total_size, PAGE_SIZE - total_size, "met-info [000] 0.0: spmtwam_idle_signal_support: %s\n",
+ TWAM_MULTIPLE_IDLE_SIGNAL);
+#endif
+
+ reset_driver_stat();
+ return total_size;
+}
+
+static int assign_slot_sspm_twam(char idle_sig, unsigned int event)
+{
+ int i;
+ int sig2int;
+
+ if (used_count == MAX_EVENT_COUNT) {
+ PR_BOOTMSG("%s exceed max used event count\n", MET_SPMTWAM_TAG);
+ return -1;
+ }
+
+ /* check duplicated */
+ for (i = 0; i < used_count; i++) {
+ if ((spmtwam_para[i].idle_sig == idle_sig) &&
+ (spmtwam_para[i].event == event)) {
+ PR_BOOTMSG("%s input duplicated event %u\n", MET_SPMTWAM_TAG, event);
+ return -2;
+ }
+ }
+
+ /* check idle_sig range in a~d or A~D */
+ if (tolower(idle_sig) < 'a' || tolower(idle_sig) > 'd') {
+ PR_BOOTMSG("%s input idle signal %c is not in a~d range\n",
+ MET_SPMTWAM_TAG, idle_sig);
+ return -3;
+ }
+
+ /* check event no */
+ if (event > MAX_TWAM_EVENT_COUNT) {
+ PR_BOOTMSG("%s input event %u exceed max twam event %u\n",
+ MET_SPMTWAM_TAG, event, MAX_TWAM_EVENT_COUNT);
+ return -4;
+ }
+
+#ifdef SPMTWAM_SINGLE_IDLE_SIGNAL
+ if (used_count > 0) {
+ for (i = 0; i < used_count; i++) {
+ if (idle_sig != spmtwam_para[i].idle_sig) {
+ PR_BOOTMSG("%s %c idle signal is defferent previous, only support one idle signal\n",
+ MET_SPMTWAM_TAG, idle_sig);
+ return -5;
+ }
+ }
+ }
+#endif
+
+ spmtwam_para[used_count].idle_sig = idle_sig;
+ spmtwam_para[used_count].event = event;
+
+ sig2int = (int) (tolower(idle_sig) - 'a');
+
+ twam_config.byte[used_count].id = event;
+ twam_config.byte[used_count].signal = sig2int;
+
+ used_count++;
+
+ return 0;
+}
+
+static char help[] =
+ " --spmtwam=clock:[speed|normal] default is normal\n"
+ " normal mode monitors 4 channels\n"
+ " speed mode monitors 4 channels\n"
+ " --spmtwam=signal:selx\n"
+ " signal= a ~ d for idle signal A~D select\n"
+ " selx= 0 ~ 31 for for channel event\n";
+
+/*
+ * Called from "met-cmd --help"
+ */
+static int spmtwam_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static int spmtwam_process_argument(const char *arg, int len)
+{
+ if (start == 1)
+ reset_driver_stat();
+
+ if (strncmp(arg, "clock:", 6) == 0) {
+ if (strncmp(&(arg[6]), "speed", 5) == 0) {
+ twam_clock_mode = TWAM_SPEED_MODE;
+ } else if (strncmp(&(arg[6]), "normal", 6) == 0) {
+ twam_clock_mode = TWAM_NORMAL_MODE;
+ } else {
+ PR_BOOTMSG("%s unknown clock mode\n", MET_SPMTWAM_TAG);
+
+ goto error;
+ }
+ } else {
+ char signal;
+ int event;
+ int ret;
+
+ if (len < 3) {
+ PR_BOOTMSG("%s input parameter is too short !!!\n", MET_SPMTWAM_TAG);
+ goto error;
+ }
+
+ /*
+ * parse arguments
+ */
+ ret = sscanf(arg, "%c:%u", &signal, &event);
+ if (ret < 2) {
+ PR_BOOTMSG("%s input parameter is wrong format !!!\n", MET_SPMTWAM_TAG);
+ goto error;
+ }
+
+ if (assign_slot_sspm_twam(signal, event) < 0) {
+ goto error;
+ }
+ }
+
+ met_spmtwam.mode = 1;
+ return 0;
+
+error:
+ reset_driver_stat();
+ return -1;
+}
+
+struct metdevice met_spmtwam = {
+ .name = "spmtwam",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_spmtwam_create,
+ .delete_subfs = met_spmtwam_delete,
+ .cpu_related = 0,
+ .start = spmtwam_start,
+ .stop = spmtwam_stop,
+ .reset = reset_driver_stat,
+ .print_help = spmtwam_print_help,
+ .print_header = spmtwam_print_header,
+ .process_argument = spmtwam_process_argument
+};
+EXPORT_SYMBOL(met_spmtwam);
diff --git a/src/devtools/met_drv_v2/common/sspm/ondiemet_sspm.c b/src/devtools/met_drv_v2/common/sspm/ondiemet_sspm.c
new file mode 100644
index 0000000..da708c1
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/ondiemet_sspm.c
@@ -0,0 +1,532 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/delay.h>
+#include <linux/module.h> /* symbol_get */
+
+#define MET_USER_EVENT_SUPPORT
+#include "met_drv.h"
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+#include "ondiemet_sspm.h"
+#include "met_kernel_symbol.h"
+
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+#ifdef CONFIG_MET_ARM_32BIT
+#include <asm/dma-mapping.h> /* arm_coherent_dma_ops */
+#else /* CONFIG_MET_ARM_32BIT */
+#include <linux/dma-mapping.h>
+#endif /* CONFIG_MET_ARM_32BIT */
+#else /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+#include "sspm_reservedmem.h"
+/* #include "sspm_reservedmem_define.h" */
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+dma_addr_t ondiemet_sspm_log_phy_addr;
+void *ondiemet_sspm_log_virt_addr;
+
+#ifdef DYNAMIC_ALLOC_ODM_BUF_SIZE
+uint32_t ondiemet_sspm_log_size = DYNAMIC_ALLOC_ODM_BUF_SIZE;
+#else
+uint32_t ondiemet_sspm_log_size = 0x800000;
+#endif
+
+
+/* SSPM_LOG_FILE 0 */
+/* SSPM_LOG_SRAM 1 */
+/* SSPM_LOG_DRAM 2 */
+int sspm_log_mode;
+/* SSPM_RUN_NORMAL mode 0 */
+/* SSPM_RUN_CONTINUOUS mode 1 */
+int sspm_run_mode;
+int met_sspm_log_discard = -1;
+int sspm_log_size = 500;
+
+int sspm_buffer_size;
+int sspm_buf_available;
+EXPORT_SYMBOL(sspm_buf_available);
+int sspm_buf_mapped = -1; /* get buffer by MET itself */
+
+
+static ssize_t sspm_ipi_supported_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(sspm_ipi_supported, 0444, sspm_ipi_supported_show, NULL);
+static ssize_t sspm_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(sspm_buffer_size, 0444, sspm_buffer_size_show, NULL);
+
+static ssize_t sspm_available_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(sspm_available, 0444, sspm_available_show, NULL);
+
+static ssize_t sspm_log_discard_show(struct device *dev, struct device_attribute *attr, char *buf);
+static DEVICE_ATTR(sspm_log_discard, 0444, sspm_log_discard_show, NULL);
+
+static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_log_mode, 0664, sspm_log_mode_show, sspm_log_mode_store);
+
+static ssize_t sspm_log_size_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_size_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_log_size, 0664, sspm_log_size_show, sspm_log_size_store);
+
+
+static ssize_t sspm_run_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_run_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_run_mode, 0664, sspm_run_mode_show, sspm_run_mode_store);
+
+static ssize_t sspm_modules_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_modules_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_modules, 0664, sspm_modules_show, sspm_modules_store);
+
+static ssize_t sspm_op_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static DEVICE_ATTR(sspm_op_ctrl, 0220, NULL, sspm_op_ctrl_store);
+
+
+static ssize_t sspm_ipi_supported_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int ipi_supported;
+ int i;
+
+ ipi_supported = 0;
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+ #ifndef SSPM_VERSION_V2
+ ipi_supported = 1;
+ #else
+ if(sspm_ipidev_symbol)
+ ipi_supported = 1;
+ #endif
+#endif
+ i = snprintf(buf, PAGE_SIZE, "%d\n", ipi_supported);
+
+ return i;
+}
+
+
+static ssize_t sspm_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_buffer_size);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_available_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", 1);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_discard_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", met_sspm_log_discard);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_log_mode);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ sspm_log_mode = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+
+static ssize_t sspm_log_size_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_log_size);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_log_size_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ sspm_log_size = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+
+static ssize_t sspm_run_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_run_mode);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_run_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ sspm_run_mode = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+static ssize_t sspm_op_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ if (value == 1)
+ sspm_start();
+ else if (value == 2)
+ sspm_stop();
+ else if (value == 3)
+ sspm_extract();
+ else if (value == 4)
+ sspm_flush();
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+static ssize_t sspm_modules_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%x\n", ondiemet_module[ONDIEMET_SSPM]);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+static ssize_t sspm_modules_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ uint32_t value;
+
+ if (kstrtouint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ ondiemet_module[ONDIEMET_SSPM] = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+int sspm_attr_init(struct device *dev)
+{
+ int ret;
+
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+#ifdef CONFIG_MET_ARM_32BIT
+ struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_coherent_dma_ops);
+
+ if (ops && ops->alloc) {
+ dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ ondiemet_sspm_log_virt_addr = ops->alloc(dev,
+ ondiemet_sspm_log_size,
+ &ondiemet_sspm_log_phy_addr,
+ GFP_KERNEL,
+ 0);
+ }
+#else /* CONFIG_MET_ARM_32BIT */
+ /* dma_alloc */
+ ondiemet_sspm_log_virt_addr = dma_alloc_coherent(dev,
+ ondiemet_sspm_log_size,
+ &ondiemet_sspm_log_phy_addr,
+ GFP_KERNEL);
+#endif /* CONFIG_MET_ARM_32BIT */
+#else /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+ phys_addr_t (*sspm_reserve_mem_get_phys_sym)(unsigned int id) = NULL;
+ phys_addr_t (*sspm_reserve_mem_get_virt_sym)(unsigned int id) = NULL;
+ phys_addr_t (*sspm_reserve_mem_get_size_sym)(unsigned int id) = NULL;
+
+ sspm_reserve_mem_get_phys_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_virt);
+ sspm_reserve_mem_get_virt_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_phys);
+ sspm_reserve_mem_get_size_sym = (phys_addr_t (*)(unsigned int id))symbol_get(sspm_reserve_mem_get_size);
+ if (sspm_reserve_mem_get_phys_sym)
+ ondiemet_sspm_log_virt_addr = (void*)sspm_reserve_mem_get_virt(MET_MEM_ID);
+ if (sspm_reserve_mem_get_virt_sym)
+ ondiemet_sspm_log_phy_addr = sspm_reserve_mem_get_phys(MET_MEM_ID);
+ if (sspm_reserve_mem_get_size_sym)
+ ondiemet_sspm_log_size = sspm_reserve_mem_get_size(MET_MEM_ID);
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+ ret = device_create_file(dev, &dev_attr_sspm_buffer_size);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_buffer_size\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_available);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_available\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_log_discard);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_discard\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_log_mode);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_mode\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_log_size);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_size\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_run_mode);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_run_mode\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_op_ctrl);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_op_ctrl\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_modules);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_modules\n");
+ return ret;
+ }
+ ret = device_create_file(dev, &dev_attr_sspm_ipi_supported);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_ipi_supported\n");
+ return ret;
+ }
+
+ if (ondiemet_sspm_log_virt_addr != NULL) {
+ start_sspm_ipi_recv_thread();
+ sspm_buf_available = 1;
+ sspm_buffer_size = ondiemet_sspm_log_size;
+ } else {
+ sspm_buf_available = 0;
+ sspm_buffer_size = -1;
+ }
+
+ return 0;
+}
+
+int sspm_attr_uninit(struct device *dev)
+{
+ /* dma_free */
+ if (ondiemet_sspm_log_virt_addr != NULL) {
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+#ifdef CONFIG_MET_ARM_32BIT
+ struct dma_map_ops *ops = (struct dma_map_ops *)symbol_get(arm_coherent_dma_ops);
+
+ if (ops && ops->free) {
+ ops->free(dev,
+ ondiemet_sspm_log_size,
+ ondiemet_sspm_log_virt_addr,
+ ondiemet_sspm_log_phy_addr,
+ 0);
+ }
+#else /* CONFIG_MET_ARM_32BIT */
+ dma_free_coherent(dev,
+ ondiemet_sspm_log_size,
+ ondiemet_sspm_log_virt_addr,
+ ondiemet_sspm_log_phy_addr);
+#endif /* CONFIG_MET_ARM_32BIT */
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+ ondiemet_sspm_log_virt_addr = NULL;
+ stop_sspm_ipi_recv_thread();
+ }
+
+ device_remove_file(dev, &dev_attr_sspm_buffer_size);
+ device_remove_file(dev, &dev_attr_sspm_available);
+ device_remove_file(dev, &dev_attr_sspm_log_discard);
+ device_remove_file(dev, &dev_attr_sspm_log_mode);
+ device_remove_file(dev, &dev_attr_sspm_log_size);
+ device_remove_file(dev, &dev_attr_sspm_run_mode);
+ device_remove_file(dev, &dev_attr_sspm_op_ctrl);
+ device_remove_file(dev, &dev_attr_sspm_modules);
+ device_remove_file(dev, &dev_attr_sspm_ipi_supported);
+
+ return 0;
+}
+
+#if 0 /* move to sspm_attr_init() */
+void sspm_get_buffer_info(void)
+{
+ if (ondiemet_sspm_log_virt_addr != NULL) {
+ sspm_buf_available = 1;
+ sspm_buffer_size = ondiemet_sspm_log_size;
+ } else {
+ sspm_buf_available = 0;
+ sspm_buffer_size = -1;
+ }
+}
+#endif
+
+/*extern const char *met_get_platform_name(void);*/
+extern char *met_get_platform(void);
+void sspm_start(void)
+{
+ int32_t ret = 0;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+ const char* platform_name = NULL;
+ unsigned int platform_id = 0;
+ met_sspm_log_discard = -1;
+
+ /* clear DRAM buffer */
+ if (ondiemet_sspm_log_virt_addr != NULL)
+ memset_io((void *)ondiemet_sspm_log_virt_addr, 0, ondiemet_sspm_log_size);
+ else
+ return;
+
+ /*platform_name = met_get_platform_name();*/
+ platform_name = met_get_platform();
+ if (platform_name) {
+ char buf[5];
+
+ memset(buf, 0x0, 5);
+ memcpy(buf, &platform_name[2], 4);
+
+ ret = kstrtouint(buf, 10, &platform_id);
+ }
+
+ /* send DRAM physical address */
+ ipi_buf[0] = MET_MAIN_ID | MET_BUFFER_INFO;
+ ipi_buf[1] = (unsigned int)ondiemet_sspm_log_phy_addr; /* address */
+ if (ret == 0)
+ ipi_buf[2] = platform_id;
+ else
+ ipi_buf[2] = 0;
+
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+
+ /* start ondiemet now */
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_START;
+ ipi_buf[1] = ondiemet_module[ONDIEMET_SSPM];
+ ipi_buf[2] = sspm_log_mode;
+ ipi_buf[3] = sspm_run_mode;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+}
+
+extern unsigned int met_get_chip_id(void);
+void sspm_stop(void)
+{
+ int32_t ret;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+
+ unsigned int chip_id = 0;
+ chip_id = met_get_chip_id();
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_STOP;
+ ipi_buf[1] = chip_id;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+void sspm_extract(void)
+{
+ int32_t ret;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+ int32_t count;
+
+ count = 20;
+ if (sspm_buf_available == 1) {
+ while ((sspm_buffer_dumping == 1) && (count != 0)) {
+ msleep(50);
+ count--;
+ }
+ ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_EXTRACT;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+
+ if (sspm_run_mode == SSPM_RUN_NORMAL)
+ ondiemet_module[ONDIEMET_SSPM] = 0;
+}
+
+void sspm_flush(void)
+{
+ int32_t ret;
+ uint32_t rdata;
+ uint32_t ipi_buf[4];
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID|MET_OP|MET_OP_FLUSH;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+
+ if (sspm_run_mode == SSPM_RUN_NORMAL)
+ ondiemet_module[ONDIEMET_SSPM] = 0;
+}
+#else /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT && ONDIEMET_SUPPORT */
+int sspm_buffer_size = -1;
+
+int sspm_attr_init(struct device *dev)
+{
+ return 0;
+}
+
+int sspm_attr_uninit(struct device *dev)
+{
+ return 0;
+}
+
+void sspm_start(void)
+{
+}
+
+void sspm_stop(void)
+{
+}
+
+void sspm_extract(void)
+{
+}
+
+void sspm_flush(void)
+{
+}
+
+#endif /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT && ONDIEMET_SUPPORT */
diff --git a/src/devtools/met_drv_v2/common/sspm/ondiemet_sspm.h b/src/devtools/met_drv_v2/common/sspm/ondiemet_sspm.h
new file mode 100644
index 0000000..23f8b1b
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/ondiemet_sspm.h
@@ -0,0 +1,153 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __ONDIEMET_SSPM_H
+#define __ONDIEMET_SSPM_H
+
+#if IS_ENABLED(CONFIG_MTK_TINYSYS_SSPM_SUPPORT) && defined(ONDIEMET_SUPPORT)
+#include "ondiemet.h"
+
+#ifndef SSPM_VERSION_V2
+#include "sspm_ipi.h"
+#else
+#include <sspm_ipi_id.h>
+#endif /* SSPM_VERSION_V2 */
+#include <linux/dma-mapping.h>
+
+/* we may use IPI_ID_PLATFORM for mt6759 to reduce SRAM */
+#ifndef SSPM_VERSION_V2
+#ifndef IPI_ID_MET
+/* #define IPI_ID_MET IPI_ID_TST1 */
+#define IPI_ID_MET IPI_ID_PLATFORM
+#endif
+#endif /* SSPM_VERSION_V2 */
+/* MET IPI command definition: mbox 0 */
+/* main func ID: bit[31-24]; sub func ID: bit[23-18]; argu 0: bit[17-0] */
+#define MET_MAIN_ID_MASK 0xff000000 /* bit 31 - 24 */
+#define MET_SUB_ID_MASK 0x00fc0000 /* bit 23 - 18 */
+#define MET_ARGU0_MASK 0x0003ffff /* bit 17 - 0 */
+#define FUNC_BIT_SHIFT 18
+#define MID_BIT_SHIFT 9
+#define MET_MAIN_ID 0x06000000
+/* handle argument and attribute */
+#define PROCESS_ARGU 0x01
+#define PROCESS_ATTR 0x02
+#define MODULE_ID_MASK 0x3fe00 /* bit 9 - 17 */
+#define ARGUMENT_MASK 0x01ff /* bit 0 - 8 */
+
+/* the following command is used for AP to MD32 */
+#define MET_OP (1 << FUNC_BIT_SHIFT)
+/* argu 0: start: 0x01; stop: 0x02; extract: 0x03 */
+#define MET_OP_START 0x00000001
+#define MET_OP_STOP 0x00000002
+#define MET_OP_EXTRACT 0x00000003
+#define MET_OP_FLUSH 0x00000004
+#define MET_SR (2 << FUNC_BIT_SHIFT) /* sample rate */
+#define MET_MODULE (3 << FUNC_BIT_SHIFT) /* module enable/disable */
+#define MET_ARGU (4 << FUNC_BIT_SHIFT) /* argument passing */
+#define MET_ATTR (5 << FUNC_BIT_SHIFT) /* attribute passing */
+/* system memory information for on-die-met log data */
+#define MET_BUFFER_INFO (6 << FUNC_BIT_SHIFT)
+#define MET_TIMESTAMP (7 << FUNC_BIT_SHIFT) /* timestamp info */
+#define MET_GPT (8 << FUNC_BIT_SHIFT) /* GPT counter reading */
+#define MET_REQ_AP2MD (9 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_RESP_AP2MD (10 << FUNC_BIT_SHIFT) /* may no need */
+/* mode: bit 15 - 0: */
+/* Bit 0: MD32 SRAM mode; Bit 1: System DRAM mode */
+/* value: 0: output to next level of storage; 1: loop in its own storage */
+#define MET_DATA_MODE (11 << FUNC_BIT_SHIFT) /* log output mode */
+/* start/stop read data into MD32 SRAM buffer; both DMA and met_printf() */
+#define MET_DATA_OP (12 << FUNC_BIT_SHIFT) /* data read operation */
+/* the following command is used for MD32 to AP */
+#define MET_DUMP_BUFFER (13 << FUNC_BIT_SHIFT)
+#define MET_REQ_MD2AP (14 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_CLOSE_FILE (15 << FUNC_BIT_SHIFT) /* Inform to close the SD file */
+#define MET_RESP_MD2AP (16 << FUNC_BIT_SHIFT)
+#define MET_RUN_MODE (17 << FUNC_BIT_SHIFT)
+
+/* Note: the module ID and its bit pattern should be fixed as below */
+/* DMA based module first */
+enum {
+ MID_PMQOS = 0,
+ MID_VCORE_DVFS,
+ MID_EMI,
+ MID_THERMAL_CPU,
+ MID_WALL_TIME,
+ MID_CPU_DVFS,
+ MID_GPU_DVFS,
+ MID_PTPOD,
+ MID_SPM,
+ MID_PROFILE,
+ MID_MET_TAG,
+ MID_TS,
+ MID_TS_ISR,
+ MID_TS_LAST,
+ MID_TS_ISR_LAST,
+ MID_SRAM_INFO,
+ MID_MET_STOP,
+ MID_IOP_MON,
+ MID_CPU_INFO_MAPPING,
+ MID_SMI,
+ MID_PMU,
+
+ MID_COMMON = 0x1F
+};
+
+#define ID_PMQOS (1 << MID_PMQOS)
+#define ID_SMI (1 << MID_SMI)
+#define ID_EMI (1 << MID_EMI)
+#define ID_THERMAL_CPU (1 << MID_THERMAL_CPU)
+#define ID_WALL_TIME (1 << MID_WALL_TIME)
+#define ID_CPU_DVFS (1 << MID_CPU_DVFS)
+#define ID_GPU_DVFS (1 << MID_GPU_DVFS)
+#define ID_VCORE_DVFS (1 << MID_VCORE_DVFS)
+#define ID_PTPOD (1 << MID_PTPOD)
+#define ID_SPM (1 << MID_SPM)
+#define ID_PROFILE (1 << MID_PROFILE)
+#define ID_COMMON (1 << MID_COMMON)
+#define ID_CPU_INFO_MAPPING (1 << MID_CPU_INFO_MAPPING)
+#define ID_SMI (1 << MID_SMI)
+#define ID_PMU (1 << MID_PMU)
+
+extern void ondiemet_extract(void);
+extern void ondiemet_stop(void);
+extern void ondiemet_start(void);
+
+extern void start_sspm_ipi_recv_thread(void);
+extern void stop_sspm_ipi_recv_thread(void);
+extern int met_ipi_to_sspm_command(void *buffer, int slot,
+ unsigned int *retbuf, int retslot);
+extern int met_ipi_to_sspm_command_async(void *buffer, int slot,
+ unsigned int *retbuf, int retslot);
+
+
+extern unsigned int ondiemet_ipi_buf[];
+
+/* extern phys_addr_t ondiemet_sspm_log_phy_addr, ondiemet_sspm_log_virt_addr; */
+extern dma_addr_t ondiemet_sspm_log_phy_addr;
+
+extern void *ondiemet_sspm_log_virt_addr;
+extern uint32_t ondiemet_sspm_log_size;
+
+extern int ondiemet_attr_init(struct device *dev);
+extern int ondiemet_attr_uninit(struct device *dev);
+extern int met_sspm_log_discard;
+
+#define SSPM_LOG_FILE 0
+#define SSPM_LOG_SRAM 1
+#define SSPM_LOG_DRAM 2
+extern int sspm_log_mode;
+#define SSPM_RUN_NORMAL 0
+#define SSPM_RUN_CONTINUOUS 1
+extern int sspm_run_mode;
+
+/* extern void sspm_get_buffer_info(void); */
+extern int sspm_buf_available;
+extern int sspm_buffer_dumping;
+
+void sspm_flush(void);
+
+#endif /* CONFIG_MTK_TINYSYS_SSPM_SUPPORT && ONDIEMET_SUPPORT */
+#endif /* __ONDIEMET_SSPM_H */
diff --git a/src/devtools/met_drv_v2/common/sspm/sspm_common.c b/src/devtools/met_drv_v2/common/sspm/sspm_common.c
new file mode 100644
index 0000000..b42006f
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/sspm_common.c
@@ -0,0 +1,271 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+
+#include "met_drv.h"
+#include "ondiemet_sspm.h"
+
+
+struct sspm_met_evnet_header {
+ unsigned int rts_event_id;
+ char *rts_event_name;
+ char *chart_line_name;
+ char *key_list;
+};
+
+
+enum {
+ #ifdef MET_SSPM_RTS_EVNET
+ #undef MET_SSPM_RTS_EVNET
+ #endif
+ #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) rts_event_id,
+ #include "met_sspm_rts_event.h"
+
+ /**********************/
+ CUR_MET_RTS_EVENT_NUM,
+ MAX_MET_RTS_EVENT_NUM = 128
+};
+
+
+struct sspm_met_evnet_header met_evnet_header[MAX_MET_RTS_EVENT_NUM] = {
+ #ifdef MET_SSPM_RTS_EVNET
+ #undef MET_SSPM_RTS_EVNET
+ #endif
+ #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) {rts_event_id, #rts_event_id, #rts_event_id, key_list},
+ #include "met_sspm_rts_event.h"
+};
+
+
+static void ondiemet_sspm_start(void);
+static void ondiemet_sspm_stop(void);
+static int ondiemet_sspm_print_help(char *buf, int len);
+static int ondiemet_sspm_process_argument(const char *arg, int len);
+static int ondiemet_sspm_print_header(char *buf, int len);
+
+
+static unsigned int event_id_flag0;
+static unsigned int event_id_flag1;
+static unsigned int event_id_flag2;
+static unsigned int event_id_flag3;
+static char *update_rts_event_tbl[MAX_MET_RTS_EVENT_NUM];
+static char sspm_help[] = " --sspm_common=rts_event_name\n";
+static char header[] = "met-info [000] 0.0: sspm_common_header: ";
+
+struct metdevice met_sspm_common = {
+ .name = "sspm_common",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .ondiemet_mode = 1,
+ .ondiemet_start = ondiemet_sspm_start,
+ .ondiemet_stop = ondiemet_sspm_stop,
+ .ondiemet_process_argument = ondiemet_sspm_process_argument,
+ .ondiemet_print_help = ondiemet_sspm_print_help,
+ .ondiemet_print_header = ondiemet_sspm_print_header,
+};
+
+
+static int ondiemet_sspm_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, sspm_help);
+}
+
+
+static int ondiemet_sspm_print_header(char *buf, int len)
+{
+ int i;
+ int write_len;
+ int flag = 0;
+ static int is_dump_header = 0;
+ static int read_idx = 0;
+
+ len = 0;
+ met_sspm_common.header_read_again = 0;
+ if (is_dump_header == 0) {
+ len = snprintf(buf, PAGE_SIZE, "%s", header);
+ is_dump_header = 1;
+ }
+
+ for (i=read_idx; i<MAX_MET_RTS_EVENT_NUM; i++) {
+ if (met_evnet_header[i].chart_line_name) {
+ if (i <32) {
+ flag = 1<<i;
+ flag = event_id_flag0 & flag;
+ } else if (i >=32 && i < 64) {
+ flag = 1<<(i-32);
+ flag = event_id_flag1 & flag;
+ } else if (i >=64 && i < 96) {
+ flag = 1<<(i-64);
+ flag = event_id_flag2 & flag;
+ } else if (i >=96 && i < 128) {
+ flag = 1<<(i-96);
+ flag = event_id_flag3 & flag;
+ }
+ if (flag == 0)
+ continue;
+
+ write_len = strlen(met_evnet_header[i].chart_line_name) + strlen(met_evnet_header[i].key_list) + 3;
+ if ((len+write_len) < PAGE_SIZE) {
+ len += snprintf(buf+len, PAGE_SIZE-len, "%u,%s,%s;",
+ met_evnet_header[i].rts_event_id,
+ met_evnet_header[i].chart_line_name,
+ met_evnet_header[i].key_list);
+ } else {
+ met_sspm_common.header_read_again = 1;
+ read_idx = i;
+ return len;
+ }
+ }
+ }
+
+ if (i == MAX_MET_RTS_EVENT_NUM) {
+ is_dump_header = 0;
+ read_idx = 0;
+ buf[len-1] = '\n';
+ for (i=0; i<MAX_MET_RTS_EVENT_NUM; i++) {
+ if (update_rts_event_tbl[i]) {
+ kfree(update_rts_event_tbl[i]);
+ update_rts_event_tbl[i] = NULL;
+ }
+ }
+ met_sspm_common.mode = 0;
+ event_id_flag0 = 0;
+ event_id_flag1 = 0;
+ event_id_flag2 = 0;
+ event_id_flag3 = 0;
+ }
+
+ return len;
+}
+
+
+static void ondiemet_sspm_start(void)
+{
+ if (sspm_buf_available == 0)
+ return ;
+
+ /* ID_COMMON = 1<<MID_COMMON */
+ ondiemet_module[ONDIEMET_SSPM] |= ID_COMMON;
+}
+
+
+static void ondiemet_sspm_stop(void)
+{
+ if (sspm_buf_available == 0)
+ return ;
+}
+
+
+static void update_event_id_flag(int event_id)
+{
+ unsigned int ipi_buf[4];
+ unsigned int rdata;
+ unsigned int res;
+
+ if (sspm_buf_available == 0)
+ return ;
+
+ /* main func ID: bit[31-24]; sub func ID: bit[23-18]; argu 0: bit[17-0]
+ #define MET_MAIN_ID_MASK 0xff000000
+ #define FUNC_BIT_SHIFT 18
+ #define MET_ARGU (4 << FUNC_BIT_SHIFT)
+ #define MID_BIT_SHIFT 9
+ */
+ if (event_id <32) {
+ event_id_flag0 |= 1<<event_id;
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = event_id_flag0;
+ ipi_buf[3] = 0;
+ res = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ } else if (event_id >=32 && event_id < 64) {
+ event_id_flag1 |= 1<<(event_id-32);
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 1;
+ ipi_buf[2] = event_id_flag1;
+ ipi_buf[3] = 0;
+ res = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ } else if (event_id >=64 && event_id < 96) {
+ event_id_flag2 |= 1<<(event_id-64);
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 2;
+ ipi_buf[2] = event_id_flag2;
+ ipi_buf[3] = 0;
+ res = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ } else if (event_id >=96 && event_id < 128) {
+ event_id_flag3 = 1<<(event_id-96);
+ ipi_buf[0] |= MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = 3;
+ ipi_buf[2] = event_id_flag3;
+ ipi_buf[3] = 0;
+ res = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+ met_sspm_common.mode = 1;
+}
+
+
+static char *strdup(const char *s)
+{
+ char *p = kmalloc(strlen(s) + 1, GFP_KERNEL);
+
+ if (p)
+ strcpy(p, s);
+ return p;
+}
+
+
+static int ondiemet_sspm_process_argument(const char *arg, int len)
+{
+ int i;
+ int rts_event_id = -1;
+ int res;
+ char *line;
+ char *token;
+
+ for (i=0; met_evnet_header[i].rts_event_name && i<MAX_MET_RTS_EVENT_NUM; i++) {
+ if (strcmp(met_evnet_header[i].rts_event_name, arg) == 0) {
+ rts_event_id = i;
+ break;
+ }
+ }
+ if (strstarts(arg, "update_rts_event_tbl")) {
+ char *ptr;
+
+ /* update_rts_event_tbl=rts_event_id;rts_event_name;chart_line_name;key_list*/
+ line = strdup(arg);
+ if (line == NULL)
+ return -1;
+ ptr = line;
+ token = strsep(&line, "=");
+
+ /* rts_event_id, */
+ token = strsep(&line, ";");
+ res = kstrtoint(token, 10, &rts_event_id);
+ met_evnet_header[rts_event_id].rts_event_id = rts_event_id;
+
+ /* rts_event_name */
+ token = strsep(&line, ";");
+ met_evnet_header[rts_event_id].rts_event_name = token;
+
+ /* chart_line_name */
+ token = strsep(&line, ";");
+ met_evnet_header[rts_event_id].chart_line_name = token;
+
+ /* key_list */
+ token = strsep(&line, ";\n");
+ met_evnet_header[rts_event_id].key_list = token;
+
+ update_rts_event_tbl[rts_event_id] = ptr;
+ }
+
+ if (rts_event_id >=0)
+ update_event_id_flag(rts_event_id);
+
+ return 0;
+}
+EXPORT_SYMBOL(met_sspm_common);
diff --git a/src/devtools/met_drv_v2/common/sspm/sspm_ipi_handle.c b/src/devtools/met_drv_v2/common/sspm/sspm_ipi_handle.c
new file mode 100644
index 0000000..67a4451
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/sspm_ipi_handle.c
@@ -0,0 +1,320 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kthread.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/signal.h>
+#include <linux/semaphore.h>
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+/* #include <asm/uaccess.h> */
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+
+#include "ondiemet_sspm.h"
+#include "ondiemet_log.h"
+#include "interface.h"
+#include "met_kernel_symbol.h"
+
+
+#ifndef SSPM_VERSION_V2
+static struct ipi_action ondiemet_sspm_isr;
+#else
+#include "core_plf_init.h"
+uint32_t rdata = 0;
+uint32_t ridx, widx, wlen;
+uint32_t ackdata = 0;
+#endif
+static uint32_t log_size;
+static uint32_t recv_buf[4];
+static struct task_struct *ondiemet_sspm_recv_task;
+static int sspm_ipi_thread_started;
+int sspm_buffer_dumping;
+int sspm_recv_thread_comp;
+
+void log_done_cb(const void *p)
+{
+ uint32_t ret;
+ uint32_t rdata = 0;
+ uint32_t ipi_buf[4];
+ uint32_t opt = (p != NULL);
+
+ if (opt == 0) {
+ ipi_buf[0] = MET_MAIN_ID | MET_RESP_AP2MD;
+ ipi_buf[1] = MET_DUMP_BUFFER;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+#ifndef SSPM_VERSION_V2
+int ondiemet_sspm_recv_thread(void *data)
+{
+ uint32_t rdata = 0, cmd, ret;
+ uint32_t ridx, widx, wlen;
+
+ ondiemet_sspm_isr.data = (void *)recv_buf;
+ ret = sspm_ipi_recv_registration(IPI_ID_TST1, &ondiemet_sspm_isr);
+ do {
+ sspm_ipi_recv_wait(IPI_ID_TST1);
+ if (sspm_recv_thread_comp == 1) {
+ while (!kthread_should_stop())
+ ;
+ return 0;
+ }
+ cmd = recv_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ sspm_buffer_dumping = 1;
+ ridx = recv_buf[1];
+ widx = recv_buf[2];
+ log_size = recv_buf[3];
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr),
+ widx * 4, log_done_cb, (void *)0);
+ } else {
+ wlen = widx - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)0);
+ }
+ break;
+ case MET_CLOSE_FILE: /* no argument */
+ /* do close file */
+ ridx = recv_buf[1];
+ widx = recv_buf[2];
+ met_sspm_log_discard = recv_buf[3];
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr),
+ widx * 4, log_done_cb, (void *)1);
+ } else {
+ wlen = widx - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ }
+ ret = ondiemet_log_manager_stop();
+ /* pr_debug("MET_CLOSE_FILE: ret=%d log_discard=%d\n", ret, met_sspm_log_discard); */
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ if (sspm_run_mode == SSPM_RUN_CONTINUOUS) {
+ /* clear the memory */
+ memset_io((void *)ondiemet_sspm_log_virt_addr, 0,
+ ondiemet_sspm_log_size);
+ /* re-start ondiemet again */
+ sspm_start();
+ }
+ break;
+ case MET_RESP_MD2AP:
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ sspm_buffer_dumping = 0;
+ break;
+ default:
+ sspm_ipi_send_ack(IPI_ID_TST1, &rdata);
+ break;
+ }
+ } while (!kthread_should_stop());
+ return 0;
+}
+
+#else /* SSPM_VERSION_V2 */
+
+int met_ipi_cb(unsigned int ipi_id, void *prdata, void *data, unsigned int len)
+{
+ uint32_t *cmd_buf = (uint32_t *)data;
+ uint32_t cmd;
+ int ret;
+
+ if (sspm_recv_thread_comp == 1)
+ return 0;
+
+ cmd = cmd_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ sspm_buffer_dumping = 1;
+ ridx = cmd_buf[1];
+ widx = cmd_buf[2];
+ log_size = cmd_buf[3];
+ break;
+ case MET_CLOSE_FILE: /* no argument */
+ /* do close file */
+ ridx = cmd_buf[1];
+ widx = cmd_buf[2];
+ met_sspm_log_discard = cmd_buf[3];
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr),
+ widx * 4, log_done_cb, (void *)1);
+ } else {
+ wlen = widx - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ }
+ ret = ondiemet_log_manager_stop();
+ /* pr_debug("MET_CLOSE_FILE: ret=%d log_discard=%d\n", ret, met_sspm_log_discard); */
+ break;
+ case MET_RESP_MD2AP:
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+int ondiemet_sspm_recv_thread(void *data)
+{
+ int ret;
+ uint32_t cmd;
+
+ ret = mtk_ipi_register(sspm_ipidev_symbol, IPIR_C_MET, met_ipi_cb, NULL, (void *)recv_buf);
+ if (ret)
+ pr_debug("[MET] ipi_register:%d failed:%d\n", IPIR_C_MET, ret);
+
+ do {
+ mtk_ipi_recv_reply(sspm_ipidev_symbol,IPIR_C_MET, (void *)&rdata, 1);
+ if (sspm_recv_thread_comp == 1) {
+ while (!kthread_should_stop())
+ ;
+ return 0;
+ }
+ cmd = recv_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)1);
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr),
+ widx * 4, log_done_cb, (void *)0);
+ } else {
+ wlen = widx - ridx;
+ ondiemet_log_req_enq((char *)(ondiemet_sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, log_done_cb, (void *)0);
+ }
+ break;
+ case MET_CLOSE_FILE: /* no argument */
+ if (sspm_run_mode == SSPM_RUN_CONTINUOUS) {
+ /* clear the memory */
+ memset_io((void *)ondiemet_sspm_log_virt_addr, 0,
+ ondiemet_sspm_log_size);
+ /* re-start ondiemet again */
+ sspm_start();
+ }
+ break;
+ case MET_RESP_MD2AP:
+ sspm_buffer_dumping = 0;
+ break;
+ default:
+ break;
+ }
+ } while (!kthread_should_stop());
+ return 0;
+}
+
+#endif /* SSPM_VERSION_V2 */
+
+
+
+void start_sspm_ipi_recv_thread(void)
+{
+#ifdef SSPM_VERSION_V2
+ int ret;
+
+ if(!sspm_ipidev_symbol)
+ return;
+
+ ret = mtk_ipi_register(sspm_ipidev_symbol, IPIS_C_MET, NULL, NULL, (void *) &ackdata);
+ if (ret)
+ pr_debug("[MET] ipi_register:%d failed:%d\n", IPIS_C_MET, ret);
+#endif
+
+ if (sspm_ipi_thread_started != 1) {
+ sspm_recv_thread_comp = 0;
+ ondiemet_sspm_recv_task =
+ kthread_run(ondiemet_sspm_recv_thread, NULL, "ondiemet_sspm_recv");
+ if (IS_ERR(ondiemet_sspm_recv_task))
+ pr_debug("MET: Can not create ondiemet_sspm_recv\n");
+ else
+ sspm_ipi_thread_started = 1;
+ }
+}
+
+void stop_sspm_ipi_recv_thread(void)
+{
+ if (ondiemet_sspm_recv_task) {
+ sspm_recv_thread_comp = 1;
+#ifndef SSPM_VERSION_V2
+ sspm_ipi_recv_complete(IPI_ID_TST1);
+#endif
+ kthread_stop(ondiemet_sspm_recv_task);
+ ondiemet_sspm_recv_task = NULL;
+ sspm_ipi_thread_started = 0;
+#ifndef SSPM_VERSION_V2
+ sspm_ipi_recv_unregistration(IPI_ID_TST1);
+#else
+ mtk_ipi_unregister(sspm_ipidev_symbol, IPIR_C_MET);
+ mtk_ipi_unregister(sspm_ipidev_symbol, IPIS_C_MET);
+#endif
+ }
+}
+
+int met_ipi_to_sspm_command(void *buffer, int slot, unsigned int *retbuf, int retslot)
+{
+ int ret;
+
+#ifndef SSPM_VERSION_V2
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, buffer, slot, retbuf, retslot);
+#else
+ if(!sspm_ipidev_symbol)
+ ret = -1;
+ else {
+ ret = mtk_ipi_send_compl(sspm_ipidev_symbol, IPIS_C_MET, IPI_SEND_WAIT, buffer, slot, 2000);
+ *retbuf = ackdata;
+ }
+#endif
+ if (ret != 0)
+ pr_debug("met_ipi_to_sspm_command error(%d)\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(met_ipi_to_sspm_command);
+
+
+int met_ipi_to_sspm_command_async(void *buffer, int slot, unsigned int *retbuf, int retslot)
+{
+ int ret;
+
+#ifndef SSPM_VERSION_V2
+ ret = sspm_ipi_send_sync(IPI_ID_MET, IPI_OPT_WAIT, buffer, slot, retbuf, retslot);
+#else
+ if(!sspm_ipidev_symbol)
+ ret = -1;
+ else {
+ ret = mtk_ipi_send(sspm_ipidev_symbol, IPIS_C_MET, IPI_SEND_WAIT, buffer, slot, 2000);
+ *retbuf = ackdata;
+ }
+#endif
+ if (ret != 0)
+ pr_debug("met_ipi_to_sspm_command error(%d)\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL(met_ipi_to_sspm_command_async);
+
+
+
diff --git a/src/devtools/met_drv_v2/common/sspm/sspm_met_smi.c b/src/devtools/met_drv_v2/common/sspm/sspm_met_smi.c
new file mode 100644
index 0000000..5e0d250
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/sspm_met_smi.c
@@ -0,0 +1,546 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+
+#ifdef USE_KERNEL_SYNC_WRITE_H
+#include <mt-plat/sync_write.h>
+#else
+#include "sync_write.h"
+#endif
+
+#ifdef USE_KERNEL_MTK_IO_H
+#include <mt-plat/mtk_io.h>
+#else
+#include "mtk_io.h"
+#endif
+
+#include "met_drv.h"
+#include "trace.h"
+
+#include "mtk_typedefs.h"
+#include "sspm_mtk_smi.h"
+#include "sspm_met_smi.h"
+#include "sspm_met_smi_name.h"
+#include "core_plf_trace.h"
+#include "core_plf_init.h"
+#include "interface.h"
+#include "sspm/ondiemet_sspm.h"
+
+#define MET_SMI_DEBUG 1
+#define MET_SMI_BUF_SIZE 128
+#define MET_SMI_DEBUGBUF_SIZE 512
+#define NPORT_IN_PM 4
+
+// SMI Encode -- Master
+#ifdef SMI_MASTER_8BIT
+// bit15~bit16
+#define MET_SMI_BIT_REQ_LARB 15
+// bit13~bit14
+#define MET_SMI_BIT_REQ_COMM 13
+// bit12:Parallel Mode */
+#define MET_SMI_BIT_PM 12
+// bit9~bit8:Destination */
+#define MET_SMI_BIT_DST 10
+/* bit5~bit4:Request Type */
+#define MET_SMI_BIT_REQ 8
+/* bit3~bit0:Master */
+#define MET_SMI_BIT_MASTER 0
+#else
+// bit15~bit16
+#define MET_SMI_BIT_REQ_LARB 15
+// bit13~bit14
+#define MET_SMI_BIT_REQ_COMM 13
+// bit12:Parallel Mode */
+#define MET_SMI_BIT_PM 12
+// bit9~bit8:Destination */
+#define MET_SMI_BIT_DST 8
+/* bit5~bit4:Request Type */
+#define MET_SMI_BIT_REQ 4
+/* bit3~bit0:Master */
+#define MET_SMI_BIT_MASTER 0
+#endif
+
+// SMI Encode -- Metadata
+/* bit6~bit5:RW */
+#define MET_SMI_BIT_RW 5
+/* bit4~bit0:Port */
+#define MET_SMI_BIT_PORT 0
+
+/*
+*declare smi: larb0-larbn:
+*real define table in met_smi_name.h
+*/
+/*MET_SMI_DESC_DEFINE();*/
+/**/
+
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+#define MAX_CONFIG_ARRAY_SIZE 20
+struct metdevice met_sspm_smi;
+struct met_smi_conf smi_conf_array[MAX_CONFIG_ARRAY_SIZE];
+int smi_array_index;
+
+//static unsigned int smi_met_larb_number = SMI_LARB_NUMBER;
+static int count = SMI_LARB_NUMBER + SMI_COMM_NUMBER;
+static struct kobject *kobj_smi;
+
+/* Request type */
+static unsigned int larb_req_type = SMI_REQ_ALL;
+static unsigned int comm_req_type = SMI_REQ_ALL;
+
+/* Parallel mode */
+static unsigned int parallel_mode;
+
+/* Read/Write type in parallel mode */
+static int comm_pm_rw_type[SMI_COMM_NUMBER][NPORT_IN_PM];
+/* Error message */
+static char err_msg[MET_SMI_BUF_SIZE];
+static char debug_msg[MET_SMI_DEBUGBUF_SIZE];
+
+/*======================================================================*/
+/* KOBJ Declarations */
+/*======================================================================*/
+/* KOBJ: larb_req_type */
+DECLARE_KOBJ_ATTR_INT(larb_req_type, larb_req_type);
+
+/* KOBJ : comm_req_type */
+DECLARE_KOBJ_ATTR_INT(comm_req_type, comm_req_type);
+
+/* KOBJ : enable_parallel_mode */
+DECLARE_KOBJ_ATTR_INT(enable_parallel_mode, parallel_mode);
+
+/* KOBJ : pm_rwtypeX */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ pm_rwtype,
+ KOBJ_ITEM_LIST(
+ {SMI_READ_ONLY, "READ"},
+ {SMI_WRITE_ONLY, "WRITE"}
+ )
+);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype1, comm_pm_rw_type[0][0], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype2, comm_pm_rw_type[0][1], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype3, comm_pm_rw_type[0][2], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype4, comm_pm_rw_type[0][3], pm_rwtype);
+
+/* KOBJ : count */
+DECLARE_KOBJ_ATTR_RO_INT(count, count);
+
+/* KOBJ : err_msg */
+DECLARE_KOBJ_ATTR_RO_STR(err_msg, err_msg);
+
+#define KOBJ_ATTR_LIST \
+do { \
+ KOBJ_ATTR_ITEM(larb_req_type); \
+ KOBJ_ATTR_ITEM(comm_req_type); \
+ KOBJ_ATTR_ITEM(enable_parallel_mode); \
+ KOBJ_ATTR_ITEM(pm_rwtype1); \
+ KOBJ_ATTR_ITEM(pm_rwtype2); \
+ KOBJ_ATTR_ITEM(pm_rwtype3); \
+ KOBJ_ATTR_ITEM(pm_rwtype4); \
+ KOBJ_ATTR_ITEM(count); \
+ KOBJ_ATTR_ITEM(err_msg); \
+} while (0)
+
+/*======================================================================*/
+/* SMI Operations */
+/*======================================================================*/
+static void met_smi_debug(char *debug_log)
+{
+ MET_TRACE("%s", debug_log);
+}
+
+static int do_smi(void)
+{
+ return met_sspm_smi.mode;
+}
+
+static void smi_init_value(void)
+{
+ int i;
+
+ smi_array_index = 0;
+ for (i = 0; i < MAX_CONFIG_ARRAY_SIZE; i++) {
+ smi_conf_array[i].master = 0;
+ smi_conf_array[i].port[0] = -1;
+ smi_conf_array[i].port[1] = -1;
+ smi_conf_array[i].port[2] = -1;
+ smi_conf_array[i].port[3] = -1;
+ smi_conf_array[i].rwtype[0] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[1] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[2] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[3] = SMI_RW_ALL;
+ smi_conf_array[i].desttype = SMI_DEST_EMI;
+ smi_conf_array[i].reqtype = SMI_REQ_ALL;
+ }
+}
+
+static int smi_init(void)
+{
+ int i;
+
+ if (smi_array_index < MAX_CONFIG_ARRAY_SIZE) {
+ for (i = 0; i < (smi_array_index + 1); i++) {
+ snprintf(debug_msg, MET_SMI_DEBUGBUF_SIZE,
+ "===SMI config: parallel_mode = %d, master = %d, port0 = %d, port1 = %d, port2 = %d, port3 = %d, rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ parallel_mode,
+ smi_conf_array[i].master,
+ smi_conf_array[i].port[0],
+ smi_conf_array[i].port[1],
+ smi_conf_array[i].port[2],
+ smi_conf_array[i].port[3],
+ smi_conf_array[i].rwtype[0],
+ smi_conf_array[i].rwtype[1],
+ smi_conf_array[i].rwtype[2],
+ smi_conf_array[i].rwtype[3],
+ smi_conf_array[i].desttype,
+ smi_conf_array[i].reqtype >> MET_SMI_BIT_REQ_LARB,
+ smi_conf_array[i].reqtype >> MET_SMI_BIT_REQ_COMM);
+ met_smi_debug(debug_msg);
+ }
+ } else {
+ met_smi_debug("smi_init() FAIL : smi_array_index overflow\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int met_smi_create(struct kobject *parent)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+do { \
+ ret = sysfs_create_file(kobj_smi, &attr_name##_attr.attr); \
+ if (ret != 0) { \
+ pr_debug("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+} while (0)
+
+ int j;
+ int ret = 0;
+
+ pr_debug(" met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n met_smi_create\n");
+
+ /* Init. */
+
+ smi_init_value();
+
+ larb_req_type = SMI_REQ_ALL;
+ comm_req_type = SMI_REQ_ALL;
+ parallel_mode = 0;
+
+ for (j = 0; j < NPORT_IN_PM; j++)
+ comm_pm_rw_type[0][j] = SMI_READ_ONLY;
+
+ kobj_smi = parent;
+
+ KOBJ_ATTR_LIST;
+
+ return ret;
+
+#undef KOBJ_ATTR_ITEM
+}
+
+void met_smi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_smi, &attr_name##_attr.attr)
+
+
+ if (kobj_smi != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_smi = NULL;
+ }
+
+#undef KOBJ_ATTR_ITEM
+}
+
+static void met_smi_start(void)
+{
+ if (do_smi()) {
+ if (smi_init() != 0) {
+ met_sspm_smi.mode = 0;
+ smi_init_value();
+ return;
+ }
+ }
+}
+
+static void met_smi_stop(void)
+{
+ int j;
+
+ if (do_smi()) {
+
+ /* Reset */
+ smi_init_value();
+
+ larb_req_type = SMI_REQ_ALL;
+ comm_req_type = SMI_REQ_ALL;
+ parallel_mode = 0;
+
+ for (j = 0; j < NPORT_IN_PM; j++)
+ comm_pm_rw_type[0][j] = SMI_READ_ONLY;
+
+
+ met_sspm_smi.mode = 0;
+ }
+ return ;
+}
+
+static char help[] =
+" --smi=master:port:rw:dest:bus monitor specified SMI banwidth\n"
+" --smi=master:p1[:p2][:p3][:p4] monitor parallel mode\n";
+
+static int smi_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, "%s", help);
+}
+
+static int get_num(const char *__restrict__ dc, int *pValue)
+{
+ int value = 0, digit;
+ int i = 0;
+
+ while (((*dc) >= '0') && ((*dc) <= '9')) {
+ digit = (int)(*dc - '0');
+ value = value * 10 + digit;
+ dc++;
+ i++;
+ }
+
+ if (i == 0)
+ return 0;
+ *pValue = value;
+
+ return i;
+}
+
+/*
+ * There are serveal cases as follows:
+ *
+ * 1. "met-cmd --start --smi=master:port:rwtype:desttype:bustype" => Can assign multiple master
+ * 2. "met-cmd --start --smi=master:port[:port1][:port2][:port3]" ==> parael mode
+ *
+ */
+static int smi_process_argument(const char *__restrict__ arg, int len)
+{
+ int args[5];
+ int i, array_index;
+ int idx;
+ unsigned int smi_conf_index = 0;
+ struct met_smi_conf smi_conf;
+
+ uint32_t ipi_buf[4];
+ uint32_t ret;
+ uint32_t rdata;
+ uint16_t sspm_master = 0;
+ uint32_t sspm_meta = 0;
+
+ if (len < 3)
+ return -1;
+
+ /*reset local config structure*/
+ memset(err_msg, 0, MET_SMI_BUF_SIZE);
+ for (i = 0; i < 4; i++) {
+ smi_conf.port[i] = -1;
+ smi_conf.rwtype[i] = SMI_RW_ALL;
+ }
+ smi_conf.master = 0;
+ smi_conf.reqtype = SMI_REQ_ALL;
+ smi_conf.desttype = SMI_DEST_EMI;
+
+ if (met_sspm_smi.mode != 0 && met_sspm_smi.mode != 1)
+ return -1;
+
+ /*
+ * parse arguments
+ * arg[0] = master
+ * arg[1] = port or port1
+ * arg[2] = rwtype or port2
+ * arg[3] = desttype or port3
+ * arg[4] = bustype or port4
+ */
+ for (i = 0; i < ARRAY_SIZE(args); i++)
+ args[i] = -1;
+ idx = 0;
+ for (i = 0; i < ARRAY_SIZE(args); i++) {
+ ret = get_num(&(arg[idx]), &(args[i]));
+ if (ret == 0)
+ break;
+ idx += ret;
+ if (arg[idx] != ':')
+ break;
+ idx++;
+ }
+
+ pr_debug("===SMI process argu: args[0](%d), args[1](%d), args[2](%d), args[3](%d), args[4](%d)\n",
+ args[0],
+ args[1],
+ args[2],
+ args[3],
+ args[4]);
+
+ /*fill local config structure*/
+ smi_conf.master = args[0];
+ smi_conf.reqtype = (larb_req_type << MET_SMI_BIT_REQ_LARB) | (comm_req_type << MET_SMI_BIT_REQ_COMM);
+ if (parallel_mode == 0) { /*legacy mode*/
+ smi_conf.rwtype[0] = args[2];
+ smi_conf.desttype = args[3];
+ smi_conf.port[0] = args[1];
+ } else { /*parallel mode*/
+ smi_conf.desttype = SMI_DEST_EMI;
+ for (i = 0; i < 4; i++) {
+ if (args[i+1] < 0)
+ break;
+ smi_conf.port[i] = args[i+1];
+ smi_conf.rwtype[i] = comm_pm_rw_type[0][i];
+ }
+ }
+
+/*debug log to ftrace*/
+#ifdef MET_SMI_DEBUG
+ snprintf(debug_msg, MET_SMI_DEBUGBUF_SIZE,
+ "(argu)===SMI process argu Master[%d]: parallel_mode = %d, master = %d, port0 = %d, port1 = %d, port2 = %d, port3 = %d, rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ args[0],
+ parallel_mode,
+ smi_conf.master,
+ smi_conf.port[0],
+ smi_conf.port[1],
+ smi_conf.port[2],
+ smi_conf.port[3],
+ smi_conf.rwtype[0],
+ smi_conf.rwtype[1],
+ smi_conf.rwtype[2],
+ smi_conf.rwtype[3],
+ smi_conf.desttype,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_LARB) & 0x3,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_COMM) & 0x3);
+ met_smi_debug(debug_msg);
+#endif
+
+ /*find the empty conf_array*/
+ for (i = 0; i < MAX_CONFIG_ARRAY_SIZE; i++) {
+ if ((smi_conf_array[i].master == smi_conf.master) && (smi_conf_array[i].port[0] != -1))
+ break;
+ }
+ if (i >= MAX_CONFIG_ARRAY_SIZE) {
+ if (smi_conf_array[0].port[0] == -1) {
+ smi_array_index = 0;
+ array_index = 0;
+ } else {
+ smi_array_index = smi_array_index + 1;
+ array_index = smi_array_index;
+ }
+ } else {
+ array_index = i;
+ }
+
+ if ((smi_array_index >= MAX_CONFIG_ARRAY_SIZE) || (array_index >= MAX_CONFIG_ARRAY_SIZE)) {
+ snprintf(err_msg, MET_SMI_BUF_SIZE,
+ "===Setting Master[%d]: check smi_array_index=%d, array_index=%d overflow (> %d)\n",
+ args[0], smi_array_index, array_index, MAX_CONFIG_ARRAY_SIZE);
+ return -1;
+ }
+
+ smi_conf_array[array_index].master = smi_conf.master;
+
+
+ if (parallel_mode == 0) { /* Legacy mode */
+ smi_conf_array[array_index].port[0] = smi_conf.port[0];
+ } else { /* Parallel mode */
+ for (i = 0; i < NPORT_IN_PM; i++) {
+ if (smi_conf_array[array_index].port[i] == -1)
+ smi_conf_array[array_index].port[i] = smi_conf.port[smi_conf_index++];
+ }
+ }
+ smi_conf_array[array_index].rwtype[0] = smi_conf.rwtype[0];
+ smi_conf_array[array_index].rwtype[1] = smi_conf.rwtype[1];
+ smi_conf_array[array_index].rwtype[2] = smi_conf.rwtype[2];
+ smi_conf_array[array_index].rwtype[3] = smi_conf.rwtype[3];
+ smi_conf_array[array_index].desttype = smi_conf.desttype;
+ smi_conf_array[array_index].reqtype = smi_conf.reqtype;
+
+ pr_debug("===SMI process argu Master[%d]: parallel_mode = %d, master = %d, port0 = %d, port1 = %d, port2 = %d, port3 = %d, rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ args[0],
+ parallel_mode,
+ smi_conf.master,
+ smi_conf.port[0],
+ smi_conf.port[1],
+ smi_conf.port[2],
+ smi_conf.port[3],
+ smi_conf.rwtype[0],
+ smi_conf.rwtype[1],
+ smi_conf.rwtype[2],
+ smi_conf.rwtype[3],
+ smi_conf.desttype,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_LARB) & 0x3,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_COMM) & 0x3);
+
+ // Encode SMI config: Master (request format from SMI driver)
+ sspm_master = sspm_master | (smi_conf_array[array_index].master << MET_SMI_BIT_MASTER);
+ sspm_master = sspm_master | 0 << MET_SMI_BIT_REQ; //reqtype value will be update in sspm side
+ sspm_master = sspm_master | (smi_conf_array[array_index].desttype << MET_SMI_BIT_DST);
+ sspm_master = sspm_master | (parallel_mode << MET_SMI_BIT_PM);
+ // Extrace info for larb and comm reqestType since of unable to recognize master belong to larb or comm.
+ // BIT13~BIT14: comm reqtype
+ // BIT15~BIT16: larb reqtype
+ sspm_master = sspm_master | smi_conf_array[array_index].reqtype;
+
+
+ // Encode SMI config: Meta (request format from SMI driver)
+ // Encode 4 Metadata into 1 unsigned int
+ // BIT0~BIT4: port
+ // BIT5~BIT6: rwtype
+ if(parallel_mode == 0){
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].port[0] << MET_SMI_BIT_PORT);
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].rwtype[0] << MET_SMI_BIT_RW);
+ }
+ else{
+ for(i = 0; i < 4; i++){
+ if(smi_conf_array[array_index].port[i] == 0xFFFFFFFF){
+ smi_conf_array[array_index].port[i] = USHRT_MAX;
+ }
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].port[i] << (MET_SMI_BIT_PORT+8*i));
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].rwtype[i] << (MET_SMI_BIT_RW+8*i));
+ }
+ }
+
+ // Transfer to SSPM side
+ if (sspm_buf_available == 1)
+ {
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_SMI << MID_BIT_SHIFT | 1;
+ ipi_buf[1] = sspm_master;
+ ipi_buf[2] = sspm_meta;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+
+ /* Set mode */
+ met_sspm_smi.mode = 1;
+ ondiemet_module[ONDIEMET_SSPM] |= ID_CPU_INFO_MAPPING;
+ }
+
+ return 0;
+}
+
+struct metdevice met_sspm_smi = {
+ .name = "smi",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_smi_create,
+ .delete_subfs = met_smi_delete,
+ .cpu_related = 0,
+ .ondiemet_mode = 1,
+ .ondiemet_start = met_smi_start,
+ .ondiemet_stop = met_smi_stop,
+ .ondiemet_process_argument = smi_process_argument,
+ .ondiemet_print_help = smi_print_help,
+};
+
diff --git a/src/devtools/met_drv_v2/common/sspm/sspm_met_smi.h b/src/devtools/met_drv_v2/common/sspm/sspm_met_smi.h
new file mode 100644
index 0000000..f51ac6c
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/sspm_met_smi.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _SMI_H_
+#define _SMI_H_
+
+#include <linux/device.h>
+
+struct met_smi {
+ int mode;
+ int master;
+ unsigned int port;
+ unsigned int rwtype; /* 0 for R+W, 1 for read, 2 for write */
+ unsigned int desttype; /* 0 for EMI+internal mem, 1 for EMI, 3 for internal mem */
+ unsigned int bustype; /* 0 for GMC, 1 for AXI */
+ /* unsigned long requesttype;// 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+ struct kobject *kobj_bus_smi;
+};
+
+struct smi_cfg {
+ int master;
+ unsigned int port;
+ unsigned int rwtype; /* 0 for R+W, 1 for read, 2 for write */
+ unsigned int desttype; /* 0 for EMI+internal mem, 1 for EMI, 3 for internal mem */
+ unsigned int bustype; /*0 for GMC, 1 for AXI */
+ /*unsigned long requesttype;// 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+};
+
+struct smi_mon_con {
+ unsigned int requesttype; /* 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+};
+
+/* ====================== SMI/EMI Interface ================================ */
+
+struct met_smi_conf {
+ unsigned int master; /*Ex : Whitney: 0~8 for larb0~larb8, 9 for common larb*/
+ int port[4]; /* port select : [0] only for legacy mode, [0~3] ports for parallel mode, -1 no select*/
+ unsigned int reqtype; /* Selects request type : 0 for all,1 for ultra,2 for preultra,3 for normal*/
+ unsigned int rwtype[4]; /* Selects read/write: 0 for R+W, 1 for read, 2 for write;*/
+ /* [0] for legacy and parallel larb0~8, [0~3] for parallel mode common*/
+ unsigned int desttype; /* Selects destination: 0 and 3 for all memory, 1 for External,2 for internal*/
+};
+
+#endif /* _SMI_H_ */
diff --git a/src/devtools/met_drv_v2/common/sspm/sspm_met_smi_name.h b/src/devtools/met_drv_v2/common/sspm/sspm_met_smi_name.h
new file mode 100644
index 0000000..c620ca0
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/sspm_met_smi_name.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _SMI_NAME_H_
+#define _SMI_NAME_H_
+/* #include "mtk_smi.h" */
+
+enum SMI_DEST {
+ SMI_DEST_ALL = 0,
+ SMI_DEST_EMI = 1,
+ SMI_DEST_INTERNAL = 2,
+ SMI_DEST_NONE = 9
+};
+
+enum SMI_RW {
+ SMI_RW_ALL = 0,
+ SMI_READ_ONLY = 1,
+ SMI_WRITE_ONLY = 2,
+ SMI_RW_RESPECTIVE = 3,
+ SMI_RW_NONE = 9
+};
+
+enum SMI_BUS {
+ SMI_BUS_GMC = 0,
+ SMI_BUS_AXI = 1,
+ SMI_BUS_NONE = 9
+};
+
+enum SMI_REQUEST {
+ SMI_REQ_ALL = 0,
+ SMI_REQ_ULTRA = 1,
+ SMI_REQ_PREULTRA = 2,
+ SMI_NORMAL_ULTRA = 3,
+ SMI_REQ_NONE = 9
+};
+
+struct smi_desc {
+ unsigned long port;
+ enum SMI_DEST desttype;
+ enum SMI_RW rwtype;
+ enum SMI_BUS bustype;
+};
+#endif /* _SMI_NAME_H_ */
diff --git a/src/devtools/met_drv_v2/common/sspm/sspm_mtk_smi.h b/src/devtools/met_drv_v2/common/sspm/sspm_mtk_smi.h
new file mode 100644
index 0000000..68161a8
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/sspm_mtk_smi.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MT_SMI_H__
+#define __MT_SMI_H__
+
+/* the default value, but the real number will get from symbol function*/
+#define SMI_LARB_NUMBER 9
+#define SMI_COMM_NUMBER 1
+#define SMI_LARB_MONITOR_NUMBER 1
+#define SMI_COMM_MONITOR_NUMBER 1
+
+#define SMI_REQ_OK (0)
+#define SMI_ERR_WRONG_REQ (-1)
+#define SMI_ERR_OVERRUN (-2)
+
+#define SMI_IOMEM_ADDR(b, off) ((void __iomem *)(((unsigned long)b)+off))
+
+#define SMI_LARB_MON_ENA(b) SMI_IOMEM_ADDR((b), 0x400)
+#define SMI_LARB_MON_CLR(b) SMI_IOMEM_ADDR((b), 0x404)
+#define SMI_LARB_MON_PORT(b) SMI_IOMEM_ADDR((b), 0x408)
+#define SMI_LARB_MON_CON(b) SMI_IOMEM_ADDR((b), 0x40C)
+
+#define SMI_LARB_MON_ACT_CNT(b) SMI_IOMEM_ADDR((b), 0x410)
+#define SMI_LARB_MON_REQ_CNT(b) SMI_IOMEM_ADDR((b), 0x414)
+#define SMI_LARB_MON_BEA_CNT(b) SMI_IOMEM_ADDR((b), 0x418)
+#define SMI_LARB_MON_BYT_CNT(b) SMI_IOMEM_ADDR((b), 0x41C)
+#define SMI_LARB_MON_CP_CNT(b) SMI_IOMEM_ADDR((b), 0x420)
+#define SMI_LARB_MON_DP_CNT(b) SMI_IOMEM_ADDR((b), 0x424)
+#define SMI_LARB_MON_OSTD_CNT(b) SMI_IOMEM_ADDR((b), 0x428)
+#define SMI_LARB_MON_CP_MAX(b) SMI_IOMEM_ADDR((b), 0x430)
+#define SMI_LARB_MON_OSTD_MAX(b) SMI_IOMEM_ADDR((b), 0x434)
+
+#define SMI_COMM_MON_ENA(b) SMI_IOMEM_ADDR((b), 0x1A0)
+#define SMI_COMM_MON_CLR(b) SMI_IOMEM_ADDR((b), 0x1A4)
+#define SMI_COMM_MON_TYPE(b) SMI_IOMEM_ADDR((b), 0x1AC)
+#define SMI_COMM_MON_CON(b) SMI_IOMEM_ADDR((b), 0x1B0)
+#define SMI_COMM_MON_ACT_CNT(b) SMI_IOMEM_ADDR((b), 0x1C0)
+#define SMI_COMM_MON_REQ_CNT(b) SMI_IOMEM_ADDR((b), 0x1C4)
+#define SMI_COMM_MON_OSTD_CNT(b) SMI_IOMEM_ADDR((b), 0x1C8)
+#define SMI_COMM_MON_BEA_CNT(b) SMI_IOMEM_ADDR((b), 0x1CC)
+#define SMI_COMM_MON_BYT_CNT(b) SMI_IOMEM_ADDR((b), 0x1D0)
+#define SMI_COMM_MON_CP_CNT(b) SMI_IOMEM_ADDR((b), 0x1D4)
+#define SMI_COMM_MON_DP_CNT(b) SMI_IOMEM_ADDR((b), 0x1D8)
+#define SMI_COMM_MON_CP_MAX(b) SMI_IOMEM_ADDR((b), 0x1DC)
+#define SMI_COMM_MON_OSTD_MAX(b) SMI_IOMEM_ADDR((b), 0x1E0)
+
+
+/*ondiemet smi ipi command*/
+enum MET_SMI_IPI_Type {
+ SMI_DRIVER_INITIAL_VALUE = 0x0,
+ SMI_DRIVER_RESET_VALUE,
+ SET_BASE_SMI,
+ SMI_ASSIGN_PORT_START,
+ SMI_ASSIGN_PORT_I,
+ SMI_ASSIGN_PORT_II,
+ SMI_ASSIGN_PORT_III,
+ SMI_ASSIGN_PORT_END,
+};
+
+
+
+
+void MET_SMI_IPI_baseaddr(void);
+int MET_SMI_Init(void);
+void MET_SMI_Fini(void);
+void MET_SMI_Enable(int larbno);
+void MET_SMI_Disable(int larbno);
+void MET_SMI_Pause(int larbno);
+void MET_SMI_Clear(int larbno);
+int MET_SMI_PowerOn(unsigned int master);
+void MET_SMI_PowerOff(unsigned int master);
+int MET_SMI_LARB_SetCfg(int larbno,
+ unsigned int pm,
+ unsigned int reqtype, unsigned int rwtype, unsigned int dsttype);
+int MET_SMI_LARB_SetPortNo(int larbno, unsigned int idx, unsigned int port);
+int MET_SMI_COMM_SetCfg(int commonno, unsigned int pm, unsigned int reqtype);
+int MET_SMI_COMM_SetPortNo(int commonno, unsigned int idx, unsigned int port);
+int MET_SMI_COMM_SetRWType(int commonno, unsigned int idx, unsigned int rw);
+
+/* config */
+int MET_SMI_GetEna(int larbno);
+int MET_SMI_GetClr(int larbno);
+int MET_SMI_GetPortNo(int larbno);
+int MET_SMI_GetCon(int larbno);
+
+/* cnt */
+int MET_SMI_GetActiveCnt(int larbno);
+int MET_SMI_GetRequestCnt(int larbno);
+int MET_SMI_GetBeatCnt(int larbno);
+int MET_SMI_GetByteCnt(int larbno);
+int MET_SMI_GetCPCnt(int larbno);
+int MET_SMI_GetDPCnt(int larbno);
+int MET_SMI_GetOSTDCnt(int larbno);
+int MET_SMI_GetCP_MAX(int larbno);
+int MET_SMI_GetOSTD_MAX(int larbno);
+
+/* common */
+void MET_SMI_Comm_Init(void);
+void MET_SMI_Comm_Enable(int commonno);
+void MET_SMI_Comm_Disable(int commonno);
+void MET_SMI_Pause(int commonno);
+void MET_SMI_Comm_Clear(int commonno);
+
+/* common config */
+int MET_SMI_Comm_GetEna(int commonno);
+int MET_SMI_Comm_GetClr(int commonno);
+int MET_SMI_Comm_GetType(int commonno);
+int MET_SMI_Comm_GetCon(int commonno);
+
+/* cnt */
+int MET_SMI_Comm_GetPortNo(int commonno);
+int MET_SMI_Comm_GetActiveCnt(int commonno);
+int MET_SMI_Comm_GetRequestCnt(int commonno);
+int MET_SMI_Comm_GetBeatCnt(int commonno);
+int MET_SMI_Comm_GetByteCnt(int commonno);
+int MET_SMI_Comm_GetCPCnt(int commonno);
+int MET_SMI_Comm_GetDPCnt(int commonno);
+int MET_SMI_Comm_GetOSTDCnt(int commonno);
+int MET_SMI_Comm_GetCP_MAX(int commonno);
+int MET_SMI_Comm_GetOSTD_MAX(int commonno);
+
+#endif /* __MT_SMI_H__ */
diff --git a/src/devtools/met_drv_v2/common/sspm/sspm_walltime.c b/src/devtools/met_drv_v2/common/sspm/sspm_walltime.c
new file mode 100644
index 0000000..83cfd90
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sspm/sspm_walltime.c
@@ -0,0 +1,44 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/random.h>
+#include <linux/fs.h>
+
+#include "met_drv.h"
+#include "trace.h"
+/* #include "plf_init.h" */
+#include "sspm/ondiemet_sspm.h"
+
+static void sspm_walltime_start(void)
+{
+ ondiemet_module[ONDIEMET_SSPM] |= ID_WALL_TIME;
+}
+
+static void sspm_walltime_stop(void)
+{
+}
+
+static const char sspm_walltime_header[] = "met-info [000] 0.0: sspm WCLK: freq\n";
+
+static int sspm_walltime_print_header(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, sspm_walltime_header);
+}
+
+struct metdevice met_sspm_walltime = {
+ .name = "sspm_wall_time",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .ondiemet_mode = 0,
+ .print_header = sspm_walltime_print_header,
+ .ondiemet_start = sspm_walltime_start,
+ .ondiemet_stop = sspm_walltime_stop,
+ .ondiemet_print_header = sspm_walltime_print_header,
+};
+EXPORT_SYMBOL(met_sspm_walltime);
diff --git a/src/devtools/met_drv_v2/common/stat.c b/src/devtools/met_drv_v2/common/stat.c
new file mode 100644
index 0000000..22817e4
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/stat.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+/* #include <linux/fs.h> */
+#include <linux/init.h>
+#include <linux/version.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+/* #include <linux/proc_fs.h> */
+#include <linux/sched.h>
+/* #include <linux/seq_file.h> */
+/* #include <linux/slab.h> */
+#include <linux/time.h>
+#include <linux/irqnr.h>
+#include <linux/vmalloc.h>
+/* #include <asm/cputime.h> */
+/* #include <asm-generic/cputime.h> */
+#include <linux/tick.h>
+#include <linux/jiffies.h>
+
+#include <asm/page.h>
+#include <linux/slab.h>
+
+#include "stat.h"
+#include "met_drv.h"
+#include "trace.h"
+
+#define MS_STAT_FMT "%5lu.%06lu"
+#define FMTLX7 ",%llx,%llx,%llx,%llx,%llx,%llx,%llx\n"
+#define FMTLX10 ",%llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx,%llx\n"
+
+
+static DEFINE_PER_CPU(int, cpu_status);
+
+
+/* void ms_st(unsigned long long timestamp, unsigned char cnt, unsigned int *value) */
+noinline void ms_st(unsigned long long timestamp, unsigned char cnt, u64 *value)
+{
+ unsigned long nano_rem = do_div(timestamp, 1000000000);
+
+ switch (cnt) {
+ case 10:
+ MET_TRACE(MS_STAT_FMT FMTLX10, (unsigned long)(timestamp), (nano_rem/1000),
+ value[0], value[1], value[2], value[3], value[4],
+ value[5], value[6], value[7], value[8], value[9]);
+ break;
+ case 7:
+ MET_TRACE(MS_STAT_FMT FMTLX7, (unsigned long)(timestamp), (nano_rem/1000),
+ value[0], value[1], value[2], value[3], value[4],
+ value[5], value[6]);
+ break;
+ }
+}
+
+static void met_stat_start(void)
+{
+ int cpu = raw_smp_processor_id();
+
+ if (get_ctrl_flags() & 1)
+ met_stat.mode = 0;
+
+ per_cpu(cpu_status, cpu) = MET_CPU_ONLINE;
+}
+
+static void met_stat_stop(void)
+{
+}
+
+static int do_stat(void)
+{
+ return met_stat.mode;
+}
+
+u64 met_usecs_to_cputime64(u64 n)
+{
+#if (NSEC_PER_SEC % HZ) == 0
+ /* Common case, HZ = 100, 128, 200, 250, 256, 500, 512, 1000 etc. */
+ return div_u64(n, NSEC_PER_SEC / HZ);
+#elif (HZ % 512) == 0
+ /* overflow after 292 years if HZ = 1024 */
+ return div_u64(n * HZ / 512, NSEC_PER_SEC / 512);
+#else
+ /*
+ * Generic case - optimized for cases where HZ is a multiple of 3.
+ * overflow after 64.99 years, exact for HZ = 60, 72, 90, 120 etc.
+ */
+ return div_u64(n * 9, (9ull * NSEC_PER_SEC + HZ / 2) / HZ);
+#endif
+}
+
+static u64 get_idle_time(int cpu)
+{
+ u64 idle, idle_time = get_cpu_idle_time_us(cpu, NULL);
+
+ if (idle_time == -1ULL) {
+ /* !NO_HZ so we can rely on cpustat.idle */
+ idle = kcpustat_cpu(cpu).cpustat[CPUTIME_IDLE];
+ } else
+ idle = met_usecs_to_cputime64(idle_time);
+
+ return idle;
+}
+
+static u64 get_iowait_time(int cpu)
+{
+ u64 iowait, iowait_time = get_cpu_iowait_time_us(cpu, NULL);
+
+ if (iowait_time == -1ULL) {
+ /* !NO_HZ so we can rely on cpustat.iowait */
+ iowait = kcpustat_cpu(cpu).cpustat[CPUTIME_IOWAIT];
+ } else
+ iowait = met_usecs_to_cputime64(iowait_time);
+
+ return iowait;
+}
+
+
+static unsigned int stat_os_polling(u64 *value, int i)
+{
+ int j = -1;
+
+ /* Copy values here to work around gcc-2.95.3, gcc-2.96 */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_USER]); /* user */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_NICE]); /* nice */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_SYSTEM]); /* system */
+ value[++j] = jiffies_64_to_clock_t(get_idle_time(i)); /* idle */
+ value[++j] = jiffies_64_to_clock_t(get_iowait_time(i)); /* iowait */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_IRQ]); /* irq */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_SOFTIRQ]); /* softirq */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_STEAL]); /* steal */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_GUEST]); /* guest */
+ value[++j] = jiffies_64_to_clock_t(kcpustat_cpu(i).cpustat[CPUTIME_GUEST_NICE]); /* guest_nice */
+
+ return j + 1;
+}
+
+static void met_stat_polling(unsigned long long stamp, int cpu)
+{
+ unsigned char count;
+ u64 value[10] = {0};
+
+ if (per_cpu(cpu_status, cpu) != MET_CPU_ONLINE)
+ return;
+
+ /* return; */
+ if (do_stat()) {
+ count = stat_os_polling(value, cpu);
+ if (count)
+ ms_st(stamp, count, value);
+ }
+}
+
+static const char header[] =
+ "met-info [000] 0.0: met_st_header: user,nice,system,idle,iowait,irq,softirq,steal,guest,guest_nice\n";
+
+static const char help[] = " --stat monitor stat\n";
+
+
+static int met_stat_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static int met_stat_print_header(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, header);
+}
+
+static void met_stat_cpu_state_notify(long cpu, unsigned long action)
+{
+ per_cpu(cpu_status, cpu) = action;
+}
+
+
+struct metdevice met_stat = {
+ .name = "stat",
+ .type = MET_TYPE_PMU,
+ .cpu_related = 1,
+ .start = met_stat_start,
+ .stop = met_stat_stop,
+ .polling_interval = 30,
+ .timed_polling = met_stat_polling,
+ .print_help = met_stat_print_help,
+ .print_header = met_stat_print_header,
+ .cpu_state_notify = met_stat_cpu_state_notify,
+};
diff --git a/src/devtools/met_drv_v2/common/stat.h b/src/devtools/met_drv_v2/common/stat.h
new file mode 100644
index 0000000..b56c5e1
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/stat.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _STAT_H_
+#define _STAT_H_
+
+#include <linux/device.h>
+
+extern struct metdevice met_stat;
+
+int stat_reg(struct kobject *parent);
+void stat_unreg(void);
+
+void stat_start(void);
+void stat_stop(void);
+void stat_polling(unsigned long long stamp, int cpu);
+
+unsigned int get_ctrl_flags(void);
+
+#endif /* _STAT_H_ */
diff --git a/src/devtools/met_drv_v2/common/switch.c b/src/devtools/met_drv_v2/common/switch.c
new file mode 100644
index 0000000..4f50171
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/switch.c
@@ -0,0 +1,294 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+/* include <asm/percpu.h> */
+#include <trace/events/sched.h>
+#include <linux/module.h>
+#include <trace/events/irq.h>
+#include <trace/events/power.h>
+
+#include "interface.h"
+#include "met_drv.h"
+#include "cpu_pmu.h"
+#include "switch.h"
+#include "sampler.h"
+#include "met_kernel_symbol.h"
+/* #include "trace.h" */
+
+/*
+ * IRQ_TIRGGER and CPU_IDLE_TRIGGER
+ */
+/* #define IRQ_TRIGGER */
+/* #define CPU_IDLE_TRIGGER */
+
+static DEFINE_PER_CPU(unsigned int, first_log);
+
+#ifdef __aarch64__
+/* #include <asm/compat.h> */
+#include <linux/compat.h>
+#endif
+
+noinline void mt_switch(struct task_struct *prev, struct task_struct *next)
+{
+ int cpu;
+ int prev_state = 0, next_state = 0;
+
+#ifdef __aarch64__
+ prev_state = !(is_compat_thread(task_thread_info(prev)));
+ next_state = !(is_compat_thread(task_thread_info(next)));
+#endif
+
+ cpu = smp_processor_id();
+ if (per_cpu(first_log, cpu)) {
+ MET_TRACE("%d, %d, %d, %d\n", prev->pid, prev_state, next->pid, next_state);
+ per_cpu(first_log, cpu) = 0;
+ }
+ else if (prev_state != next_state)
+ MET_TRACE("%d, %d, %d, %d\n", prev->pid, prev_state, next->pid, next_state);
+}
+
+
+#if 0 /* move to kernel space */
+MET_DEFINE_PROBE(sched_switch,
+ TP_PROTO(bool preempt, struct task_struct *prev, struct task_struct *next))
+{
+ /* speedup sched_switch callback handle */
+ if (met_switch.mode == 0)
+ return;
+
+ if (met_switch.mode & MT_SWITCH_EVENT_TIMER)
+ met_event_timer_notify();
+
+ if (met_switch.mode & MT_SWITCH_64_32BIT)
+ mt_switch(prev, next);
+
+ if (met_switch.mode & MT_SWITCH_SCHEDSWITCH) {
+ if (get_pmu_profiling_version() == 1)
+ cpupmu_polling(0, smp_processor_id());
+#ifdef MET_SUPPORT_CPUPMU_V2
+ else if (get_pmu_profiling_version() == 2)
+ cpupmu_polling_v2(0, smp_processor_id());
+#endif
+ }
+}
+#endif
+
+void met_sched_switch(struct task_struct *prev, struct task_struct *next)
+{
+ /* speedup sched_switch callback handle */
+ if (met_switch.mode == 0)
+ return;
+
+ if (met_switch.mode & MT_SWITCH_EVENT_TIMER)
+ met_event_timer_notify();
+
+ if (met_switch.mode & MT_SWITCH_64_32BIT)
+ mt_switch(prev, next);
+
+ /* met_perf_cpupmu_status: 0: stop, others: polling */
+ if ((met_switch.mode & MT_SWITCH_SCHEDSWITCH) && met_perf_cpupmu_status)
+ met_perf_cpupmu_polling(0, smp_processor_id());
+}
+
+#ifdef IRQ_TRIGGER
+MET_DEFINE_PROBE(irq_handler_entry, TP_PROTO(int irq, struct irqaction *action))
+{
+ if (met_switch.mode & MT_SWITCH_EVENT_TIMER) {
+ met_event_timer_notify();
+ return;
+ }
+}
+#endif
+
+#ifdef CPU_IDLE_TRIGGER
+MET_DEFINE_PROBE(cpu_idle, TP_PROTO(unsigned int state, unsigned int cpu_id))
+{
+ if (met_switch.mode & MT_SWITCH_EVENT_TIMER) {
+ met_event_timer_notify();
+ return;
+ }
+}
+#endif
+
+#ifdef MET_ANYTIME
+/*
+ * create related subfs file node
+ */
+
+static ssize_t default_on_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "1\n");
+}
+
+static struct kobj_attribute default_on_attr = __ATTR(default_on, 0664, default_on_show, NULL);
+static struct kobject *kobj_cpu;
+#endif
+
+static int met_switch_create_subfs(struct kobject *parent)
+{
+ int ret = 0;
+
+ /* register tracepoints */
+#if 0
+ if (MET_REGISTER_TRACE(sched_switch)) {
+ pr_debug("can not register callback of sched_switch\n");
+ return -ENODEV;
+ }
+#else
+ if (met_export_api_symbol->met_reg_switch)
+ ret = met_export_api_symbol->met_reg_switch();
+#endif
+#ifdef CPU_IDLE_TRIGGER
+ if (MET_REGISTER_TRACE(cpu_idle)) {
+ pr_debug("can not register callback of irq_handler_entry\n");
+ return -ENODEV;
+ }
+#endif
+#ifdef IRQ_TRIGGER
+ if (MET_REGISTER_TRACE(irq_handler_entry)) {
+ pr_debug("can not register callback of irq_handler_entry\n");
+ return -ENODEV;
+ }
+#endif
+
+#ifdef MET_ANYTIME
+ /*
+ * to create default_on file node
+ * let user space can know we can support MET default on
+ */
+ kobj_cpu = parent;
+ ret = sysfs_create_file(kobj_cpu, &default_on_attr.attr);
+ if (ret != 0) {
+ pr_debug("Failed to create default_on in sysfs\n");
+ return -1;
+ }
+#endif
+
+ return ret;
+}
+
+
+static void met_switch_delete_subfs(void)
+{
+#ifdef MET_ANYTIME
+ if (kobj_cpu != NULL) {
+ sysfs_remove_file(kobj_cpu, &default_on_attr.attr);
+ kobj_cpu = NULL;
+ }
+#endif
+#ifdef IRQ_TRIGGER
+ MET_UNREGISTER_TRACE(irq_handler_entry);
+#endif
+#ifdef CPU_IDLE_TRIGGER
+ MET_UNREGISTER_TRACE(cpu_idle);
+#endif
+#if 0
+ MET_UNREGISTER_TRACE(sched_switch);
+#else
+ if (met_export_api_symbol->met_unreg_switch)
+ met_export_api_symbol->met_unreg_switch();
+#endif
+
+}
+
+
+static void (*cpu_timed_polling)(unsigned long long stamp, int cpu);
+/* static void (*cpu_tagged_polling)(unsigned long long stamp, int cpu); */
+
+static void met_switch_start(void)
+{
+ int cpu;
+
+ if (met_switch.mode & MT_SWITCH_SCHEDSWITCH) {
+ cpu_timed_polling = met_cpupmu.timed_polling;
+ /* cpu_tagged_polling = met_cpupmu.tagged_polling; */
+ met_cpupmu.timed_polling = NULL;
+ /* met_cpupmu.tagged_polling = NULL; */
+ }
+
+ for_each_possible_cpu(cpu) {
+ per_cpu(first_log, cpu) = 1;
+ }
+
+}
+
+
+static void met_switch_stop(void)
+{
+ int cpu;
+
+ if (met_switch.mode & MT_SWITCH_SCHEDSWITCH) {
+ met_cpupmu.timed_polling = cpu_timed_polling;
+ /* met_cpupmu.tagged_polling = cpu_tagged_polling; */
+ }
+
+ for_each_possible_cpu(cpu) {
+ per_cpu(first_log, cpu) = 0;
+ }
+
+}
+
+
+static int met_switch_process_argument(const char *arg, int len)
+{
+ unsigned int value = 0;
+ /*ex: mxitem is 0x0005, max value should be (5-1) + (5-2) = 0x100 + 0x11 = 7 */
+ unsigned int max_value = ((MT_SWITCH_MX_ITEM * 2) - 3);
+
+
+ if (met_parse_num(arg, &value, len) < 0)
+ goto arg_switch_exit;
+
+ if ((value < 1) || (value > max_value))
+ goto arg_switch_exit;
+
+ met_switch.mode = value;
+ return 0;
+
+arg_switch_exit:
+ met_switch.mode = 0;
+ return -EINVAL;
+}
+
+static const char header[] =
+ "met-info [000] 0.0: met_switch_header: prev_pid,prev_state,next_pid,next_state\n";
+
+static const char help[] =
+" --switch=mode mode:0x1 - output CPUPMU whenever sched_switch\n"
+" mode:0x2 - output Aarch 32/64 state whenever state changed (no CPUPMU)\n"
+" mode:0x4 - force output count at tag_start/tag_end\n"
+" mode:0x8 - task switch timer\n"
+" mode:0xF - mode 0x1 + 0x2 + 04 + 08\n";
+
+static int met_switch_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static int met_switch_print_header(char *buf, int len)
+{
+ int ret = 0;
+
+ ret =
+ snprintf(buf, PAGE_SIZE, "met-info [000] 0.0: mp_cpu_switch_base: %d\n",
+ met_switch.mode);
+ if (met_switch.mode & MT_SWITCH_64_32BIT)
+ ret += snprintf(buf + ret, PAGE_SIZE, header);
+
+ return ret;
+}
+
+
+struct metdevice met_switch = {
+ .name = "switch",
+ .type = MET_TYPE_PMU,
+ .create_subfs = met_switch_create_subfs,
+ .delete_subfs = met_switch_delete_subfs,
+ .start = met_switch_start,
+ .stop = met_switch_stop,
+ .process_argument = met_switch_process_argument,
+ .print_help = met_switch_print_help,
+ .print_header = met_switch_print_header,
+};
diff --git a/src/devtools/met_drv_v2/common/switch.h b/src/devtools/met_drv_v2/common/switch.h
new file mode 100644
index 0000000..3446df7
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/switch.h
@@ -0,0 +1,29 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MT_SWITCH__
+#define __MT_SWITCH__
+/*
+ * =========================
+ * !!!!!!!!!!!NOTICE!!!!!!!!
+ * =========================
+ * MT_SWITCH OPTION must delcare as Mask value
+ * And sort them from smallest to largest
+ * MT_SWITCH_MX_ITEM was used to determine argument range
+*/
+enum {
+ /* =================== */
+ /* user define mt switch event */
+ /* =================== */
+ MT_SWITCH_SCHEDSWITCH = 0x0001,
+ MT_SWITCH_64_32BIT = 0x0002,
+ MT_SWITCH_TAGPOLLING = 0x0004,
+ MT_SWITCH_EVENT_TIMER = 0x0008,
+ /* =================== */
+ MT_SWITCH_MX_ITEM
+};
+
+extern struct metdevice met_switch;
+#endif
diff --git a/src/devtools/met_drv_v2/common/sync_write.h b/src/devtools/met_drv_v2/common/sync_write.h
new file mode 100644
index 0000000..0bcac7d
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/sync_write.h
@@ -0,0 +1,80 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef MT_SYNC_WRITE_H
+#define MT_SYNC_WRITE_H
+
+#if defined(__KERNEL__)
+
+#include <linux/io.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Define macros.
+ */
+#define mt_reg_sync_writel(v, a) \
+ do { \
+ __raw_writel((v), (void __force __iomem *)((a))); \
+ dsb(sy); \
+ } while (0)
+
+#define mt_reg_sync_writew(v, a) \
+ do { \
+ __raw_writew((v), (void __force __iomem *)((a))); \
+ dsb(sy); \
+ } while (0)
+
+#define mt_reg_sync_writeb(v, a) \
+ do { \
+ __raw_writeb((v), (void __force __iomem *)((a))); \
+ dsb(sy); \
+ } while (0)
+
+#if IS_ENABLED(CONFIG_64BIT)
+#define mt_reg_sync_writeq(v, a) \
+ do { \
+ __raw_writeq((v), (void __force __iomem *)((a))); \
+ dsb(sy); \
+ } while (0)
+#endif
+
+#else /* __KERNEL__ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#define mt_reg_sync_writel(v, a) mt65xx_reg_sync_writel(v, a)
+#define mt_reg_sync_writew(v, a) mt65xx_reg_sync_writew(v, a)
+#define mt_reg_sync_writeb(v, a) mt65xx_reg_sync_writeb(v, a)
+
+#define dsb() \
+ { \
+ __asm__ __volatile__("dsb sy" : : : "memory"); \
+ }
+
+#define mt65xx_reg_sync_writel(v, a) \
+ do { \
+ *(volatile unsigned int *)(a) = (v); \
+ dsb(); \
+ } while (0)
+
+#define mt65xx_reg_sync_writew(v, a) \
+ do { \
+ *(volatile unsigned short *)(a) = (v); \
+ dsb(); \
+ } while (0)
+
+#define mt65xx_reg_sync_writeb(v, a) \
+ do { \
+ *(volatile unsigned char *)(a) = (v); \
+ dsb(); \
+ } while (0)
+
+#endif /* __KERNEL__ */
+
+#endif /* !MT_SYNC_WRITE_H */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met.c b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met.c
new file mode 100644
index 0000000..df11dc0
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met.c
@@ -0,0 +1,190 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/string.h>
+
+#include "met_drv.h" /* for metdevice */
+#include "interface.h" /* for PR_BOOTMSG */
+#include "tinysys_cpu_eb.h"
+#include "tinysys_mgr.h" /* for ondiemet_module */
+#include "cpu_eb_met_log.h" /* for cpu_eb_buffer_size */
+#include "cpu_eb_cpu_pmu_hw_def.h" /* for cpu_eb_cpu_pmu_header */
+#include "cpu_eb_ptpod_hw_def.h" /* for cpu_eb_ptpod_header */
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+static void _cpu_eb_start(void);
+static void _cpu_eb_stop(void);
+static int _cpu_eb_process_argument(const char *arg, int len);
+static int _cpu_eb_print_help(char *buf, int len);
+static int _cpu_eb_print_header(char *buf, int len);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+struct metdevice met_cpu_eb = {
+ .name = "cpu_eb",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_MISC,
+ .cpu_related = 0,
+ .ondiemet_mode = 1,
+ .ondiemet_start = _cpu_eb_start,
+ .ondiemet_stop = _cpu_eb_stop,
+ .ondiemet_process_argument = _cpu_eb_process_argument,
+ .ondiemet_print_help = _cpu_eb_print_help,
+ .ondiemet_print_header = _cpu_eb_print_header,
+};
+EXPORT_SYMBOL(met_cpu_eb);
+
+
+/*****************************************************************************
+ * internal variable declaration
+ *****************************************************************************/
+static const char help[] = "--cpu_eb=module_name\n";
+static const char header[] = "met-info [000] 0.0: cpu_eb_header: ";
+
+
+/*****************************************************************************
+ * external function implement
+ *****************************************************************************/
+void notify_cpu_eb_cpu_pmu(int flag)
+{
+ if (flag == 1) {
+ ondiemet_module[ONDIEMET_CPU_EB] |= (0x1 << MID_EB_CPU_PMU);
+ } else {
+ ondiemet_module[ONDIEMET_CPU_EB] &= ~(0x1 << MID_EB_CPU_PMU);
+ }
+}
+
+
+/*****************************************************************************
+ * internal function implement
+ *****************************************************************************/
+static void _cpu_eb_start(void)
+{
+ if (cpu_eb_buffer_size == 0) {
+ ondiemet_module[ONDIEMET_CPU_EB] = 0;
+ met_cpu_eb.mode = 0;
+ return;
+ }
+
+ return;
+}
+
+
+static void _cpu_eb_stop(void)
+{
+ return;
+}
+
+
+static int _cpu_eb_process_argument(const char *arg, int len)
+{
+ if (strncmp(arg, "cpu_pmu", strlen("cpu_pmu")) == 0) {
+ ondiemet_module[ONDIEMET_CPU_EB] |= (0x1 << MID_EB_CPU_PMU);
+ }
+
+ if (strncmp(arg, "sensor_network", strlen("sensor_network")) == 0) {
+ ondiemet_module[ONDIEMET_CPU_EB] |= (0x1 << MID_EB_SENSOR_NETWORK);
+ }
+
+ if (strncmp(arg, "system_pi", strlen("system_pi")) == 0) {
+ ondiemet_module[ONDIEMET_CPU_EB] |= (0x1 << MID_EB_SYSTEM_PI);
+ }
+
+ if (strncmp(arg, "ptpod", strlen("ptpod")) == 0) {
+ ondiemet_module[ONDIEMET_CPU_EB] |= (0x1 << MID_EB_PTPOD);
+ }
+ met_cpu_eb.mode = 1;
+
+ return 0;
+}
+
+
+static int _cpu_eb_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+
+static int _cpu_eb_print_header(char *buf, int len)
+{
+ int cnt = 0;
+ int cpu_pmu_flag = 0;
+ int ptpod_flag = 0;
+
+ if (met_cpu_eb.mode == 0) {
+ PR_BOOTMSG("eb %s %d\n", __FUNCTION__, __LINE__);
+ return 0;
+ }
+
+ len = snprintf(buf, PAGE_SIZE, "%s", header);
+ if (ondiemet_module[ONDIEMET_CPU_EB] & (0x1 << MID_EB_CPU_PMU)) {
+ len += snprintf(buf + len, PAGE_SIZE - len, "cpu_pmu");
+ cnt++;
+ cpu_pmu_flag = 1;
+ }
+
+ if (ondiemet_module[ONDIEMET_CPU_EB] & (0x1 << MID_EB_SENSOR_NETWORK)) {
+ if (cnt > 0)
+ len += snprintf(buf + len, PAGE_SIZE - len, ",sensor_network");
+ else
+ len += snprintf(buf + len, PAGE_SIZE - len, "sensor_network");
+ cnt++;
+ }
+
+ if (ondiemet_module[ONDIEMET_CPU_EB] & (0x1 << MID_EB_SYSTEM_PI)) {
+ if (cnt > 0)
+ len += snprintf(buf + len, PAGE_SIZE - len, ",system_pi");
+ else
+ len += snprintf(buf + len, PAGE_SIZE - len, "system_pi");
+ cnt++;
+ }
+
+ if (ondiemet_module[ONDIEMET_CPU_EB] & (0x1 << MID_EB_PTPOD)) {
+ if (cnt > 0)
+ len += snprintf(buf + len, PAGE_SIZE - len, ",ptpod");
+ else
+ len += snprintf(buf + len, PAGE_SIZE - len, "ptpod");
+ cnt++;
+ ptpod_flag = 1;
+ }
+
+ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+
+ if (cpu_pmu_flag == 1) {
+ len += snprintf(buf + len, PAGE_SIZE - len, cpu_eb_cpu_pmu_header);
+ }
+
+ if (ptpod_flag == 1) {
+ len += snprintf(buf + len, PAGE_SIZE - len, cpu_eb_ptpod_header);
+ }
+
+ ondiemet_module[ONDIEMET_CPU_EB] = 0;
+ met_cpu_eb.mode = 0;
+
+ return len;
+}
+
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met.h b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met.h
new file mode 100644
index 0000000..96ae5c0
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met.h
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __CPU_EB_MET_H__
+#define __CPU_EB_MET_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include "met_drv.h" /* for metdevice */
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+void notify_cpu_eb_cpu_pmu(int flag);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+extern struct metdevice met_cpu_eb;
+
+
+#endif /* __CPU_EB_MET_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_ipi_handle.c b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_ipi_handle.c
new file mode 100644
index 0000000..c108fb3
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_ipi_handle.c
@@ -0,0 +1,419 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/kthread.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/signal.h>
+#include <linux/semaphore.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <asm/io.h> /* for ioremap and iounmap */
+
+#include "mtk_tinysys_ipi.h" /* for mtk_ipi_device */
+#include "mcupm_ipi_id.h" /* for mcupm_ipidev */
+
+#include "cpu_eb_met_log.h"
+#include "cpu_eb_met_ipi_handle.h"
+#include "tinysys_cpu_eb.h" /* for mcupm_ipidev_symbol */
+#include "tinysys_mgr.h" /* for ondiemet_module */
+#include "interface.h"
+#include "core_plf_init.h"
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+extern unsigned int met_get_chip_id(void);
+extern char *met_get_platform(void);
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+static void _log_done_cb(const void *p);
+static int _met_ipi_cb(
+ unsigned int ipi_id,
+ void *prdata,
+ void *data,
+ unsigned int len);
+static int _cpu_eb_recv_thread(void *data);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+int cpu_eb_buf_available;
+EXPORT_SYMBOL(cpu_eb_buf_available);
+
+
+/*****************************************************************************
+ * internal variable declaration
+ *****************************************************************************/
+struct mtk_ipi_device *mcupm_ipidev_symbol;
+static unsigned int recv_buf[4];
+static unsigned int rdata;
+static unsigned int ackdata;
+static unsigned int ridx, widx, wlen;
+static unsigned int log_size;
+static struct task_struct *_cpu_eb_recv_task;
+static int cpu_eb_ipi_thread_started;
+static int cpu_eb_buffer_dumping;
+static int cpu_eb_recv_thread_comp;
+static int cpu_eb_run_mode = CPU_EB_RUN_NORMAL;
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+void start_cpu_eb_ipi_recv_thread()
+{
+ int ret = 0;
+
+ if (mcupm_ipidev_symbol == NULL) {
+ mcupm_ipidev_symbol = (struct mtk_ipi_device *)symbol_get(mcupm_ipidev);
+ }
+
+ if (mcupm_ipidev_symbol == NULL) {
+ PR_BOOTMSG("mcupm_ipidev_symbol is NULL\n", __FUNCTION__);
+ return;
+ }
+
+ // Tinysys send ipi to APSYS
+ ret = mtk_ipi_register(mcupm_ipidev_symbol, IPIR_C_MET, _met_ipi_cb,
+ NULL, (void *) &recv_buf);
+ if (ret) {
+ PR_BOOTMSG("mtk_ipi_register:%d failed:%d\n", IPIR_C_MET, ret);
+ } else {
+ PR_BOOTMSG("mtk_ipi_register IPIR_C_MET success \n");
+ }
+
+ // APSYS send ipi to Tinysys
+ ret = mtk_ipi_register(mcupm_ipidev_symbol, IPIS_C_MET, NULL,
+ NULL, (void *) &ackdata);
+ if (ret) {
+ PR_BOOTMSG("mtk_ipi_register:%d failed:%d\n", IPIS_C_MET, ret);
+ } else {
+ PR_BOOTMSG("mtk_ipi_register IPIS_C_MET success \n");
+ }
+
+ if (cpu_eb_ipi_thread_started != 1) {
+ cpu_eb_recv_thread_comp = 0;
+ _cpu_eb_recv_task = kthread_run(_cpu_eb_recv_thread,
+ NULL, "cpu_ebcpu_eb_recv");
+ if (IS_ERR(_cpu_eb_recv_task)) {
+ PR_BOOTMSG("Can not create cpu_ebcpu_eb_recv\n");
+
+ } else {
+ cpu_eb_ipi_thread_started = 1;
+ }
+ }
+}
+
+
+void stop_cpu_eb_ipi_recv_thread()
+{
+ if (_cpu_eb_recv_task) {
+ cpu_eb_recv_thread_comp = 1;
+
+ kthread_stop(_cpu_eb_recv_task);
+ _cpu_eb_recv_task = NULL;
+ cpu_eb_ipi_thread_started = 0;
+
+ if (mcupm_ipidev_symbol) {
+ // Tinysys send ipi to APSYS
+ mtk_ipi_unregister(mcupm_ipidev_symbol, IPIR_C_MET);
+ // APSYS send ipi to Tinysys
+ mtk_ipi_unregister(mcupm_ipidev_symbol, IPIS_C_MET);
+ }
+ }
+}
+
+
+void cpu_eb_start(void)
+{
+ int ret = 0;
+ unsigned int rdata = 0;
+ unsigned int ipi_buf[4];
+ const char* platform_name = NULL;
+ unsigned int platform_id = 0;
+
+ /* clear DRAM buffer */
+ if (cpu_eb_log_virt_addr != NULL) {
+ memset_io((void *)cpu_eb_log_virt_addr, 0, cpu_eb_buffer_size);
+ } else {
+ return;
+ }
+
+ platform_name = met_get_platform();
+ if (platform_name) {
+ char buf[5];
+
+ memset(buf, 0x0, 5);
+ memcpy(buf, &platform_name[2], 4);
+ ret = kstrtouint(buf, 10, &platform_id);
+ }
+
+ /* send DRAM physical address */
+ ipi_buf[0] = MET_MAIN_ID | MET_BUFFER_INFO;
+ ipi_buf[1] = (unsigned int)cpu_eb_log_phy_addr; /* address */
+ if (ret == 0) {
+ ipi_buf[2] = platform_id;
+ } else {
+ ipi_buf[2] = 0;
+ }
+
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_cpu_eb_command((void *)ipi_buf, 4, &rdata, 1);
+
+ /* start ondiemet now */
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_START;
+ ipi_buf[1] = ondiemet_module[ONDIEMET_CPU_EB] ;
+ ipi_buf[2] = CPU_EB_LOG_FILE;
+ ipi_buf[3] = CPU_EB_RUN_NORMAL;
+ ret = met_ipi_to_cpu_eb_command((void *)ipi_buf, 4, &rdata, 1);
+}
+
+
+void cpu_eb_stop(void)
+{
+ int ret = 0;
+ unsigned int rdata = 0;
+ unsigned int ipi_buf[4];
+ unsigned int chip_id = 0;
+
+ chip_id = met_get_chip_id();
+ if (cpu_eb_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_STOP;
+ ipi_buf[1] = chip_id;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_cpu_eb_command((void *)ipi_buf, 4, &rdata, 1);
+ }
+}
+
+
+void cpu_eb_extract(void)
+{
+ int ret;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+ int count;
+
+ count = 20;
+ if (cpu_eb_buf_available == 1) {
+ while ((cpu_eb_buffer_dumping == 1) && (count != 0)) {
+ msleep(50);
+ count--;
+ }
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_EXTRACT;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_cpu_eb_command((void *)ipi_buf, 4, &rdata, 1);
+
+ }
+}
+
+
+void cpu_eb_flush(void)
+{
+ int ret;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ if (cpu_eb_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_FLUSH;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_cpu_eb_command((void *)ipi_buf, 4, &rdata, 1);
+ }
+}
+
+
+int met_ipi_to_cpu_eb_command(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot)
+{
+ int ret = 0;
+
+ if (mcupm_ipidev_symbol == NULL) {
+ return -1;
+ }
+
+ ret = mtk_ipi_send_compl(mcupm_ipidev_symbol, IPIS_C_MET,
+ IPI_SEND_WAIT, (void*)buffer, slot, 2000);
+ *retbuf = ackdata;
+ if (ret != 0) {
+ PR_BOOTMSG("met_ipi_to_cpu_eb_command error(%d)\n", ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(met_ipi_to_cpu_eb_command);
+
+
+int met_ipi_to_cpu_eb_command_async(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot)
+{
+ int ret = 0;
+
+ if (mcupm_ipidev_symbol == NULL) {
+ return -1;
+ }
+ ret = mtk_ipi_send(mcupm_ipidev_symbol, IPIS_C_MET,
+ IPI_SEND_WAIT, (void*)buffer, slot, 2000);
+ *retbuf = ackdata;
+
+ if (ret != 0) {
+ PR_BOOTMSG("met_ipi_to_cpu_eb_command_async error(%d)\n", ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(met_ipi_to_cpu_eb_command_async);
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+static void _log_done_cb(const void *p)
+{
+ unsigned int ret;
+ unsigned int rdata = 0;
+ unsigned int ipi_buf[4];
+ unsigned int opt = (p != NULL);
+
+ if (opt == 0) {
+ cpu_eb_buffer_dumping = 0;
+
+ ipi_buf[0] = MET_MAIN_ID | MET_RESP_AP2MD;
+ ipi_buf[1] = MET_DUMP_BUFFER;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_cpu_eb_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+
+static int _met_ipi_cb(unsigned int ipi_id, void *prdata, void *data, unsigned int len)
+{
+ unsigned int cmd;
+
+ if (cpu_eb_recv_thread_comp == 1) {
+ PR_BOOTMSG("eb %s %d\n", __FUNCTION__, __LINE__);
+ return 0;
+ }
+
+ cmd = recv_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ cpu_eb_buffer_dumping = 1;
+ ridx = recv_buf[1];
+ widx = recv_buf[2];
+ log_size = recv_buf[3];
+ break;
+
+ case MET_CLOSE_FILE: /* no argument */
+ /* do close file */
+ ridx = recv_buf[1];
+ widx = recv_buf[2];
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static int _cpu_eb_recv_thread(void *data)
+{
+ int ret = 0;
+ unsigned int cmd = 0;
+
+ do {
+ ret = mtk_ipi_recv_reply(mcupm_ipidev_symbol, IPIR_C_MET, (void *)&rdata, 1);
+ if (ret) {
+ PR_BOOTMSG("ipi_register:%d failed:%d\n", IPIR_C_MET, ret);
+ }
+ if (cpu_eb_recv_thread_comp == 1) {
+ while (!kthread_should_stop()) {
+ ;
+ }
+ return 0;
+ }
+
+ cmd = recv_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ cpu_eb_log_req_enq((char *)(cpu_eb_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)1);
+ cpu_eb_log_req_enq((char *)(cpu_eb_log_virt_addr),
+ widx * 4, _log_done_cb, (void *)0);
+ } else {
+ wlen = widx - ridx;
+ cpu_eb_log_req_enq((char *)(cpu_eb_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)0);
+ }
+ break;
+
+ case MET_CLOSE_FILE: /* no argument */
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ cpu_eb_log_req_enq((char *)(cpu_eb_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)1);
+ cpu_eb_log_req_enq((char *)(cpu_eb_log_virt_addr),
+ widx * 4, _log_done_cb, (void *)1);
+ } else {
+ wlen = widx - ridx;
+ cpu_eb_log_req_enq((char *)(cpu_eb_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)1);
+ }
+ ret = cpu_eb_log_stop();
+ if (cpu_eb_run_mode == CPU_EB_RUN_CONTINUOUS) {
+ /* clear the memory */
+ memset_io((void *)cpu_eb_log_virt_addr, 0,
+ cpu_eb_buffer_size);
+ /* re-start ondiemet again */
+ cpu_eb_start();
+ }
+ break;
+
+ default:
+ break;
+ }
+ } while (!kthread_should_stop());
+
+ return 0;
+}
+
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_ipi_handle.h b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_ipi_handle.h
new file mode 100644
index 0000000..f70fb28
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_ipi_handle.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __CPU_EB_MET_IPI_HANDLE_H__
+#define __CPU_EB_MET_IPI_HANDLE_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+void start_cpu_eb_ipi_recv_thread(void);
+void stop_cpu_eb_ipi_recv_thread(void);
+
+void cpu_eb_start(void);
+void cpu_eb_stop(void);
+void cpu_eb_extract(void);
+void cpu_eb_flush(void);
+
+int met_ipi_to_cpu_eb_command(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot);
+int met_ipi_to_cpu_eb_command_async(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+
+
+#endif /* __CPU_EB_MET_IPI_HANDLE_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_log.c b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_log.c
new file mode 100644
index 0000000..6e1f623
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_log.c
@@ -0,0 +1,691 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/completion.h>
+#include <linux/module.h> /* symbol_get */
+
+#include "interface.h"
+
+#include "mcupm_driver.h"
+#include "mcupm_driver.h"
+
+#include "cpu_eb_met_log.h"
+#include "cpu_eb_met_ipi_handle.h"
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+#define CPU_EB_LOG_REQ 1
+#define CPU_EB_LOG_STOP 2
+
+#define PID_NONE (-1)
+
+#define CPU_EB_LOG_STOP_MODE 0
+#define CPU_EB_LOG_RUN_MODE 1
+#define CPU_EB_LOG_DEBUG_MODE 2
+
+#define _cpu_eb_log_req_init(req, cmd, s, n, pf, p) \
+ do { \
+ INIT_LIST_HEAD(&req->list); \
+ req->cmd_type = cmd; \
+ req->src = s; \
+ req->num = n; \
+ req->on_fini_cb = pf; \
+ req->param = p; \
+ } while (0)
+
+#define _cpu_eb_log_req_fini(req) \
+ do { \
+ if (req->on_fini_cb) \
+ req->on_fini_cb(req->param); \
+ kfree(req); \
+ } while (0)
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+struct cpu_eb_log_req_q_t {
+ struct list_head listq;
+ struct mutex lockq;
+ struct completion new_evt_comp;
+ int closeq_flag;
+} cpu_eb_log_req_q;
+
+struct cpu_eb_log_req {
+ struct list_head list;
+ int cmd_type;
+ const char *src;
+ size_t num;
+
+ void (*on_fini_cb)(const void *p);
+ const void *param;
+};
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+static void _log_stop_cb(const void *p);
+static int _down_freezable_interruptible(struct completion *comp);
+
+static void _cpu_eb_log_req_q_init(struct cpu_eb_log_req_q_t *q);
+static void _cpu_eb_log_req_undeq(struct cpu_eb_log_req *req);
+static int _cpu_eb_log_req_enq(struct cpu_eb_log_req *req);
+static struct cpu_eb_log_req *_cpu_eb_log_req_deq(void);
+static void _cpu_eb_log_req_open(void);
+static int _cpu_eb_log_req_closed(void);
+static int _cpu_eb_log_req_working(void);
+static void *_cpu_eb_trace_seq_next(struct seq_file *seqf, loff_t *offset);
+
+static void *cpu_eb_trace_seq_start(struct seq_file *seqf, loff_t *offset);
+static void cpu_eb_trace_seq_stop(struct seq_file *seqf, void *p);
+static void *cpu_eb_trace_seq_next(struct seq_file *seqf, void *p, loff_t *offset);
+static int cpu_eb_trace_seq_show(struct seq_file *seqf, void *p);
+static int cpu_eb_trace_open(struct inode *inode, struct file *fp);
+
+static ssize_t cpu_eb_log_write_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count);
+static ssize_t cpu_eb_log_run_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t cpu_eb_log_run_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+void *cpu_eb_log_virt_addr;
+
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+dma_addr_t cpu_eb_log_phy_addr;
+#else
+unsigned int cpu_eb_log_phy_addr;
+#endif
+
+unsigned int cpu_eb_buffer_size;
+
+extern int cpu_eb_buf_available;
+
+
+/*****************************************************************************
+ * internal variable declaration
+ *****************************************************************************/
+static int cpu_eb_trace_run;
+static pid_t trace_owner_pid = PID_NONE;
+
+static struct mutex lock_tracef;
+static struct mutex lock_trace_owner_pid;
+
+static struct completion log_start_comp;
+static struct completion log_stop_comp;
+
+static DEVICE_ATTR(cpu_eb_log_write, 0220, NULL, cpu_eb_log_write_store);
+static DEVICE_ATTR(cpu_eb_log_run, 0664, cpu_eb_log_run_show, cpu_eb_log_run_store);;
+
+static const struct seq_operations cpu_eb_trace_seq_ops = {
+ .start = cpu_eb_trace_seq_start,
+ .next = cpu_eb_trace_seq_next,
+ .stop = cpu_eb_trace_seq_stop,
+ .show = cpu_eb_trace_seq_show
+};
+
+static const struct file_operations cpu_eb_trace_fops = {
+ .owner = THIS_MODULE,
+ .open = cpu_eb_trace_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+
+/*****************************************************************************
+ * external function ipmlement
+ *****************************************************************************/
+int cpu_eb_log_init(struct device *dev)
+{
+ int ret = 0;
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ struct dentry *d;
+ struct dentry *met_dir = NULL;
+#else
+ struct proc_dir_entry *d;
+ struct proc_dir_entry *met_dir = NULL;
+#endif
+ phys_addr_t (*get_size_sym)(unsigned int id) = NULL;
+
+ met_dir = dev_get_drvdata(dev);
+ mutex_init(&lock_tracef);
+ _cpu_eb_log_req_q_init(&cpu_eb_log_req_q);
+ init_completion(&log_start_comp);
+ init_completion(&log_stop_comp);
+ mutex_init(&lock_trace_owner_pid);
+
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ d = debugfs_create_file("cpu_eb_trace", 0600, met_dir, NULL, &cpu_eb_trace_fops);
+ if (!d) {
+ PR_BOOTMSG("can not create devide node in debugfs: cpu_eb_trace\n");
+ return -ENOMEM;
+ }
+#else
+ d = proc_create("cpu_eb_trace", 0600, met_dir, &cpu_eb_trace_fops);
+ if (!d) {
+ PR_BOOTMSG("can not create devide node in procfs: cpu_eb_trace\n");
+ return -ENOMEM;
+ }
+#endif
+
+ cpu_eb_trace_run = _cpu_eb_log_req_working();
+ ret = device_create_file(dev, &dev_attr_cpu_eb_log_run);
+ if (ret != 0) {
+ PR_BOOTMSG("can not create device node: cpu_eb_log_run\n");
+ return ret;
+ }
+
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+ cpu_eb_log_virt_addr = dma_alloc_coherent(dev, 0x800000,
+ &cpu_eb_log_phy_addr, GFP_ATOMIC);
+ if (cpu_eb_log_virt_addr) {
+ cpu_eb_buffer_size = 0x800000;
+ cpu_eb_buf_available = 1;
+ } else {
+ cpu_eb_buf_available = 0;
+ }
+#else
+ get_size_sym = symbol_get(mcupm_reserve_mem_get_size);
+ if (get_size_sym) {
+ cpu_eb_buffer_size = get_size_sym(MCUPM_MET_ID);
+ PR_BOOTMSG("cpu_eb_buffer_size=%x\n", cpu_eb_buffer_size);
+ } else {
+ PR_BOOTMSG("symbol_get mcupm_reserve_mem_get_size failure\n");
+ }
+
+ if (cpu_eb_buffer_size > 0) {
+ phys_addr_t (*get_phys_sym)(unsigned int id) = NULL;
+ phys_addr_t (*get_virt_sym)(unsigned int id) = NULL;
+
+ get_phys_sym = symbol_get(mcupm_reserve_mem_get_virt);
+ get_virt_sym = symbol_get(mcupm_reserve_mem_get_phys);
+ if (get_phys_sym) {
+ cpu_eb_log_virt_addr = (void*)get_phys_sym(MCUPM_MET_ID);
+ PR_BOOTMSG("cpu_eb_log_virt_addr=%x\n", cpu_eb_log_virt_addr);
+ } else {
+ PR_BOOTMSG("symbol_get mcupm_reserve_mem_get_virt failure\n");
+ }
+ if (get_virt_sym) {
+ cpu_eb_log_phy_addr = get_virt_sym(MCUPM_MET_ID);
+ PR_BOOTMSG("cpu_eb_log_phy_addr=%x\n", cpu_eb_log_phy_addr);
+ } else {
+ PR_BOOTMSG("symbol_get mcupm_reserve_mem_get_phys failure\n");
+ }
+ cpu_eb_buf_available = 1;
+ } else {
+ cpu_eb_buf_available = 0;
+ }
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+ start_cpu_eb_ipi_recv_thread();
+
+ return 0;
+}
+
+
+int cpu_eb_log_uninit(struct device *dev)
+{
+ stop_cpu_eb_ipi_recv_thread();
+
+ if (cpu_eb_log_virt_addr != NULL) {
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+ dma_free_coherent(dev, cpu_eb_buffer_size, cpu_eb_log_virt_addr,
+ cpu_eb_log_phy_addr);
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+ cpu_eb_log_virt_addr = NULL;
+ }
+
+ device_remove_file(dev, &dev_attr_cpu_eb_log_run);
+ return 0;
+}
+
+
+int cpu_eb_log_start(void)
+{
+ int ret = 0;
+
+ /* TODO: choose a better return value */
+ if (_cpu_eb_log_req_working()) {
+ return -EINVAL;
+ }
+
+ if (!_cpu_eb_log_req_closed()) {
+ /*ret = down_killable(&log_start_sema);*/
+ ret = wait_for_completion_killable(&log_start_comp);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ _cpu_eb_log_req_open();
+
+ return 0;
+}
+
+
+int cpu_eb_log_stop(void)
+{
+ int ret = 0;
+ struct cpu_eb_log_req *req = NULL;
+
+ if (_cpu_eb_log_req_closed()) {
+ return -EINVAL;
+ }
+
+ req = kmalloc(sizeof(*req), GFP_ATOMIC);
+ _cpu_eb_log_req_init(req, CPU_EB_LOG_STOP, NULL, 0, _log_stop_cb, NULL);
+
+ init_completion(&log_start_comp);
+ init_completion(&log_stop_comp);
+
+ ret = _cpu_eb_log_req_enq(req);
+ if (ret) {
+ return ret;
+ }
+
+ return wait_for_completion_killable(&log_stop_comp);
+}
+
+
+int cpu_eb_log_req_enq(
+ const char *src, size_t num,
+ void (*on_fini_cb)(const void *p),
+ const void *param)
+{
+ struct cpu_eb_log_req *req = kmalloc(sizeof(*req), GFP_ATOMIC);
+
+ _cpu_eb_log_req_init(req, CPU_EB_LOG_REQ, src, num, on_fini_cb, param);
+ return _cpu_eb_log_req_enq(req);
+}
+
+
+int cpu_eb_parse_num(const char *str, unsigned int *value, int len)
+{
+ int ret = 0;
+
+ if (len <= 0) {
+ return -1;
+ }
+
+ if ((len > 2) && ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')))) {
+ ret = kstrtouint(str, 16, value);
+ } else {
+ ret = kstrtouint(str, 10, value);
+ }
+
+ if (ret != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+static void _log_stop_cb(const void *p)
+{
+ complete(&log_start_comp);
+ complete(&log_stop_comp);
+}
+
+
+static int _down_freezable_interruptible(struct completion *comp)
+{
+ int ret = 0;
+
+ freezer_do_not_count();
+ ret = wait_for_completion_interruptible(comp);
+ freezer_count();
+
+ return ret;
+}
+
+
+static void _cpu_eb_log_req_q_init(struct cpu_eb_log_req_q_t *q)
+{
+ INIT_LIST_HEAD(&q->listq);
+ mutex_init(&q->lockq);
+ init_completion(&q->new_evt_comp);
+ q->closeq_flag = 1;
+}
+
+
+/*
+ undequeue is seen as a roll-back operation,
+ so it can be done even when the queue is closed
+*/
+static void _cpu_eb_log_req_undeq(struct cpu_eb_log_req *req)
+{
+ mutex_lock(&cpu_eb_log_req_q.lockq);
+ list_add(&req->list, &cpu_eb_log_req_q.listq);
+ mutex_unlock(&cpu_eb_log_req_q.lockq);
+
+ complete(&cpu_eb_log_req_q.new_evt_comp);
+}
+
+
+static int _cpu_eb_log_req_enq(struct cpu_eb_log_req *req)
+{
+ mutex_lock(&cpu_eb_log_req_q.lockq);
+ if (cpu_eb_log_req_q.closeq_flag) {
+ mutex_unlock(&cpu_eb_log_req_q.lockq);
+ return -EBUSY;
+ }
+
+ list_add_tail(&req->list, &cpu_eb_log_req_q.listq);
+ if (req->cmd_type == CPU_EB_LOG_STOP) {
+ cpu_eb_log_req_q.closeq_flag = 1;
+ }
+ mutex_unlock(&cpu_eb_log_req_q.lockq);
+
+ complete(&cpu_eb_log_req_q.new_evt_comp);
+
+ return 0;
+}
+
+
+static struct cpu_eb_log_req *_cpu_eb_log_req_deq(void)
+{
+ struct cpu_eb_log_req *ret_req;
+
+ if (_down_freezable_interruptible(&cpu_eb_log_req_q.new_evt_comp)) {
+ return NULL;
+ }
+
+ mutex_lock(&cpu_eb_log_req_q.lockq);
+ ret_req = list_entry(cpu_eb_log_req_q.listq.next, struct cpu_eb_log_req, list);
+ list_del_init(&ret_req->list);
+ mutex_unlock(&cpu_eb_log_req_q.lockq);
+
+ return ret_req;
+}
+
+
+static void _cpu_eb_log_req_open(void)
+{
+ mutex_lock(&cpu_eb_log_req_q.lockq);
+ cpu_eb_log_req_q.closeq_flag = 0;
+ mutex_unlock(&cpu_eb_log_req_q.lockq);
+}
+
+
+static int _cpu_eb_log_req_closed(void)
+{
+ int ret = 0;
+
+ mutex_lock(&cpu_eb_log_req_q.lockq);
+ ret = cpu_eb_log_req_q.closeq_flag && list_empty(&cpu_eb_log_req_q.listq);
+ mutex_unlock(&cpu_eb_log_req_q.lockq);
+
+ return ret;
+}
+
+
+static int _cpu_eb_log_req_working(void)
+{
+ int ret = 0;
+
+ mutex_lock(&cpu_eb_log_req_q.lockq);
+ ret = !cpu_eb_log_req_q.closeq_flag;
+ mutex_unlock(&cpu_eb_log_req_q.lockq);
+
+ return ret;
+}
+
+
+static void *_cpu_eb_trace_seq_next(struct seq_file *seqf, loff_t *offset)
+{
+ struct cpu_eb_log_req *next_req;
+
+ if (cpu_eb_trace_run == CPU_EB_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("_cpu_eb_trace_seq_next: pid: %d\n", current->pid);
+ }
+
+ if (_cpu_eb_log_req_closed()) {
+ return NULL;
+ }
+
+ next_req = _cpu_eb_log_req_deq();
+ if (next_req == NULL) {
+ return NULL;
+ }
+
+ if (next_req->cmd_type == CPU_EB_LOG_STOP) {
+ _cpu_eb_log_req_fini(next_req);
+ return NULL;
+ }
+
+ return (void *) next_req;
+}
+
+
+static void *cpu_eb_trace_seq_start(struct seq_file *seqf, loff_t *offset)
+{
+ void *ret;
+
+ if (cpu_eb_trace_run == CPU_EB_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("cpu_eb_trace_seq_start: locked_pid: %d, pid: %d, offset: %llu\n",
+ trace_owner_pid, current->pid, *offset);
+ }
+
+ if (!mutex_trylock(&lock_tracef)) {
+ return NULL;
+ }
+
+ mutex_lock(&lock_trace_owner_pid);
+ trace_owner_pid = current->pid;
+ current->flags |= PF_NOFREEZE;
+ mutex_unlock(&lock_trace_owner_pid);
+
+ ret = _cpu_eb_trace_seq_next(seqf, offset);
+
+ return ret;
+}
+
+
+static void cpu_eb_trace_seq_stop(struct seq_file *seqf, void *p)
+{
+ if (cpu_eb_trace_run == CPU_EB_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("cpu_eb_trace_seq_stop: pid: %d\n", current->pid);
+ }
+
+ mutex_lock(&lock_trace_owner_pid);
+ if (current->pid == trace_owner_pid) {
+ trace_owner_pid = PID_NONE;
+ mutex_unlock(&lock_tracef);
+ }
+ mutex_unlock(&lock_trace_owner_pid);
+}
+
+
+static void *cpu_eb_trace_seq_next(struct seq_file *seqf, void *p, loff_t *offset)
+{
+ if (cpu_eb_trace_run == CPU_EB_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("cpu_eb_trace_seq_next: pid: %d\n", current->pid);
+ }
+ (*offset)++;
+ return _cpu_eb_trace_seq_next(seqf, offset);
+}
+
+
+static int cpu_eb_trace_seq_show(struct seq_file *seqf, void *p)
+{
+ struct cpu_eb_log_req *req = (struct cpu_eb_log_req *) p;
+ size_t l_sz;
+ size_t r_sz;
+ struct cpu_eb_log_req *l_req;
+ struct cpu_eb_log_req *r_req;
+ int ret = 0;
+
+ if (cpu_eb_trace_run == CPU_EB_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("cpu_eb_trace_seq_show: pid: %d\n", current->pid);
+ }
+
+ if (req->num >= seqf->size) {
+ l_req = kmalloc(sizeof(*req), GFP_ATOMIC);
+ r_req = req;
+
+ l_sz = seqf->size >> 1;
+ r_sz = req->num - l_sz;
+ _cpu_eb_log_req_init(l_req, CPU_EB_LOG_REQ, req->src, l_sz, NULL, NULL);
+ _cpu_eb_log_req_init(r_req, CPU_EB_LOG_REQ, req->src + l_sz,
+ r_sz, req->on_fini_cb, req->param);
+
+ _cpu_eb_log_req_undeq(r_req);
+ req = l_req;
+
+ if (cpu_eb_trace_run == CPU_EB_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("cpu_eb_trace_seq_show: split request\n");
+ }
+ }
+
+ ret = seq_write(seqf, req->src, req->num);
+ if (ret) {
+ /* check if seq_file buffer overflows */
+ if (seqf->count == seqf->size) {
+ _cpu_eb_log_req_undeq(req);
+ } else {
+ if (cpu_eb_trace_run == CPU_EB_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("cpu_eb_trace_seq_show: \
+ reading trace record failed, \
+ some data may be lost or corrupted\n");
+ }
+ _cpu_eb_log_req_fini(req);
+ }
+ return 0;
+ }
+
+ _cpu_eb_log_req_fini(req);
+ return 0;
+}
+
+
+static int cpu_eb_trace_open(struct inode *inode, struct file *fp)
+{
+ return seq_open(fp, &cpu_eb_trace_seq_ops);
+}
+
+
+static ssize_t cpu_eb_log_write_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *plog = NULL;
+
+ plog = kmalloc_array(count, sizeof(*plog), GFP_ATOMIC);
+ if (!plog) {
+ /* TODO: use a better error code */
+ return -EINVAL;
+ }
+
+ memcpy(plog, buf, count);
+
+ mutex_lock(&dev->mutex);
+ cpu_eb_log_req_enq(plog, strnlen(plog, count), kfree, plog);
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
+
+static ssize_t cpu_eb_log_run_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int sz;
+
+ mutex_lock(&dev->mutex);
+ sz = snprintf(buf, PAGE_SIZE, "%d\n", cpu_eb_trace_run);
+ mutex_unlock(&dev->mutex);
+ return sz;
+}
+
+
+static ssize_t cpu_eb_log_run_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = 0;
+ int prev_run_state;
+
+ mutex_lock(&dev->mutex);
+
+ prev_run_state = cpu_eb_trace_run;
+ if (kstrtoint(buf, 10, &cpu_eb_trace_run) != 0) {
+ return -EINVAL;
+ }
+
+ if (cpu_eb_trace_run <= CPU_EB_LOG_STOP_MODE) {
+ cpu_eb_trace_run = CPU_EB_LOG_STOP_MODE;
+ cpu_eb_log_stop();
+
+ if (prev_run_state == CPU_EB_LOG_DEBUG_MODE) {
+ device_remove_file(dev, &dev_attr_cpu_eb_log_write);
+ }
+ } else if (cpu_eb_trace_run == CPU_EB_LOG_RUN_MODE) {
+ cpu_eb_trace_run = CPU_EB_LOG_RUN_MODE;
+ cpu_eb_log_start();
+
+ if (prev_run_state == CPU_EB_LOG_DEBUG_MODE) {
+ device_remove_file(dev, &dev_attr_cpu_eb_log_write);
+ }
+ } else {
+ cpu_eb_trace_run = CPU_EB_LOG_DEBUG_MODE;
+ cpu_eb_log_start();
+
+ if (prev_run_state != CPU_EB_LOG_DEBUG_MODE) {
+ ret = device_create_file(dev, &dev_attr_cpu_eb_log_write);
+ if (ret != 0) {
+ PR_BOOTMSG("can not create device node: \
+ cpu_eb_log_write\n");
+ }
+ }
+ }
+
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_log.h b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_log.h
new file mode 100644
index 0000000..aed1e91
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/cpu_eb_met_log.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __CPU_EB_MET_LOG_H__
+#define __CPU_EB_MET_LOG_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/device.h>
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+#include <linux/dma-mapping.h>
+#endif
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+int cpu_eb_log_init(struct device *dev);
+int cpu_eb_log_uninit(struct device *dev);
+int cpu_eb_log_start(void);
+int cpu_eb_log_stop(void);
+
+int cpu_eb_log_req_enq(
+ const char *src, size_t num,
+ void (*on_fini_cb)(const void *p),
+ const void *param);
+int cpu_eb_parse_num(const char *str, unsigned int *value, int len);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+extern void *cpu_eb_log_virt_addr;
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+extern dma_addr_t cpu_eb_log_phy_addr;
+#else
+extern unsigned int cpu_eb_log_phy_addr;
+#endif
+extern unsigned int cpu_eb_buffer_size;
+
+#endif /* __CPU_EB_MET_LOG_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/tinysys_cpu_eb.h b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/tinysys_cpu_eb.h
new file mode 100644
index 0000000..a10a52f
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/cpu_eb/tinysys_cpu_eb.h
@@ -0,0 +1,127 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __TINYSYS_CPU_EB_H__
+#define __TINYSYS_CPU_EB_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include "mtk_tinysys_ipi.h" /* for mtk_ipi_device */
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+/* MET IPI command definition: mbox 0 */
+/* main func ID: bit[31-24]; sub func ID: bit[23-18]; argu 0: bit[17-0] */
+#define MET_MAIN_ID_MASK 0xff000000 /* bit 31 - 24 */
+#define MET_SUB_ID_MASK 0x00fc0000 /* bit 23 - 18 */
+#define MET_ARGU0_MASK 0x0003ffff /* bit 17 - 0 */
+#define FUNC_BIT_SHIFT 18
+#define MID_BIT_SHIFT 9
+#define MET_MAIN_ID 0x06000000
+/* handle argument and attribute */
+#define PROCESS_ARGU 0x01
+#define PROCESS_ATTR 0x02
+#define MODULE_ID_MASK 0x3fe00 /* bit 9 - 17 */
+#define ARGUMENT_MASK 0x01ff /* bit 0 - 8 */
+
+/* the following command is used for AP to MD32 */
+/* argu 0: start: 0x01; stop: 0x02; extract: 0x03 */
+#define MET_OP_START 0x00000001
+#define MET_OP_STOP 0x00000002
+#define MET_OP_EXTRACT 0x00000003
+#define MET_OP_FLUSH 0x00000004
+#define MET_OP (1 << FUNC_BIT_SHIFT)
+#define MET_SR (2 << FUNC_BIT_SHIFT) /* sample rate */
+#define MET_MODULE (3 << FUNC_BIT_SHIFT) /* module enable/disable */
+#define MET_ARGU (4 << FUNC_BIT_SHIFT) /* argument passing */
+#define MET_ATTR (5 << FUNC_BIT_SHIFT) /* attribute passing */
+/* system memory information for on-die-met log data */
+#define MET_BUFFER_INFO (6 << FUNC_BIT_SHIFT)
+#define MET_TIMESTAMP (7 << FUNC_BIT_SHIFT) /* timestamp info */
+#define MET_GPT (8 << FUNC_BIT_SHIFT) /* GPT counter reading */
+#define MET_REQ_AP2MD (9 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_RESP_AP2MD (10 << FUNC_BIT_SHIFT) /* may no need */
+/* mode: bit 15 - 0: */
+/* Bit 0: MD32 SRAM mode; Bit 1: System DRAM mode */
+/* value: 0: output to next level of storage; 1: loop in its own storage */
+#define MET_DATA_MODE (11 << FUNC_BIT_SHIFT) /* log output mode */
+/* start/stop read data into MD32 SRAM buffer; both DMA and met_printf() */
+#define MET_DATA_OP (12 << FUNC_BIT_SHIFT) /* data read operation */
+/* the following command is used for MD32 to AP */
+#define MET_DUMP_BUFFER (13 << FUNC_BIT_SHIFT)
+#define MET_REQ_MD2AP (14 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_CLOSE_FILE (15 << FUNC_BIT_SHIFT) /* Inform to close the SD file */
+#define MET_RESP_MD2AP (16 << FUNC_BIT_SHIFT)
+#define MET_RUN_MODE (17 << FUNC_BIT_SHIFT)
+
+#define ID_PMQOS (1 << MID_PMQOS)
+#define ID_SMI (1 << MID_SMI)
+#define ID_EMI (1 << MID_EMI)
+#define ID_THERMAL_CPU (1 << MID_THERMAL_CPU)
+#define ID_WALL_TIME (1 << MID_WALL_TIME)
+#define ID_CPU_DVFS (1 << MID_CPU_DVFS)
+#define ID_GPU_DVFS (1 << MID_GPU_DVFS)
+#define ID_VCORE_DVFS (1 << MID_VCORE_DVFS)
+#define ID_PTPOD (1 << MID_PTPOD)
+#define ID_SPM (1 << MID_SPM)
+#define ID_PROFILE (1 << MID_PROFILE)
+#define ID_COMMON (1 << MID_COMMON)
+#define ID_CPU_INFO_MAPPING (1 << MID_CPU_INFO_MAPPING)
+#define ID_SMI (1 << MID_SMI)
+#define ID_PMU (1 << MID_PMU)
+
+#define CPU_EB_LOG_FILE 0
+#define CPU_EB_LOG_SRAM 1
+#define CPU_EB_LOG_DRAM 2
+
+#define CPU_EB_RUN_NORMAL 0
+#define CPU_EB_RUN_CONTINUOUS 1
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+/* Note: the module ID and its bit pattern should be fixed as below */
+/* DMA based module first */
+enum {
+ MID_PMQOS = 0,
+ MID_VCORE_DVFS = 1,
+ MID_EMI = 2,
+ MID_THERMAL_CPU = 3,
+ MID_WALL_TIME = 4,
+ MID_CPU_DVFS = 5,
+ MID_GPU_DVFS = 6,
+ MID_PTPOD = 7,
+ MID_SPM = 8,
+ MID_PROFILE = 9,
+ MID_MET_TAG = 10,
+ MID_TS = 11,
+ MID_TS_ISR = 12,
+ MID_TS_LAST = 13,
+ MID_TS_ISR_LAST = 14,
+ MID_SRAM_INFO = 15,
+ MID_MET_STOP = 16,
+ MID_IOP_MON = 17,
+ MID_CPU_INFO_MAPPING = 18,
+ MID_SMI = 19,
+ MID_PMU = 20,
+
+ MID_EB_CPU_PMU = 21,
+ MID_EB_SENSOR_NETWORK = 22,
+ MID_EB_SYSTEM_PI = 23,
+ MID_EB_PTPOD = 24,
+
+ MID_COMMON = 0x1F
+};
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+extern struct mtk_ipi_device *mcupm_ipidev_symbol;
+
+
+#endif /* __TINYSYS_CPU_EB_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_common.c b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_common.c
new file mode 100644
index 0000000..2f47ab2
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_common.c
@@ -0,0 +1,260 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/kernel.h>
+
+#include "met_drv.h"
+#include "tinysys_sspm.h"
+#include "tinysys_mgr.h"
+
+#include "sspm_met_log.h"
+#include "sspm_met_ipi_handle.h" /* for met_ipi_to_sspm_command */
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+struct sspm_met_evnet_header {
+ unsigned int rts_event_id;
+ char *rts_event_name;
+ char *chart_line_name;
+ char *key_list;
+};
+
+enum {
+ #ifdef MET_SSPM_RTS_EVNET
+ #undef MET_SSPM_RTS_EVNET
+ #endif
+ #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) rts_event_id,
+ #include "met_sspm_rts_event.h"
+
+ /* Note: always put at last */
+ CUR_MET_RTS_EVENT_NUM,
+ MAX_MET_RTS_EVENT_NUM = 128
+};
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+static void ondiemet_sspm_start(void);
+static void ondiemet_sspm_stop(void);
+static int ondiemet_sspm_print_help(char *buf, int len);
+static int ondiemet_sspm_process_argument(const char *arg, int len);
+static int ondiemet_sspm_print_header(char *buf, int len);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * internal variable
+ *****************************************************************************/
+static unsigned int event_id_flag[MAX_MET_RTS_EVENT_NUM / 32];
+static char *update_rts_event_tbl[MAX_MET_RTS_EVENT_NUM];
+static char sspm_help[] = " --sspm_common=rts_event_name\n";
+static char header[] = "met-info [000] 0.0: sspm_common_header: ";
+
+static struct sspm_met_evnet_header met_evnet_header[MAX_MET_RTS_EVENT_NUM] = {
+ #ifdef MET_SSPM_RTS_EVNET
+ #undef MET_SSPM_RTS_EVNET
+ #endif
+ #define MET_SSPM_RTS_EVNET(rts_event_id, key_list) \
+ {rts_event_id, #rts_event_id, #rts_event_id, key_list},
+ #include "met_sspm_rts_event.h"
+};
+
+struct metdevice met_sspm_common = {
+ .name = "sspm_common",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .cpu_related = 0,
+ .ondiemet_mode = 1,
+ .ondiemet_start = ondiemet_sspm_start,
+ .ondiemet_stop = ondiemet_sspm_stop,
+ .ondiemet_process_argument = ondiemet_sspm_process_argument,
+ .ondiemet_print_help = ondiemet_sspm_print_help,
+ .ondiemet_print_header = ondiemet_sspm_print_header,
+};
+
+
+/*****************************************************************************
+ * internal function implement
+ *****************************************************************************/
+static int ondiemet_sspm_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, sspm_help);
+}
+
+
+static int ondiemet_sspm_print_header(char *buf, int len)
+{
+ int i;
+ int write_len;
+ int flag = 0;
+ int mask = 0;
+ int group;
+ static int is_dump_header = 0;
+ static int read_idx = 0;
+
+ len = 0;
+ met_sspm_common.header_read_again = 0;
+ if (is_dump_header == 0) {
+ len = snprintf(buf, PAGE_SIZE, "%s", header);
+ is_dump_header = 1;
+ }
+
+ for (i = read_idx; i < CUR_MET_RTS_EVENT_NUM; i++) {
+ if (met_evnet_header[i].chart_line_name) {
+ group = i / 32;
+ mask = 1 << (i - group * 32);
+ flag = event_id_flag[group] & mask;
+ if (flag == 0) {
+ continue;
+ }
+
+ write_len = strlen(met_evnet_header[i].chart_line_name) + strlen(met_evnet_header[i].key_list) + 3;
+ if ((len + write_len) < PAGE_SIZE) {
+ len += snprintf(buf+len, PAGE_SIZE-len, "%u,%s,%s;",
+ met_evnet_header[i].rts_event_id,
+ met_evnet_header[i].chart_line_name,
+ met_evnet_header[i].key_list);
+ } else {
+ met_sspm_common.header_read_again = 1;
+ read_idx = i;
+ return len;
+ }
+ }
+ }
+
+ if (i == CUR_MET_RTS_EVENT_NUM) {
+ is_dump_header = 0;
+ read_idx = 0;
+ buf[len - 1] = '\n';
+ for (i = 0; i < CUR_MET_RTS_EVENT_NUM; i++) {
+ if (update_rts_event_tbl[i]) {
+ kfree(update_rts_event_tbl[i]);
+ update_rts_event_tbl[i] = NULL;
+ }
+ }
+ met_sspm_common.mode = 0;
+ for (i = 0 ; i < CUR_MET_RTS_EVENT_NUM / 32; i++) {
+ event_id_flag[i] = 0;
+ }
+ }
+
+ return len;
+}
+
+
+static void ondiemet_sspm_start(void)
+{
+ if (sspm_buffer_size == 0) {
+ return;
+ }
+
+ ondiemet_module[ONDIEMET_SSPM] |= ID_COMMON;
+}
+
+
+static void ondiemet_sspm_stop(void)
+{
+ return;
+}
+
+
+static void update_event_id_flag(int event_id)
+{
+ unsigned int ipi_buf[4] = {0};
+ unsigned int rdata = 0;
+ unsigned int res = 0;
+ unsigned int group = 0;
+
+ if (sspm_buffer_size == 0)
+ return ;
+
+ group = event_id / 32;
+ event_id_flag[group] |= 1 << (event_id - group * 32);
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_COMMON<<MID_BIT_SHIFT | 1;
+ ipi_buf[1] = group;
+ ipi_buf[2] = event_id_flag[group];
+ ipi_buf[3] = 0;
+ res = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+
+ met_sspm_common.mode = 1;
+}
+
+
+static char *strdup(const char *s)
+{
+ char *p = kmalloc(strlen(s) + 1, GFP_KERNEL);
+
+ if (p) {
+ strcpy(p, s);
+ }
+
+ return p;
+}
+
+
+static int ondiemet_sspm_process_argument(const char *arg, int len)
+{
+ int i = 0;
+ int rts_event_id = -1;
+ int res = 0;
+ char *line = NULL;
+ char *token = NULL;
+
+ for (i = 0; met_evnet_header[i].rts_event_name && i < MAX_MET_RTS_EVENT_NUM; i++) {
+ if (strcmp(met_evnet_header[i].rts_event_name, arg) == 0) {
+ rts_event_id = i;
+ break;
+ }
+ }
+
+ if (strstarts(arg, "update_rts_event_tbl")) {
+ char *ptr = NULL;
+
+ /* update_rts_event_tbl=rts_event_id;rts_event_name;chart_line_name;key_list*/
+ line = strdup(arg);
+ if (line == NULL) {
+ return -1;
+ }
+ ptr = line;
+ token = strsep(&line, "=");
+
+ /* rts_event_id, */
+ token = strsep(&line, ";");
+ res = kstrtoint(token, 10, &rts_event_id);
+ met_evnet_header[rts_event_id].rts_event_id = rts_event_id;
+
+ /* rts_event_name */
+ token = strsep(&line, ";");
+ met_evnet_header[rts_event_id].rts_event_name = token;
+
+ /* chart_line_name */
+ token = strsep(&line, ";");
+ met_evnet_header[rts_event_id].chart_line_name = token;
+
+ /* key_list */
+ token = strsep(&line, ";\n");
+ met_evnet_header[rts_event_id].key_list = token;
+
+ update_rts_event_tbl[rts_event_id] = ptr;
+ }
+
+ if (rts_event_id >= 0) {
+ update_event_id_flag(rts_event_id);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(met_sspm_common);
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_ipi_handle.c b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_ipi_handle.c
new file mode 100644
index 0000000..7933436
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_ipi_handle.c
@@ -0,0 +1,439 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/kthread.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+#include <linux/signal.h>
+#include <linux/semaphore.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/syscalls.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/fcntl.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <asm/io.h> /* for ioremap and iounmap */
+
+#include "mtk_tinysys_ipi.h" /* for mtk_ipi_device */
+#include "sspm_ipi_id.h" /* for sspm_ipidev */
+#include "sspm_met_log.h" /* for sspm_ipidev_symbol */
+#include "sspm_met_ipi_handle.h"
+#include "interface.h"
+#include "core_plf_init.h"
+#include "tinysys_sspm.h"
+#include "tinysys_mgr.h" /* for ondiemet_module */
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+extern unsigned int met_get_chip_id(void);
+extern char *met_get_platform(void);
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+static void _log_done_cb(const void *p);
+static int _met_ipi_cb(
+ unsigned int ipi_id,
+ void *prdata,
+ void *data,
+ unsigned int len);
+static int _sspm_recv_thread(void *data);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+int sspm_buf_available;
+EXPORT_SYMBOL(sspm_buf_available);
+
+
+/*****************************************************************************
+ * internal variable declaration
+ *****************************************************************************/
+static unsigned int ridx, widx, wlen;
+static unsigned int recv_buf[4];
+static unsigned int ackdata;
+static unsigned int rdata;
+static unsigned int log_size;
+static struct task_struct *_sspm_recv_task;
+static int sspm_ipi_thread_started;
+static int sspm_buffer_dumping;
+static int sspm_recv_thread_comp;
+static int sspm_run_mode = SSPM_RUN_NORMAL;
+
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+void start_sspm_ipi_recv_thread()
+{
+ int ret = 0;
+
+ if (sspm_ipidev_symbol == NULL) {
+ sspm_ipidev_symbol = (struct mtk_ipi_device *)symbol_get(sspm_ipidev);
+ }
+
+ if (sspm_ipidev_symbol == NULL) {
+ return;
+ }
+
+ // tinysys send ipi to APSYS
+ ret = mtk_ipi_register(sspm_ipidev_symbol, IPIR_C_MET, _met_ipi_cb,
+ NULL, (void *)&recv_buf);
+ if (ret) {
+ PR_BOOTMSG("[MET] ipi_register:%d failed:%d\n", IPIR_C_MET, ret);
+ } else {
+ PR_BOOTMSG("mtk_ipi_register IPIR_C_MET success \n");
+ }
+
+ // APSYS send ipi to tinysys
+ ret = mtk_ipi_register(sspm_ipidev_symbol, IPIS_C_MET, NULL,
+ NULL, (void *)&ackdata);
+ if (ret) {
+ pr_debug("[MET] ipi_register:%d failed:%d\n", IPIS_C_MET, ret);
+ } else {
+ PR_BOOTMSG("mtk_ipi_register IPIS_C_MET success \n");
+ }
+
+ if (sspm_ipi_thread_started != 1) {
+ sspm_recv_thread_comp = 0;
+ _sspm_recv_task = kthread_run(_sspm_recv_thread,
+ NULL, "sspmsspm_recv");
+ if (IS_ERR(_sspm_recv_task)) {
+ pr_debug("MET: Can not create sspmsspm_recv\n");
+ } else {
+ sspm_ipi_thread_started = 1;
+ }
+ }
+}
+
+
+void stop_sspm_ipi_recv_thread()
+{
+ if (_sspm_recv_task) {
+ sspm_recv_thread_comp = 1;
+
+ kthread_stop(_sspm_recv_task);
+ _sspm_recv_task = NULL;
+ sspm_ipi_thread_started = 0;
+
+ if (sspm_ipidev_symbol) {
+ // tinysys send ipi to APSYS
+ mtk_ipi_unregister(sspm_ipidev_symbol, IPIR_C_MET);
+ // APSYS send ipi to tinysys
+ mtk_ipi_unregister(sspm_ipidev_symbol, IPIS_C_MET);
+ }
+ }
+}
+
+
+void sspm_start(void)
+{
+ int ret = 0;
+ unsigned int rdata = 0;
+ unsigned int ipi_buf[4];
+ const char* platform_name = NULL;
+ unsigned int platform_id = 0;
+
+ /* clear DRAM buffer */
+ if (sspm_log_virt_addr != NULL) {
+ memset_io((void *)sspm_log_virt_addr, 0, sspm_buffer_size);
+ } else {
+ return;
+ }
+
+ platform_name = met_get_platform();
+ if (platform_name) {
+ char buf[5];
+
+ memset(buf, 0x0, 5);
+ memcpy(buf, &platform_name[2], 4);
+
+ ret = kstrtouint(buf, 10, &platform_id);
+ }
+
+ /* send DRAM physical address */
+ ipi_buf[0] = MET_MAIN_ID | MET_BUFFER_INFO;
+ ipi_buf[1] = (unsigned int)sspm_log_phy_addr; /* address */
+ if (ret == 0)
+ ipi_buf[2] = platform_id;
+ else
+ ipi_buf[2] = 0;
+
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command(ipi_buf, 0, &rdata, 1);
+
+ /* start ondiemet now */
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_START;
+ ipi_buf[1] = ondiemet_module[ONDIEMET_SSPM] ;
+ ipi_buf[2] = SSPM_LOG_FILE;
+ ipi_buf[3] = SSPM_RUN_NORMAL;
+ ret = met_ipi_to_sspm_command(ipi_buf, 0, &rdata, 1);
+}
+
+
+void sspm_stop(void)
+{
+ int ret = 0;
+ unsigned int rdata = 0;
+ unsigned int ipi_buf[4];
+ unsigned int chip_id = 0;
+
+ chip_id = met_get_chip_id();
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_STOP;
+ ipi_buf[1] = chip_id;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command(ipi_buf, 0, &rdata, 1);
+ }
+}
+
+
+void sspm_extract(void)
+{
+ int ret;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+ int count;
+
+ count = 20;
+ if (sspm_buf_available == 1) {
+ while ((sspm_buffer_dumping == 1) && (count != 0)) {
+ msleep(50);
+ count--;
+ }
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_EXTRACT;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command(ipi_buf, 0, &rdata, 1);
+ }
+
+ if (sspm_run_mode == SSPM_RUN_NORMAL) {
+ ondiemet_module[ONDIEMET_SSPM] = 0;
+ }
+}
+
+
+void sspm_flush(void)
+{
+ int ret;
+ unsigned int rdata;
+ unsigned int ipi_buf[4];
+
+ if (sspm_buf_available == 1) {
+ ipi_buf[0] = MET_MAIN_ID | MET_OP | MET_OP_FLUSH;
+ ipi_buf[1] = 0;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+
+ if (sspm_run_mode == SSPM_RUN_NORMAL) {
+ ondiemet_module[ONDIEMET_SSPM] = 0;
+ }
+}
+
+
+int met_ipi_to_sspm_command(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot)
+{
+ int ret = 0;
+
+ if (sspm_ipidev_symbol == NULL) {
+ PR_BOOTMSG("%s\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = mtk_ipi_send_compl(sspm_ipidev_symbol, IPIS_C_MET, IPI_SEND_WAIT,
+ (void*)buffer, slot, 2000);
+ *retbuf = ackdata;
+
+ if (ret != 0) {
+ PR_BOOTMSG("%s 0x%X, 0x%X, 0x%X, 0x%X\n", __FUNCTION__,
+ buffer[0], buffer[1], buffer[2], buffer[3]);
+ pr_debug("met_ipi_to_sspm_command error(%d)\n", ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(met_ipi_to_sspm_command);
+
+
+int met_ipi_to_sspm_command_async(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot)
+{
+ int ret = 0;
+
+ if(sspm_ipidev_symbol == NULL) {
+ PR_BOOTMSG("%s\n", __FUNCTION__);
+ return -1;
+ }
+
+ ret = mtk_ipi_send(sspm_ipidev_symbol, IPIS_C_MET, IPI_SEND_WAIT,
+ (void*)buffer, slot, 2000);
+ *retbuf = ackdata;
+
+ if (ret != 0) {
+ PR_BOOTMSG("%s 0x%X, 0x%X, 0x%X, 0x%X\n", __FUNCTION__,
+ buffer[0], buffer[1], buffer[2], buffer[3]);
+ pr_debug("met_ipi_to_sspm_command error(%d)\n", ret);
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL(met_ipi_to_sspm_command_async);
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+static void _log_done_cb(const void *p)
+{
+ unsigned int ret;
+ unsigned int rdata = 0;
+ unsigned int ipi_buf[4];
+ unsigned int opt = (p != NULL);
+
+ if (opt == 0) {
+ ipi_buf[0] = MET_MAIN_ID | MET_RESP_AP2MD;
+ ipi_buf[1] = MET_DUMP_BUFFER;
+ ipi_buf[2] = 0;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+ }
+}
+
+
+static int _met_ipi_cb(unsigned int ipi_id, void *prdata, void *data, unsigned int len)
+{
+ unsigned int *cmd_buf = (unsigned int *)data;
+ unsigned int cmd;
+ int ret;
+
+ if (sspm_recv_thread_comp == 1) {
+ PR_BOOTMSG("%s %d\n", __FUNCTION__, __LINE__);
+ return 0;
+ }
+
+ cmd = cmd_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ sspm_buffer_dumping = 1;
+ ridx = cmd_buf[1];
+ widx = cmd_buf[2];
+ log_size = cmd_buf[3];
+ break;
+
+ case MET_CLOSE_FILE: /* no argument */
+ /* do close file */
+ ridx = cmd_buf[1];
+ widx = cmd_buf[2];
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ sspm_log_req_enq((char *)(sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)1);
+ sspm_log_req_enq((char *)(sspm_log_virt_addr),
+ widx * 4, _log_done_cb, (void *)1);
+ } else {
+ wlen = widx - ridx;
+ sspm_log_req_enq((char *)(sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)1);
+ }
+ ret = sspm_log_stop();
+ break;
+
+ case MET_RESP_MD2AP:
+ break;
+
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+static int _sspm_recv_thread(void *data)
+{
+ int ret = 0;
+ unsigned int cmd = 0;
+
+ do {
+ ret = mtk_ipi_recv_reply(sspm_ipidev_symbol, IPIR_C_MET, (void *)&rdata, 1);
+ if (ret) {
+ pr_debug("[MET] ipi_register:%d failed:%d\n", IPIR_C_MET, ret);
+ }
+
+ if (sspm_recv_thread_comp == 1) {
+ while (!kthread_should_stop()) {
+ ;
+ }
+ return 0;
+ }
+
+ cmd = recv_buf[0] & MET_SUB_ID_MASK;
+ switch (cmd) {
+ case MET_DUMP_BUFFER: /* mbox 1: start index; 2: size */
+ if (widx < ridx) { /* wrapping occurs */
+ wlen = log_size - ridx;
+ sspm_log_req_enq((char *)(sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)1);
+ sspm_log_req_enq((char *)(sspm_log_virt_addr),
+ widx * 4, _log_done_cb, (void *)0);
+ } else {
+ wlen = widx - ridx;
+ sspm_log_req_enq((char *)(sspm_log_virt_addr) + (ridx << 2),
+ wlen * 4, _log_done_cb, (void *)0);
+ }
+ break;
+
+ case MET_CLOSE_FILE: /* no argument */
+ if (sspm_run_mode == SSPM_RUN_CONTINUOUS) {
+ /* clear the memory */
+ memset_io((void *)sspm_log_virt_addr, 0,
+ sspm_buffer_size);
+ /* re-start ondiemet again */
+ sspm_start();
+ }
+ break;
+
+ case MET_RESP_MD2AP:
+ sspm_buffer_dumping = 0;
+ break;
+
+ default:
+ break;
+ }
+ } while (!kthread_should_stop());
+
+ return 0;
+}
+
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_ipi_handle.h b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_ipi_handle.h
new file mode 100644
index 0000000..c0c3f60
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_ipi_handle.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __SSPM_MET_IPI_HANDLE_H__
+#define __SSPM_MET_IPI_HANDLE_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+void start_sspm_ipi_recv_thread(void);
+void stop_sspm_ipi_recv_thread(void);
+
+void sspm_start(void);
+void sspm_stop(void);
+void sspm_extract(void);
+void sspm_flush(void);
+
+int met_ipi_to_sspm_command(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot);
+int met_ipi_to_sspm_command_async(
+ unsigned int *buffer,
+ int slot,
+ unsigned int *retbuf,
+ int retslot);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+
+
+#endif /* __SSPM_MET_IPI_HANDLE_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_log.c b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_log.c
new file mode 100644
index 0000000..38942a6
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_log.c
@@ -0,0 +1,707 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/debugfs.h>
+#include <linux/proc_fs.h>
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/completion.h>
+#include <linux/module.h> /* symbol_get */
+
+#include "sspm_reservedmem.h"
+#include "sspm_reservedmem_define.h"
+
+#include "interface.h"
+
+#include "sspm_met_log.h"
+#include "sspm_met_ipi_handle.h"
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+#define SSPM_LOG_REQ 1
+#define SSPM_LOG_STOP 2
+
+#define PID_NONE (-1)
+
+#define SSPM_LOG_STOP_MODE 0
+#define SSPM_LOG_RUN_MODE 1
+#define SSPM_LOG_DEBUG_MODE 2
+
+#define _sspm_log_req_init(req, cmd, s, n, pf, p) \
+ do { \
+ INIT_LIST_HEAD(&req->list); \
+ req->cmd_type = cmd; \
+ req->src = s; \
+ req->num = n; \
+ req->on_fini_cb = pf; \
+ req->param = p; \
+ } while (0)
+
+#define _sspm_log_req_fini(req) \
+ do { \
+ if (req->on_fini_cb) \
+ req->on_fini_cb(req->param); \
+ kfree(req); \
+ } while (0)
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+struct sspm_log_req_q_t {
+ struct list_head listq;
+ struct mutex lockq;
+ struct completion new_evt_comp;
+ int closeq_flag;
+} sspm_log_req_q;
+
+struct sspm_log_req {
+ struct list_head list;
+ int cmd_type;
+ const char *src;
+ size_t num;
+
+ void (*on_fini_cb)(const void *p);
+ const void *param;
+};
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+static void _log_stop_cb(const void *p);
+static int _down_freezable_interruptible(struct completion *comp);
+
+static void _sspm_log_req_q_init(struct sspm_log_req_q_t *q);
+static void _sspm_log_req_undeq(struct sspm_log_req *req);
+static int _sspm_log_req_enq(struct sspm_log_req *req);
+static struct sspm_log_req *_sspm_log_req_deq(void);
+static void _sspm_log_req_open(void);
+static int _sspm_log_req_closed(void);
+static int _sspm_log_req_working(void);
+static void *_sspm_trace_seq_next(struct seq_file *seqf, loff_t *offset);
+
+static void *sspm_trace_seq_start(struct seq_file *seqf, loff_t *offset);
+static void sspm_trace_seq_stop(struct seq_file *seqf, void *p);
+static void *sspm_trace_seq_next(struct seq_file *seqf, void *p, loff_t *offset);
+static int sspm_trace_seq_show(struct seq_file *seqf, void *p);
+static int sspm_trace_open(struct inode *inode, struct file *fp);
+
+static ssize_t ondiemet_log_write_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count);
+static ssize_t ondiemet_log_run_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf);
+static ssize_t ondiemet_log_run_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+void *sspm_log_virt_addr;
+
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+dma_addr_t sspm_log_phy_addr;
+#else
+unsigned int sspm_log_phy_addr;
+#endif
+
+unsigned int sspm_buffer_size;
+
+extern int sspm_buf_available;
+
+
+/*****************************************************************************
+ * internal variable declaration
+ *****************************************************************************/
+static int sspm_trace_run;
+static pid_t trace_owner_pid = PID_NONE;
+
+static struct mutex lock_tracef;
+static struct mutex lock_trace_owner_pid;
+
+static struct completion log_start_comp;
+static struct completion log_stop_comp;
+
+static DEVICE_ATTR(ondiemet_log_write, 0220, NULL, ondiemet_log_write_store);
+static DEVICE_ATTR(ondiemet_log_run, 0664, ondiemet_log_run_show, ondiemet_log_run_store);;
+
+static const struct seq_operations sspm_trace_seq_ops = {
+ .start = sspm_trace_seq_start,
+ .next = sspm_trace_seq_next,
+ .stop = sspm_trace_seq_stop,
+ .show = sspm_trace_seq_show
+};
+
+static const struct file_operations sspm_trace_fops = {
+ .owner = THIS_MODULE,
+ .open = sspm_trace_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release
+};
+
+
+/*****************************************************************************
+ * external function ipmlement
+ *****************************************************************************/
+int sspm_log_init(struct device *dev)
+{
+ int ret = 0;
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ struct dentry *d;
+ struct dentry *met_dir = NULL;
+#else
+ struct proc_dir_entry *d;
+ struct proc_dir_entry *met_dir = NULL;
+#endif
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+#else
+ phys_addr_t (*get_size_sym)(unsigned int id) = NULL;
+#endif
+
+ met_dir = dev_get_drvdata(dev);
+ mutex_init(&lock_tracef);
+ _sspm_log_req_q_init(&sspm_log_req_q);
+ init_completion(&log_start_comp);
+ init_completion(&log_stop_comp);
+ mutex_init(&lock_trace_owner_pid);
+
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ d = debugfs_create_file("trace", 0600, met_dir, NULL, &sspm_trace_fops);
+ if (!d) {
+ PR_BOOTMSG("can not create devide node in debugfs: sspm_trace\n");
+ return -ENOMEM;
+ }
+#else
+ d = proc_create("trace", 0600, met_dir, &sspm_trace_fops);
+ if (!d) {
+ PR_BOOTMSG("can not create devide node in procfs: sspm_trace\n");
+ return -ENOMEM;
+ }
+#endif
+
+ sspm_trace_run = _sspm_log_req_working();
+ ret = device_create_file(dev, &dev_attr_ondiemet_log_run);
+ if (ret != 0) {
+ PR_BOOTMSG("can not create device node: sspm_log_run\n");
+ return ret;
+ }
+
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+ sspm_log_virt_addr = dma_alloc_coherent(dev, 0x800000,
+ &sspm_log_phy_addr, GFP_KERNEL);
+ if (sspm_log_virt_addr) {
+ sspm_buffer_size = 0x800000;
+ sspm_buf_available = 1;
+ } else {
+ sspm_buf_available = 0;
+ }
+#else
+ get_size_sym = symbol_get(sspm_reserve_mem_get_size);
+ if (get_size_sym) {
+ sspm_buffer_size = get_size_sym(MET_MEM_ID);
+ PR_BOOTMSG("sspm_buffer_size=%x \n", sspm_buffer_size);
+ } else {
+ PR_BOOTMSG("symbol_get sspm_reserve_mem_get_size failure\n");
+ }
+
+ if (sspm_buffer_size > 0) {
+ phys_addr_t (*get_phys_sym)(unsigned int id) = NULL;
+ phys_addr_t (*get_virt_sym)(unsigned int id) = NULL;
+
+ get_phys_sym = symbol_get(sspm_reserve_mem_get_virt);
+ get_virt_sym = symbol_get(sspm_reserve_mem_get_phys);
+ if (get_phys_sym) {
+ sspm_log_virt_addr = (void*)get_phys_sym(MET_MEM_ID);
+ // mark for Colgin porting
+ // PR_BOOTMSG("sspm_log_virt_addr=%x \n", sspm_log_virt_addr);
+ } else {
+ PR_BOOTMSG("symbol_get sspm_reserve_mem_get_virt failure\n");
+ }
+ if (get_virt_sym) {
+ sspm_log_phy_addr = get_virt_sym(MET_MEM_ID);
+ PR_BOOTMSG("sspm_log_phy_addr=%x \n", sspm_log_phy_addr);
+ } else {
+ PR_BOOTMSG("symbol_get sspm_reserve_mem_get_phys failure\n");
+ }
+ sspm_buf_available = 1;
+ } else {
+ sspm_buf_available = 0;
+ }
+
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+
+ start_sspm_ipi_recv_thread();
+
+ return 0;
+}
+
+
+int sspm_log_uninit(struct device *dev)
+{
+ stop_sspm_ipi_recv_thread();
+
+ if (sspm_log_virt_addr != NULL) {
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+ dma_free_coherent(dev, sspm_buffer_size, sspm_log_virt_addr,
+ sspm_log_phy_addr);
+#endif /* CONFIG_MTK_GMO_RAM_OPTIMIZE */
+ sspm_log_virt_addr = NULL;
+ }
+
+ device_remove_file(dev, &dev_attr_ondiemet_log_run);
+ return 0;
+}
+
+
+int sspm_log_start(void)
+{
+ int ret = 0;
+
+ /* TODO: choose a better return value */
+ if (_sspm_log_req_working()) {
+ return -EINVAL;
+ }
+
+ if (!_sspm_log_req_closed()) {
+ ret = wait_for_completion_killable(&log_start_comp);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ _sspm_log_req_open();
+
+ return 0;
+}
+
+
+int sspm_log_stop(void)
+{
+ int ret = 0;
+ struct sspm_log_req *req = NULL;
+
+ if (_sspm_log_req_closed()) {
+ return -EINVAL;
+ }
+
+ req = kmalloc(sizeof(*req), GFP_KERNEL);
+ if (!req) {
+ /* TODO: use a better error code */
+ return -EINVAL;
+ }
+
+ _sspm_log_req_init(req, SSPM_LOG_STOP, NULL, 0, _log_stop_cb, NULL);
+
+ init_completion(&log_start_comp);
+ init_completion(&log_stop_comp);
+
+ ret = _sspm_log_req_enq(req);
+ if (ret) {
+ return ret;
+ }
+
+ return wait_for_completion_killable(&log_stop_comp);
+}
+
+
+int sspm_log_req_enq(
+ const char *src, size_t num,
+ void (*on_fini_cb)(const void *p),
+ const void *param)
+{
+ struct sspm_log_req *req = kmalloc(sizeof(*req), GFP_KERNEL);
+
+ if (!req) {
+ /* TODO: use a better error code */
+ return -EINVAL;
+ }
+
+ _sspm_log_req_init(req, SSPM_LOG_REQ, src, num, on_fini_cb, param);
+ return _sspm_log_req_enq(req);
+}
+
+
+int sspm_parse_num(const char *str, unsigned int *value, int len)
+{
+ int ret = 0;
+
+ if (len <= 0) {
+ return -1;
+ }
+
+ if ((len > 2) && ((str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X')))) {
+ ret = kstrtouint(str, 16, value);
+ } else {
+ ret = kstrtouint(str, 10, value);
+ }
+
+ if (ret != 0) {
+ return -1;
+ }
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+static void _log_stop_cb(const void *p)
+{
+ complete(&log_start_comp);
+ complete(&log_stop_comp);
+}
+
+
+static int _down_freezable_interruptible(struct completion *comp)
+{
+ int ret = 0;
+
+ freezer_do_not_count();
+ ret = wait_for_completion_interruptible(comp);
+ freezer_count();
+
+ return ret;
+}
+
+
+static void _sspm_log_req_q_init(struct sspm_log_req_q_t *q)
+{
+ INIT_LIST_HEAD(&q->listq);
+ mutex_init(&q->lockq);
+ init_completion(&q->new_evt_comp);
+ q->closeq_flag = 1;
+}
+
+
+/*
+ undequeue is seen as a roll-back operation,
+ so it can be done even when the queue is closed
+*/
+static void _sspm_log_req_undeq(struct sspm_log_req *req)
+{
+ mutex_lock(&sspm_log_req_q.lockq);
+ list_add(&req->list, &sspm_log_req_q.listq);
+ mutex_unlock(&sspm_log_req_q.lockq);
+
+ complete(&sspm_log_req_q.new_evt_comp);
+}
+
+
+static int _sspm_log_req_enq(struct sspm_log_req *req)
+{
+ mutex_lock(&sspm_log_req_q.lockq);
+ if (sspm_log_req_q.closeq_flag) {
+ mutex_unlock(&sspm_log_req_q.lockq);
+ return -EBUSY;
+ }
+
+ list_add_tail(&req->list, &sspm_log_req_q.listq);
+ if (req->cmd_type == SSPM_LOG_STOP) {
+ sspm_log_req_q.closeq_flag = 1;
+ }
+ mutex_unlock(&sspm_log_req_q.lockq);
+
+ complete(&sspm_log_req_q.new_evt_comp);
+
+ return 0;
+}
+
+
+static struct sspm_log_req *_sspm_log_req_deq(void)
+{
+ struct sspm_log_req *ret_req;
+
+ if (_down_freezable_interruptible(&sspm_log_req_q.new_evt_comp)) {
+ return NULL;
+ }
+
+ mutex_lock(&sspm_log_req_q.lockq);
+ ret_req = list_entry(sspm_log_req_q.listq.next, struct sspm_log_req, list);
+ list_del_init(&ret_req->list);
+ mutex_unlock(&sspm_log_req_q.lockq);
+
+ return ret_req;
+}
+
+
+static void _sspm_log_req_open(void)
+{
+ mutex_lock(&sspm_log_req_q.lockq);
+ sspm_log_req_q.closeq_flag = 0;
+ mutex_unlock(&sspm_log_req_q.lockq);
+}
+
+
+static int _sspm_log_req_closed(void)
+{
+ int ret = 0;
+
+ mutex_lock(&sspm_log_req_q.lockq);
+ ret = sspm_log_req_q.closeq_flag && list_empty(&sspm_log_req_q.listq);
+ mutex_unlock(&sspm_log_req_q.lockq);
+
+ return ret;
+}
+
+
+static int _sspm_log_req_working(void)
+{
+ int ret = 0;
+
+ mutex_lock(&sspm_log_req_q.lockq);
+ ret = !sspm_log_req_q.closeq_flag;
+ mutex_unlock(&sspm_log_req_q.lockq);
+
+ return ret;
+}
+
+
+static void *_sspm_trace_seq_next(struct seq_file *seqf, loff_t *offset)
+{
+ struct sspm_log_req *next_req;
+
+ if (sspm_trace_run == SSPM_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("_sspm_trace_seq_next: pid: %d\n", current->pid);
+ }
+
+ if (_sspm_log_req_closed()) {
+ return NULL;
+ }
+
+ next_req = _sspm_log_req_deq();
+ if (next_req == NULL) {
+ return NULL;
+ }
+
+ if (next_req->cmd_type == SSPM_LOG_STOP) {
+ _sspm_log_req_fini(next_req);
+ return NULL;
+ }
+
+ return (void *) next_req;
+}
+
+
+static void *sspm_trace_seq_start(struct seq_file *seqf, loff_t *offset)
+{
+ void *ret;
+
+ if (sspm_trace_run == SSPM_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("sspm_trace_seq_start: locked_pid: %d, pid: %d, offset: %llu\n",
+ trace_owner_pid, current->pid, *offset);
+ }
+
+ if (!mutex_trylock(&lock_tracef)) {
+ return NULL;
+ }
+
+ mutex_lock(&lock_trace_owner_pid);
+ trace_owner_pid = current->pid;
+ current->flags |= PF_NOFREEZE;
+ mutex_unlock(&lock_trace_owner_pid);
+
+ ret = _sspm_trace_seq_next(seqf, offset);
+
+ return ret;
+}
+
+
+static void sspm_trace_seq_stop(struct seq_file *seqf, void *p)
+{
+ if (sspm_trace_run == SSPM_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("sspm_trace_seq_stop: pid: %d\n", current->pid);
+ }
+
+ mutex_lock(&lock_trace_owner_pid);
+ if (current->pid == trace_owner_pid) {
+ trace_owner_pid = PID_NONE;
+ mutex_unlock(&lock_tracef);
+ }
+ mutex_unlock(&lock_trace_owner_pid);
+}
+
+
+static void *sspm_trace_seq_next(struct seq_file *seqf, void *p, loff_t *offset)
+{
+ if (sspm_trace_run == SSPM_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("sspm_trace_seq_next: pid: %d\n", current->pid);
+ }
+ (*offset)++;
+ return _sspm_trace_seq_next(seqf, offset);
+}
+
+
+static int sspm_trace_seq_show(struct seq_file *seqf, void *p)
+{
+ struct sspm_log_req *req = (struct sspm_log_req *)p;
+ size_t l_sz;
+ size_t r_sz;
+ struct sspm_log_req *l_req;
+ struct sspm_log_req *r_req;
+ int ret = 0;
+
+ if (sspm_trace_run == SSPM_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("sspm_trace_seq_show: pid: %d\n", current->pid);
+ }
+
+ if (req->num >= seqf->size) {
+ l_req = kmalloc(sizeof(*req), GFP_KERNEL);
+ r_req = req;
+
+ if (!l_req) {
+ /* TODO: use a better error code */
+ return -EINVAL;
+ }
+
+ l_sz = seqf->size >> 1;
+ r_sz = req->num - l_sz;
+ _sspm_log_req_init(l_req, SSPM_LOG_REQ, req->src, l_sz, NULL, NULL);
+ _sspm_log_req_init(r_req, SSPM_LOG_REQ, req->src + l_sz,
+ r_sz, req->on_fini_cb, req->param);
+
+ _sspm_log_req_undeq(r_req);
+ req = l_req;
+
+ if (sspm_trace_run == SSPM_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("sspm_trace_seq_show: split request\n");
+ }
+ }
+
+ ret = seq_write(seqf, req->src, req->num);
+ if (ret) {
+ /* check if seq_file buffer overflows */
+ if (seqf->count == seqf->size) {
+ _sspm_log_req_undeq(req);
+ } else {
+ if (sspm_trace_run == SSPM_LOG_DEBUG_MODE) {
+ PR_BOOTMSG("sspm_trace_seq_show: \
+ reading trace record failed, \
+ some data may be lost or corrupted\n");
+ }
+ _sspm_log_req_fini(req);
+ }
+ return 0;
+ }
+
+ _sspm_log_req_fini(req);
+ return 0;
+}
+
+
+static int sspm_trace_open(struct inode *inode, struct file *fp)
+{
+ return seq_open(fp, &sspm_trace_seq_ops);
+}
+
+
+static ssize_t ondiemet_log_write_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ char *plog = NULL;
+
+ plog = kmalloc_array(count, sizeof(*plog), GFP_KERNEL);
+ if (!plog) {
+ /* TODO: use a better error code */
+ return -EINVAL;
+ }
+ memcpy(plog, buf, count);
+
+ mutex_lock(&dev->mutex);
+ sspm_log_req_enq(plog, strnlen(plog, count), kfree, plog);
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
+
+static ssize_t ondiemet_log_run_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int sz;
+
+ mutex_lock(&dev->mutex);
+ sz = snprintf(buf, PAGE_SIZE, "%d\n", sspm_trace_run);
+ mutex_unlock(&dev->mutex);
+ return sz;
+}
+
+
+static ssize_t ondiemet_log_run_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int ret = 0;
+ int prev_run_state;
+
+ mutex_lock(&dev->mutex);
+ prev_run_state = sspm_trace_run;
+ if (kstrtoint(buf, 10, &sspm_trace_run) != 0) {
+ return -EINVAL;
+ }
+
+ if (sspm_trace_run <= SSPM_LOG_STOP_MODE) {
+ sspm_trace_run = SSPM_LOG_STOP_MODE;
+ sspm_log_stop();
+
+ if (prev_run_state == SSPM_LOG_DEBUG_MODE) {
+ device_remove_file(dev, &dev_attr_ondiemet_log_write);
+ }
+ } else if (sspm_trace_run == SSPM_LOG_RUN_MODE) {
+ sspm_trace_run = SSPM_LOG_RUN_MODE;
+ sspm_log_start();
+
+ if (prev_run_state == SSPM_LOG_DEBUG_MODE) {
+ device_remove_file(dev, &dev_attr_ondiemet_log_write);
+ }
+ } else {
+ sspm_trace_run = SSPM_LOG_DEBUG_MODE;
+ sspm_log_start();
+
+ if (prev_run_state != SSPM_LOG_DEBUG_MODE) {
+ ret = device_create_file(dev, &dev_attr_ondiemet_log_write);
+ if (ret != 0) {
+ PR_BOOTMSG("can not create device node: \
+ sspm_log_write\n");
+ }
+ }
+ }
+ mutex_unlock(&dev->mutex);
+
+ return count;
+}
+
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_log.h b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_log.h
new file mode 100644
index 0000000..b066322
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_log.h
@@ -0,0 +1,52 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef _ONDIEMET_LOG_H_
+#define _ONDIEMET_LOG_H_
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/device.h>
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+#include <linux/dma-mapping.h>
+#endif
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+int sspm_log_init(struct device *dev);
+int sspm_log_uninit(struct device *dev);
+int sspm_log_start(void);
+int sspm_log_stop(void);
+
+int sspm_log_req_enq(
+ const char *src, size_t num,
+ void (*on_fini_cb)(const void *p),
+ const void *param);
+int sspm_parse_num(const char *str, unsigned int *value, int len);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+extern void *sspm_log_virt_addr;
+#if IS_ENABLED(CONFIG_MTK_GMO_RAM_OPTIMIZE) || IS_ENABLED(CONFIG_MTK_MET_MEM_ALLOC)
+extern dma_addr_t sspm_log_phy_addr;
+#else
+extern unsigned int sspm_log_phy_addr;
+#endif
+extern unsigned int sspm_buffer_size;
+
+#endif /* _ONDIEMET_LOG_H_ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi.c b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi.c
new file mode 100644
index 0000000..f3c663a
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi.c
@@ -0,0 +1,569 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+
+#ifdef USE_KERNEL_SYNC_WRITE_H
+#include <mt-plat/sync_write.h>
+#else
+#include "sync_write.h"
+#endif
+
+#ifdef USE_KERNEL_MTK_IO_H
+#include <mt-plat/mtk_io.h>
+#else
+#include "mtk_io.h"
+#endif
+
+#include "met_drv.h"
+#include "trace.h"
+#include "core_plf_trace.h"
+#include "core_plf_init.h"
+#include "interface.h"
+#include "mtk_typedefs.h"
+
+#include "tinysys_mgr.h"
+#include "tinysys_sspm.h"
+
+#include "sspm_mtk_smi.h"
+#include "sspm_met_smi.h"
+#include "sspm_met_smi_name.h"
+#include "sspm_met_log.h"
+#include "sspm_met_ipi_handle.h" /* for met_ipi_to_sspm_command */
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+#define MET_SMI_DEBUG 1
+#define MET_SMI_BUF_SIZE 128
+#define MET_SMI_DEBUGBUF_SIZE 512
+#define NPORT_IN_PM 4
+
+// SMI Encode -- Master
+#ifdef SMI_MASTER_8BIT
+// bit15~bit16
+#define MET_SMI_BIT_REQ_LARB 15
+// bit13~bit14
+#define MET_SMI_BIT_REQ_COMM 13
+// bit12:Parallel Mode */
+#define MET_SMI_BIT_PM 12
+// bit9~bit8:Destination */
+#define MET_SMI_BIT_DST 10
+/* bit5~bit4:Request Type */
+#define MET_SMI_BIT_REQ 8
+/* bit3~bit0:Master */
+#define MET_SMI_BIT_MASTER 0
+#else
+// bit15~bit16
+#define MET_SMI_BIT_REQ_LARB 15
+// bit13~bit14
+#define MET_SMI_BIT_REQ_COMM 13
+// bit12:Parallel Mode */
+#define MET_SMI_BIT_PM 12
+// bit9~bit8:Destination */
+#define MET_SMI_BIT_DST 8
+/* bit5~bit4:Request Type */
+#define MET_SMI_BIT_REQ 4
+/* bit3~bit0:Master */
+#define MET_SMI_BIT_MASTER 0
+#endif
+
+// SMI Encode -- Metadata
+/* bit6~bit5:RW */
+#define MET_SMI_BIT_RW 5
+/* bit4~bit0:Port */
+#define MET_SMI_BIT_PORT 0
+
+/*
+*declare smi: larb0-larbn:
+*real define table in met_smi_name.h
+*/
+/*MET_SMI_DESC_DEFINE();*/
+/**/
+
+/*======================================================================*/
+/* Global variable definitions */
+/*======================================================================*/
+#define MAX_CONFIG_ARRAY_SIZE 20
+struct metdevice met_sspm_smi;
+struct met_smi_conf smi_conf_array[MAX_CONFIG_ARRAY_SIZE];
+int smi_array_index;
+
+//static unsigned int smi_met_larb_number = SMI_LARB_NUMBER;
+static int count = SMI_LARB_NUMBER + SMI_COMM_NUMBER;
+static struct kobject *kobj_smi;
+
+/* Request type */
+static unsigned int larb_req_type = SMI_REQ_ALL;
+static unsigned int comm_req_type = SMI_REQ_ALL;
+
+/* Parallel mode */
+static unsigned int parallel_mode;
+
+/* Read/Write type in parallel mode */
+static int comm_pm_rw_type[SMI_COMM_NUMBER][NPORT_IN_PM];
+/* Error message */
+static char err_msg[MET_SMI_BUF_SIZE];
+static char debug_msg[MET_SMI_DEBUGBUF_SIZE];
+
+/*======================================================================*/
+/* KOBJ Declarations */
+/*======================================================================*/
+/* KOBJ: larb_req_type */
+DECLARE_KOBJ_ATTR_INT(larb_req_type, larb_req_type);
+
+/* KOBJ : comm_req_type */
+DECLARE_KOBJ_ATTR_INT(comm_req_type, comm_req_type);
+
+/* KOBJ : enable_parallel_mode */
+DECLARE_KOBJ_ATTR_INT(enable_parallel_mode, parallel_mode);
+
+/* KOBJ : pm_rwtypeX */
+DECLARE_KOBJ_ATTR_STR_LIST_ITEM(
+ pm_rwtype,
+ KOBJ_ITEM_LIST(
+ {SMI_READ_ONLY, "READ"},
+ {SMI_WRITE_ONLY, "WRITE"}
+ )
+);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype1, comm_pm_rw_type[0][0], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype2, comm_pm_rw_type[0][1], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype3, comm_pm_rw_type[0][2], pm_rwtype);
+DECLARE_KOBJ_ATTR_STR_LIST(pm_rwtype4, comm_pm_rw_type[0][3], pm_rwtype);
+
+/* KOBJ : count */
+DECLARE_KOBJ_ATTR_RO_INT(count, count);
+
+/* KOBJ : err_msg */
+DECLARE_KOBJ_ATTR_RO_STR(err_msg, err_msg);
+
+#define KOBJ_ATTR_LIST \
+do { \
+ KOBJ_ATTR_ITEM(larb_req_type); \
+ KOBJ_ATTR_ITEM(comm_req_type); \
+ KOBJ_ATTR_ITEM(enable_parallel_mode); \
+ KOBJ_ATTR_ITEM(pm_rwtype1); \
+ KOBJ_ATTR_ITEM(pm_rwtype2); \
+ KOBJ_ATTR_ITEM(pm_rwtype3); \
+ KOBJ_ATTR_ITEM(pm_rwtype4); \
+ KOBJ_ATTR_ITEM(count); \
+ KOBJ_ATTR_ITEM(err_msg); \
+} while (0)
+
+/*======================================================================*/
+/* SMI Operations */
+/*======================================================================*/
+static void met_smi_debug(char *debug_log)
+{
+ MET_TRACE("%s", debug_log);
+}
+
+static int do_smi(void)
+{
+ return met_sspm_smi.mode;
+}
+
+static void smi_init_value(void)
+{
+ int i = 0;
+
+ smi_array_index = 0;
+ for (i = 0; i < MAX_CONFIG_ARRAY_SIZE; i++) {
+ smi_conf_array[i].master = 0;
+ smi_conf_array[i].port[0] = -1;
+ smi_conf_array[i].port[1] = -1;
+ smi_conf_array[i].port[2] = -1;
+ smi_conf_array[i].port[3] = -1;
+ smi_conf_array[i].rwtype[0] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[1] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[2] = SMI_RW_ALL;
+ smi_conf_array[i].rwtype[3] = SMI_RW_ALL;
+ smi_conf_array[i].desttype = SMI_DEST_EMI;
+ smi_conf_array[i].reqtype = SMI_REQ_ALL;
+ }
+}
+
+static int smi_init(void)
+{
+ int i = 0;
+
+ if (smi_array_index < MAX_CONFIG_ARRAY_SIZE) {
+ for (i = 0; i < (smi_array_index + 1); i++) {
+ snprintf(debug_msg, MET_SMI_DEBUGBUF_SIZE,
+ "===SMI config: parallel_mode = %d, master = %d, \
+ port0 = %d, port1 = %d, port2 = %d, port3 = %d, \
+ rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, \
+ desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ parallel_mode,
+ smi_conf_array[i].master,
+ smi_conf_array[i].port[0],
+ smi_conf_array[i].port[1],
+ smi_conf_array[i].port[2],
+ smi_conf_array[i].port[3],
+ smi_conf_array[i].rwtype[0],
+ smi_conf_array[i].rwtype[1],
+ smi_conf_array[i].rwtype[2],
+ smi_conf_array[i].rwtype[3],
+ smi_conf_array[i].desttype,
+ smi_conf_array[i].reqtype >> MET_SMI_BIT_REQ_LARB,
+ smi_conf_array[i].reqtype >> MET_SMI_BIT_REQ_COMM);
+ met_smi_debug(debug_msg);
+ }
+ } else {
+ met_smi_debug("smi_init() FAIL : smi_array_index overflow\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int met_smi_create(struct kobject *parent)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+do { \
+ ret = sysfs_create_file(kobj_smi, &attr_name##_attr.attr); \
+ if (ret != 0) { \
+ pr_debug("Failed to create " #attr_name " in sysfs\n"); \
+ return ret; \
+ } \
+} while (0)
+
+ int j = 0;
+ int ret = 0;
+
+ pr_debug("met_smi_create\n \
+ met_smi_create\n \
+ met_smi_create\n \
+ met_smi_create\n \
+ met_smi_create\n \
+ met_smi_create\n \
+ met_smi_create\n \
+ met_smi_create\n");
+
+ /* Init. */
+
+ smi_init_value();
+
+ larb_req_type = SMI_REQ_ALL;
+ comm_req_type = SMI_REQ_ALL;
+ parallel_mode = 0;
+
+ for (j = 0; j < NPORT_IN_PM; j++)
+ comm_pm_rw_type[0][j] = SMI_READ_ONLY;
+
+ kobj_smi = parent;
+
+ KOBJ_ATTR_LIST;
+
+ return ret;
+
+#undef KOBJ_ATTR_ITEM
+}
+
+void met_smi_delete(void)
+{
+#define KOBJ_ATTR_ITEM(attr_name) \
+ sysfs_remove_file(kobj_smi, &attr_name##_attr.attr)
+
+
+ if (kobj_smi != NULL) {
+ KOBJ_ATTR_LIST;
+ kobj_smi = NULL;
+ }
+
+#undef KOBJ_ATTR_ITEM
+}
+
+static void met_smi_start(void)
+{
+ if (do_smi()) {
+ if (smi_init() != 0) {
+ met_sspm_smi.mode = 0;
+ smi_init_value();
+ return;
+ }
+ }
+}
+
+static void met_smi_stop(void)
+{
+ int j = 0;
+
+ if (do_smi()) {
+ /* Reset */
+ smi_init_value();
+
+ larb_req_type = SMI_REQ_ALL;
+ comm_req_type = SMI_REQ_ALL;
+ parallel_mode = 0;
+
+ for (j = 0; j < NPORT_IN_PM; j++)
+ comm_pm_rw_type[0][j] = SMI_READ_ONLY;
+
+ met_sspm_smi.mode = 0;
+ }
+ return ;
+}
+
+static char help[] =
+" --smi=master:port:rw:dest:bus monitor specified SMI banwidth\n"
+" --smi=master:p1[:p2][:p3][:p4] monitor parallel mode\n";
+
+static int smi_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, "%s", help);
+}
+
+static int get_num(const char *__restrict__ dc, int *pValue)
+{
+ int value = 0;
+ int digit = 0;
+ int i = 0;
+
+ while (((*dc) >= '0') && ((*dc) <= '9')) {
+ digit = (int)(*dc - '0');
+ value = value * 10 + digit;
+ dc++;
+ i++;
+ }
+
+ if (i == 0)
+ return 0;
+ *pValue = value;
+
+ return i;
+}
+
+/*
+ * There are serveal cases as follows:
+ *
+ * 1. "met-cmd --start --smi=master:port:rwtype:desttype:bustype" => Can assign multiple master
+ * 2. "met-cmd --start --smi=master:port[:port1][:port2][:port3]" ==> parael mode
+ *
+ */
+static int smi_process_argument(const char *__restrict__ arg, int len)
+{
+ int args[5] = {0};
+ int i = 0;
+ int array_index = 0;
+ int idx = 0;
+ unsigned int smi_conf_index = 0;
+ struct met_smi_conf smi_conf;
+
+ uint32_t ipi_buf[4] = {0};
+ uint32_t ret = 0;
+ uint32_t rdata = 0;
+ uint16_t sspm_master = 0;
+ uint32_t sspm_meta = 0;
+
+ if (len < 3)
+ return -1;
+
+ /*reset local config structure*/
+ memset(err_msg, 0, MET_SMI_BUF_SIZE);
+ for (i = 0; i < 4; i++) {
+ smi_conf.port[i] = -1;
+ smi_conf.rwtype[i] = SMI_RW_ALL;
+ }
+ smi_conf.master = 0;
+ smi_conf.reqtype = SMI_REQ_ALL;
+ smi_conf.desttype = SMI_DEST_EMI;
+
+ if (met_sspm_smi.mode != 0 && met_sspm_smi.mode != 1)
+ return -1;
+
+ /*
+ * parse arguments
+ * arg[0] = master
+ * arg[1] = port or port1
+ * arg[2] = rwtype or port2
+ * arg[3] = desttype or port3
+ * arg[4] = bustype or port4
+ */
+ for (i = 0; i < ARRAY_SIZE(args); i++)
+ args[i] = -1;
+ idx = 0;
+ for (i = 0; i < ARRAY_SIZE(args); i++) {
+ ret = get_num(&(arg[idx]), &(args[i]));
+ if (ret == 0)
+ break;
+ idx += ret;
+ if (arg[idx] != ':')
+ break;
+ idx++;
+ }
+
+ pr_debug("===SMI process argu: args[0](%d), args[1](%d), args[2](%d), args[3](%d), args[4](%d)\n",
+ args[0],
+ args[1],
+ args[2],
+ args[3],
+ args[4]);
+
+ /*fill local config structure*/
+ smi_conf.master = args[0];
+ smi_conf.reqtype = (larb_req_type << MET_SMI_BIT_REQ_LARB) | (comm_req_type << MET_SMI_BIT_REQ_COMM);
+ if (parallel_mode == 0) { /*legacy mode*/
+ smi_conf.rwtype[0] = args[2];
+ smi_conf.desttype = args[3];
+ smi_conf.port[0] = args[1];
+ } else { /*parallel mode*/
+ smi_conf.desttype = SMI_DEST_EMI;
+ for (i = 0; i < 4; i++) {
+ if (args[i+1] < 0)
+ break;
+ smi_conf.port[i] = args[i+1];
+ smi_conf.rwtype[i] = comm_pm_rw_type[0][i];
+ }
+ }
+
+/*debug log to ftrace*/
+#ifdef MET_SMI_DEBUG
+ snprintf(debug_msg, MET_SMI_DEBUGBUF_SIZE,
+ "(argu)===SMI process argu Master[%d]: parallel_mode = %d, \
+ master = %d, port0 = %d, port1 = %d, port2 = %d, port3 = %d, \
+ rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, \
+ desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ args[0],
+ parallel_mode,
+ smi_conf.master,
+ smi_conf.port[0],
+ smi_conf.port[1],
+ smi_conf.port[2],
+ smi_conf.port[3],
+ smi_conf.rwtype[0],
+ smi_conf.rwtype[1],
+ smi_conf.rwtype[2],
+ smi_conf.rwtype[3],
+ smi_conf.desttype,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_LARB) & 0x3,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_COMM) & 0x3);
+ met_smi_debug(debug_msg);
+#endif
+
+ /*find the empty conf_array*/
+ for (i = 0; i < MAX_CONFIG_ARRAY_SIZE; i++) {
+ if ((smi_conf_array[i].master == smi_conf.master) && (smi_conf_array[i].port[0] != -1))
+ break;
+ }
+ if (i >= MAX_CONFIG_ARRAY_SIZE) {
+ if (smi_conf_array[0].port[0] == -1) {
+ smi_array_index = 0;
+ array_index = 0;
+ } else {
+ smi_array_index = smi_array_index + 1;
+ array_index = smi_array_index;
+ }
+ } else {
+ array_index = i;
+ }
+
+ if ((smi_array_index >= MAX_CONFIG_ARRAY_SIZE) || (array_index >= MAX_CONFIG_ARRAY_SIZE)) {
+ snprintf(err_msg, MET_SMI_BUF_SIZE,
+ "===Setting Master[%d]: check smi_array_index=%d, array_index=%d overflow (> %d)\n",
+ args[0], smi_array_index, array_index, MAX_CONFIG_ARRAY_SIZE);
+ return -1;
+ }
+
+ smi_conf_array[array_index].master = smi_conf.master;
+
+
+ if (parallel_mode == 0) { /* Legacy mode */
+ smi_conf_array[array_index].port[0] = smi_conf.port[0];
+ } else { /* Parallel mode */
+ for (i = 0; i < NPORT_IN_PM; i++) {
+ if (smi_conf_array[array_index].port[i] == -1)
+ smi_conf_array[array_index].port[i] = smi_conf.port[smi_conf_index++];
+ }
+ }
+ smi_conf_array[array_index].rwtype[0] = smi_conf.rwtype[0];
+ smi_conf_array[array_index].rwtype[1] = smi_conf.rwtype[1];
+ smi_conf_array[array_index].rwtype[2] = smi_conf.rwtype[2];
+ smi_conf_array[array_index].rwtype[3] = smi_conf.rwtype[3];
+ smi_conf_array[array_index].desttype = smi_conf.desttype;
+ smi_conf_array[array_index].reqtype = smi_conf.reqtype;
+
+ pr_debug("===SMI process argu Master[%d]: parallel_mode = %d, master = %d, \
+ port0 = %d, port1 = %d, port2 = %d, port3 = %d, \
+ rwtype0 = %d, rwtype1 = %d, rwtype2 = %d, rwtype3 = %d, \
+ desttype = %d, reqtype(larb) = %d, reqtype(comm) = %d\n",
+ args[0],
+ parallel_mode,
+ smi_conf.master,
+ smi_conf.port[0],
+ smi_conf.port[1],
+ smi_conf.port[2],
+ smi_conf.port[3],
+ smi_conf.rwtype[0],
+ smi_conf.rwtype[1],
+ smi_conf.rwtype[2],
+ smi_conf.rwtype[3],
+ smi_conf.desttype,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_LARB) & 0x3,
+ (smi_conf.reqtype >> MET_SMI_BIT_REQ_COMM) & 0x3);
+
+ // Encode SMI config: Master (request format from SMI driver)
+ sspm_master = sspm_master | (smi_conf_array[array_index].master << MET_SMI_BIT_MASTER);
+ sspm_master = sspm_master | 0 << MET_SMI_BIT_REQ; //reqtype value will be update in sspm side
+ sspm_master = sspm_master | (smi_conf_array[array_index].desttype << MET_SMI_BIT_DST);
+ sspm_master = sspm_master | (parallel_mode << MET_SMI_BIT_PM);
+ // Extrace info for larb and comm reqestType since of unable to recognize master belong to larb or comm.
+ // BIT13~BIT14: comm reqtype
+ // BIT15~BIT16: larb reqtype
+ sspm_master = sspm_master | smi_conf_array[array_index].reqtype;
+
+ // Encode SMI config: Meta (request format from SMI driver)
+ // Encode 4 Metadata into 1 unsigned int
+ // BIT0~BIT4: port
+ // BIT5~BIT6: rwtype
+ if (parallel_mode == 0){
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].port[0] << MET_SMI_BIT_PORT);
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].rwtype[0] << MET_SMI_BIT_RW);
+ } else {
+ for (i = 0; i < 4; i++){
+ if (smi_conf_array[array_index].port[i] == 0xFFFFFFFF){
+ smi_conf_array[array_index].port[i] = USHRT_MAX;
+ }
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].port[i] << (MET_SMI_BIT_PORT+8*i));
+ sspm_meta = sspm_meta | (smi_conf_array[array_index].rwtype[i] << (MET_SMI_BIT_RW+8*i));
+ }
+ }
+
+ // Transfer to SSPM side
+ if (sspm_buffer_size > 0) {
+ ipi_buf[0] = MET_MAIN_ID | MET_ARGU | MID_SMI << MID_BIT_SHIFT | 1;
+ ipi_buf[1] = sspm_master;
+ ipi_buf[2] = sspm_meta;
+ ipi_buf[3] = 0;
+ ret = met_ipi_to_sspm_command((void *)ipi_buf, 0, &rdata, 1);
+
+ /* Set mode */
+ met_sspm_smi.mode = 1;
+ ondiemet_module[ONDIEMET_SSPM] |= ID_CPU_INFO_MAPPING;
+ }
+
+ return 0;
+}
+
+struct metdevice met_sspm_smi = {
+ .name = "smi",
+ .owner = THIS_MODULE,
+ .type = MET_TYPE_BUS,
+ .create_subfs = met_smi_create,
+ .delete_subfs = met_smi_delete,
+ .cpu_related = 0,
+ .ondiemet_mode = 1,
+ .ondiemet_start = met_smi_start,
+ .ondiemet_stop = met_smi_stop,
+ .ondiemet_process_argument = smi_process_argument,
+ .ondiemet_print_help = smi_print_help,
+};
+EXPORT_SYMBOL(met_sspm_smi);
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi.h b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi.h
new file mode 100644
index 0000000..30529ee
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _SMI_H_
+#define _SMI_H_
+
+#include <linux/device.h>
+
+struct met_smi {
+ int mode;
+ int master;
+ unsigned int port;
+ unsigned int rwtype; /* 0 for R+W, 1 for read, 2 for write */
+ unsigned int desttype; /* 0 for EMI+internal mem, 1 for EMI, 3 for internal mem */
+ unsigned int bustype; /* 0 for GMC, 1 for AXI */
+ /* unsigned long requesttype;// 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+ struct kobject *kobj_bus_smi;
+};
+
+struct smi_cfg {
+ int master;
+ unsigned int port;
+ unsigned int rwtype; /* 0 for R+W, 1 for read, 2 for write */
+ unsigned int desttype; /* 0 for EMI+internal mem, 1 for EMI, 3 for internal mem */
+ unsigned int bustype; /*0 for GMC, 1 for AXI */
+ /*unsigned long requesttype;// 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+};
+
+struct smi_mon_con {
+ unsigned int requesttype; /* 0:All, 1:ultra high, 2:pre-ultrahigh, 3:normal. */
+};
+
+/* ====================== SMI/EMI Interface ================================ */
+
+struct met_smi_conf {
+ unsigned int master; /*Ex : Whitney: 0~8 for larb0~larb8, 9 for common larb*/
+ int port[4]; /* port select : [0] only for legacy mode, [0~3] ports for parallel mode, -1 no select*/
+ unsigned int reqtype; /* Selects request type : 0 for all,1 for ultra,2 for preultra,3 for normal*/
+ unsigned int rwtype[4]; /* Selects read/write: 0 for R+W, 1 for read, 2 for write;*/
+ /* [0] for legacy and parallel larb0~8, [0~3] for parallel mode common*/
+ unsigned int desttype; /* Selects destination: 0 and 3 for all memory, 1 for External,2 for internal*/
+};
+
+#endif /* _SMI_H_ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi_name.h b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi_name.h
new file mode 100644
index 0000000..1dc1076
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_met_smi_name.h
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _SMI_NAME_H_
+#define _SMI_NAME_H_
+// mark for Colgin porting
+// #include "mtk_smi.h"
+
+enum SMI_DEST {
+ SMI_DEST_ALL = 0,
+ SMI_DEST_EMI = 1,
+ SMI_DEST_INTERNAL = 2,
+ SMI_DEST_NONE = 9
+};
+
+enum SMI_RW {
+ SMI_RW_ALL = 0,
+ SMI_READ_ONLY = 1,
+ SMI_WRITE_ONLY = 2,
+ SMI_RW_RESPECTIVE = 3,
+ SMI_RW_NONE = 9
+};
+
+enum SMI_BUS {
+ SMI_BUS_GMC = 0,
+ SMI_BUS_AXI = 1,
+ SMI_BUS_NONE = 9
+};
+
+enum SMI_REQUEST {
+ SMI_REQ_ALL = 0,
+ SMI_REQ_ULTRA = 1,
+ SMI_REQ_PREULTRA = 2,
+ SMI_NORMAL_ULTRA = 3,
+ SMI_REQ_NONE = 9
+};
+
+struct smi_desc {
+ unsigned long port;
+ enum SMI_DEST desttype;
+ enum SMI_RW rwtype;
+ enum SMI_BUS bustype;
+};
+#endif /* _SMI_NAME_H_ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_mtk_smi.h b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_mtk_smi.h
new file mode 100644
index 0000000..82bc368
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/sspm_mtk_smi.h
@@ -0,0 +1,125 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MT_SMI_H__
+#define __MT_SMI_H__
+
+/* the default value, but the real number will get from symbol function*/
+#define SMI_LARB_NUMBER 9
+#define SMI_COMM_NUMBER 1
+#define SMI_LARB_MONITOR_NUMBER 1
+#define SMI_COMM_MONITOR_NUMBER 1
+
+#define SMI_REQ_OK (0)
+#define SMI_ERR_WRONG_REQ (-1)
+#define SMI_ERR_OVERRUN (-2)
+
+#define SMI_IOMEM_ADDR(b, off) ((void __iomem *)(((unsigned long)b)+off))
+
+#define SMI_LARB_MON_ENA(b) SMI_IOMEM_ADDR((b), 0x400)
+#define SMI_LARB_MON_CLR(b) SMI_IOMEM_ADDR((b), 0x404)
+#define SMI_LARB_MON_PORT(b) SMI_IOMEM_ADDR((b), 0x408)
+#define SMI_LARB_MON_CON(b) SMI_IOMEM_ADDR((b), 0x40C)
+
+#define SMI_LARB_MON_ACT_CNT(b) SMI_IOMEM_ADDR((b), 0x410)
+#define SMI_LARB_MON_REQ_CNT(b) SMI_IOMEM_ADDR((b), 0x414)
+#define SMI_LARB_MON_BEA_CNT(b) SMI_IOMEM_ADDR((b), 0x418)
+#define SMI_LARB_MON_BYT_CNT(b) SMI_IOMEM_ADDR((b), 0x41C)
+#define SMI_LARB_MON_CP_CNT(b) SMI_IOMEM_ADDR((b), 0x420)
+#define SMI_LARB_MON_DP_CNT(b) SMI_IOMEM_ADDR((b), 0x424)
+#define SMI_LARB_MON_OSTD_CNT(b) SMI_IOMEM_ADDR((b), 0x428)
+#define SMI_LARB_MON_CP_MAX(b) SMI_IOMEM_ADDR((b), 0x430)
+#define SMI_LARB_MON_OSTD_MAX(b) SMI_IOMEM_ADDR((b), 0x434)
+
+#define SMI_COMM_MON_ENA(b) SMI_IOMEM_ADDR((b), 0x1A0)
+#define SMI_COMM_MON_CLR(b) SMI_IOMEM_ADDR((b), 0x1A4)
+#define SMI_COMM_MON_TYPE(b) SMI_IOMEM_ADDR((b), 0x1AC)
+#define SMI_COMM_MON_CON(b) SMI_IOMEM_ADDR((b), 0x1B0)
+#define SMI_COMM_MON_ACT_CNT(b) SMI_IOMEM_ADDR((b), 0x1C0)
+#define SMI_COMM_MON_REQ_CNT(b) SMI_IOMEM_ADDR((b), 0x1C4)
+#define SMI_COMM_MON_OSTD_CNT(b) SMI_IOMEM_ADDR((b), 0x1C8)
+#define SMI_COMM_MON_BEA_CNT(b) SMI_IOMEM_ADDR((b), 0x1CC)
+#define SMI_COMM_MON_BYT_CNT(b) SMI_IOMEM_ADDR((b), 0x1D0)
+#define SMI_COMM_MON_CP_CNT(b) SMI_IOMEM_ADDR((b), 0x1D4)
+#define SMI_COMM_MON_DP_CNT(b) SMI_IOMEM_ADDR((b), 0x1D8)
+#define SMI_COMM_MON_CP_MAX(b) SMI_IOMEM_ADDR((b), 0x1DC)
+#define SMI_COMM_MON_OSTD_MAX(b) SMI_IOMEM_ADDR((b), 0x1E0)
+
+
+/*ondiemet smi ipi command*/
+enum MET_SMI_IPI_Type {
+ SMI_DRIVER_INITIAL_VALUE = 0x0,
+ SMI_DRIVER_RESET_VALUE,
+ SET_BASE_SMI,
+ SMI_ASSIGN_PORT_START,
+ SMI_ASSIGN_PORT_I,
+ SMI_ASSIGN_PORT_II,
+ SMI_ASSIGN_PORT_III,
+ SMI_ASSIGN_PORT_END,
+};
+
+
+
+
+void MET_SMI_IPI_baseaddr(void);
+int MET_SMI_Init(void);
+void MET_SMI_Fini(void);
+void MET_SMI_Enable(int larbno);
+void MET_SMI_Disable(int larbno);
+void MET_SMI_Pause(int larbno);
+void MET_SMI_Clear(int larbno);
+int MET_SMI_PowerOn(unsigned int master);
+void MET_SMI_PowerOff(unsigned int master);
+int MET_SMI_LARB_SetCfg(int larbno,
+ unsigned int pm,
+ unsigned int reqtype, unsigned int rwtype, unsigned int dsttype);
+int MET_SMI_LARB_SetPortNo(int larbno, unsigned int idx, unsigned int port);
+int MET_SMI_COMM_SetCfg(int commonno, unsigned int pm, unsigned int reqtype);
+int MET_SMI_COMM_SetPortNo(int commonno, unsigned int idx, unsigned int port);
+int MET_SMI_COMM_SetRWType(int commonno, unsigned int idx, unsigned int rw);
+
+/* config */
+int MET_SMI_GetEna(int larbno);
+int MET_SMI_GetClr(int larbno);
+int MET_SMI_GetPortNo(int larbno);
+int MET_SMI_GetCon(int larbno);
+
+/* cnt */
+int MET_SMI_GetActiveCnt(int larbno);
+int MET_SMI_GetRequestCnt(int larbno);
+int MET_SMI_GetBeatCnt(int larbno);
+int MET_SMI_GetByteCnt(int larbno);
+int MET_SMI_GetCPCnt(int larbno);
+int MET_SMI_GetDPCnt(int larbno);
+int MET_SMI_GetOSTDCnt(int larbno);
+int MET_SMI_GetCP_MAX(int larbno);
+int MET_SMI_GetOSTD_MAX(int larbno);
+
+/* common */
+void MET_SMI_Comm_Init(void);
+void MET_SMI_Comm_Enable(int commonno);
+void MET_SMI_Comm_Disable(int commonno);
+void MET_SMI_Pause(int commonno);
+void MET_SMI_Comm_Clear(int commonno);
+
+/* common config */
+int MET_SMI_Comm_GetEna(int commonno);
+int MET_SMI_Comm_GetClr(int commonno);
+int MET_SMI_Comm_GetType(int commonno);
+int MET_SMI_Comm_GetCon(int commonno);
+
+/* cnt */
+int MET_SMI_Comm_GetPortNo(int commonno);
+int MET_SMI_Comm_GetActiveCnt(int commonno);
+int MET_SMI_Comm_GetRequestCnt(int commonno);
+int MET_SMI_Comm_GetBeatCnt(int commonno);
+int MET_SMI_Comm_GetByteCnt(int commonno);
+int MET_SMI_Comm_GetCPCnt(int commonno);
+int MET_SMI_Comm_GetDPCnt(int commonno);
+int MET_SMI_Comm_GetOSTDCnt(int commonno);
+int MET_SMI_Comm_GetCP_MAX(int commonno);
+int MET_SMI_Comm_GetOSTD_MAX(int commonno);
+
+#endif /* __MT_SMI_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/sspm/tinysys_sspm.h b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/tinysys_sspm.h
new file mode 100644
index 0000000..c7ad40d
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/sspm/tinysys_sspm.h
@@ -0,0 +1,122 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __ONDIEMET_SSPM_H__
+#define __ONDIEMET_SSPM_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include "mtk_tinysys_ipi.h" /* for mtk_ipi_device */
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+/* MET IPI command definition: mbox 0 */
+/* main func ID: bit[31-24]; sub func ID: bit[23-18]; argu 0: bit[17-0] */
+#define MET_MAIN_ID_MASK 0xff000000 /* bit 31 - 24 */
+#define MET_SUB_ID_MASK 0x00fc0000 /* bit 23 - 18 */
+#define MET_ARGU0_MASK 0x0003ffff /* bit 17 - 0 */
+#define FUNC_BIT_SHIFT 18
+#define MID_BIT_SHIFT 9
+#define MET_MAIN_ID 0x06000000
+/* handle argument and attribute */
+#define PROCESS_ARGU 0x01
+#define PROCESS_ATTR 0x02
+#define MODULE_ID_MASK 0x3fe00 /* bit 9 - 17 */
+#define ARGUMENT_MASK 0x01ff /* bit 0 - 8 */
+
+/* the following command is used for AP to MD32 */
+/* argu 0: start: 0x01; stop: 0x02; extract: 0x03 */
+#define MET_OP_START 0x00000001
+#define MET_OP_STOP 0x00000002
+#define MET_OP_EXTRACT 0x00000003
+#define MET_OP_FLUSH 0x00000004
+#define MET_OP (1 << FUNC_BIT_SHIFT)
+#define MET_SR (2 << FUNC_BIT_SHIFT) /* sample rate */
+#define MET_MODULE (3 << FUNC_BIT_SHIFT) /* module enable/disable */
+#define MET_ARGU (4 << FUNC_BIT_SHIFT) /* argument passing */
+#define MET_ATTR (5 << FUNC_BIT_SHIFT) /* attribute passing */
+/* system memory information for on-die-met log data */
+#define MET_BUFFER_INFO (6 << FUNC_BIT_SHIFT)
+#define MET_TIMESTAMP (7 << FUNC_BIT_SHIFT) /* timestamp info */
+#define MET_GPT (8 << FUNC_BIT_SHIFT) /* GPT counter reading */
+#define MET_REQ_AP2MD (9 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_RESP_AP2MD (10 << FUNC_BIT_SHIFT) /* may no need */
+/* mode: bit 15 - 0: */
+/* Bit 0: MD32 SRAM mode; Bit 1: System DRAM mode */
+/* value: 0: output to next level of storage; 1: loop in its own storage */
+#define MET_DATA_MODE (11 << FUNC_BIT_SHIFT) /* log output mode */
+/* start/stop read data into MD32 SRAM buffer; both DMA and met_printf() */
+#define MET_DATA_OP (12 << FUNC_BIT_SHIFT) /* data read operation */
+/* the following command is used for MD32 to AP */
+#define MET_DUMP_BUFFER (13 << FUNC_BIT_SHIFT)
+#define MET_REQ_MD2AP (14 << FUNC_BIT_SHIFT) /* user defined command */
+#define MET_CLOSE_FILE (15 << FUNC_BIT_SHIFT) /* Inform to close the SD file */
+#define MET_RESP_MD2AP (16 << FUNC_BIT_SHIFT)
+#define MET_RUN_MODE (17 << FUNC_BIT_SHIFT)
+
+#define ID_PMQOS (1 << MID_PMQOS)
+#define ID_SMI (1 << MID_SMI)
+#define ID_EMI (1 << MID_EMI)
+#define ID_THERMAL_CPU (1 << MID_THERMAL_CPU)
+#define ID_WALL_TIME (1 << MID_WALL_TIME)
+#define ID_CPU_DVFS (1 << MID_CPU_DVFS)
+#define ID_GPU_DVFS (1 << MID_GPU_DVFS)
+#define ID_VCORE_DVFS (1 << MID_VCORE_DVFS)
+#define ID_PTPOD (1 << MID_PTPOD)
+#define ID_SPM (1 << MID_SPM)
+#define ID_PROFILE (1 << MID_PROFILE)
+#define ID_COMMON (1 << MID_COMMON)
+#define ID_CPU_INFO_MAPPING (1 << MID_CPU_INFO_MAPPING)
+#define ID_SMI (1 << MID_SMI)
+#define ID_PMU (1 << MID_PMU)
+
+#define SSPM_LOG_FILE 0
+#define SSPM_LOG_SRAM 1
+#define SSPM_LOG_DRAM 2
+
+#define SSPM_RUN_NORMAL 0
+#define SSPM_RUN_CONTINUOUS 1
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+/* Note: the module ID and its bit pattern should be fixed as below */
+/* DMA based module first */
+enum {
+ MID_PMQOS = 0,
+ MID_VCORE_DVFS,
+ MID_EMI,
+ MID_THERMAL_CPU,
+ MID_WALL_TIME,
+ MID_CPU_DVFS,
+ MID_GPU_DVFS,
+ MID_PTPOD,
+ MID_SPM,
+ MID_PROFILE,
+ MID_MET_TAG,
+ MID_TS,
+ MID_TS_ISR,
+ MID_TS_LAST,
+ MID_TS_ISR_LAST,
+ MID_SRAM_INFO,
+ MID_MET_STOP,
+ MID_IOP_MON,
+ MID_CPU_INFO_MAPPING,
+ MID_SMI,
+ MID_PMU,
+
+ MID_COMMON = 0x1F
+};
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+extern struct mtk_ipi_device *sspm_ipidev_symbol;
+extern int sspm_buf_available;
+
+#endif /* __ONDIEMET_SSPM_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_log.c b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_log.c
new file mode 100644
index 0000000..e20da51
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_log.c
@@ -0,0 +1,204 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/debugfs.h>
+#include <linux/proc_fs.h>
+#include <linux/semaphore.h>
+#include <linux/module.h> /* symbol_get */
+#include <linux/jiffies.h> /* timespec_to_jiffies */
+#include <linux/uaccess.h> /* copy_to_user */
+#include <asm/io.h> /* for ioremap and iounmap */
+
+#include "interface.h"
+
+#include "tinysys_mgr.h"
+#include "tinysys_log.h"
+
+#if FEATURE_SSPM_NUM
+#include "sspm_reservedmem.h"
+#include "sspm_reservedmem_define.h"
+#include "sspm/sspm_met_log.h"
+#endif
+
+#if FEATURE_CPU_EB_NUM
+#include "mcupm_driver.h"
+#include "cpu_eb/cpu_eb_met_log.h"
+#endif
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+#define IPI_COMMOND_SIZE 4
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+enum {
+ kTINYSYS_LOG_START,
+ kTINYSYS_LOG_STOP,
+ kTINYSYS_LOG_IDLE,
+};
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+static void _reset(int status, int type);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * internal variable declaration
+ *****************************************************************************/
+#if FEATURE_SSPM_NUM
+static unsigned int _g_sspm_status;
+#endif
+
+#if FEATURE_CPU_EB_NUM
+static unsigned int _g_cpu_eb_status;
+#endif
+
+
+/*****************************************************************************
+ * external function ipmlement
+ *****************************************************************************/
+int tinysys_log_manager_init(struct device *dev)
+{
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ struct dentry *dbgfs_met_dir = NULL;
+
+ dbgfs_met_dir = debugfs_create_dir("ondiemet", NULL);
+ if (dbgfs_met_dir == NULL) {
+ PR_BOOTMSG("[MET] can not create debugfs directory: ondiemet\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(dev, dbgfs_met_dir);
+#else
+ struct proc_dir_entry *procfs_met_dir = NULL;
+
+ procfs_met_dir = proc_mkdir("ondiemet", NULL);
+ if (procfs_met_dir == NULL) {
+ PR_BOOTMSG("[MET] can not create procfs directory: ondiemet\n");
+ return -ENOMEM;
+ }
+ dev_set_drvdata(dev, procfs_met_dir);
+#endif
+
+#if FEATURE_SSPM_NUM
+ sspm_log_init(dev);
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ cpu_eb_log_init(dev);
+#endif
+
+ return 0;
+}
+
+
+int tinysys_log_manager_uninit(struct device *dev)
+{
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ struct dentry *dbgfs_met_dir = NULL;
+#else
+ struct proc_dir_entry *procfs_met_dir = NULL;
+#endif
+
+#if FEATURE_SSPM_NUM
+ sspm_log_uninit(dev);
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ cpu_eb_log_uninit(dev);
+#endif
+
+#ifdef ONDIEMET_MOUNT_DEBUGFS
+ dbgfs_met_dir = dev_get_drvdata(dev);
+ if (dbgfs_met_dir) {
+ debugfs_remove_recursive(dbgfs_met_dir);
+ dev_set_drvdata(dev, NULL);
+ }
+#else
+ procfs_met_dir = dev_get_drvdata(dev);
+ if (procfs_met_dir) {
+ proc_remove(procfs_met_dir);
+ dev_set_drvdata(dev, NULL);
+ }
+#endif
+
+ return 0;
+}
+
+
+int tinysys_log_manager_start(void)
+{
+#if FEATURE_SSPM_NUM
+ sspm_log_start();
+ _reset(kTINYSYS_LOG_START, ONDIEMET_SSPM);
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ cpu_eb_log_start();
+ _reset(kTINYSYS_LOG_START, ONDIEMET_CPU_EB);
+#endif
+
+ return 0;
+}
+
+
+int tinysys_log_manager_stop(void)
+{
+#if FEATURE_SSPM_NUM
+ sspm_log_stop();
+ _reset(kTINYSYS_LOG_STOP, ONDIEMET_SSPM);
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ cpu_eb_log_stop();
+ _reset(kTINYSYS_LOG_STOP, ONDIEMET_CPU_EB);
+#endif
+
+ return 0;
+}
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+static void _reset(int status, int type)
+{
+ switch (type) {
+#if FEATURE_SSPM_NUM
+ case ONDIEMET_SSPM:
+ _g_sspm_status = status;
+ break;
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ case ONDIEMET_CPU_EB:
+ _g_cpu_eb_status = status;
+ break;
+#endif
+
+ default:
+ return;
+ }
+}
+
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_log.h b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_log.h
new file mode 100644
index 0000000..911ddcc
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_log.h
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __TINYSYS_LOG_H__
+#define __TINYSYS_LOG_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/device.h>
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+int tinysys_log_manager_init(struct device *dev);
+int tinysys_log_manager_uninit(struct device *dev);
+int tinysys_log_manager_start(void);
+int tinysys_log_manager_stop(void);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+
+
+#endif /* __TINYSYS_LOG_H__ */
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_mgr.c b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_mgr.c
new file mode 100644
index 0000000..d5bbf3e
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_mgr.c
@@ -0,0 +1,818 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/device.h> /* DEVICE_ATTR */
+
+#include "interface.h"
+
+#include "tinysys_mgr.h"
+#include "tinysys_log.h"
+
+#if FEATURE_SSPM_NUM
+#include "sspm/sspm_met_ipi_handle.h"
+#include "sspm/sspm_met_log.h"
+#endif
+
+#if FEATURE_CPU_EB_NUM
+#include "cpu_eb/cpu_eb_met_ipi_handle.h"
+#include "cpu_eb/cpu_eb_met_log.h"
+#endif
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+
+
+/*****************************************************************************
+ * internal function declaration
+ *****************************************************************************/
+#if FEATURE_SSPM_NUM
+static ssize_t sspm_ipi_supported_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_buffer_size_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_available_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_discard_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t sspm_log_size_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_log_size_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t sspm_run_mode_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_run_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t sspm_modules_show(struct device *dev, struct device_attribute *attr, char *buf);
+static ssize_t sspm_modules_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+static ssize_t sspm_op_ctrl_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count);
+
+static int _create_sspm_node(struct device *dev);
+static void _remove_sspm_node(struct device *dev);
+#endif
+
+#if FEATURE_CPU_EB_NUM
+static ssize_t _cpu_eb_ipi_supported_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf);
+
+static ssize_t _cpu_eb_buffer_size_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf);
+
+static ssize_t _cpu_eb_available_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf);
+
+static ssize_t _cpu_eb_log_discard_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf);
+
+static ssize_t _cpu_eb_log_size_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf);
+static ssize_t _cpu_eb_log_size_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count);
+
+static ssize_t _cpu_eb_run_mode_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf);
+static ssize_t _cpu_eb_run_mode_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count);
+
+static ssize_t _cpu_eb_modules_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf);
+static ssize_t _cpu_eb_modules_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count);
+
+static ssize_t _cpu_eb_op_ctrl_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count);
+
+static int _create_cpu_eb_node(struct kobject *kobj);
+static void _remove_cpu_eb_node(void);
+#endif
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+unsigned int ondiemet_module[ONDIEMET_NUM];
+EXPORT_SYMBOL(ondiemet_module);
+
+
+/*****************************************************************************
+ * internal variable declaration
+ *****************************************************************************/
+static struct kobject *_g_tinysys_kobj;
+
+#if FEATURE_SSPM_NUM
+static int _sspm_log_mode;
+static int _sspm_run_mode;
+static int _sspm_log_size;
+static int _sspm_log_discard;
+
+static DEVICE_ATTR(sspm_ipi_supported, 0444, sspm_ipi_supported_show, NULL);
+static DEVICE_ATTR(sspm_buffer_size, 0444, sspm_buffer_size_show, NULL);
+static DEVICE_ATTR(sspm_available, 0444, sspm_available_show, NULL);
+static DEVICE_ATTR(sspm_log_discard, 0444, sspm_log_discard_show, NULL);
+static DEVICE_ATTR(sspm_log_mode, 0664, sspm_log_mode_show, sspm_log_mode_store);
+static DEVICE_ATTR(sspm_log_size, 0664, sspm_log_size_show, sspm_log_size_store);
+static DEVICE_ATTR(sspm_run_mode, 0664, sspm_run_mode_show, sspm_run_mode_store);
+static DEVICE_ATTR(sspm_modules, 0664, sspm_modules_show, sspm_modules_store);
+static DEVICE_ATTR(sspm_op_ctrl, 0220, NULL, sspm_op_ctrl_store);
+#endif
+
+#if FEATURE_CPU_EB_NUM
+static int _cpu_eb_run_mode;
+static int _cpu_eb_log_size;
+static int _cpu_eb_log_discard;
+static struct kobject *_cpu_eb_kobj;
+static struct kobj_attribute _attr_cpu_eb_ipi_supported = \
+ __ATTR(ipi_supported, 0444, _cpu_eb_ipi_supported_show, NULL);
+static struct kobj_attribute _attr_cpu_eb_buffer_size = \
+ __ATTR(buffer_size, 0444, _cpu_eb_buffer_size_show, NULL);
+static struct kobj_attribute _attr_cpu_eb_available = \
+ __ATTR(available, 0444, _cpu_eb_available_show, NULL);
+static struct kobj_attribute _attr_cpu_eb_log_discard = \
+ __ATTR(log_discard, 0444, _cpu_eb_log_discard_show, NULL);
+static struct kobj_attribute _attr_cpu_eb_log_size = \
+ __ATTR(log_size, 0664, _cpu_eb_log_size_show, _cpu_eb_log_size_store);
+static struct kobj_attribute _attr_cpu_eb_run_mode = \
+ __ATTR(run_mode, 0664, _cpu_eb_run_mode_show, _cpu_eb_run_mode_store);
+static struct kobj_attribute _attr_cpu_eb_modules = \
+ __ATTR(modules, 0664, _cpu_eb_modules_show, _cpu_eb_modules_store);
+static struct kobj_attribute _attr_cpu_eb_op_ctrl = \
+ __ATTR(op_ctrl, 0220, NULL, _cpu_eb_op_ctrl_store);
+#endif
+
+
+/*****************************************************************************
+ * external function ipmlement
+ *****************************************************************************/
+int ondiemet_attr_init(struct device *dev)
+{
+ int ret = 0;
+
+ PR_BOOTMSG("%s\n", __FUNCTION__);
+ _g_tinysys_kobj = kobject_create_and_add("tinysys", &dev->kobj);
+ if (_g_tinysys_kobj == NULL) {
+ pr_debug("can not create kobject: tinysys\n");
+ return -1;
+ }
+
+#if FEATURE_SSPM_NUM
+ ret = _create_sspm_node(dev);
+ if (ret != 0) {
+ pr_debug("can not create sspm node\n");
+ return ret;
+ }
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ ret = _create_cpu_eb_node(_g_tinysys_kobj);
+ if (ret != 0) {
+ pr_debug("can not create cpu eb node\n");
+ return ret;
+ }
+#endif
+
+ return ret;
+}
+
+
+int ondiemet_attr_uninit(struct device *dev)
+{
+#if FEATURE_SSPM_NUM
+ _remove_sspm_node(dev);
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ _remove_cpu_eb_node();
+#endif
+
+ if (_g_tinysys_kobj != NULL) {
+ kobject_del(_g_tinysys_kobj);
+ kobject_put(_g_tinysys_kobj);
+ _g_tinysys_kobj = NULL;
+ }
+
+ return 0;
+}
+
+
+int ondiemet_log_manager_init(struct device *dev)
+{
+ return tinysys_log_manager_init(dev);
+}
+
+
+int ondiemet_log_manager_uninit(struct device *dev)
+{
+ return tinysys_log_manager_uninit(dev);
+}
+
+
+void ondiemet_log_manager_start()
+{
+ tinysys_log_manager_start();
+}
+
+
+void ondiemet_log_manager_stop()
+{
+ tinysys_log_manager_stop();
+}
+
+
+void ondiemet_start()
+{
+#if FEATURE_SSPM_NUM
+ sspm_start();
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ cpu_eb_start();
+#endif
+
+}
+
+
+void ondiemet_stop()
+{
+#if FEATURE_SSPM_NUM
+ sspm_stop();
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ cpu_eb_stop();
+#endif
+
+}
+
+
+void ondiemet_extract()
+{
+#if FEATURE_SSPM_NUM
+ sspm_extract();
+#endif
+
+#if FEATURE_CPU_EB_NUM
+ cpu_eb_extract();
+#endif
+
+}
+
+
+/*****************************************************************************
+ * internal function ipmlement
+ *****************************************************************************/
+#if FEATURE_SSPM_NUM
+static ssize_t sspm_ipi_supported_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int ipi_supported = 1;
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", ipi_supported);
+
+ return i;
+}
+
+
+static ssize_t sspm_buffer_size_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", sspm_buffer_size);
+
+ return i;
+}
+
+
+static ssize_t sspm_available_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", 1);
+
+ return i;
+}
+
+
+static ssize_t sspm_log_discard_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", _sspm_log_discard);
+
+ return i;
+}
+
+static ssize_t sspm_log_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ int i;
+
+ mutex_lock(&dev->mutex);
+ i = snprintf(buf, PAGE_SIZE, "%d\n", _sspm_log_mode);
+ mutex_unlock(&dev->mutex);
+ return i;
+}
+
+
+static ssize_t sspm_log_mode_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+{
+ int value;
+
+ if (kstrtoint(buf, 0, &value) != 0)
+ return -EINVAL;
+ mutex_lock(&dev->mutex);
+ _sspm_log_mode = value;
+ mutex_unlock(&dev->mutex);
+ return count;
+}
+
+
+static ssize_t sspm_log_size_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", _sspm_log_size);
+
+ return i;
+}
+
+
+static ssize_t sspm_log_size_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int value = 0;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ _sspm_log_size = value;
+
+ return count;
+}
+
+
+static ssize_t sspm_run_mode_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", _sspm_run_mode);
+
+ return i;
+}
+
+
+static ssize_t sspm_run_mode_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int value = 0;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ _sspm_run_mode = value;
+
+ return count;
+}
+
+
+static ssize_t sspm_op_ctrl_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int value = 0;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ if (value == 1) {
+ sspm_start();
+ } else if (value == 2) {
+ sspm_stop();
+ } else if (value == 3) {
+ sspm_extract();
+ } else if (value == 4) {
+ sspm_flush();
+ }
+
+ return count;
+}
+
+
+static ssize_t sspm_modules_show(
+ struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "0x%X\n", ondiemet_module[ONDIEMET_SSPM]);
+
+ return i;
+}
+
+static ssize_t sspm_modules_store(
+ struct device *dev,
+ struct device_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ unsigned int value;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ ondiemet_module[ONDIEMET_SSPM] = value;
+
+ return count;
+}
+
+
+static int _create_sspm_node(struct device *dev)
+{
+ int ret = 0;
+
+ ret = device_create_file(dev, &dev_attr_sspm_ipi_supported);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_ipi_supported\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_buffer_size);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_buffer_size\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_available);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_available\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_log_discard);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_discard\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_log_mode);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_mode\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_log_size);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_log_size\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_run_mode);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_run_mode\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_modules);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_modules\n");
+ return ret;
+ }
+
+ ret = device_create_file(dev, &dev_attr_sspm_op_ctrl);
+ if (ret != 0) {
+ pr_debug("can not create device file: sspm_op_ctrl\n");
+ return ret;
+ }
+ return ret;
+}
+
+
+static void _remove_sspm_node(struct device *dev)
+{
+ device_remove_file(dev, &dev_attr_sspm_ipi_supported);
+ device_remove_file(dev, &dev_attr_sspm_buffer_size);
+ device_remove_file(dev, &dev_attr_sspm_available);
+ device_remove_file(dev, &dev_attr_sspm_log_discard);
+ device_remove_file(dev, &dev_attr_sspm_log_mode);
+ device_remove_file(dev, &dev_attr_sspm_log_size);
+ device_remove_file(dev, &dev_attr_sspm_run_mode);
+ device_remove_file(dev, &dev_attr_sspm_modules);
+ device_remove_file(dev, &dev_attr_sspm_op_ctrl);
+}
+#endif
+
+
+#if FEATURE_CPU_EB_NUM
+static ssize_t _cpu_eb_ipi_supported_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int ipi_supported = 1;
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", ipi_supported);
+
+ return i;
+}
+
+
+static ssize_t _cpu_eb_buffer_size_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", cpu_eb_buffer_size);
+
+ return i;
+}
+
+
+static ssize_t _cpu_eb_available_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", 1);
+
+ return i;
+}
+
+
+static ssize_t _cpu_eb_log_discard_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", _cpu_eb_log_discard);
+
+ return i;
+}
+
+
+static ssize_t _cpu_eb_log_size_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", _cpu_eb_log_size);
+
+ return i;
+}
+
+
+static ssize_t _cpu_eb_log_size_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int value = 0;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ _cpu_eb_log_size = value;
+
+ return count;
+}
+
+
+static ssize_t _cpu_eb_run_mode_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "%d\n", _cpu_eb_run_mode);
+
+ return i;
+}
+
+
+static ssize_t _cpu_eb_run_mode_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int value = 0;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ _cpu_eb_run_mode = value;
+
+ return count;
+}
+
+
+static ssize_t _cpu_eb_op_ctrl_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ int value = 0;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ if (value == 1) {
+ cpu_eb_start();
+ } else if (value == 2) {
+ cpu_eb_stop();
+ } else if (value == 3) {
+ cpu_eb_extract();
+ } else if (value == 4) {
+ cpu_eb_flush();
+ }
+
+ return count;
+}
+
+
+static ssize_t _cpu_eb_modules_show(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ char *buf)
+{
+ int i = 0;
+
+ i = snprintf(buf, PAGE_SIZE, "0x%X\n", ondiemet_module[ONDIEMET_CPU_EB]);
+
+ return i;
+}
+
+static ssize_t _cpu_eb_modules_store(
+ struct kobject *kobj,
+ struct kobj_attribute *attr,
+ const char *buf,
+ size_t count)
+{
+ unsigned int value;
+
+ if (kstrtoint(buf, 0, &value) != 0) {
+ return -EINVAL;
+ }
+
+ ondiemet_module[ONDIEMET_CPU_EB] = value;
+
+ return count;
+}
+
+
+static int _create_cpu_eb_node(struct kobject *parent)
+{
+ int ret = 0;
+
+ _cpu_eb_kobj = kobject_create_and_add("cpu_eb", parent);
+ if (_cpu_eb_kobj == NULL) {
+ return -1;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_available.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: available\n");
+ return ret;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_buffer_size.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: buffer_size\n");
+ return ret;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_log_discard.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: log_discard\n");
+ return ret;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_log_size.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: log_size\n");
+ return ret;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_run_mode.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: run_mode\n");
+ return ret;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_op_ctrl.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: op_ctrl\n");
+ return ret;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_modules.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: modules\n");
+ return ret;
+ }
+
+ ret = sysfs_create_file(_cpu_eb_kobj, &_attr_cpu_eb_ipi_supported.attr);
+ if (ret != 0) {
+ pr_debug("can not create device file: ipi_supported\n");
+ return ret;
+ }
+ return ret;
+}
+
+
+static void _remove_cpu_eb_node()
+{
+ if (_cpu_eb_kobj != NULL) {
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_buffer_size.attr);
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_available.attr);
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_log_discard.attr);
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_log_size.attr);
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_run_mode.attr);
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_op_ctrl.attr);
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_modules.attr);
+ sysfs_remove_file(_cpu_eb_kobj, &_attr_cpu_eb_ipi_supported.attr);
+
+ kobject_del(_cpu_eb_kobj);
+ kobject_put(_cpu_eb_kobj);
+ _cpu_eb_kobj = NULL;
+ }
+}
+#endif
diff --git a/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_mgr.h b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_mgr.h
new file mode 100644
index 0000000..f44f44c
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/tinysys/v1/tinysys_mgr.h
@@ -0,0 +1,51 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+#ifndef __TINYSYS_MGR_H__
+#define __TINYSYS_MGR_H__
+/*****************************************************************************
+ * headers
+ *****************************************************************************/
+#include <linux/device.h>
+
+
+/*****************************************************************************
+ * define declaration
+ *****************************************************************************/
+#define ONDIEMET_NUM (FEATURE_SSPM_NUM + FEATURE_CPU_EB_NUM + FEATURE_SCP_NUM)
+
+
+/*****************************************************************************
+ * struct & enum declaration
+ *****************************************************************************/
+enum {
+ ONDIEMET_SSPM,
+ ONDIEMET_CPU_EB,
+ ONDIEMET_SCP,
+};
+
+
+/*****************************************************************************
+ * external function declaration
+ *****************************************************************************/
+int ondiemet_attr_init(struct device *dev);
+int ondiemet_attr_uninit(struct device *dev);
+
+int ondiemet_log_manager_init(struct device *dev);
+int ondiemet_log_manager_uninit(struct device *dev);
+void ondiemet_log_manager_start(void);
+void ondiemet_log_manager_stop(void);
+
+void ondiemet_start(void);
+void ondiemet_stop(void);
+void ondiemet_extract(void);
+
+
+/*****************************************************************************
+ * external variable declaration
+ *****************************************************************************/
+extern unsigned int ondiemet_module[ONDIEMET_NUM];
+
+
+#endif /* __TINYSYS_MGR_H__ */
diff --git a/src/devtools/met_drv_v2/common/trace.h b/src/devtools/met_drv_v2/common/trace.h
new file mode 100644
index 0000000..8dd5d65
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/trace.h
@@ -0,0 +1,105 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _TRACE_H_
+#define _TRACE_H_
+
+
+extern void (*mp_cp_ptr)(unsigned long long timestamp,
+ struct task_struct *task,
+ unsigned long program_counter,
+ unsigned long dcookie,
+ unsigned long offset,
+ unsigned char cnt, unsigned int *value);
+
+#define MP_FMT1 "%x\n"
+#define MP_FMT2 "%x,%x\n"
+#define MP_FMT3 "%x,%x,%x\n"
+#define MP_FMT4 "%x,%x,%x,%x\n"
+#define MP_FMT5 "%x,%x,%x,%x,%x\n"
+#define MP_FMT6 "%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT7 "%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT8 "%x,%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT9 "%x,%x,%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT10 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT11 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT12 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT13 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT14 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n"
+#define MP_FMT15 "%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x,%x\n"
+
+#define MET_GENERAL_PRINT(FUNC, count, value) \
+do { \
+ switch (count) { \
+ case 1: { \
+ FUNC(MP_FMT1, value[0]); \
+ } \
+ break; \
+ case 2: { \
+ FUNC(MP_FMT2, value[0], value[1]); \
+ } \
+ break; \
+ case 3: { \
+ FUNC(MP_FMT3, value[0], value[1], value[2]); \
+ } \
+ break; \
+ case 4: { \
+ FUNC(MP_FMT4, value[0], value[1], value[2], value[3]); \
+ } \
+ break; \
+ case 5: { \
+ FUNC(MP_FMT5, value[0], value[1], value[2], value[3], value[4]); \
+ } \
+ break; \
+ case 6: { \
+ FUNC(MP_FMT6, value[0], value[1], value[2], value[3], value[4], value[5]); \
+ } \
+ break; \
+ case 7: { \
+ FUNC(MP_FMT7, value[0], value[1], value[2], value[3], value[4], value[5], value[6]); \
+ } \
+ break; \
+ case 8: { \
+ FUNC(MP_FMT8, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7]); \
+ } \
+ break; \
+ case 9: { \
+ FUNC(MP_FMT9, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], \
+ value[8]); \
+ } \
+ break; \
+ case 10: { \
+ FUNC(MP_FMT10, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], \
+ value[8], value[9]); \
+ } \
+ break; \
+ case 11: { \
+ FUNC(MP_FMT11, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], \
+ value[8], value[9], value[10]); \
+ } \
+ break; \
+ case 12: { \
+ FUNC(MP_FMT12, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], \
+ value[8], value[9], value[10], value[11]); \
+ } \
+ break; \
+ case 13: { \
+ FUNC(MP_FMT13, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], \
+ value[8], value[9], value[10], value[11], value[12]); \
+ } \
+ break; \
+ case 14: { \
+ FUNC(MP_FMT14, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], \
+ value[8], value[9], value[10], value[11], value[12], value[13]); \
+ } \
+ break; \
+ case 15: { \
+ FUNC(MP_FMT15, value[0], value[1], value[2], value[3], value[4], value[5], value[6], value[7], \
+ value[8], value[9], value[10], value[11], value[12], value[13], value[14]); \
+ } \
+ break; \
+ } \
+} while (0)
+#endif /* _TRACE_H_ */
diff --git a/src/devtools/met_drv_v2/common/trace_event.c b/src/devtools/met_drv_v2/common/trace_event.c
new file mode 100644
index 0000000..7d0002a
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/trace_event.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <asm/page.h>
+#include "interface.h"
+#include "met_drv.h"
+
+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
+#include <trace/events/gpu.h>
+
+#define show_secs_from_ns(ns) \
+ ({ \
+ u64 t = ns + (NSEC_PER_USEC / 2); \
+ do_div(t, NSEC_PER_SEC); \
+ t; \
+ })
+
+#define show_usecs_from_ns(ns) \
+ ({ \
+ u64 t = ns + (NSEC_PER_USEC / 2) ; \
+ u32 rem; \
+ do_div(t, NSEC_PER_USEC); \
+ rem = do_div(t, USEC_PER_SEC); \
+ })
+
+static int event_gpu_registered;
+static int event_gpu_enabled;
+
+noinline void gpu_sched_switch(const char *gpu_name, u64 timestamp,
+ u32 next_ctx_id, s32 next_prio, u32 next_job_id)
+{
+ MET_TRACE("gpu_name=%s ts=%llu.%06lu next_ctx_id=%lu next_prio=%ld next_job_id=%lu\n",
+ gpu_name,
+ (unsigned long long)show_secs_from_ns(timestamp),
+ (unsigned long)show_usecs_from_ns(timestamp),
+ (unsigned long)next_ctx_id, (long)next_prio, (unsigned long)next_job_id);
+}
+
+MET_DEFINE_PROBE(gpu_sched_switch, TP_PROTO(const char *gpu_name, u64 timestamp,
+ u32 next_ctx_id, s32 next_prio, u32 next_job_id))
+{
+ gpu_sched_switch(gpu_name, timestamp, next_ctx_id, next_prio, next_job_id);
+}
+
+noinline void gpu_job_enqueue(u32 ctx_id, u32 job_id, const char *type)
+{
+ MET_TRACE("ctx_id=%lu job_id=%lu type=%s",
+ (unsigned long)ctx_id, (unsigned long)job_id, type);
+}
+
+MET_DEFINE_PROBE(gpu_job_enqueue, TP_PROTO(u32 ctx_id, u32 job_id, const char *type))
+{
+ gpu_job_enqueue(ctx_id, job_id, type);
+}
+#endif
+
+
+#ifdef MET_EVENT_POWER_SUPPORT
+#include "met_power.h"
+#include "met_kernel_symbol.h"
+
+static int event_power_registered;
+static int event_power_enabled;
+
+const char *
+met_trace_print_symbols_seq(char* pclass_name, unsigned long val,
+ const struct trace_print_flags *symbol_array)
+{
+ int i;
+ size_t new_fsize=0;
+ char _buf[32];
+ const char *ret = pclass_name;
+
+ for (i = 0; symbol_array[i].name; i++) {
+
+ if (val != symbol_array[i].mask)
+ continue;
+
+ new_fsize = sprintf(pclass_name, symbol_array[i].name, strlen(symbol_array[i].name));
+ break;
+ }
+
+ if (new_fsize == 0) {
+ snprintf(_buf, 32, "0x%lx", val);
+ new_fsize = sprintf(pclass_name, _buf, strlen(_buf));
+ }
+
+ return ret;
+}
+
+#define __print_symbolic(pclass_name, value, symbol_array...) \
+ ({ \
+ static const struct trace_print_flags symbols[] = \
+ { symbol_array, { -1, NULL }}; \
+ met_trace_print_symbols_seq(pclass_name, value, symbols); \
+ })
+
+#ifdef pm_qos_update_request
+#undef pm_qos_update_request
+#endif
+void pm_qos_update_request(int pm_qos_class, s32 value)
+{
+ char class_name[64];
+ MET_TRACE("pm_qos_class=%s value=%d owner=%s\n",
+ __print_symbolic(class_name, pm_qos_class,
+ { _PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" },
+ { _PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" },
+ { _PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }),
+ value);
+}
+//#endif
+
+#ifdef pm_qos_update_target
+#undef pm_qos_update_target
+#endif
+void pm_qos_update_target(unsigned int action, int prev_value, int curr_value)
+{
+ char class_name[64];
+
+ MET_TRACE("action=%s prev_value=%d curr_value=%d\n",
+ __print_symbolic(class_name, action,
+ { _PM_QOS_ADD_REQ, "ADD_REQ" },
+ { _PM_QOS_UPDATE_REQ, "UPDATE_REQ" },
+ { _PM_QOS_REMOVE_REQ, "REMOVE_REQ" }),
+ prev_value, curr_value);
+}
+#endif
+//#endif
+
+static int reset_driver_stat(void)
+{
+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
+ event_gpu_enabled = 0;
+#endif
+#ifdef MET_EVENT_POWER_SUPPORT
+ event_power_enabled = 0;
+#endif
+
+ met_trace_event.mode = 0;
+ return 0;
+}
+
+
+
+static void met_event_start(void)
+{
+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
+ /* register trace event for gpu */
+ do {
+ if (!event_gpu_enabled)
+ break;
+ if (MET_REGISTER_TRACE(gpu_sched_switch)) {
+ pr_debug("can not register callback of gpu_sched_switch\n");
+ break;
+ }
+ if (MET_REGISTER_TRACE(gpu_job_enqueue)) {
+ pr_debug("can not register callback of gpu_job_enqueue\n");
+ MET_UNREGISTER_TRACE(gpu_sched_switch);
+ break;
+ }
+ event_gpu_registered = 1;
+ } while (0);
+#endif
+
+#ifdef MET_EVENT_POWER_SUPPORT
+ /* register trace event for power */
+ do {
+ if (!event_power_enabled)
+ break;
+ if (met_export_api_symbol->met_reg_event_power)
+ if (met_export_api_symbol->met_reg_event_power()) {
+ pr_debug("can not register callback of met_reg_event_power\n");
+ break;
+ }
+ event_power_registered = 1;
+ } while (0);
+#endif
+
+}
+
+static void met_event_stop(void)
+{
+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
+ /* unregister trace event for gpu */
+ if (event_gpu_registered) {
+ MET_UNREGISTER_TRACE(gpu_job_enqueue);
+ MET_UNREGISTER_TRACE(gpu_sched_switch);
+ event_gpu_registered = 0;
+ }
+#endif
+
+#ifdef MET_EVENT_POWER_SUPPORT
+ /* unregister trace event for power */
+ if (event_power_registered) {
+ if (met_export_api_symbol->met_unreg_event_power)
+ met_export_api_symbol->met_unreg_event_power();
+ event_power_registered = 0;
+ }
+#endif
+}
+
+static int met_event_process_argument(const char *arg, int len)
+{
+ int ret = -1;
+
+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
+ if (strcasecmp(arg, "gpu") == 0) {
+ event_gpu_enabled = 1;
+ met_trace_event.mode = 1;
+ ret = 0;
+ }
+#endif
+#ifdef MET_EVENT_POWER_SUPPORT
+ if (strcasecmp(arg, "power") == 0) {
+ event_power_enabled = 1;
+ met_trace_event.mode = 1;
+ ret = 0;
+ }
+#endif
+ return ret;
+}
+
+static const char help[] = "\b"
+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
+ " --event=gpu output gpu trace events\n"
+#endif
+#ifdef MET_EVENT_POWER_SUPPORT
+ " --event=power output pmqos trace events\n"
+#endif
+ ;
+
+static int met_event_print_help(char *buf, int len)
+{
+ return snprintf(buf, PAGE_SIZE, help);
+}
+
+static const char header[] =
+ "met-info [000] 0.0: met_ftrace_event:"
+#if IS_ENABLED(CONFIG_GPU_TRACEPOINTS)
+ " gpu:gpu_sched_switch gpu:gpu_job_enqueue"
+#endif
+#ifdef MET_EVENT_POWER_SUPPORT
+ " power:pm_qos_update_request power:pm_qos_update_target"
+#endif
+ "\n";
+
+static int met_event_print_header(char *buf, int len)
+{
+ int ret;
+
+ ret = snprintf(buf, PAGE_SIZE, header);
+ return ret;
+}
+
+struct metdevice met_trace_event = {
+ .name = "event",
+ .type = MET_TYPE_PMU,
+ .start = met_event_start,
+ .stop = met_event_stop,
+ .reset = reset_driver_stat,
+ .process_argument = met_event_process_argument,
+ .print_help = met_event_print_help,
+ .print_header = met_event_print_header,
+};
diff --git a/src/devtools/met_drv_v2/common/util.c b/src/devtools/met_drv_v2/common/util.c
new file mode 100644
index 0000000..a53495b
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/util.c
@@ -0,0 +1,80 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "util.h"
+#include <linux/fs.h>
+#include <linux/kernel.h>
+/* #include <asm/uaccess.h> */
+#include <linux/uaccess.h>
+
+#ifdef FILELOG
+
+static char tmp[1000] = { 0 };
+
+ /*TODO*/
+/**
+ * open file
+ * @param name path to open
+ * @return file pointer
+ */
+struct file *open_file(const char *name)
+{
+ struct file *fp = NULL;
+
+ fp = filp_open(name, O_WRONLY | O_APPEND /*| O_TRUNC */ | O_CREAT, 0664);
+ if (unlikely(fp == NULL)) {
+ pr_debug(KERNEL_INFO "can not open result file");
+ return NULL;
+ }
+ return fp;
+}
+
+/**
+ * write to file
+ * @param fp file pointer
+ * @param format format string
+ * @param ... variable-length subsequent arguments
+ */
+void write_file(struct file *fp, const char *format, ...)
+{
+ va_list va;
+ mm_segment_t fs = get_fs();
+
+ va_start(va, format);
+ vsnprintf(tmp, sizeof(tmp), format, va);
+ set_fs(KERNEL_DS);
+ vfs_write(fp, tmp, strlen(tmp), &(fp->f_pos));
+ set_fs(fs);
+ va_end(va);
+}
+
+/**
+ * close file
+ * @param fp file pointer
+ * @return exit code
+ */
+int close_file(struct file *fp)
+{
+ if (likely(fp != NULL)) {
+ filp_close(fp, NULL);
+ fp = NULL;
+ return 0;
+ }
+ pr_debug("cannot close file pointer:%p\n", fp);
+ return -1;
+}
+
+void filelog(char *str)
+{
+ struct file *fp;
+
+ fp = open_file("/data/met.log");
+ if (fp != NULL) {
+ write_file(fp, "%s", str);
+ close_file(fp);
+ }
+}
+
+#endif /* FILELOG */
diff --git a/src/devtools/met_drv_v2/common/util.h b/src/devtools/met_drv_v2/common/util.h
new file mode 100644
index 0000000..2645a08
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/util.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef _SRC_UTIL_H_
+#define _SRC_UTIL_H_
+
+/* #define FILELOG 1 */
+
+#ifdef FILELOG
+void filelog(char *str);
+#else
+#define filelog(str)
+#endif
+
+#endif /* _SRC_UTIL_H_ */
diff --git a/src/devtools/met_drv_v2/common/v6_pmu_hw.c b/src/devtools/met_drv_v2/common/v6_pmu_hw.c
new file mode 100644
index 0000000..348866f
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/v6_pmu_hw.c
@@ -0,0 +1,234 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "cpu_pmu.h"
+
+/*******************************
+ * ARM v6 operations *
+ *******************************/
+#define ARMV6_PMCR_ENABLE (1 << 0)
+#define ARMV6_PMCR_CTR01_RESET (1 << 1)
+#define ARMV6_PMCR_CCOUNT_RESET (1 << 2)
+#define ARMV6_PMCR_CCOUNT_DIV (1 << 3)
+#define ARMV6_PMCR_COUNT0_IEN (1 << 4)
+#define ARMV6_PMCR_COUNT1_IEN (1 << 5)
+#define ARMV6_PMCR_CCOUNT_IEN (1 << 6)
+#define ARMV6_PMCR_COUNT0_OVERFLOW (1 << 8)
+#define ARMV6_PMCR_COUNT1_OVERFLOW (1 << 9)
+#define ARMV6_PMCR_CCOUNT_OVERFLOW (1 << 10)
+#define ARMV6_PMCR_EVT_COUNT0_SHIFT 20
+#define ARMV6_PMCR_EVT_COUNT0_MASK (0xFF << ARMV6_PMCR_EVT_COUNT0_SHIFT)
+#define ARMV6_PMCR_EVT_COUNT1_SHIFT 12
+#define ARMV6_PMCR_EVT_COUNT1_MASK (0xFF << ARMV6_PMCR_EVT_COUNT1_SHIFT)
+
+#define ARMV6_PMCR_OVERFLOWED_MASK \
+ (ARMV6_PMCR_COUNT0_OVERFLOW | ARMV6_PMCR_COUNT1_OVERFLOW | \
+ ARMV6_PMCR_CCOUNT_OVERFLOW)
+
+enum armv6_counters {
+ ARMV6_COUNTER0 = 0,
+ ARMV6_COUNTER1,
+ ARMV6_CYCLE_COUNTER,
+};
+
+static inline unsigned long armv6_pmcr_read(void)
+{
+ u32 val;
+
+ asm volatile ("mrc p15, 0, %0, c15, c12, 0":"=r" (val));
+ return val;
+}
+
+static inline void armv6_pmcr_write(unsigned long val)
+{
+ asm volatile ("mcr p15, 0, %0, c15, c12, 0"::"r" (val));
+}
+
+static inline unsigned int armv6_pmu_read_count(unsigned int idx)
+{
+ unsigned long value = 0;
+
+ if (idx == ARMV6_CYCLE_COUNTER)
+ asm volatile ("mrc p15, 0, %0, c15, c12, 1":"=r" (value));
+ else if (idx == ARMV6_COUNTER0)
+ asm volatile ("mrc p15, 0, %0, c15, c12, 2":"=r" (value));
+ else if (idx == ARMV6_COUNTER1)
+ asm volatile ("mrc p15, 0, %0, c15, c12, 3":"=r" (value));
+
+ return value;
+}
+
+static inline void armv6_pmu_overflow(void)
+{
+ unsigned int val;
+
+ val = armv6_pmcr_read();
+ val |= ARMV6_PMCR_OVERFLOWED_MASK;
+ armv6_pmcr_write(val);
+}
+
+static inline unsigned int armv6_pmu_control_read(void)
+{
+ u32 val;
+
+ asm volatile ("mrc p15, 0, %0, c15, c12, 0":"=r" (val));
+ return val;
+}
+
+static inline void armv6_pmu_control_write(unsigned int setting)
+{
+ unsigned long val;
+
+ val = armv6_pmcr_read();
+ val |= setting;
+ armv6_pmcr_write(val);
+}
+
+static void armv6_pmu_hw_reset_all(void)
+{
+ unsigned long val;
+
+ val = armv6_pmcr_read();
+ val &= ~ARMV6_PMCR_ENABLE; /* disable all counters */
+ val |= (ARMV6_PMCR_CTR01_RESET | ARMV6_PMCR_CCOUNT_RESET); /* reset CCNT, PMNC1/2 counter to zero */
+ armv6_pmcr_write(val);
+
+ armv6_pmu_overflow();
+}
+
+static void armv6pmu_enable_event(int idx, unsigned short config)
+{
+ unsigned long val, mask, evt;
+
+ if (idx == ARMV6_CYCLE_COUNTER) {
+ mask = 0;
+ evt = ARMV6_PMCR_CCOUNT_IEN;
+ } else if (idx == ARMV6_COUNTER0) {
+ mask = ARMV6_PMCR_EVT_COUNT0_MASK;
+ evt = (config << ARMV6_PMCR_EVT_COUNT0_SHIFT) | ARMV6_PMCR_COUNT0_IEN;
+ } else if (idx == ARMV6_COUNTER1) {
+ mask = ARMV6_PMCR_EVT_COUNT1_MASK;
+ evt = (config << ARMV6_PMCR_EVT_COUNT1_SHIFT) | ARMV6_PMCR_COUNT1_IEN;
+ } else {
+ pr_debug("invalid counter number (%d)\n", idx);
+ return;
+ }
+
+ /*
+ * Mask out the current event and set the counter to count the event
+ * that we're interested in.
+ */
+ val = armv6_pmcr_read();
+ val &= ~mask;
+ val |= evt;
+ armv6_pmcr_write(val);
+}
+
+/***********************************
+ * MET ARM v6 operations *
+ ***********************************/
+enum ARM_TYPE {
+ ARM1136 = 0xB36,
+ ARM1156 = 0xB56,
+ ARM1176 = 0xB76,
+ CHIP_UNKNOWN = 0xFFF
+};
+
+struct chip_pmu {
+ enum ARM_TYPE type;
+};
+
+static struct chip_pmu chips[] = {
+ {ARM1136},
+ {ARM1156},
+ {ARM1176},
+};
+
+static int armv6_pmu_hw_check_event(struct met_pmu *pmu, int idx, int event)
+{
+ int i;
+
+ /* Check if event is duplicate */
+ for (i = 0; i < idx; i++) {
+ if (pmu[i].event == event)
+ break;
+ }
+ if (i < idx) {
+ /* pr_debug("++++++ found duplicate event 0x%02x i=%d\n", event, i); */
+ return -1;
+ }
+
+ return 0;
+}
+
+static void armv6_pmu_hw_start(struct met_pmu *pmu, int count)
+{
+ int i;
+ int generic = count - 1;
+
+ armv6_pmu_hw_reset_all();
+
+ for (i = 0; i < generic; i++) {
+ if (pmu[i].mode == MODE_POLLING)
+ armv6pmu_enable_event(i, pmu[i].event);
+ }
+
+ if (pmu[count - 1].mode == MODE_POLLING)
+ armv6pmu_enable_event(2, pmu[2].event);
+
+ armv6_pmu_control_write(ARMV6_PMCR_ENABLE);
+}
+
+static void armv6_pmu_hw_stop(int count)
+{
+ armv6_pmu_hw_reset_all();
+}
+
+static unsigned int armv6_pmu_hw_polling(struct met_pmu *pmu, int count, unsigned int *pmu_value)
+{
+ int i, cnt = 0;
+ int generic = count - 1;
+
+ for (i = 0; i < generic; i++) {
+ if (pmu[i].mode == MODE_POLLING) {
+ pmu_value[cnt] = armv6_pmu_read_count(i);
+ cnt++;
+ }
+ }
+
+ if (pmu[count - 1].mode == MODE_POLLING) {
+ pmu_value[cnt] = armv6_pmu_read_count(2);
+ cnt++;
+ }
+
+ armv6_pmu_control_write(ARMV6_PMCR_ENABLE | ARMV6_PMCR_CTR01_RESET |
+ ARMV6_PMCR_CCOUNT_RESET);
+
+ return cnt;
+}
+
+struct cpu_pmu_hw armv6_pmu = {
+ .name = "armv6_pmu",
+ .check_event = armv6_pmu_hw_check_event,
+ .start = armv6_pmu_hw_start,
+ .stop = armv6_pmu_hw_stop,
+ .polling = armv6_pmu_hw_polling,
+};
+
+struct cpu_pmu_hw *v6_cpu_pmu_hw_init(int typeid)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(chips); i++)
+ if (chips[i].type == typeid)
+ break;
+
+ if (i == ARRAY_SIZE(chips))
+ return NULL;
+
+ armv6_pmu.nr_cnt = 3;
+
+ return &armv6_pmu;
+}
diff --git a/src/devtools/met_drv_v2/common/v6_pmu_hw.h b/src/devtools/met_drv_v2/common/v6_pmu_hw.h
new file mode 100644
index 0000000..27eb8c1
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/v6_pmu_hw.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __V6_PMU_HW_H__
+#define __V6_PMU_HW_H__
+
+extern struct cpu_pmu_hw armv6_pmu;
+extern struct cpu_pmu_hw *v6_cpu_pmu_hw_init(int typeid);
+
+#endif
diff --git a/src/devtools/met_drv_v2/common/v7_pmu_hw.c b/src/devtools/met_drv_v2/common/v7_pmu_hw.c
new file mode 100644
index 0000000..3f42369
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/v7_pmu_hw.c
@@ -0,0 +1,288 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include "cpu_pmu.h"
+#include "v6_pmu_hw.h"
+
+/*******************************
+ * ARM v7 operations *
+ *******************************/
+#define ARMV7_PMCR_E (1 << 0) /* enable all counters */
+#define ARMV7_PMCR_P (1 << 1)
+#define ARMV7_PMCR_C (1 << 2)
+#define ARMV7_PMCR_D (1 << 3)
+#define ARMV7_PMCR_X (1 << 4)
+#define ARMV7_PMCR_DP (1 << 5)
+#define ARMV7_PMCR_N_SHIFT 11 /* Number of counters supported */
+#define ARMV7_PMCR_N_MASK 0x1f
+#define ARMV7_PMCR_MASK 0x3f /* mask for writable bits */
+
+static unsigned int armv7_get_ic(void)
+{
+ unsigned int value;
+ /* Read Main ID Register */
+ asm volatile ("mrc p15, 0, %0, c0, c0, 0":"=r" (value));
+
+ value = (value & 0xffff) >> 4; /* primary part number */
+ return value;
+}
+
+static inline void armv7_pmu_counter_select(unsigned int idx)
+{
+ asm volatile ("mcr p15, 0, %0, c9, c12, 5"::"r" (idx));
+ isb();
+}
+
+static inline void armv7_pmu_type_select(unsigned int idx, unsigned int type)
+{
+ armv7_pmu_counter_select(idx);
+ asm volatile ("mcr p15, 0, %0, c9, c13, 1"::"r" (type));
+}
+
+static inline unsigned int armv7_pmu_read_count(unsigned int idx)
+{
+ unsigned int value;
+
+ if (idx == 31) {
+ asm volatile ("mrc p15, 0, %0, c9, c13, 0":"=r" (value));
+ } else {
+ armv7_pmu_counter_select(idx);
+ asm volatile ("mrc p15, 0, %0, c9, c13, 2":"=r" (value));
+ }
+ return value;
+}
+
+static inline void armv7_pmu_write_count(int idx, u32 value)
+{
+ if (idx == 31) {
+ asm volatile ("mcr p15, 0, %0, c9, c13, 0"::"r" (value));
+ } else {
+ armv7_pmu_counter_select(idx);
+ asm volatile ("mcr p15, 0, %0, c9, c13, 2"::"r" (value));
+ }
+}
+
+static inline void armv7_pmu_enable_count(unsigned int idx)
+{
+ asm volatile ("mcr p15, 0, %0, c9, c12, 1"::"r" (1 << idx));
+}
+
+static inline void armv7_pmu_disable_count(unsigned int idx)
+{
+ asm volatile ("mcr p15, 0, %0, c9, c12, 2"::"r" (1 << idx));
+}
+
+static inline void armv7_pmu_enable_intr(unsigned int idx)
+{
+ asm volatile ("mcr p15, 0, %0, c9, c14, 1"::"r" (1 << idx));
+}
+
+static inline void armv7_pmu_disable_intr(unsigned int idx)
+{
+ asm volatile ("mcr p15, 0, %0, c9, c14, 2"::"r" (1 << idx));
+}
+
+static inline unsigned int armv7_pmu_overflow(void)
+{
+ unsigned int val;
+
+ asm volatile ("mrc p15, 0, %0, c9, c12, 3":"=r" (val)); /* read */
+ asm volatile ("mcr p15, 0, %0, c9, c12, 3"::"r" (val));
+ return val;
+}
+
+static inline unsigned int armv7_pmu_control_read(void)
+{
+ u32 val;
+
+ asm volatile ("mrc p15, 0, %0, c9, c12, 0":"=r" (val));
+ return val;
+}
+
+static inline void armv7_pmu_control_write(unsigned int val)
+{
+ val &= ARMV7_PMCR_MASK;
+ isb();
+ asm volatile ("mcr p15, 0, %0, c9, c12, 0"::"r" (val));
+}
+
+static int armv7_pmu_hw_get_counters(void)
+{
+ int count = armv7_pmu_control_read();
+ /* N, bits[15:11] */
+ count = ((count >> ARMV7_PMCR_N_SHIFT) & ARMV7_PMCR_N_MASK);
+ return count;
+}
+
+static void armv7_pmu_hw_reset_all(int generic_counters)
+{
+ int i;
+
+ armv7_pmu_control_write(ARMV7_PMCR_C | ARMV7_PMCR_P);
+ /* generic counter */
+ for (i = 0; i < generic_counters; i++) {
+ armv7_pmu_disable_intr(i);
+ armv7_pmu_disable_count(i);
+ }
+ /* cycle counter */
+ armv7_pmu_disable_intr(31);
+ armv7_pmu_disable_count(31);
+ armv7_pmu_overflow(); /* clear overflow */
+}
+
+/***********************************
+ * MET ARM v7 operations *
+ ***********************************/
+enum ARM_TYPE {
+ CORTEX_A7 = 0xC07,
+ CORTEX_A9 = 0xC09,
+ CORTEX_A12 = 0xC0D,
+ CORTEX_A15 = 0xC0F,
+ CORTEX_A17 = 0xC0E,
+ CORTEX_A53 = 0xD03,
+ CORTEX_A57 = 0xD07,
+ CHIP_UNKNOWN = 0xFFF
+};
+
+struct chip_pmu {
+ enum ARM_TYPE type;
+};
+
+static struct chip_pmu chips[] = {
+ {CORTEX_A7},
+ {CORTEX_A9},
+ {CORTEX_A12},
+ {CORTEX_A15},
+ {CORTEX_A17},
+ {CORTEX_A53},
+ {CORTEX_A57},
+};
+
+static int armv7_pmu_hw_check_event(struct met_pmu *pmu, int idx, int event)
+{
+ int i;
+
+ /* Check if event is duplicate */
+ for (i = 0; i < idx; i++) {
+ if (pmu[i].event == event)
+ break;
+ }
+ if (i < idx) {
+ /* pr_debug("++++++ found duplicate event 0x%02x i=%d\n", event, i); */
+ return -1;
+ }
+
+ return 0;
+}
+
+static void armv7_pmu_hw_start(struct met_pmu *pmu, int count)
+{
+ int i;
+ int generic = count - 1;
+
+ armv7_pmu_hw_reset_all(generic);
+ for (i = 0; i < generic; i++) {
+ if (pmu[i].mode == MODE_POLLING) {
+ armv7_pmu_type_select(i, pmu[i].event);
+ armv7_pmu_enable_count(i);
+ }
+ }
+ if (pmu[count - 1].mode == MODE_POLLING) { /* cycle counter */
+ armv7_pmu_enable_count(31);
+ }
+ armv7_pmu_control_write(ARMV7_PMCR_E);
+}
+
+static void armv7_pmu_hw_stop(int count)
+{
+ int generic = count - 1;
+
+ armv7_pmu_hw_reset_all(generic);
+}
+
+static unsigned int armv7_pmu_hw_polling(struct met_pmu *pmu, int count, unsigned int *pmu_value)
+{
+ int i, cnt = 0;
+ int generic = count - 1;
+
+ for (i = 0; i < generic; i++) {
+ if (pmu[i].mode == MODE_POLLING) {
+ pmu_value[cnt] = armv7_pmu_read_count(i);
+ cnt++;
+ }
+ }
+ if (pmu[count - 1].mode == MODE_POLLING) {
+ pmu_value[cnt] = armv7_pmu_read_count(31);
+ cnt++;
+ }
+ armv7_pmu_control_write(ARMV7_PMCR_C | ARMV7_PMCR_P | ARMV7_PMCR_E);
+
+ return cnt;
+}
+
+#define ARMV7_PMU_EVTYPE_EVENT 0xff
+
+static unsigned long armv7_perf_event_get_evttype(struct perf_event *ev) {
+
+ struct hw_perf_event *hwc;
+
+ hwc = &ev->hw;
+ return hwc->config_base & ARMV7_PMU_EVTYPE_EVENT;
+}
+
+#define PMU_OVSR_MASK 0xffffffff /* Mask for writable bits */
+
+static u32 armv7_pmu_read_clear_overflow_flag(void)
+{
+ u32 value;
+
+ asm volatile ("mrc p3, 3, %0, c9, c12, 3":"=r" (value));
+
+ /* Write to clear flags */
+ value &= PMU_OVSR_MASK;
+ asm volatile ("mcr p3, 3, %0, c9, c12, 3"::"r" (value));
+
+ return value;
+}
+
+static struct met_pmu pmus[MXNR_CPU][MXNR_PMU_EVENTS];
+
+struct cpu_pmu_hw armv7_pmu = {
+ .name = "armv7_pmu",
+ .check_event = armv7_pmu_hw_check_event,
+ .start = armv7_pmu_hw_start,
+ .stop = armv7_pmu_hw_stop,
+ .polling = armv7_pmu_hw_polling,
+ .perf_event_get_evttype = armv7_perf_event_get_evttype,
+ .pmu_read_clear_overflow_flag = armv7_pmu_read_clear_overflow_flag,
+};
+
+struct cpu_pmu_hw *cpu_pmu_hw_init(void)
+{
+ int i;
+ enum ARM_TYPE type;
+ struct cpu_pmu_hw *pmu;
+
+ type = (enum ARM_TYPE)armv7_get_ic();
+ for (i = 0; i < ARRAY_SIZE(chips); i++)
+ if (chips[i].type == type)
+ break;
+
+ if (i < ARRAY_SIZE(chips)) {
+ armv7_pmu.nr_cnt = armv7_pmu_hw_get_counters() + 1;
+ pmu = &armv7_pmu;
+ } else
+ pmu = v6_cpu_pmu_hw_init(type);
+
+ if (pmu == NULL)
+ return NULL;
+
+ for (i = 0; i < MXNR_CPU; i++) {
+ pmu->event_count[i] = pmu->nr_cnt;
+ pmu->pmu[i] = pmus[i];
+ }
+
+ return pmu;
+}
diff --git a/src/devtools/met_drv_v2/common/v8_dsu_hw.c b/src/devtools/met_drv_v2/common/v8_dsu_hw.c
new file mode 100644
index 0000000..06a56bc
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/v8_dsu_hw.c
@@ -0,0 +1,48 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <asm/cpu.h>
+#include "met_kernel_symbol.h"
+#include "cpu_dsu.h"
+
+//dsu support 6 event
+#define DSU_EVENT_MAX_CNT 6
+
+static int armv8_dsu_hw_check_event(struct met_dsu *pmu, int idx, int event)
+{
+ int i;
+
+ /* Check if event is duplicate */
+ for (i = 0; i < idx; i++) {
+ if (pmu[i].event == event)
+ break;
+ }
+ if (i < idx) {
+ /* pr_debug("++++++ found duplicate event 0x%02x i=%d\n", event, i); */
+ return -1;
+ }
+ return 0;
+}
+
+
+static struct met_dsu pmus[MXNR_DSU_EVENTS];
+
+struct cpu_dsu_hw armv8_dsu = {
+ .name = "armv8_dsu",
+ .check_event = armv8_dsu_hw_check_event,
+};
+
+static void init_dsu(void)
+{
+ armv8_dsu.event_count = DSU_EVENT_MAX_CNT;
+}
+
+struct cpu_dsu_hw *cpu_dsu_hw_init(void)
+{
+
+ init_dsu();
+ armv8_dsu.pmu = pmus;
+ return &armv8_dsu;
+}
diff --git a/src/devtools/met_drv_v2/common/v8_pmu_hw.c b/src/devtools/met_drv_v2/common/v8_pmu_hw.c
new file mode 100644
index 0000000..05b5801
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/v8_pmu_hw.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/perf_event.h>
+#include <asm/cpu.h>
+#include "met_kernel_symbol.h"
+#include "cpu_pmu.h"
+
+/*******************************
+ * ARM v8 operations *
+ *******************************/
+/*
+ * Per-CPU PMCR: config reg
+ */
+#define ARMV8_PMCR_E (1 << 0) /* Enable all counters */
+#define ARMV8_PMCR_P (1 << 1) /* Reset all counters */
+#define ARMV8_PMCR_C (1 << 2) /* Cycle counter reset */
+#define ARMV8_PMCR_D (1 << 3) /* CCNT counts every 64th cpu cycle */
+#define ARMV8_PMCR_X (1 << 4) /* Export to ETM */
+#define ARMV8_PMCR_DP (1 << 5) /* Disable CCNT if non-invasive debug */
+#define ARMV8_PMCR_N_SHIFT 11 /* Number of counters supported */
+#define ARMV8_PMCR_N_MASK 0x1f
+#define ARMV8_PMCR_MASK 0x3f /* Mask for writable bits */
+
+/*
+ * PMOVSR: counters overflow flag status reg
+ */
+#define ARMV8_OVSR_MASK 0xffffffff /* Mask for writable bits */
+#define ARMV8_OVERFLOWED_MASK ARMV8_OVSR_MASK
+
+static inline void armv8_pmu_counter_select(unsigned int idx)
+{
+ asm volatile ("msr pmselr_el0, %x0"::"r" (idx));
+ isb();
+}
+
+static inline void armv8_pmu_type_select(unsigned int idx, unsigned int type)
+{
+ armv8_pmu_counter_select(idx);
+ asm volatile ("msr pmxevtyper_el0, %x0"::"r" (type));
+}
+
+static inline unsigned int armv8_pmu_read_count(unsigned int idx)
+{
+ unsigned int value;
+
+ if (idx == 31) {
+ asm volatile ("mrs %x0, pmccntr_el0":"=r" (value));
+ } else {
+ armv8_pmu_counter_select(idx);
+ asm volatile ("mrs %x0, pmxevcntr_el0":"=r" (value));
+ }
+ return value;
+}
+
+static inline void armv8_pmu_enable_count(unsigned int idx)
+{
+ asm volatile ("msr pmcntenset_el0, %x0"::"r" (1 << idx));
+}
+
+static inline void armv8_pmu_disable_count(unsigned int idx)
+{
+ asm volatile ("msr pmcntenclr_el0, %x0"::"r" (1 << idx));
+}
+
+static inline void armv8_pmu_enable_intr(unsigned int idx)
+{
+ asm volatile ("msr pmintenset_el1, %x0"::"r" (1 << idx));
+}
+
+static inline void armv8_pmu_disable_intr(unsigned int idx)
+{
+ asm volatile ("msr pmintenclr_el1, %x0"::"r" (1 << idx));
+ isb();
+ asm volatile ("msr pmovsclr_el0, %x0"::"r" (1 << idx));
+ isb();
+}
+
+static inline unsigned int armv8_pmu_overflow(void)
+{
+ unsigned int val;
+
+ asm volatile ("mrs %x0, pmovsclr_el0":"=r" (val)); /* read */
+ val &= ARMV8_OVSR_MASK;
+ asm volatile ("mrs %x0, pmovsclr_el0"::"r" (val));
+ return val;
+}
+
+static inline unsigned int armv8_pmu_control_read(void)
+{
+ unsigned int val;
+
+ asm volatile ("mrs %x0, pmcr_el0":"=r" (val));
+ return val;
+}
+
+static inline void armv8_pmu_control_write(u32 val)
+{
+ val &= ARMV8_PMCR_MASK;
+ isb();
+ asm volatile ("msr pmcr_el0, %x0"::"r" (val));
+}
+
+static void armv8_pmu_hw_reset_all(int generic_counters)
+{
+ int i;
+
+ armv8_pmu_control_write(ARMV8_PMCR_C | ARMV8_PMCR_P);
+ /* generic counter */
+ for (i = 0; i < generic_counters; i++) {
+ armv8_pmu_disable_intr(i);
+ armv8_pmu_disable_count(i);
+ }
+ /* cycle counter */
+ armv8_pmu_disable_intr(31);
+ armv8_pmu_disable_count(31);
+ armv8_pmu_overflow(); /* clear overflow */
+}
+
+/***********************************
+ * MET ARM v8 operations *
+ ***********************************/
+enum ARM_TYPE {
+ CORTEX_A53 = 0xD03,
+ CORTEX_A35 = 0xD04,
+ CORTEX_A55 = 0xD05,
+ CORTEX_A57 = 0xD07,
+ CORTEX_A72 = 0xD08,
+ CORTEX_A73 = 0xD09,
+ CORTEX_A75 = 0xD0A,
+ CORTEX_A76 = 0xD0B,
+ CORTEX_A77 = 0xD0D,
+ CHIP_UNKNOWN = 0xFFF
+};
+
+struct chip_pmu {
+ enum ARM_TYPE type;
+ unsigned int event_count;
+};
+
+static struct chip_pmu chips[] = {
+ {CORTEX_A35, 6+1},
+ {CORTEX_A53, 6+1},
+ {CORTEX_A55, 6+1},
+ {CORTEX_A57, 6+1},
+ {CORTEX_A72, 6+1},
+ {CORTEX_A73, 6+1},
+ {CORTEX_A75, 6+1},
+ {CORTEX_A76, 6+1},
+ {CORTEX_A77, 6+1},
+};
+
+static int armv8_pmu_hw_check_event(struct met_pmu *pmu, int idx, int event)
+{
+ int i;
+
+ /* Check if event is duplicate */
+ for (i = 0; i < idx; i++) {
+ if (pmu[i].event == event)
+ break;
+ }
+ if (i < idx) {
+ /* pr_debug("++++++ found duplicate event 0x%02x i=%d\n", event, i); */
+ return -1;
+ }
+
+ return 0;
+}
+
+static void armv8_pmu_hw_start(struct met_pmu *pmu, int count)
+{
+ int i;
+ int generic = count - 1;
+
+ armv8_pmu_hw_reset_all(generic);
+ for (i = 0; i < generic; i++) {
+ if (pmu[i].mode == MODE_POLLING) {
+ armv8_pmu_type_select(i, pmu[i].event);
+ armv8_pmu_enable_count(i);
+ }
+ }
+ if (pmu[count - 1].mode == MODE_POLLING) { /* cycle counter */
+ armv8_pmu_enable_count(31);
+ }
+ armv8_pmu_control_write(ARMV8_PMCR_E);
+}
+
+static void armv8_pmu_hw_stop(int count)
+{
+ int generic = count - 1;
+
+ armv8_pmu_hw_reset_all(generic);
+}
+
+static unsigned int armv8_pmu_hw_polling(struct met_pmu *pmu, int count, unsigned int *pmu_value)
+{
+ int i, cnt = 0;
+ int generic = count - 1;
+
+ for (i = 0; i < generic; i++) {
+ if (pmu[i].mode == MODE_POLLING) {
+ pmu_value[cnt] = armv8_pmu_read_count(i);
+ cnt++;
+ }
+ }
+ if (pmu[count - 1].mode == MODE_POLLING) {
+ pmu_value[cnt] = armv8_pmu_read_count(31);
+ cnt++;
+ }
+ armv8_pmu_control_write(ARMV8_PMCR_C | ARMV8_PMCR_P | ARMV8_PMCR_E);
+
+ return cnt;
+}
+
+static unsigned long armv8_perf_event_get_evttype(struct perf_event *ev) {
+
+ struct hw_perf_event *hwc;
+
+ hwc = &ev->hw;
+ return hwc->config_base & ARMV8_PMU_EVTYPE_EVENT;
+}
+
+#define PMU_OVSR_MASK 0xffffffff /* Mask for writable bits */
+
+static u32 armv8_pmu_read_clear_overflow_flag(void)
+{
+ u32 value;
+
+ asm volatile ("mrs %x0, pmovsclr_el0":"=r" (value));
+
+ /* Write to clear flags */
+ value &= PMU_OVSR_MASK;
+ asm volatile ("msr pmovsclr_el0, %x0"::"r" (value));
+
+ return value;
+}
+
+static struct met_pmu pmus[MXNR_CPU][MXNR_PMU_EVENTS];
+
+struct cpu_pmu_hw armv8_pmu = {
+ .name = "armv8_pmu",
+ .check_event = armv8_pmu_hw_check_event,
+ .start = armv8_pmu_hw_start,
+ .stop = armv8_pmu_hw_stop,
+ .polling = armv8_pmu_hw_polling,
+ .perf_event_get_evttype = armv8_perf_event_get_evttype,
+ .pmu_read_clear_overflow_flag = armv8_pmu_read_clear_overflow_flag,
+};
+
+static void init_pmus(void)
+{
+ int cpu;
+ int i;
+
+ for_each_possible_cpu(cpu) {
+ struct cpuinfo_arm64 *cpuinfo = NULL;
+ if (cpu >= MXNR_CPU)
+ continue;
+ if (met_export_api_symbol->met_get_cpuinfo)
+ met_export_api_symbol->met_get_cpuinfo(cpu, &cpuinfo);
+
+ if (cpuinfo == NULL)
+ continue;
+
+ /* PR_BOOTMSG("CPU[%d]: reg_midr = %x\n", cpu, cpuinfo->reg_midr); */
+ /* PR_BOOTMSG("CPU[%d]: MIDR_PARTNUM = %x\n", cpu, MIDR_PARTNUM(cpuinfo->reg_midr)); */
+ for (i = 0; i < ARRAY_SIZE(chips); i++) {
+ if (chips[i].type == MIDR_PARTNUM(cpuinfo->reg_midr)) {
+ armv8_pmu.event_count[cpu] = chips[i].event_count;
+ break;
+ }
+ }
+ }
+}
+
+struct cpu_pmu_hw *cpu_pmu_hw_init(void)
+{
+ int cpu;
+
+ init_pmus();
+ for (cpu = 0; cpu < MXNR_CPU; cpu++)
+ armv8_pmu.pmu[cpu] = pmus[cpu];
+
+ return &armv8_pmu;
+}
diff --git a/src/devtools/met_drv_v2/common/version.h b/src/devtools/met_drv_v2/common/version.h
new file mode 100644
index 0000000..ba33a4a
--- /dev/null
+++ b/src/devtools/met_drv_v2/common/version.h
@@ -0,0 +1,6 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#define MET_BACKEND_VERSION "6.2.0"
diff --git a/src/devtools/met_drv_v2/default/Kbuild b/src/devtools/met_drv_v2/default/Kbuild
new file mode 100644
index 0000000..9b2bb87
--- /dev/null
+++ b/src/devtools/met_drv_v2/default/Kbuild
@@ -0,0 +1,6 @@
+obj-m := met.o
+
+ccflags-y += -I$(srctree)/include/
+
+met-y := default/met_main.o
+
diff --git a/src/devtools/met_drv_v2/default/met_main.c b/src/devtools/met_drv_v2/default/met_main.c
new file mode 100644
index 0000000..33ada72
--- /dev/null
+++ b/src/devtools/met_drv_v2/default/met_main.c
@@ -0,0 +1,33 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/hrtimer.h>
+#include <linux/cpu.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/profile.h>
+#include <linux/dcache.h>
+#include <linux/types.h>
+#include <linux/dcookies.h>
+#include <linux/sched.h>
+#include <linux/fs.h>
+
+static int __init met_drv_init(void)
+{
+ pr_info("Hello MET default module\n");
+ return 0;
+}
+
+static void __exit met_drv_exit(void)
+{
+}
+module_init(met_drv_init);
+module_exit(met_drv_exit);
+
+MODULE_AUTHOR("DT_DM5");
+MODULE_DESCRIPTION("MET_DEFAULT");
+MODULE_LICENSE("GPL");
diff --git a/src/devtools/met_drv_v2/mt2735/Kbuild b/src/devtools/met_drv_v2/mt2735/Kbuild
new file mode 100644
index 0000000..b37838f
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt2735/Kbuild
@@ -0,0 +1,3 @@
+MET_PLF := $(MTK_PLATFORM)
+
+met-y +=
diff --git a/src/devtools/met_drv_v2/mt2735/Kbuild.platform.inc b/src/devtools/met_drv_v2/mt2735/Kbuild.platform.inc
new file mode 100644
index 0000000..42f9063
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt2735/Kbuild.platform.inc
@@ -0,0 +1,55 @@
+################################################################################
+# Copyright (C) 2019 MediaTek Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+################################################################################
+
+################################################################################
+# Include Path
+################################################################################
+MET_VCOREDVFS_INC := $(srctree)/drivers/misc/mediatek/base/power/include/vcorefs_v3
+MET_PTPOD_INC := $(srctree)/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/$(MTK_PLATFORM)/
+
+################################################################################
+# Feature Spec
+# CPUPMU_VERSION: V8_0/V8_2
+# EMI_SEDA_VERSION: SEDA2/SEDA3/SEDA3_5
+# SPMTWAM_VERSION: ap/sspm
+# SPMTWAM_IDLE_SIGNAL_SUPPORT: single/mutilple
+################################################################################
+CPUPMU_VERSION := V8_2
+EMI_SEDA_VERSION := SEDA3_5
+SPMTWAM_VERSION := none
+SPMTWAM_IDLE_SIGNAL_SUPPORT := none
+GPU_STALL_CNT_TYPE := single
+SSPM_VERSION := v2
+DYNAMIC_ALLOC_ODM_BUF_SIZE := 0x800000
+EMI_LOWEFF_SUPPORT := y
+
+################################################################################
+# Feature On/Off
+################################################################################
+FEATURE_GPU := n
+FEATURE_SPMTWAM := n
+FEATURE_EVENT_POWER := n
+FEATURE_ONDIEMET := n
+
+
+################################################################################
+# TINYSYS On/Off
+################################################################################
+TINYSYS_VERSION := v1
+FEATURE_TINYSYS := y
+FEATURE_SSPM_NUM := 1
+FEATURE_CPU_EB_NUM := 0
+FEATURE_SCP_NUM := 0
+ifeq ($(FEATURE_TINYSYS), y)
+ FEATURE_ONDIEMET := n
+endif
diff --git a/src/devtools/met_drv_v2/mt2735/met_dramc.h b/src/devtools/met_drv_v2/mt2735/met_dramc.h
new file mode 100644
index 0000000..d7aa38e
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt2735/met_dramc.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_DRAMC_H__
+#define __MTK_DRAMC_H__
+
+#define DRAMC_VER 2
+
+
+#endif /* __MTK_DRAMC_REG_H__ */
diff --git a/src/devtools/met_drv_v2/mt2735/met_gpu_monitor.h b/src/devtools/met_drv_v2/mt2735/met_gpu_monitor.h
new file mode 100644
index 0000000..f6a1b8e
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt2735/met_gpu_monitor.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ */
+
+#ifndef __MET_GPU_MONITOR_H__
+#define __MET_GPU_MONITOR_H__
+
+#define MET_GPU_STALL_MONITOR
+#define IO_ADDR_GPU_STALL 0x1021c000
+#define IO_SIZE_GPU_STALL 0x1000
+#define OFFSET_STALL_GPU_M0_CHECK 0x200
+#define OFFSET_STALL_GPU_M1_CHECK 0x204
+#define OFFSET_STALL_GPU_M0_EMI_CHECK 0x208
+#define OFFSET_STALL_GPU_M1_EMI_CHECK 0x20c
+
+#endif /* __MET_GPU_MONITOR_H__ */
diff --git a/src/devtools/met_drv_v2/mt2735/met_reg_addr.h b/src/devtools/met_drv_v2/mt2735/met_reg_addr.h
new file mode 100644
index 0000000..9f970c8
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt2735/met_reg_addr.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#ifndef __MET_REG_ADDR_H__
+
+#define EMI_REG_BASE (0x10219000)
+#define EMI_REG_SIZE 0x1000
+
+
+#define EMI_CH0_REG_BASE (0x10235000)
+/*#define EMI_CH1_REG_BASE (0x10245000)*/
+#define EMI_CH_REG_SIZE 0xA90
+#define EMI_CHN_BASE(n) (EMI_CH0_REG_BASE + n*(0x10000))
+
+#endif
diff --git a/src/devtools/met_drv_v2/mt2735/met_sspm_rts_event.h b/src/devtools/met_drv_v2/mt2735/met_sspm_rts_event.h
new file mode 100644
index 0000000..a10ab11
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt2735/met_sspm_rts_event.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+MET_SSPM_RTS_EVNET(SSPM_PTPOD, "_id,voltage")
+MET_SSPM_RTS_EVNET(SSPM_MET_UNIT_TEST, "test")
+MET_SSPM_RTS_EVNET(SSPM_QOS_BOUND_STATE, "idx,state,num,event,emibw_mon_total,emibw_mon_cpu,emibw_mon_gpu,emibw_mon_mm,emibw_mon_md,emibw_req_total,emibw_req_cpu,emibw_req_gpu,emibw_req_mm,emibw_req_md,smibw_mon_venc,smibw_mon_cam,smibw_mon_img,smibw_mon_mdp,smibw_mon_gpu,smibw_mon_apu,smibw_mon_vpu0,smibw_mon_vpu1,smibw_mon_mdla,smibw_req_venc,smibw_req_cam,smibw_req_img,smibw_req_mdp,smibw_req_gpu,smibw_req_apu,smibw_req_vpu0,smibw_req_vpu1,smibw_req_mdla,lat_mon_cpu,lat_mon_vpu0,lat_mon_vpu1,lat_mon_mdla")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_NON_WFX, "non_wfx_0,non_wfx_1,non_wfx_2,non_wfx_3,non_wfx_4,non_wfx_5,non_wfx_6,non_wfx_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_LOADING, "ratio,cps")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_POWER, "c_up_array_0,c_up_array_1,c_down_array_0,c_down_array_1,c_up_0,c_up_1,c_down_0,c_dwon_1,c_up,c_down,v_up,v_down,v2f_0,v2f_1")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_OPP, "v_dram_opp,v_dram_opp_cur,c_opp_cur_0,c_opp_cur_1,d_times_up,d_times_down")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_RATIO, "ratio_max_0,ratio_max_1,ratio_0,ratio_1,ratio_2,ratio_3,ratio_4,ratio_5,ratio_6,ratio_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_BW, "total_bw")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_CP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_VP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_DE_TIMES, "up0,up1,up2,up3,down0,down1,down2,down3,reset")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_ACTIVE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_IDLE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_OFF_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_STALL_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_L3DC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_INST_SPEC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_CYCLES, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_NON_WFX_CTR, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_L3_BW, "L3_BW")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_EMI_BW, "cpu_emi_bw")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DVFS, "vproc2,vproc1,cpuL_freq,cpuB_freq,cpu_L_opp,cpu_B_opp,cci_volt,cci_freq,cci_opp")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__LKG_POWER, "cpu_L,cpu_B,dsu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__POWER, "cpu_L,cpu_B,dsu,mcusys")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__GPU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__DVFS, "vgpu,gpu_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__URATE, "tex,alu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__POWER, "gpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__CAM_STATE_RATIO, "RAW_A_active,RAW_B_active,RAW_C_active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IMG_STATE_RATIO, "P2_active,P2_idle,MFB_active,WPE_active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IPE_STATE_RATIO, "FDVT_active,DVP_active,DVS_active,DV_idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__MDP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DISP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__ADSP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VENC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDEC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__INFRA_STATE_RATIO, "dact,cact,idle,dcm")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDO_CODING_TYPE, "venc,vdec")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DVFS, "vcore,cam_freq,img_freq,ipe_freq,dpe_freq,venc_freq,vdec_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__POWER, "cam,img,ipe,mdp,disp,adsp,venc,vdec,dramc,infra_top,aphy_vcore")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__MEM_IDX, "read_bw,write_bw,srr_pct,pdir_pct,phr_pct,acc_util,mr4")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__DVFS, "ddr_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__POWER, "aphy_vddq_0p6v,aphy_vm_0p75v,aphy_vio_1p2v,aphy_vio_1p8v,dram_vddq_0p6v,dram_vdd2_1p1v,dram_vdd1_1p8v")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU0_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU1_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__DVFS, "vvpu,vpu0_freq,vpu1_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__POWER, "vpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__ACTIVE_RATIO, "pool,dw,fc,conv,ewe,sb")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__TOTAL_CYCLES, "total_cycles")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__DVFS, "vmdla,mdla_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__POWER, "mdla")
+MET_SSPM_RTS_EVNET(__SSPM_APUSYS_QOS_CNT__, "bw_VPU0,bw_VPU1,bw_MDLA0,bw_MDLA1,lt_VPU0,lt_VPU1,lt_MDLA0,lt_MDLA1")
+MET_SSPM_RTS_EVNET(__SSPM_GPU_APU_SSC_CNT__, "GPU_0_R,GPU_0_W,APU_0_R,APU_0_W,GPU_1_R,GPU_1_W,APU_1_R,APU_1_W")
diff --git a/src/devtools/met_drv_v2/mt6880/Kbuild b/src/devtools/met_drv_v2/mt6880/Kbuild
new file mode 100644
index 0000000..b37838f
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6880/Kbuild
@@ -0,0 +1,3 @@
+MET_PLF := $(MTK_PLATFORM)
+
+met-y +=
diff --git a/src/devtools/met_drv_v2/mt6880/Kbuild.platform.inc b/src/devtools/met_drv_v2/mt6880/Kbuild.platform.inc
new file mode 100644
index 0000000..42f9063
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6880/Kbuild.platform.inc
@@ -0,0 +1,55 @@
+################################################################################
+# Copyright (C) 2019 MediaTek Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+################################################################################
+
+################################################################################
+# Include Path
+################################################################################
+MET_VCOREDVFS_INC := $(srctree)/drivers/misc/mediatek/base/power/include/vcorefs_v3
+MET_PTPOD_INC := $(srctree)/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/$(MTK_PLATFORM)/
+
+################################################################################
+# Feature Spec
+# CPUPMU_VERSION: V8_0/V8_2
+# EMI_SEDA_VERSION: SEDA2/SEDA3/SEDA3_5
+# SPMTWAM_VERSION: ap/sspm
+# SPMTWAM_IDLE_SIGNAL_SUPPORT: single/mutilple
+################################################################################
+CPUPMU_VERSION := V8_2
+EMI_SEDA_VERSION := SEDA3_5
+SPMTWAM_VERSION := none
+SPMTWAM_IDLE_SIGNAL_SUPPORT := none
+GPU_STALL_CNT_TYPE := single
+SSPM_VERSION := v2
+DYNAMIC_ALLOC_ODM_BUF_SIZE := 0x800000
+EMI_LOWEFF_SUPPORT := y
+
+################################################################################
+# Feature On/Off
+################################################################################
+FEATURE_GPU := n
+FEATURE_SPMTWAM := n
+FEATURE_EVENT_POWER := n
+FEATURE_ONDIEMET := n
+
+
+################################################################################
+# TINYSYS On/Off
+################################################################################
+TINYSYS_VERSION := v1
+FEATURE_TINYSYS := y
+FEATURE_SSPM_NUM := 1
+FEATURE_CPU_EB_NUM := 0
+FEATURE_SCP_NUM := 0
+ifeq ($(FEATURE_TINYSYS), y)
+ FEATURE_ONDIEMET := n
+endif
diff --git a/src/devtools/met_drv_v2/mt6880/met_dramc.h b/src/devtools/met_drv_v2/mt6880/met_dramc.h
new file mode 100644
index 0000000..d7aa38e
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6880/met_dramc.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_DRAMC_H__
+#define __MTK_DRAMC_H__
+
+#define DRAMC_VER 2
+
+
+#endif /* __MTK_DRAMC_REG_H__ */
diff --git a/src/devtools/met_drv_v2/mt6880/met_gpu_monitor.h b/src/devtools/met_drv_v2/mt6880/met_gpu_monitor.h
new file mode 100644
index 0000000..f6a1b8e
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6880/met_gpu_monitor.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ */
+
+#ifndef __MET_GPU_MONITOR_H__
+#define __MET_GPU_MONITOR_H__
+
+#define MET_GPU_STALL_MONITOR
+#define IO_ADDR_GPU_STALL 0x1021c000
+#define IO_SIZE_GPU_STALL 0x1000
+#define OFFSET_STALL_GPU_M0_CHECK 0x200
+#define OFFSET_STALL_GPU_M1_CHECK 0x204
+#define OFFSET_STALL_GPU_M0_EMI_CHECK 0x208
+#define OFFSET_STALL_GPU_M1_EMI_CHECK 0x20c
+
+#endif /* __MET_GPU_MONITOR_H__ */
diff --git a/src/devtools/met_drv_v2/mt6880/met_reg_addr.h b/src/devtools/met_drv_v2/mt6880/met_reg_addr.h
new file mode 100644
index 0000000..9f970c8
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6880/met_reg_addr.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#ifndef __MET_REG_ADDR_H__
+
+#define EMI_REG_BASE (0x10219000)
+#define EMI_REG_SIZE 0x1000
+
+
+#define EMI_CH0_REG_BASE (0x10235000)
+/*#define EMI_CH1_REG_BASE (0x10245000)*/
+#define EMI_CH_REG_SIZE 0xA90
+#define EMI_CHN_BASE(n) (EMI_CH0_REG_BASE + n*(0x10000))
+
+#endif
diff --git a/src/devtools/met_drv_v2/mt6880/met_sspm_rts_event.h b/src/devtools/met_drv_v2/mt6880/met_sspm_rts_event.h
new file mode 100644
index 0000000..a10ab11
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6880/met_sspm_rts_event.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+MET_SSPM_RTS_EVNET(SSPM_PTPOD, "_id,voltage")
+MET_SSPM_RTS_EVNET(SSPM_MET_UNIT_TEST, "test")
+MET_SSPM_RTS_EVNET(SSPM_QOS_BOUND_STATE, "idx,state,num,event,emibw_mon_total,emibw_mon_cpu,emibw_mon_gpu,emibw_mon_mm,emibw_mon_md,emibw_req_total,emibw_req_cpu,emibw_req_gpu,emibw_req_mm,emibw_req_md,smibw_mon_venc,smibw_mon_cam,smibw_mon_img,smibw_mon_mdp,smibw_mon_gpu,smibw_mon_apu,smibw_mon_vpu0,smibw_mon_vpu1,smibw_mon_mdla,smibw_req_venc,smibw_req_cam,smibw_req_img,smibw_req_mdp,smibw_req_gpu,smibw_req_apu,smibw_req_vpu0,smibw_req_vpu1,smibw_req_mdla,lat_mon_cpu,lat_mon_vpu0,lat_mon_vpu1,lat_mon_mdla")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_NON_WFX, "non_wfx_0,non_wfx_1,non_wfx_2,non_wfx_3,non_wfx_4,non_wfx_5,non_wfx_6,non_wfx_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_LOADING, "ratio,cps")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_POWER, "c_up_array_0,c_up_array_1,c_down_array_0,c_down_array_1,c_up_0,c_up_1,c_down_0,c_dwon_1,c_up,c_down,v_up,v_down,v2f_0,v2f_1")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_OPP, "v_dram_opp,v_dram_opp_cur,c_opp_cur_0,c_opp_cur_1,d_times_up,d_times_down")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_RATIO, "ratio_max_0,ratio_max_1,ratio_0,ratio_1,ratio_2,ratio_3,ratio_4,ratio_5,ratio_6,ratio_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_BW, "total_bw")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_CP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_VP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_DE_TIMES, "up0,up1,up2,up3,down0,down1,down2,down3,reset")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_ACTIVE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_IDLE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_OFF_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_STALL_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_L3DC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_INST_SPEC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_CYCLES, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_NON_WFX_CTR, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_L3_BW, "L3_BW")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_EMI_BW, "cpu_emi_bw")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DVFS, "vproc2,vproc1,cpuL_freq,cpuB_freq,cpu_L_opp,cpu_B_opp,cci_volt,cci_freq,cci_opp")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__LKG_POWER, "cpu_L,cpu_B,dsu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__POWER, "cpu_L,cpu_B,dsu,mcusys")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__GPU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__DVFS, "vgpu,gpu_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__URATE, "tex,alu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__POWER, "gpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__CAM_STATE_RATIO, "RAW_A_active,RAW_B_active,RAW_C_active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IMG_STATE_RATIO, "P2_active,P2_idle,MFB_active,WPE_active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IPE_STATE_RATIO, "FDVT_active,DVP_active,DVS_active,DV_idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__MDP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DISP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__ADSP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VENC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDEC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__INFRA_STATE_RATIO, "dact,cact,idle,dcm")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDO_CODING_TYPE, "venc,vdec")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DVFS, "vcore,cam_freq,img_freq,ipe_freq,dpe_freq,venc_freq,vdec_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__POWER, "cam,img,ipe,mdp,disp,adsp,venc,vdec,dramc,infra_top,aphy_vcore")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__MEM_IDX, "read_bw,write_bw,srr_pct,pdir_pct,phr_pct,acc_util,mr4")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__DVFS, "ddr_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__POWER, "aphy_vddq_0p6v,aphy_vm_0p75v,aphy_vio_1p2v,aphy_vio_1p8v,dram_vddq_0p6v,dram_vdd2_1p1v,dram_vdd1_1p8v")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU0_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU1_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__DVFS, "vvpu,vpu0_freq,vpu1_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__POWER, "vpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__ACTIVE_RATIO, "pool,dw,fc,conv,ewe,sb")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__TOTAL_CYCLES, "total_cycles")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__DVFS, "vmdla,mdla_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__POWER, "mdla")
+MET_SSPM_RTS_EVNET(__SSPM_APUSYS_QOS_CNT__, "bw_VPU0,bw_VPU1,bw_MDLA0,bw_MDLA1,lt_VPU0,lt_VPU1,lt_MDLA0,lt_MDLA1")
+MET_SSPM_RTS_EVNET(__SSPM_GPU_APU_SSC_CNT__, "GPU_0_R,GPU_0_W,APU_0_R,APU_0_W,GPU_1_R,GPU_1_W,APU_1_R,APU_1_W")
diff --git a/src/devtools/met_drv_v2/mt6890/Kbuild b/src/devtools/met_drv_v2/mt6890/Kbuild
new file mode 100644
index 0000000..b37838f
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6890/Kbuild
@@ -0,0 +1,3 @@
+MET_PLF := $(MTK_PLATFORM)
+
+met-y +=
diff --git a/src/devtools/met_drv_v2/mt6890/Kbuild.platform.inc b/src/devtools/met_drv_v2/mt6890/Kbuild.platform.inc
new file mode 100644
index 0000000..42f9063
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6890/Kbuild.platform.inc
@@ -0,0 +1,55 @@
+################################################################################
+# Copyright (C) 2019 MediaTek Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+################################################################################
+
+################################################################################
+# Include Path
+################################################################################
+MET_VCOREDVFS_INC := $(srctree)/drivers/misc/mediatek/base/power/include/vcorefs_v3
+MET_PTPOD_INC := $(srctree)/drivers/misc/mediatek/base/power/cpufreq_v1/src/mach/$(MTK_PLATFORM)/
+
+################################################################################
+# Feature Spec
+# CPUPMU_VERSION: V8_0/V8_2
+# EMI_SEDA_VERSION: SEDA2/SEDA3/SEDA3_5
+# SPMTWAM_VERSION: ap/sspm
+# SPMTWAM_IDLE_SIGNAL_SUPPORT: single/mutilple
+################################################################################
+CPUPMU_VERSION := V8_2
+EMI_SEDA_VERSION := SEDA3_5
+SPMTWAM_VERSION := none
+SPMTWAM_IDLE_SIGNAL_SUPPORT := none
+GPU_STALL_CNT_TYPE := single
+SSPM_VERSION := v2
+DYNAMIC_ALLOC_ODM_BUF_SIZE := 0x800000
+EMI_LOWEFF_SUPPORT := y
+
+################################################################################
+# Feature On/Off
+################################################################################
+FEATURE_GPU := n
+FEATURE_SPMTWAM := n
+FEATURE_EVENT_POWER := n
+FEATURE_ONDIEMET := n
+
+
+################################################################################
+# TINYSYS On/Off
+################################################################################
+TINYSYS_VERSION := v1
+FEATURE_TINYSYS := y
+FEATURE_SSPM_NUM := 1
+FEATURE_CPU_EB_NUM := 0
+FEATURE_SCP_NUM := 0
+ifeq ($(FEATURE_TINYSYS), y)
+ FEATURE_ONDIEMET := n
+endif
diff --git a/src/devtools/met_drv_v2/mt6890/met_dramc.h b/src/devtools/met_drv_v2/mt6890/met_dramc.h
new file mode 100644
index 0000000..d7aa38e
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6890/met_dramc.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+#ifndef __MTK_DRAMC_H__
+#define __MTK_DRAMC_H__
+
+#define DRAMC_VER 2
+
+
+#endif /* __MTK_DRAMC_REG_H__ */
diff --git a/src/devtools/met_drv_v2/mt6890/met_gpu_monitor.h b/src/devtools/met_drv_v2/mt6890/met_gpu_monitor.h
new file mode 100644
index 0000000..f6a1b8e
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6890/met_gpu_monitor.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2016 MediaTek Inc.
+ */
+
+#ifndef __MET_GPU_MONITOR_H__
+#define __MET_GPU_MONITOR_H__
+
+#define MET_GPU_STALL_MONITOR
+#define IO_ADDR_GPU_STALL 0x1021c000
+#define IO_SIZE_GPU_STALL 0x1000
+#define OFFSET_STALL_GPU_M0_CHECK 0x200
+#define OFFSET_STALL_GPU_M1_CHECK 0x204
+#define OFFSET_STALL_GPU_M0_EMI_CHECK 0x208
+#define OFFSET_STALL_GPU_M1_EMI_CHECK 0x20c
+
+#endif /* __MET_GPU_MONITOR_H__ */
diff --git a/src/devtools/met_drv_v2/mt6890/met_reg_addr.h b/src/devtools/met_drv_v2/mt6890/met_reg_addr.h
new file mode 100644
index 0000000..9f970c8
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6890/met_reg_addr.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (C) 2019 MediaTek Inc.
+ *
+ */
+#ifndef __MET_REG_ADDR_H__
+
+#define EMI_REG_BASE (0x10219000)
+#define EMI_REG_SIZE 0x1000
+
+
+#define EMI_CH0_REG_BASE (0x10235000)
+/*#define EMI_CH1_REG_BASE (0x10245000)*/
+#define EMI_CH_REG_SIZE 0xA90
+#define EMI_CHN_BASE(n) (EMI_CH0_REG_BASE + n*(0x10000))
+
+#endif
diff --git a/src/devtools/met_drv_v2/mt6890/met_sspm_rts_event.h b/src/devtools/met_drv_v2/mt6890/met_sspm_rts_event.h
new file mode 100644
index 0000000..a10ab11
--- /dev/null
+++ b/src/devtools/met_drv_v2/mt6890/met_sspm_rts_event.h
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 MediaTek Inc.
+ */
+
+MET_SSPM_RTS_EVNET(SSPM_PTPOD, "_id,voltage")
+MET_SSPM_RTS_EVNET(SSPM_MET_UNIT_TEST, "test")
+MET_SSPM_RTS_EVNET(SSPM_QOS_BOUND_STATE, "idx,state,num,event,emibw_mon_total,emibw_mon_cpu,emibw_mon_gpu,emibw_mon_mm,emibw_mon_md,emibw_req_total,emibw_req_cpu,emibw_req_gpu,emibw_req_mm,emibw_req_md,smibw_mon_venc,smibw_mon_cam,smibw_mon_img,smibw_mon_mdp,smibw_mon_gpu,smibw_mon_apu,smibw_mon_vpu0,smibw_mon_vpu1,smibw_mon_mdla,smibw_req_venc,smibw_req_cam,smibw_req_img,smibw_req_mdp,smibw_req_gpu,smibw_req_apu,smibw_req_vpu0,smibw_req_vpu1,smibw_req_mdla,lat_mon_cpu,lat_mon_vpu0,lat_mon_vpu1,lat_mon_mdla")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_NON_WFX, "non_wfx_0,non_wfx_1,non_wfx_2,non_wfx_3,non_wfx_4,non_wfx_5,non_wfx_6,non_wfx_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_LOADING, "ratio,cps")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_POWER, "c_up_array_0,c_up_array_1,c_down_array_0,c_down_array_1,c_up_0,c_up_1,c_down_0,c_dwon_1,c_up,c_down,v_up,v_down,v2f_0,v2f_1")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_OPP, "v_dram_opp,v_dram_opp_cur,c_opp_cur_0,c_opp_cur_1,d_times_up,d_times_down")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_RATIO, "ratio_max_0,ratio_max_1,ratio_0,ratio_1,ratio_2,ratio_3,ratio_4,ratio_5,ratio_6,ratio_7")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_BW, "total_bw")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_CP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_VP_RATIO, "up0,up1,up2,up3,down0,down1,down2,down3")
+MET_SSPM_RTS_EVNET(SSPM_CM_MGR_DE_TIMES, "up0,up1,up2,up3,down0,down1,down2,down3,reset")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_ACTIVE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_IDLE_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_OFF_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_STALL_RATIO, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_L3DC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_INST_SPEC, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_PMU_CYCLES, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__CORE_NON_WFX_CTR, "cpu0,cpu1,cpu2,cpu3,cpu4,cpu5,cpu6,cpu7")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DSU_L3_BW, "L3_BW")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__MCUSYS_EMI_BW, "cpu_emi_bw")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__DVFS, "vproc2,vproc1,cpuL_freq,cpuB_freq,cpu_L_opp,cpu_B_opp,cci_volt,cci_freq,cci_opp")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__LKG_POWER, "cpu_L,cpu_B,dsu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CPU__POWER, "cpu_L,cpu_B,dsu,mcusys")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__GPU_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__DVFS, "vgpu,gpu_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__URATE, "tex,alu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_GPU__POWER, "gpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__CAM_STATE_RATIO, "RAW_A_active,RAW_B_active,RAW_C_active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IMG_STATE_RATIO, "P2_active,P2_idle,MFB_active,WPE_active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__IPE_STATE_RATIO, "FDVT_active,DVP_active,DVS_active,DV_idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__MDP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DISP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__ADSP_STATE_RATIO, "active,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VENC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDEC_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__INFRA_STATE_RATIO, "dact,cact,idle,dcm")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__VDO_CODING_TYPE, "venc,vdec")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__DVFS, "vcore,cam_freq,img_freq,ipe_freq,dpe_freq,venc_freq,vdec_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_CORE__POWER, "cam,img,ipe,mdp,disp,adsp,venc,vdec,dramc,infra_top,aphy_vcore")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__MEM_IDX, "read_bw,write_bw,srr_pct,pdir_pct,phr_pct,acc_util,mr4")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__DVFS, "ddr_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_DRAM__POWER, "aphy_vddq_0p6v,aphy_vm_0p75v,aphy_vio_1p2v,aphy_vio_1p8v,dram_vddq_0p6v,dram_vdd2_1p1v,dram_vdd1_1p8v")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU0_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__VPU1_STATE_RATIO, "active,idle,off")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__DVFS, "vvpu,vpu0_freq,vpu1_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_VPU__POWER, "vpu")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__ACTIVE_RATIO, "pool,dw,fc,conv,ewe,sb")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__TOTAL_CYCLES, "total_cycles")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__DVFS, "vmdla,mdla_freq")
+MET_SSPM_RTS_EVNET(SSPM_SWPM_MDLA__POWER, "mdla")
+MET_SSPM_RTS_EVNET(__SSPM_APUSYS_QOS_CNT__, "bw_VPU0,bw_VPU1,bw_MDLA0,bw_MDLA1,lt_VPU0,lt_VPU1,lt_MDLA0,lt_MDLA1")
+MET_SSPM_RTS_EVNET(__SSPM_GPU_APU_SSC_CNT__, "GPU_0_R,GPU_0_W,APU_0_R,APU_0_W,GPU_1_R,GPU_1_W,APU_1_R,APU_1_W")
diff --git a/src/devtools/meta/NOTICE b/src/devtools/meta/NOTICE
new file mode 100644
index 0000000..17cd927
--- /dev/null
+++ b/src/devtools/meta/NOTICE
@@ -0,0 +1,23 @@
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
+following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
+disclaimer.
+ * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other materials provided with the distribution.
+ * Neither the name of the <ORGANIZATION> nor the names of its contributors may be used to endorse or promote
+products derived from this software without specific prior written permission.
+
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
diff --git a/src/devtools/meta/files/meta_tst.init b/src/devtools/meta/files/meta_tst.init
new file mode 100644
index 0000000..a604ccf
--- /dev/null
+++ b/src/devtools/meta/files/meta_tst.init
@@ -0,0 +1,16 @@
+#!/bin/sh /etc/rc.common
+
+START=98
+
+USE_PROCD=1
+NAME=meta_tst
+PROG=/usr/bin/meta_tst
+
+start_service() {
+ echo "start meta_tst"
+ procd_open_instance
+ procd_set_param command /usr/bin/meta_tst
+ procd_set_param stdout 1
+ procd_set_param stderr 1
+ procd_close_instance
+}
diff --git a/src/devtools/meta/src/LICENSE b/src/devtools/meta/src/LICENSE
new file mode 100644
index 0000000..77f59ed
--- /dev/null
+++ b/src/devtools/meta/src/LICENSE
@@ -0,0 +1,31 @@
+Copyright Statement:
+
+This software/firmware and related documentation ("MediaTek Software") are
+protected under relevant copyright laws. The information contained herein is
+confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+the prior written permission of MediaTek inc. and/or its licensors, any
+reproduction, modification, use or disclosure of MediaTek Software, and
+information contained herein, in whole or in part, shall be strictly
+prohibited.
+
+MediaTek Inc. (C) 2015. All rights reserved.
+
+BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
diff --git a/src/devtools/meta/src/Makefile b/src/devtools/meta/src/Makefile
new file mode 100644
index 0000000..f994290
--- /dev/null
+++ b/src/devtools/meta/src/Makefile
@@ -0,0 +1,61 @@
+TARGET := meta_tst
+
+FLAGS += -DFT_GPS_FEATURE
+FLAGS += -DFT_NVRAM_FEATURE
+
+INCLUDES += \
+ -I./common/inc \
+ -I./misc/snappy \
+ -I./adaptor/gps \
+ -I./adaptor/Meta_APEditor \
+ -I../../../libnvram/1.0.0-r0/libnvram-1.0.0/libfile_op \
+ -I../../../libnvram/1.0.0-r0/libnvram-1.0.0/libnvram \
+
+SRCS := \
+
+
+CXXSRCS := \
+ ./common/src/tst_main.cpp \
+ ./common/src/CmdTarget.cpp \
+ ./common/src/Context.cpp \
+ ./common/src/Device.cpp \
+ ./common/src/Frame.cpp \
+ ./common/src/FtModule.cpp \
+ ./common/src/MdRxWatcher.cpp \
+ ./common/src/Modem.cpp \
+ ./common/src/SerPort.cpp \
+ ./common/src/UsbRxWatcher.cpp \
+ ./common/src/PortHandle.cpp \
+ ./common/src/MSocket.cpp \
+ ./common/src/Meta_mipc.cpp \
+ ./misc/snappy/snappy-sinksource.cpp \
+ ./misc/snappy/snappy-stubs-internal.cpp \
+ ./misc/snappy/snappy.cpp \
+ ./misc/snappy/snappy-c.cpp \
+ ./adaptor/gps/meta_gps.cpp \
+ ./adaptor/Meta_APEditor/Meta_APEditor_Para.c \
+
+EXTRA_CXXFLAGS := -std=c++11
+
+OBJS := ${SRCS:%.c=%.o}
+
+CXXOBJS := ${CXXSRCS:%.cpp=%.o}
+
+LDFLAGS += -L. -lz -ldl -lpthread
+
+.PHONY: all
+all : $(TARGET)
+
+${TARGET}: $(OBJS) $(CXXOBJS)
+ $(CXX) $(OBJS) $(CXXOBJS) $(LDFLAGS) $(LIBS) $(CFLAGS) -o $@ $(INCLUDES)
+
+%.o: %.c
+ ${CC} $(CFLAGS) -c $< -o $@ $(INCLUDES) $(FLAGS)
+
+%.o: %.cpp
+ ${CXX} $(CXXFLAGS) $(CFLAGS) -c $< -o $@ $(INCLUDES) $(FLAGS) $(EXTRA_CXXFLAGS)
+
+.PHONY: clean
+clean:
+ $(warning "makefile meta_tst clean")
+ rm -rf $(OBJS) $(CXXOBJS) $(TARGET)
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.c b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.c
new file mode 100644
index 0000000..9544120
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.c
@@ -0,0 +1,206 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include "libnvram.h"
+#include "libnvram_log.h"
+#include "MetaPub.h"
+#include "Meta_APEditor_Para.h"
+#include "errno.h"
+
+
+//-----------------------------------------------------------------------------
+bool META_Editor_Init(void)
+{
+ return true;
+}
+//-----------------------------------------------------------------------------
+bool META_Editor_Deinit(void)
+{
+ return true;
+}
+//-----------------------------------------------------------------------------
+bool META_Editor_ReadFile_OP(FT_AP_Editor_read_req *pReq)
+{
+ FT_AP_Editor_read_cnf kCnf;
+ F_INFO kFileInfo;
+ int iNvmRecSize = 0, iReadSize;
+ F_ID iFD;
+ char* pBuffer = NULL;
+ bool IsRead =true;
+
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_read_cnf));
+ kCnf.header.id = pReq->header.id + 1;
+ kCnf.header.token = pReq->header.token;
+ kCnf.file_idx = pReq->file_idx;
+ kCnf.para = pReq->para;
+
+ iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+ if (iFD.iFileDesc == -1)
+ {
+ NVRAM_LOG("Error AP_Editor_ReadFile can't open file: file index-%d, %d\n", pReq->file_idx, iNvmRecSize);
+ kCnf.status = META_FAILED;
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+ return false;
+ }
+ iNvmRecSize = kFileInfo.i4RecSize;
+
+ if (pReq->para > kFileInfo.i4RecNum)
+ {
+ NVRAM_LOG("Error AP_Editor_ReadFile para: %d, %d\n", pReq->file_idx, pReq->para);
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+ return false;
+ }
+
+ /* Open NVRAM realted files */
+ pBuffer = (char*)malloc(iNvmRecSize);
+ if (pBuffer == NULL) {
+ NVRAM_LOG("Error AP_Editor_ReadFile:memory malloc error\r\n");
+ return false;
+ }
+ if (lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR) < 0) {
+ NVRAM_LOG("Error AP_Editor_ReadFile :seek fail,error:%s\n",strerror(errno));
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+ free(pBuffer);
+ return false;
+ }
+
+ iReadSize=read(iFD.iFileDesc, pBuffer, iNvmRecSize);
+ if(iNvmRecSize != iReadSize){
+ NVRAM_LOG("Error AP_Editor_ReadFile :Read size not match:iReadSize(%d),iNvmRecSize(%d),error:%s\n",iReadSize,iNvmRecSize,strerror(errno));
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+ free(pBuffer);
+ return false;
+ }
+
+ NVM_CloseFileDesc(iFD);
+
+ kCnf.read_status = META_STATUS_SUCCESS;
+ kCnf.status = META_SUCCESS;
+
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), pBuffer, iNvmRecSize);
+
+ NVRAM_LOG("AP_Editor_ReadFile result: file_idx ~ %d para ~ %d read ~ %d\n", pReq->file_idx, pReq->para, iReadSize);
+ free(pBuffer);
+
+ return true;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_write_cnf META_Editor_WriteFile_OP(
+ FT_AP_Editor_write_req *pReq,
+ char *peer_buf,
+ unsigned short peer_len)
+{
+ FT_AP_Editor_write_cnf kCnf;
+ F_INFO kFileInfo;
+ int iNvmRecSize = 0, iWriteSize;
+ F_ID iFD;
+ bool IsRead = false;
+
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_write_cnf));
+ kCnf.file_idx = pReq->file_idx;
+ kCnf.para = pReq->para;
+
+ if ((peer_buf == NULL) || (peer_len == 0)) {
+ NVRAM_LOG("Error AP_Editor_WriteFile Peer Buffer Error\n");
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+
+ iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+ if (iFD.iFileDesc == -1) {
+ NVRAM_LOG("Error AP_Editor_WriteFile can't open file: file index-%d, %d\n",
+ pReq->file_idx, iNvmRecSize);
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+ iNvmRecSize = kFileInfo.i4RecSize;
+ if ((pReq->para > kFileInfo.i4RecNum) || (peer_len > kFileInfo.i4RecSize)) {
+ NVRAM_LOG("Error AP_Editor_WriteFile para: %d, %d, %d\n", pReq->file_idx, pReq->para, peer_len);
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ return kCnf;
+
+ }
+ if (lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR) < 0) {
+ NVRAM_LOG("Error AP_Editor_WriteFile :seek fail,error:%s\n",strerror(errno));
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+
+ iWriteSize = write(iFD.iFileDesc, peer_buf, iNvmRecSize);
+ if(iNvmRecSize != iWriteSize){
+ NVRAM_LOG("Error AP_Editor_WriteFile :Write size not match:iWriteSize(%d),iNvmRecSize(%d),error:%s\n",iWriteSize,iNvmRecSize,strerror(errno));
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+ NVM_CloseFileDesc(iFD);
+
+ kCnf.write_status = META_STATUS_SUCCESS;
+ kCnf.status = META_SUCCESS;
+
+ NVRAM_LOG("AP_Editor_WriteFile result: file_idx-%d para-%d write-%d\n", pReq->file_idx, pReq->para, iWriteSize);
+ NVRAM_LOG("AddBackupFileNum Begin");
+ NVM_AddBackupFileNum(pReq->file_idx);
+ NVRAM_LOG("AddBackupFileNum End");
+ return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf META_Editor_ResetFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+ FT_AP_Editor_reset_cnf kCnf;
+
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+ if (!NVM_ResetFileToDefault(pReq->file_idx))
+ {
+ printf("Error AP_Editor_ResetFile\n");
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+
+ kCnf.status = META_SUCCESS;
+ return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf META_Editor_ResetAllFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+ int i;
+ FT_AP_Editor_reset_cnf kCnf;
+ FT_AP_Editor_reset_req kReq;
+
+ F_INFO kFileInfo = NVM_ReadFileVerInfo(0);
+
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+ memset(&kReq, 0, sizeof(FT_AP_Editor_reset_req));
+
+ if ((pReq->file_idx != 0xFCCF) || (pReq->reset_category != 0xFC))
+ {
+ kCnf.status = META_FAILED;
+ NVRAM_LOG("Error AP_Editor_ResetAllFile para is wrong - %d", pReq->file_idx);
+ return kCnf;
+ }
+
+ for (i = 0; i < kFileInfo.i4MaxFileLid; ++i)
+ {
+ kReq.file_idx = i;
+ kCnf = META_Editor_ResetFile_OP(&kReq);
+ if (kCnf.status == META_FAILED) {
+ NVRAM_LOG("Error AP_Editor_ResetAllFile: file_idx-%d\n", kReq.file_idx);
+ return kCnf;
+ }
+ }
+
+ return kCnf;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.cpp b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.cpp
new file mode 100644
index 0000000..4ba7079
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.cpp
@@ -0,0 +1,299 @@
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#include "libnvram.h"
+#include "libnvram_log.h"
+#include "MetaPub.h"
+#include "Meta_APEditor_Para.h"
+#include "errno.h"
+#if 1
+#include <vendor/mediatek/hardware/nvram/1.1/INvram.h>
+#include "cutils/log.h"
+#include <vector>
+#include <stdint.h>
+#include <android-base/logging.h>
+
+using std::string;
+
+
+static void covertArray2Vector(const char* in, int len, std::vector<uint8_t>& out) {
+ out.clear();
+ for(int i = 0; i < len; i++) {
+ out.push_back(in[i]);
+ }
+}
+static void covertVector2Array(std::vector<uint8_t> in, char* out) {
+ int size = in.size();
+ for(int i = 0; i < size; i++) {
+ out[i] = in.at(i);
+ }
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+bool META_Editor_Init(void)
+{
+ return true;
+}
+//-----------------------------------------------------------------------------
+bool META_Editor_Deinit(void)
+{
+ return true;
+}
+
+//readFileById(int32_t lid, uint16_t para) generates (string data, int32_t readsize, int8_t retval);
+
+//-----------------------------------------------------------------------------
+bool META_Editor_ReadFile_OP(FT_AP_Editor_read_req *pReq)
+{
+#if 1
+ FT_AP_Editor_read_cnf kCnf;
+ F_INFO kFileInfo;
+ int iNvmRecSize = 0, iReadSize;
+ F_ID iFD;
+ char* pBuffer = NULL;
+ char* ptempbuf = NULL;
+ bool IsRead =true;
+ using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+ android::sp<INvram> client = INvram::getService();
+
+ if (client == NULL) {
+ LOG(INFO) << "client is NULL";
+ }
+
+ char *nvrambuff=NULL;
+ std::vector<uint8_t> nvramvec;
+ int ret=0;
+ int Readsize = 0;
+ std::string readnvram;
+ int i =0;
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_read_cnf));
+ kCnf.header.id = pReq->header.id + 1;
+ kCnf.header.token = pReq->header.token;
+ kCnf.file_idx = pReq->file_idx;
+ kCnf.para = pReq->para;
+
+ auto callback = [&] (const std::string& data, int32_t readsize, int8_t retval) {
+ readnvram=data;
+ ret=(int)retval;
+ Readsize=(int)readsize;
+ //NVRAM_LOG("readnvram %s readsize %d retval%d\n", readnvram, readsize, retval);
+ LOG(INFO) << "readnvram@1:" << readnvram;
+
+ };
+ client->readFileBylid(pReq->file_idx,pReq->para,callback);
+ NVRAM_LOG("ret=%d, Readsize=%d\n", ret, Readsize);
+#if 0
+ iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+ if (iFD.iFileDesc == -1)
+ {
+ NVRAM_LOG("Error AP_Editor_ReadFile can't open file: file index-%d, %d\n", pReq->file_idx, iNvmRecSize);
+ kCnf.status = META_FAILED;
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+ return false;
+ }
+ iNvmRecSize = kFileInfo.i4RecSize;
+
+ if (pReq->para > kFileInfo.i4RecNum)
+ {
+ NVRAM_LOG("Error AP_Editor_ReadFile para: %d, %d\n", pReq->file_idx, pReq->para);
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+ return false;
+ }
+
+ /* Open NVRAM realted files */
+ pBuffer = (char*)malloc(iNvmRecSize);
+ if (pBuffer == NULL) {
+ NVRAM_LOG("Error AP_Editor_ReadFile:memory malloc error\r\n");
+ return false;
+ }
+ lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR);
+ iReadSize=read(iFD.iFileDesc, pBuffer, iNvmRecSize);
+ if(iNvmRecSize != iReadSize){
+ NVRAM_LOG("Error AP_Editor_ReadFile :Read size not match:iReadSize(%d),iNvmRecSize(%d),error:%s\n",iReadSize,iNvmRecSize,strerror(errno));
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), NULL, 0);
+ free(pBuffer);
+ return false;
+ }
+
+ NVM_CloseFileDesc(iFD);
+
+#endif
+ kCnf.read_status = META_STATUS_SUCCESS;
+ kCnf.status = META_SUCCESS;
+ pBuffer = (char*)malloc(Readsize);
+ ptempbuf = (char*)malloc(2*Readsize+1);
+ //char *cstr = new char[str.length() + 1];
+ strncpy(ptempbuf, readnvram.c_str(), 2*Readsize);
+ ptempbuf[2*Readsize] = '\0';
+
+ NVRAM_LOG("ptempbuf[0]%x, ptempbuf[1]%x, ptempbuf[2]%x, ptempbuf[3]%x, ptempbuf[4]%x, ptempbuf[5]%x, ptempbuf[6]%x, ptempbuf[7]%x, ptempbuf[8]%x \n",
+ ptempbuf[0],ptempbuf[1],ptempbuf[2],ptempbuf[3],ptempbuf[4],ptempbuf[5],ptempbuf[6],ptempbuf[7],ptempbuf[8]);
+
+ for(i=0;i<2*Readsize; i+=2)
+ {
+ sscanf(ptempbuf+i, "%02X", &pBuffer[i/2]);
+ }
+ NVRAM_LOG("pBuffer[0]%x, pBuffer[1]%x, pBuffer[2]%x, pBuffer[3]%x, pBuffer[4]%x, pBuffer[5]%x, pBuffer[6]%x, pBuffer[7]%x, pBuffer[8]%x \n",
+ pBuffer[0],pBuffer[1],pBuffer[2],pBuffer[3],pBuffer[4],pBuffer[5],pBuffer[6],pBuffer[7],pBuffer[8]);
+
+
+ //covertVector2Array(readnvram,pBuffer);
+
+ //WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), pBuffer, iNvmRecSize);
+ WriteDataToPC(&kCnf, sizeof(FT_AP_Editor_read_cnf), pBuffer, Readsize);
+
+ NVRAM_LOG("AP_Editor_ReadFile result: file_idx ~ %d para ~ %d read ~ %d\n", pReq->file_idx, pReq->para, Readsize);
+ free(pBuffer);
+#endif
+ return true;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_write_cnf META_Editor_WriteFile_OP(
+ FT_AP_Editor_write_req *pReq,
+ char *peer_buf,
+ unsigned short peer_len)
+{
+ FT_AP_Editor_write_cnf kCnf;
+ F_INFO kFileInfo;
+ int iNvmRecSize = 0, iWriteSize;
+ F_ID iFD;
+ bool IsRead = false;
+ std::vector<uint8_t> nvramvec;
+ int ret=0;
+ using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+ android::sp<INvram> client = INvram::getService();
+
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_write_cnf));
+ kCnf.file_idx = pReq->file_idx;
+ kCnf.para = pReq->para;
+
+ if ((peer_buf == NULL) || (peer_len == 0)) {
+ NVRAM_LOG("Error AP_Editor_WriteFile Peer Buffer Error\n");
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+
+#if 0
+ iFD = NVM_GetFileDesc(pReq->file_idx,&(kFileInfo.i4RecSize),&(kFileInfo.i4RecNum),IsRead);
+ if (iFD.iFileDesc == -1) {
+ NVRAM_LOG("Error AP_Editor_WriteFile can't open file: file index-%d, %d\n",
+ pReq->file_idx, iNvmRecSize);
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+ iNvmRecSize = kFileInfo.i4RecSize;
+ if ((pReq->para > kFileInfo.i4RecNum) || (peer_len > kFileInfo.i4RecSize)) {
+ NVRAM_LOG("Error AP_Editor_WriteFile para: %d, %d, %d\n", pReq->file_idx, pReq->para, peer_len);
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ return kCnf;
+
+ }
+ lseek(iFD.iFileDesc, (pReq->para - 1) * iNvmRecSize, SEEK_CUR);
+ iWriteSize = write(iFD.iFileDesc, peer_buf, iNvmRecSize);
+ if(iNvmRecSize != iWriteSize){
+ NVRAM_LOG("Error AP_Editor_WriteFile :Write size not match:iWriteSize(%d),iNvmRecSize(%d),error:%s\n",iWriteSize,iNvmRecSize,strerror(errno));
+ NVM_CloseFileDesc(iFD);
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+ NVM_CloseFileDesc(iFD);
+#else
+auto callback = [&] (int32_t writesize, int8_t retval) {
+ ret=(int)retval;
+ iWriteSize=(int)writesize;
+};
+covertArray2Vector(peer_buf,peer_len,nvramvec);
+
+
+client->writeFileBylid(pReq->file_idx,pReq->para,nvramvec,callback);
+NVRAM_LOG("ret=%d, iWriteSize=%d\n", ret, iWriteSize);
+
+
+#endif
+
+ kCnf.write_status = META_STATUS_SUCCESS;
+if(ret == 0)
+ kCnf.status = META_SUCCESS;
+else
+ kCnf.status = META_FAILED;
+
+ NVRAM_LOG("AP_Editor_WriteFile result: file_idx-%d para-%d write-%d\n", pReq->file_idx, pReq->para, iWriteSize);
+ NVRAM_LOG("AddBackupFileNum Begin");
+ //NVM_AddBackupFileNum(pReq->file_idx);
+ ret=client->AddBackupFileNum(pReq->file_idx);
+ NVRAM_LOG("AddBackupFileNum End ret=%d",ret);
+ return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf META_Editor_ResetFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+ FT_AP_Editor_reset_cnf kCnf;
+ using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+ android::sp<INvram> client = INvram::getService();
+
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+ //if (!NVM_ResetFileToDefault(pReq->file_idx))
+ if (!client->ResetFileToDefault(pReq->file_idx))
+ {
+ printf("Error AP_Editor_ResetFile\n");
+ kCnf.status = META_FAILED;
+ return kCnf;
+ }
+
+ kCnf.status = META_SUCCESS;
+ return kCnf;
+}
+//-----------------------------------------------------------------------------
+FT_AP_Editor_reset_cnf META_Editor_ResetAllFile_OP(FT_AP_Editor_reset_req *pReq)
+{
+ int i;
+ FT_AP_Editor_reset_cnf kCnf;
+ FT_AP_Editor_reset_req kReq;
+ #if 0
+ F_INFO kFileInfo = NVM_ReadFileVerInfo(0);
+ #else
+ using ::vendor::mediatek::hardware::nvram::V1_1::INvram;
+ android::sp<INvram> client = INvram::getService();
+ int FileInfoRecSize = 0, FileInfoRecNum= 0, FileInfoMaxFileLid = 0;
+ auto callback = [&] (int32_t i4RecSize, int32_t i4RecNum, int32_t i4MaxFileLid) {
+ FileInfoRecSize=(int)i4RecSize;
+ FileInfoRecNum=(int)i4RecNum;
+ FileInfoMaxFileLid=(int)i4MaxFileLid;
+};
+ client->ReadFileVerInfo(0,callback);
+ NVRAM_LOG("FileInfoRecSize %d, FileInfoRecNum %d, FileInfoMaxFileLid %d", FileInfoRecSize,FileInfoRecNum,FileInfoMaxFileLid);
+ #endif
+ memset(&kCnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+ memset(&kReq, 0, sizeof(FT_AP_Editor_reset_req));
+
+ if ((pReq->file_idx != 0xFCCF) || (pReq->reset_category != 0xFC))
+ {
+ kCnf.status = META_FAILED;
+ NVRAM_LOG("Error AP_Editor_ResetAllFile para is wrong - %d", pReq->file_idx);
+ return kCnf;
+ }
+
+ //for (i = 0; i < kFileInfo.i4MaxFileLid; ++i)
+ for (i = 0; i < FileInfoMaxFileLid; ++i)
+ {
+ kReq.file_idx = i;
+ kCnf = META_Editor_ResetFile_OP(&kReq);
+ if (kCnf.status == META_FAILED) {
+ NVRAM_LOG("Error AP_Editor_ResetAllFile: file_idx-%d\n", kReq.file_idx);
+ return kCnf;
+ }
+ }
+
+ return kCnf;
+}
+//-----------------------------------------------------------------------------
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.h b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.h
new file mode 100644
index 0000000..c43e5b4
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/Meta_APEditor_Para.h
@@ -0,0 +1,246 @@
+/*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2008
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+
+/*******************************************************************************
+ *
+ * Filename:
+ * ---------
+ * Meta_APEditor.h
+ *
+ * Project:
+ * --------
+ * DUMA
+ *
+ * Description:
+ * ------------
+ * header file of main function
+ *
+ * Author:
+ * -------
+ * Nick Huang (mtk02183) 12/09/2009
+ *
+ *******************************************************************************/
+
+
+#ifndef __AP_EDITOR_PARA_H__
+#define __AP_EDITOR_PARA_H__
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+ /********************************************
+ * Generic Primitives for AP_Editor READ/WRITE
+ ********************************************/
+
+ typedef struct
+ {
+ FT_H header; //the header of ft module
+ unsigned short file_idx; // file lid
+ unsigned short para; //record id
+ } FT_AP_Editor_read_req;
+
+ typedef struct
+ {
+ FT_H header; //the header of ft module
+ unsigned short file_idx; //file lid
+ unsigned short para; //record id
+ unsigned char read_status; //read nvram file status: 0 is fail
+ unsigned char status; //the status of ft module: 0 is success
+ } FT_AP_Editor_read_cnf;
+
+
+ typedef struct
+ {
+ FT_H header; //the header of ft module
+ unsigned short file_idx; //file lid
+ unsigned short para; //record id
+ } FT_AP_Editor_write_req;
+
+ typedef struct
+ {
+ FT_H header; //the header of ft module
+ unsigned short file_idx; //file lid
+ unsigned short para; //record id
+ unsigned char write_status; //the write status
+ unsigned char status; //the status of ft module: 0 is success
+ } FT_AP_Editor_write_cnf;
+
+
+ typedef struct
+ {
+ FT_H header; //the header of ft module
+ unsigned char reset_category; //0xff indicate reset all files
+ unsigned short file_idx; //0xffff indicate reset all files
+ } FT_AP_Editor_reset_req;
+
+ typedef struct
+ {
+ FT_H header; //the header of ft module
+ unsigned char reset_status; //the status of reset file to default value
+ unsigned char status; //the status of ft module, 0 is success
+ } FT_AP_Editor_reset_cnf;
+
+
+ /* implement these functions in AP_Editor.LIB */
+ /********************************************************************************
+ //FUNCTION:
+ // META_Editor_Init
+ //DESCRIPTION:
+ // this function is called to initial the meta_editor module.
+ //
+ //PARAMETERS:
+ // None
+ //
+ //RETURN VALUE:
+ // TRUE: is scuccess, otherwise is fail
+ //
+ //DEPENDENCY:
+ // None
+ //
+ //GLOBALS AFFECTED
+ // None
+ ********************************************************************************/
+ bool META_Editor_Init(void);
+
+
+ /********************************************************************************
+ //FUNCTION:
+ // META_Editor_Deinit
+ //DESCRIPTION:
+ // this function is called to de-initial the meta_editor module.
+ //
+ //PARAMETERS:
+ // None
+ //
+ //RETURN VALUE:
+ // TRUE: is scuccess, otherwise is fail
+ //
+ //DEPENDENCY:
+ // META_Editor_Init must have been called
+ //
+ //GLOBALS AFFECTED
+ // None
+ ********************************************************************************/
+ bool META_Editor_Deinit(void);
+
+ /********************************************************************************
+ //FUNCTION:
+ // META_Editor_ReadFile_OP
+ //DESCRIPTION:
+ // this function is called to Read a record of NvRam file from Target side to PC.
+ //
+ //PARAMETERS:
+ // req:
+ //
+ //RETURN VALUE:
+ // TRUE: is scuccess, otherwise is fail. the data will be send to PC in the function body
+ //
+ //DEPENDENCY:
+ // META_Editor_Init must have been called
+ //
+ //GLOBALS AFFECTED
+ ********************************************************************************/
+ bool META_Editor_ReadFile_OP(FT_AP_Editor_read_req *req);
+
+ /********************************************************************************
+ //FUNCTION:
+ // META_Editor_WriteFile_OP
+ //DESCRIPTION:
+ // this function is called to write a record of NvRam file from PC side to Target.
+ //
+ //PARAMETERS:
+ // None
+ //
+ //RETURN VALUE:
+ // refers to the definition of "FT_AP_Editor_write_cnf"
+ //
+ //DEPENDENCY:
+ // META_Editor_Init must have been called
+ //
+ //GLOBALS AFFECTED
+ // None
+ ********************************************************************************/
+ FT_AP_Editor_write_cnf META_Editor_WriteFile_OP(FT_AP_Editor_write_req *req,
+ char *peer_buf,
+ unsigned short peer_len);
+
+ /********************************************************************************
+ //FUNCTION:
+ // META_Editor_ResetFile_OP
+ //DESCRIPTION:
+ // this function is called to reset a NvRam to default value.
+ //
+ //PARAMETERS:
+ // None
+ //
+ //RETURN VALUE:
+ // refers to the definition of "FT_AP_Editor_reset_cnf"
+ //
+ //DEPENDENCY:
+ // META_Editor_Init must have been called
+ //
+ //GLOBALS AFFECTED
+ // None
+ ********************************************************************************/
+ FT_AP_Editor_reset_cnf META_Editor_ResetFile_OP(FT_AP_Editor_reset_req *req);
+
+ /********************************************************************************
+ //FUNCTION:
+ // META_Editor_ResetAllFile_OP
+ //DESCRIPTION:
+ // this function is called to Reset all of NvRam files to default value.
+ //
+ //PARAMETERS:
+ // None
+ //
+ //RETURN VALUE:
+ // refers to the definition of "FT_AP_Editor_reset_cnf"
+ //
+ //DEPENDENCY:
+ // META_Editor_Init must have been called
+ //
+ //GLOBALS AFFECTED
+ // None
+ ********************************************************************************/
+ FT_AP_Editor_reset_cnf META_Editor_ResetAllFile_OP(FT_AP_Editor_reset_req *req);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/Meta_APEditor/README b/src/devtools/meta/src/adaptor/Meta_APEditor/README
new file mode 100644
index 0000000..782e903
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/Meta_APEditor/README
@@ -0,0 +1,19 @@
+
+
+
+WHAT IT DOES?
+=============
+libmeta_apeditor is a static library which offer a interface for meta tool to access nvram
+
+
+HOW IT WAS BUILT?
+==================
+depend on library libc libnvram libft
+need to include header file in
+$(MTK_PATH_SOURCE)/external/meta/common/inc\
+$(MTK_PATH_SOURCE)/external/nvram/libnvram
+
+HOW TO USE IT?
+==============
+
+include this staic library by adding BUILD_STATIC_LIBRARY in your Android.mk
diff --git a/src/devtools/meta/src/adaptor/bluetooth/README b/src/devtools/meta/src/adaptor/bluetooth/README
new file mode 100644
index 0000000..8b558c1
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/README
@@ -0,0 +1,33 @@
+This directory contains BT Meta mode test library
+
+
+WHAT IT DOES?
+=============
+It provide BT test feature on meta mode, including BT power on/off, write/read and some other functions.
+
+HOW IT WAS BUILT?
+==================
+
+It needs the following libs from AOSP:
+1. libc.so
+2. libcutils
+3. libnetutils
+
+and the following libs from MediaTek:
+1. libft.a
+
+
+HOW TO USE IT?
+==============
+
+Files in this directory is used to
+generate a library which's name is 'libmeta_bluetooth'
+
+
+libmeta_bluetooth
+The lib 'libmeta_bluetooth' is loaded when target enter meta mode,
+Meta main thread will call META BT APIs, if meta gps tool is launched.
+
+
+All the source code of this library were written by MediaTek co..
+
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt.c b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.c
new file mode 100644
index 0000000..338b5ba
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.c
@@ -0,0 +1,583 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2014. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <dlfcn.h>
+
+#include "meta_bt.h"
+
+
+/**************************************************************************
+ * G L O B A L V A R I A B L E S *
+***************************************************************************/
+
+static int bt_fd = -1;
+static BOOL bt_enabled = FALSE;
+static BT_CNF_CB cnf_cb = NULL;
+static BT_CNF bt_cnf;
+
+/* Used to read serial port */
+static pthread_t rxThread;
+static BOOL fgKillThread = FALSE;
+
+/* mtk bt library */
+static void *glib_handle = NULL;
+typedef int (*INIT)(void);
+typedef int (*DEINIT)(int fd);
+typedef int (*WRITE)(int fd, unsigned char *buf, unsigned int len);
+typedef int (*READ)(int fd, unsigned char *buf, unsigned int len);
+typedef int (*GETID)(unsigned int *pChipId, unsigned int *pAdieId);
+
+INIT meta_bt_init = NULL;
+DEINIT meta_bt_restore = NULL;
+WRITE meta_bt_send_data = NULL;
+READ meta_bt_receive_data = NULL;
+GETID meta_bt_get_combo_id = NULL;
+
+/**************************************************************************
+ * F U N C T I O N D E C L A R A T I O N S *
+***************************************************************************/
+static unsigned int BT_Get_On_Off_State(void);
+static BOOL BT_Send_HciCmd(BT_HCI_CMD *pHciCmd);
+static BOOL BT_Recv_HciEvent(BT_HCI_EVENT *pHciEvent);
+static BOOL BT_Send_AclData(BT_HCI_BUFFER *pAclData);
+static BOOL BT_Recv_AclData(BT_HCI_BUFFER *pAclData);
+
+static void* BT_Meta_Thread(void* ptr);
+
+/**************************************************************************
+ * F U N C T I O N S *
+***************************************************************************/
+
+static void bt_send_resp(BT_CNF *cnf, unsigned short size, void *buf, unsigned short len)
+{
+ if (cnf_cb)
+ cnf_cb(cnf, buf, len);
+ else
+ WriteDataToPC(cnf, size, buf, len);
+}
+
+void META_BT_Register(BT_CNF_CB callback)
+{
+ cnf_cb = callback;
+}
+
+BOOL META_BT_init(void)
+{
+ const char *errstr;
+
+ TRC();
+
+ glib_handle = dlopen("libbluetooth_mtk_pure.so", RTLD_LAZY);
+ if (!glib_handle) {
+ ERR("%s\n", dlerror());
+ goto error;
+ }
+
+ dlerror(); /* Clear any existing error */
+
+ meta_bt_init = dlsym(glib_handle, "bt_init");
+ meta_bt_restore = dlsym(glib_handle, "bt_restore");
+ meta_bt_send_data = dlsym(glib_handle, "bt_send_data");
+ meta_bt_receive_data = dlsym(glib_handle, "bt_receive_data");
+ meta_bt_get_combo_id = dlsym(glib_handle, "wait_connsys_ready");
+
+ if ((errstr = dlerror()) != NULL) {
+ ERR("Can't find function symbols %s\n", errstr);
+ goto error;
+ }
+
+ bt_fd = meta_bt_init();
+ if (bt_fd < 0)
+ goto error;
+
+ DBG("BT is enabled success\n");
+
+ /* Create RX thread */
+ fgKillThread = FALSE;
+ pthread_create(&rxThread, NULL, BT_Meta_Thread, (void*)&bt_cnf);
+
+ bt_enabled = TRUE;
+ sched_yield();
+
+ return TRUE;
+
+error:
+ if (glib_handle) {
+ dlclose(glib_handle);
+ glib_handle = NULL;
+ }
+
+ return FALSE;
+}
+
+void META_BT_deinit(void)
+{
+ TRC();
+
+ /* Stop RX thread */
+ fgKillThread = TRUE;
+ /* Wait until thread exit */
+ pthread_join(rxThread, NULL);
+
+ if (!glib_handle) {
+ ERR("mtk bt library is unloaded!\n");
+ }
+ else {
+ if (bt_fd < 0) {
+ ERR("bt driver fd is invalid!\n");
+ }
+ else {
+ meta_bt_restore(bt_fd);
+ bt_fd = -1;
+ }
+ dlclose(glib_handle);
+ glib_handle = NULL;
+ }
+
+ bt_enabled = FALSE;
+ return;
+}
+
+void META_BT_OP(BT_REQ *req, UNUSED_ATTR char *buf, UNUSED_ATTR unsigned short len)
+{
+ TRC();
+
+ if (NULL == req) {
+ ERR("Invalid arguments or operation!\n");
+ return;
+ }
+
+ memset(&bt_cnf, 0, sizeof(BT_CNF));
+ bt_cnf.header.id = FT_BT_CNF_ID;
+ bt_cnf.header.token = req->header.token;
+ bt_cnf.op = req->op;
+
+ if (req->op == BT_OP_GET_ON_OFF_ST) {
+ DBG("run BT_Get_On_Off_State\n");
+ bt_cnf.result.bt_on_off_state = BT_Get_On_Off_State();
+ bt_cnf.bt_status = TRUE;
+ bt_cnf.status = META_SUCCESS;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ return;
+ }
+
+ if (bt_enabled == FALSE) {
+ /*
+ Initialize BT module when it is called first time
+ to avoid the case that PC tool not send BT_OP_INIT
+ */
+ if (META_BT_init() == FALSE) {
+ bt_cnf.bt_status = FALSE;
+ bt_cnf.status = META_FAILED;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ return;
+ }
+ }
+
+ switch (req->op)
+ {
+ case BT_OP_INIT:
+ if ((bt_enabled == FALSE) && (META_BT_init() == FALSE)){
+ bt_cnf.bt_status = FALSE;
+ bt_cnf.status = META_FAILED;
+ }
+ else{
+ bt_cnf.bt_status = TRUE;
+ bt_cnf.status = META_SUCCESS;
+ }
+
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ break;
+
+ case BT_OP_DEINIT:
+ if (bt_enabled == TRUE)
+ META_BT_deinit();
+
+ bt_cnf.bt_status = TRUE;
+ bt_cnf.status = META_SUCCESS;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ break;
+
+ case BT_OP_GET_CHIP_ID:
+ {
+ UINT32 chipId, adieId;
+
+ DBG("BT_OP_GET_CHIP_ID\n");
+ if (meta_bt_get_combo_id(&chipId, &adieId) < 0) {
+ ERR("Get combo chip id fails\n");
+ bt_cnf.bt_status = FALSE;
+ bt_cnf.status = META_FAILED;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ break;
+ }
+ bt_cnf.result.dummy = chipId;
+ bt_cnf.bt_status = TRUE;
+ bt_cnf.status = META_SUCCESS;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ break;
+ }
+ case BT_OP_HCI_SEND_COMMAND:
+ DBG("BT_OP_HCI_SEND_COMMAND\n");
+ if (BT_Send_HciCmd(&req->cmd.hcicmd) == FALSE) {
+ bt_cnf.bt_status = FALSE;
+ bt_cnf.status = META_FAILED;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ }
+ break;
+
+ case BT_OP_HCI_SEND_DATA:
+ DBG("BT_OP_HCI_SEND_DATA\n");
+ if (BT_Send_AclData(&req->cmd.hcibuf) == FALSE) {
+ bt_cnf.bt_status = FALSE;
+ bt_cnf.status = META_FAILED;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ }
+ break;
+
+ case BT_OP_HCI_CLEAN_COMMAND:
+ case BT_OP_HCI_TX_PURE_TEST:
+ case BT_OP_HCI_RX_TEST_START:
+ case BT_OP_HCI_RX_TEST_END:
+ case BT_OP_HCI_TX_PURE_TEST_V2:
+ case BT_OP_HCI_RX_TEST_START_V2:
+ case BT_OP_ENABLE_NVRAM_ONLINE_UPDATE:
+ case BT_OP_DISABLE_NVRAM_ONLINE_UPDATE:
+
+ case BT_OP_ENABLE_PCM_CLK_SYNC_SIGNAL:
+ case BT_OP_DISABLE_PCM_CLK_SYNC_SIGNAL:
+ /* Need to confirm with CCCI driver buddy */
+ DBG("Not implemented command %d\n", req->op);
+ bt_cnf.status = META_FAILED;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ break;
+
+ default:
+ DBG("Unknown command %d\n", req->op);
+ bt_cnf.status = META_FAILED;
+ bt_send_resp(&bt_cnf, sizeof(BT_CNF), NULL, 0);
+ break;
+ }
+
+ return;
+}
+
+unsigned int BT_Get_On_Off_State(void)
+{
+ #define BT_DRV_IF "/proc/driver/bt_dbg"
+ #define BT_DBG_NODE_ENABLE "4w2T8M65K5?2af+a ON"
+ #define BT_DBG_NODE_DISABLE "4w2T8M65K5?2af+a OFF"
+ #define LEN_10 10
+ int fd;
+ int retval = 0;
+ unsigned int ret = 2;
+ unsigned char buf[LEN_10];
+
+ fd = open(BT_DRV_IF, O_RDWR | O_NOCTTY);
+ if (fd < 0) {
+ DBG("%s: Can't open %s, errno[%d][%s]", __func__, BT_DRV_IF, errno, strerror(errno));
+ return ret;
+ } else {
+ write(fd, BT_DBG_NODE_ENABLE, strlen(BT_DBG_NODE_ENABLE)); // enable debug function
+ retval = write(fd, "0x0E 0x00 0x00", 14);
+ if (retval > 0) {
+ DBG("%s: write %s: retval[%d]", __func__, BT_DRV_IF, retval);
+ }
+ retval = read(fd, buf, LEN_10);
+ if (retval > 0 && retval < LEN_10) {
+ buf[retval] = '\0';
+ ret = buf[0];
+ DBG("%s: retval[%d], ret[%d]", __func__, retval, ret);
+ } else {
+ buf[0] = '\0';
+ }
+ write(fd, BT_DBG_NODE_DISABLE, strlen(BT_DBG_NODE_DISABLE)); // disable debug function
+ }
+ close(fd);
+
+ /* return value
+ * 0: bt off
+ * 1: bt on
+ * 2: unknown
+ */
+ return ret;
+}
+
+static BOOL BT_Send_HciCmd(BT_HCI_CMD *pHciCmd)
+{
+ UINT8 ucHciCmd[256+4];
+ UINT8 i = 0;
+ unsigned char str[100] = {""};
+ unsigned char buf_str[6] = {""};
+
+ if (!glib_handle) {
+ ERR("mtk bt library is unloaded!\n");
+ return FALSE;
+ }
+ if (bt_fd < 0) {
+ ERR("bt driver fd is invalid!\n");
+ return FALSE;
+ }
+
+ ucHciCmd[0] = 0x01;
+ ucHciCmd[1] = (pHciCmd->opcode) & 0xFF;
+ ucHciCmd[2] = (pHciCmd->opcode >> 8) & 0xFF;
+ ucHciCmd[3] = pHciCmd->len;
+
+ DBG("OpCode 0x%04x len %d\n", pHciCmd->opcode, (int)pHciCmd->len);
+
+ if (pHciCmd->len) {
+ memcpy(&ucHciCmd[4], pHciCmd->parms, pHciCmd->len);
+ }
+
+ if (meta_bt_send_data(bt_fd, ucHciCmd, pHciCmd->len + 4) < 0) {
+ ERR("Write HCI command fails errno %d\n", errno);
+ return FALSE;
+ }
+
+ /* Dump packet */
+ for (i = 0; i < pHciCmd->len + 4; i++) {
+ if ((i % 16 == 0) && (i != 0)) {
+ DBG("%s\n", str);
+ memset(str, 0, sizeof(str));
+ }
+ if(snprintf(buf_str, sizeof(buf_str), "0x%02x ", ucHciCmd[i]) < 0) {
+ ERR("snprintf error!\n");
+ break;
+ }
+ strncat(str, buf_str, strlen(buf_str));
+ }
+ DBG("%s\n", str);
+
+ return TRUE;
+}
+
+static BOOL BT_Recv_HciEvent(BT_HCI_EVENT *pHciEvent)
+{
+ UINT8 i = 0;
+ unsigned char str[100] = {""};
+ unsigned char buf_str[6] = {""};
+ pHciEvent->status = FALSE;
+
+ if (!glib_handle) {
+ ERR("mtk bt library is unloaded!\n");
+ return FALSE;
+ }
+ if (bt_fd < 0) {
+ ERR("bt driver fd is invalid!\n");
+ return FALSE;
+ }
+
+ if (meta_bt_receive_data(bt_fd, &pHciEvent->event, 1) < 0) {
+ ERR("Read event code fails errno %d\n", errno);
+ return FALSE;
+ }
+
+ DBG("Read event code: %02x\n", pHciEvent->event);
+
+ if (meta_bt_receive_data(bt_fd, &pHciEvent->len, 1) < 0) {
+ ERR("Read event length fails errno %d\n", errno);
+ return FALSE;
+ }
+
+ DBG("Read event length: %d\n", pHciEvent->len);
+
+ if (pHciEvent->len) {
+ if (meta_bt_receive_data(bt_fd, pHciEvent->parms, pHciEvent->len) < 0) {
+ ERR("Read event param fails errno %d\n", errno);
+ return FALSE;
+ }
+ }
+
+ pHciEvent->status = TRUE;
+
+ /* Dump packet */
+ for (i = 0; i < pHciEvent->len; i++) {
+ if ((i % 16 == 0) && (i != 0)) {
+ DBG("%s\n", str);
+ memset(str, 0, sizeof(str));
+ }
+ if(snprintf(buf_str, sizeof(buf_str), "0x%02x ", pHciEvent->parms[i]) < 0) {
+ ERR("snprintf error!\n");
+ break;
+ }
+ strncat(str, buf_str, strlen(buf_str));
+ }
+ DBG("%s\n", str);
+
+ return TRUE;
+}
+
+static BOOL BT_Send_AclData(BT_HCI_BUFFER *pAclData)
+{
+ UINT8 ucAclData[1029];
+
+ if (!glib_handle) {
+ ERR("mtk bt library is unloaded!\n");
+ return FALSE;
+ }
+ if (bt_fd < 0) {
+ ERR("bt driver fd is invalid!\n");
+ return FALSE;
+ }
+
+ ucAclData[0] = 0x02;
+ ucAclData[1] = (pAclData->con_hdl) & 0xFF;
+ ucAclData[2] = (pAclData->con_hdl >> 8) & 0xFF;
+ ucAclData[3] = (pAclData->len) & 0xFF;
+ ucAclData[4] = (pAclData->len >> 8) & 0xFF;
+
+ if (pAclData->len) {
+ memcpy(&ucAclData[5], pAclData->buffer, pAclData->len);
+ }
+
+ if (meta_bt_send_data(bt_fd, ucAclData, pAclData->len + 5) < 0) {
+ ERR("Write ACL data fails errno %d\n", errno);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOL BT_Recv_AclData(BT_HCI_BUFFER *pAclData)
+{
+ if (!glib_handle) {
+ ERR("mtk bt library is unloaded!\n");
+ return FALSE;
+ }
+ if (bt_fd < 0) {
+ ERR("bt driver fd is invalid!\n");
+ return FALSE;
+ }
+
+ if (meta_bt_receive_data(bt_fd, (UINT8*)&pAclData->con_hdl, 2) < 0) {
+ ERR("Read connection handle fails errno %d\n", errno);
+ return FALSE;
+ }
+
+ pAclData->con_hdl = ((pAclData->con_hdl & 0xFF) << 8) | ((pAclData->con_hdl >> 8) & 0xFF);
+
+ if (meta_bt_receive_data(bt_fd, (UINT8*)&pAclData->len, 2) < 0) {
+ ERR("Read ACL data length fails errno %d\n", errno);
+ return FALSE;
+ }
+
+ pAclData->len = ((pAclData->len & 0xFF) << 8) | ((pAclData->len >> 8) & 0xFF);
+
+ if (pAclData->len) {
+ if (meta_bt_receive_data(bt_fd, pAclData->buffer, pAclData->len) < 0) {
+ ERR("Read ACL data fails errno %d\n", errno);
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+static void *BT_Meta_Thread(void *ptr)
+{
+ BT_CNF *pBtCnf = (BT_CNF*)ptr;
+ BT_HCI_EVENT hci_event;
+ BT_HCI_BUFFER acl_data;
+ UINT8 ucHeader = 0;
+
+ TRC();
+
+ while (!fgKillThread) {
+
+ if (!glib_handle) {
+ ERR("mtk bt library is unloaded!\n");
+ break;
+ }
+ if (bt_fd < 0) {
+ ERR("bt driver fd is invalid!\n");
+ break;
+ }
+
+ if (meta_bt_receive_data(bt_fd, &ucHeader, sizeof(ucHeader)) < 0) {
+ ERR("Zero byte read\n");
+ continue;
+ }
+
+ switch (ucHeader) {
+ case 0x04:
+ DBG("Receive HCI event\n");
+ if (BT_Recv_HciEvent(&hci_event)) {
+ pBtCnf->bt_status = TRUE;
+ pBtCnf->result_type = PKT_TYPE_EVENT;
+ memcpy(&pBtCnf->result.hcievent, &hci_event, sizeof(hci_event));
+ pBtCnf->status = META_SUCCESS;
+ bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+ }
+ else {
+ pBtCnf->bt_status = FALSE;
+ pBtCnf->status = META_FAILED;
+ bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+ }
+ break;
+
+ case 0x02:
+ DBG("Receive ACL data\n");
+ if (BT_Recv_AclData(&acl_data)) {
+ pBtCnf->bt_status = TRUE;
+ pBtCnf->result_type = PKT_TYPE_ACL;
+ memcpy(&pBtCnf->result.hcibuf, &acl_data, sizeof(acl_data));
+ pBtCnf->status = META_SUCCESS;
+ bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+ }
+ else {
+ pBtCnf->bt_status = FALSE;
+ pBtCnf->status = META_FAILED;
+ bt_send_resp(pBtCnf, sizeof(BT_CNF), NULL, 0);
+ }
+ break;
+
+ default:
+ ERR("Unexpected BT packet header %02x\n", ucHeader);
+ goto CleanUp;
+ }
+ }
+
+CleanUp:
+ return NULL;
+}
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt.h b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.h
new file mode 100644
index 0000000..e656ca8
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt.h
@@ -0,0 +1,64 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2014. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __META_BT_H__
+#define __META_BT_H__
+
+#include "MetaPub.h"
+#include "meta_bt_para.h"
+
+
+#define LOG_TAG "BT_META "
+#include <log/log.h>
+
+#define BT_META_DEBUG 1
+#define ERR(f, ...) ALOGE("%s: " f, __FUNCTION__, ##__VA_ARGS__)
+#define WAN(f, ...) ALOGW("%s: " f, __FUNCTION__, ##__VA_ARGS__)
+#if BT_META_DEBUG
+#define DBG(f, ...) ALOGD("%s: " f, __FUNCTION__, ##__VA_ARGS__)
+#define TRC(f) ALOGW("%s #%d", __FUNCTION__, __LINE__)
+#else
+#define DBG(...) ((void)0)
+#define TRC(f) ((void)0)
+#endif
+
+typedef void (*BT_CNF_CB)(BT_CNF *cnf, void *buf, unsigned short len);
+
+extern void META_BT_Register(BT_CNF_CB callback);
+
+#endif
+
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt_para.h b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_para.h
new file mode 100644
index 0000000..8ae49e0
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_para.h
@@ -0,0 +1,162 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2014. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#ifndef __META_BT_PARA_H__
+#define __META_BT_PARA_H__
+
+#include "MetaPub.h"
+
+#define UNUSED_ATTR __attribute__((unused))
+
+#define FT_CNF_OK 0
+#define FT_CNF_FAIL 1
+
+#include <stdbool.h>
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef BOOL
+#define BOOL bool
+#endif
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define PKT_TYPE_CMD 0
+#define PKT_TYPE_EVENT 1
+#define PKT_TYPE_SCO 2
+#define PKT_TYPE_ACL 3
+
+/*
+* Test case enum defination for BT_module
+*/
+typedef enum {
+ BT_OP_HCI_SEND_COMMAND = 0
+ ,BT_OP_HCI_CLEAN_COMMAND
+ ,BT_OP_HCI_SEND_DATA
+ ,BT_OP_HCI_TX_PURE_TEST
+ ,BT_OP_HCI_RX_TEST_START
+ ,BT_OP_HCI_RX_TEST_END
+ ,BT_OP_HCI_TX_PURE_TEST_V2
+ ,BT_OP_HCI_RX_TEST_START_V2
+ ,BT_OP_ENABLE_NVRAM_ONLINE_UPDATE
+ ,BT_OP_DISABLE_NVRAM_ONLINE_UPDATE
+ ,BT_OP_ENABLE_PCM_CLK_SYNC_SIGNAL
+ ,BT_OP_DISABLE_PCM_CLK_SYNC_SIGNAL
+ ,BT_OP_GET_CHIP_ID
+ ,BT_OP_INIT
+ ,BT_OP_DEINIT
+ ,BT_OP_GET_ON_OFF_ST
+ ,BT_OP_END
+} BT_OP;
+
+typedef enum {
+ BT_CHIP_ID_MT6611 = 0
+ ,BT_CHIP_ID_MT6612
+ ,BT_CHIP_ID_MT6616
+ ,BT_CHIP_ID_MT6620
+ ,BT_CHIP_ID_MT6622
+ ,BT_CHIP_ID_MT6626
+} BT_CHIP_ID;
+
+/*
+* Structure Defination
+*/
+typedef struct _BT_HCI_CMD {
+ UINT16 opcode;
+ UINT8 len;
+ UINT8 parms[256];
+} BT_HCI_CMD;
+
+typedef struct _BT_HCI_BUFFER {
+ UINT16 con_hdl;
+ UINT16 len;
+ UINT8 buffer[1024];
+} BT_HCI_BUFFER;
+
+typedef union _BT_CMD {
+ BT_HCI_CMD hcicmd;
+ BT_HCI_BUFFER hcibuf;
+ UINT32 dummy;
+} BT_CMD;
+
+typedef struct _BT_HCI_EVENT {
+ UINT8 event;
+ UINT16 handle;
+ UINT8 len;
+ UINT8 status;
+ UINT8 parms[256];
+} BT_HCI_EVENT;
+
+typedef union _BT_RESULT {
+ BT_HCI_EVENT hcievent;
+ BT_HCI_BUFFER hcibuf;
+ UINT8 bt_on_off_state;
+ UINT32 dummy;
+} BT_RESULT;
+
+typedef struct _BT_REQ {
+ FT_H header;
+ BT_OP op;
+ BT_CMD cmd;
+} BT_REQ;
+
+typedef struct _BT_CNF {
+ FT_H header;
+ BT_OP op;
+ UINT32 bt_status;
+ UINT8 result_type; /* result type */
+ BT_RESULT result; /* result */
+ META_RESULT status;
+} BT_CNF;
+
+BOOL META_BT_init(void);
+void META_BT_deinit(void);
+void META_BT_OP(BT_REQ *req, char *buf, unsigned short len);
+
+#ifdef __cplusplus
+};
+#endif
+#endif
diff --git a/src/devtools/meta/src/adaptor/bluetooth/meta_bt_test.c b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_test.c
new file mode 100644
index 0000000..9082d45
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/bluetooth/meta_bt_test.c
@@ -0,0 +1,131 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * MediaTek Inc. (C) 2014. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "meta_bt.h"
+
+static void bt_info_callback(BT_CNF *cnf, void *buf, unsigned short len)
+{
+ char *type[] = {
+ "BT_OP_HCI_SEND_COMMAND", "BT_OP_HCI_CLEAN_COMMAND", "BT_OP_HCI_SEND_DATA", "BT_OP_HCI_TX_PURE_TEST",
+ "BT_OP_HCI_RX_TEST_START", "BT_OP_HCI_RX_TEST_END", "BT_OP_HCI_TX_PURE_TEST_V2", "BT_OP_HCI_RX_TEST_START_V2",
+ "BT_OP_ENABLE_NVRAM_ONLINE_UPDATE", "BT_OP_DISABLE_NVRAM_ONLINE_UPDATE", "BT_OP_ENABLE_PCM_CLK_SYNC_SIGNAL", "BT_OP_DISABLE_PCM_CLK_SYNC_SIGNAL",
+ "BT_OP_GET_CHIP_ID", "BT_OP_INIT", "BT_OP_DEINIT", "BT_OP_GET_ON_OFF_ST"};
+
+ printf("[META_BT] <CNF> %s, bt_status: %d, result_type: %d, status: %d\n",
+ type[cnf->op],
+ cnf->bt_status, cnf->result_type, cnf->status);
+
+ if (cnf->result_type == PKT_TYPE_EVENT) {
+ printf("[META_BT] HCI event %02x, len %d\n", cnf->result.hcievent.event, (int)cnf->result.hcievent.len);
+ printf("[META_BT] HCI event %02x-%02x-%02x-%02x\n",
+ cnf->result.hcievent.parms[0], cnf->result.hcievent.parms[1],
+ cnf->result.hcievent.parms[2], cnf->result.hcievent.parms[3]);
+
+ }
+ else if (cnf->result_type == PKT_TYPE_ACL) {
+ printf("[META_BT] ACL con_hdl %d, len: %d\n", (int)cnf->result.hcibuffer.con_hdl, (int)cnf->result.hcibuffer.len);
+ }
+ else {
+ printf("[META_BT] Unexpected result type\n");
+ }
+}
+
+int main(int argc, const char** argv)
+{
+ BT_REQ req;
+
+ memset(&req, 0, sizeof(BT_REQ));
+
+ META_BT_Register(bt_info_callback);
+
+ if (META_BT_init() == FALSE) {
+ printf("BT init fails\n");
+ return -1;
+ }
+#if 0
+ req.op = BT_OP_HCI_SEND_COMMAND;
+ req.cmd.hcicmd.opcode = 0x0c03;
+ req.cmd.hcicmd.len = 0;
+ req.cmd.hcicmd.parms[0] = 0;
+ META_BT_OP(&req, NULL, 0);
+
+ sleep(1);
+
+ req.op = BT_OP_HCI_CLEAN_COMMAND;
+ META_BT_OP(&req, NULL, 0);
+
+ sleep(1);
+
+ req.op = BT_OP_HCI_SEND_COMMAND;
+ req.cmd.hcicmd.opcode = 0xfc72;
+ req.cmd.hcicmd.len = 1;
+ req.cmd.hcicmd.parms[0] = 0x23;
+ META_BT_OP(&req, NULL, 0);
+
+ sleep(1);
+
+ req.op = BT_OP_HCI_CLEAN_COMMAND;
+ META_BT_OP(&req, NULL, 0);
+#endif
+ sleep(1);
+ /* 01,04,05,33,8B,9E,05,0A */
+ req.op = BT_OP_HCI_SEND_COMMAND;
+ req.cmd.hcicmd.opcode = 0x0401;
+ req.cmd.hcicmd.len = 5;
+ req.cmd.hcicmd.parms[0] = 0x33;
+ req.cmd.hcicmd.parms[1] = 0x8B;
+ req.cmd.hcicmd.parms[2] = 0x9E;
+ req.cmd.hcicmd.parms[3] = 0x05;
+ req.cmd.hcicmd.parms[4] = 0x0A;
+ META_BT_OP(&req, NULL, 0);
+
+ sleep(20);
+
+ req.op = BT_OP_HCI_CLEAN_COMMAND;
+ META_BT_OP(&req, NULL, 0);
+
+ sleep(1);
+
+ META_BT_deinit();
+ META_BT_Register(NULL);
+
+ return 0;
+}
+
diff --git a/src/devtools/meta/src/adaptor/gps/meta_gps.cpp b/src/devtools/meta/src/adaptor/gps/meta_gps.cpp
new file mode 100644
index 0000000..0a029ce
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/gps/meta_gps.cpp
@@ -0,0 +1,546 @@
+/*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2008
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Use of this source code is subject to the terms of the Microsoft end-user
+// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
+// If you did not accept the terms of the EULA, you are not authorized to use
+// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
+// install media.
+//
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * meta_gps.cpp
+ *
+ * Project:
+ * --------
+ * DUMA
+ *
+ * Description:
+ * ------------
+ * Implement GPS interface for META mode.
+ *
+ * Author:
+ * -------
+ * LiChunhui (MTK80143)
+ *
+ *============================================================================
+ * HISTORY
+ * Below this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * $Revision:$
+ * $Modtime:$
+ * $Log:$
+ *
+ * Mar 20 2009 mtk80143
+ * [DUMA00111323] [GPS] modify for GPS META
+ * Add for GPS meta
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#include <stdio.h> /* Standard input/output definitions */
+#include <string.h> /* String function definitions */
+#include <unistd.h> /* UNIX standard function definitions */
+#include <fcntl.h> /* File control definitions */
+#include <errno.h> /* Error number definitions */
+#include <termios.h> /* POSIX terminal control definitions */
+#include <time.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/socket.h>
+#include <sys/epoll.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <strings.h>
+#include <sys/un.h> // struct sockaddr_un
+#include "LogDefine.h"
+
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#include <cutils/log.h>
+//for read NVRAM
+#include "libnvram.h"
+#include "CFG_GPS_File.h"
+#include "CFG_GPS_Default.h"
+#include "CFG_file_lid.h"
+#include "Custom_NvRam_LID.h"
+#endif
+#ifdef GPS_PROPERTY
+#undef GPS_PROPERTY
+#endif
+#define GPS_DATA_PATH "/etc/gnss/"
+#define GPS_PROPERTY GPS_DATA_PATH"GPS_CHIP_FTM.cfg"
+//static ap_nvram_gps_config_struct stGPSReadback;
+#define MNL_ATTR_PWRCTL "/sys/class/gpsdrv/gps/pwrctl"
+#define MNL_ATTR_SUSPEND "/sys/class/gpsdrv/gps/suspend"
+#define MNL_ATTR_STATE "/sys/class/gpsdrv/gps/state"
+#define MNL_ATTR_PWRSAVE "/sys/class/gpsdrv/gps/pwrsave"
+#define MNL_ATTR_STATUS "/sys/class/gpsdrv/gps/status"
+#define BUF_TAIL_LENGTH 3
+#define ACK_BUF_SIZE 1024
+static int mnld_terminated = 0;
+
+enum {
+ GPS_PWRCTL_UNSUPPORTED = 0xFF,
+ GPS_PWRCTL_OFF = 0x00,
+ GPS_PWRCTL_ON = 0x01,
+ GPS_PWRCTL_RST = 0x02,
+ GPS_PWRCTL_OFF_FORCE = 0x03,
+ GPS_PWRCTL_RST_FORCE = 0x04,
+ GPS_PWRCTL_MAX = 0x05,
+};
+
+#define C_INVALID_PID (-1) /*invalid process id*/
+#define C_INVALID_TID (-1) /*invalid thread id*/
+#define C_INVALID_FD (-1) /*invalid file handle*/
+#define C_INVALID_SOCKET (-1) /*invalid socket id*/
+
+#define MND_ERR META_LOG
+#define MND_MSG META_LOG
+#ifndef META_LOG
+#define META_LOG ALOGD
+#endif
+#ifndef UNUSED
+#define UNUSED(x) (x)=(x)
+#endif
+
+//// meta test
+#define META_TO_MNLD_SOCKET "mtk_meta2mnld"
+#ifdef IS_SUPPORT_SP
+#include <hidl/LegacySupport.h>
+#include <vendor/mediatek/hardware/lbs/1.0/ILbs.h>
+#endif
+#include "meta_gps_para.h"
+//#include "Meta2MnldInterface.h"
+#define META2MNLD_INTERFACE_PROTOCOL_TYPE 303
+#define META2MNLD_INTERFACE_BUFF_SIZE 12
+/**
+ * The interface from Meta to Mnld
+ */
+typedef enum {
+ META2MNLD_INTERFACE_REQ_GNSS_LOCATION = 0,
+ META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION = 1,
+} Meta2MnldInterface_message_id;
+
+void mtk_socket_put_char(char* buff, int* offset, char input) {
+ *((char*)&buff[*offset]) = input;
+ *offset += 1;
+}
+
+void mtk_socket_put_short(char* buff, int* offset, short input) {
+ mtk_socket_put_char(buff, offset, input & 0xff);
+ mtk_socket_put_char(buff, offset, (input >> 8) & 0xff);
+}
+
+void mtk_socket_put_int(char* buff, int* offset, int input) {
+ mtk_socket_put_short(buff, offset, input & 0xffff);
+ mtk_socket_put_short(buff, offset, (input >> 16) & 0xffff);
+}
+
+// -1 means failure
+int safe_sendto(const char* path, const char* buff, int len) {
+ int ret = 0;
+ struct sockaddr_un addr;
+ int retry = 10;
+ int fd = socket(PF_LOCAL, SOCK_DGRAM, 0);
+ if (fd < 0) {
+ META_LOG("safe_sendto() socket() failed reason=[%s]%d",
+ strerror(errno), errno);
+ return -1;
+ }
+
+ int flags = fcntl(fd, F_GETFL, 0);
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1){
+ META_LOG("fcntl failed reason=[%s]%d",
+ strerror(errno), errno);
+
+ close(fd);
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sun_path[0] = 0;
+ strncpy(addr.sun_path + 1, path,sizeof(addr.sun_path) - 1);
+ addr.sun_family = AF_UNIX;
+
+ while ((ret = sendto(fd, buff, len, 0,
+ (const struct sockaddr *)&addr, sizeof(addr))) == -1) {
+ if (errno == EINTR) continue;
+ if (errno == EAGAIN) {
+ if (retry-- > 0) {
+ usleep(100 * 1000);
+ continue;
+ }
+ }
+ META_LOG("safe_sendto() sendto() failed path=[%s] ret=%d reason=[%s]%d",
+ path, ret, strerror(errno), errno);
+ break;
+ }
+
+ close(fd);
+ return ret;
+}
+
+void hidl_request_gps(bool turnOn) {
+ char _buff[META2MNLD_INTERFACE_BUFF_SIZE] = {0};
+ int _offset = 0;
+ int src = 0;
+ int msg = turnOn ? META2MNLD_INTERFACE_REQ_GNSS_LOCATION: META2MNLD_INTERFACE_CANCEL_GNSS_LOCATION;
+
+ mtk_socket_put_int(_buff, &_offset, META2MNLD_INTERFACE_PROTOCOL_TYPE);
+ mtk_socket_put_int(_buff, &_offset, msg);
+ mtk_socket_put_int(_buff, &_offset, src);
+ int size = (_offset < (int)(sizeof(_buff)/sizeof(_buff[0])))? _offset : sizeof(_buff)/sizeof(_buff[0]);
+ META_LOG("Send req gnss location to LBS service offset: %d size: %d", _offset, size);
+ if(safe_sendto(META_TO_MNLD_SOCKET, _buff, size) == -1) {
+ META_LOG("safe_sendto fail!!!");
+ }
+}
+//// end
+
+static GPS_CNF gps_cnf1;
+static GPS_CNF gps_cnf2;
+
+pid_t mnl_pid = C_INVALID_PID;
+int sockfd = C_INVALID_SOCKET;
+pthread_t gps_meta_thread_handle = C_INVALID_TID;
+
+/*****************************************************************************/
+static void sighlr(int signo)
+{
+ //pthread_t self = pthread_self();
+
+ META_LOG("Wait MNLD terminated");
+ if (signo == SIGCHLD) {
+ META_LOG("MNLD terminated");
+ mnld_terminated = 1;
+ }
+}
+/*****************************************************************************/
+int setup_signal_handler(void)
+{
+ struct sigaction actions;
+ int err;
+
+ /*the signal handler is MUST, otherwise, the thread will not be killed*/
+ memset(&actions, 0, sizeof(actions));
+ sigemptyset(&actions.sa_mask);
+ actions.sa_flags = 0;
+ actions.sa_handler = sighlr;
+
+ if ((err = sigaction(SIGALRM, &actions, NULL))) {
+ META_LOG("register signal handler for SIGALRM: %s\n", strerror(errno));
+ return -1;
+ }
+ if ((err = sigaction(SIGCHLD, &actions, NULL))) {
+ META_LOG("register signal handler for SIGALRM: %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
+}
+/*****************************************************************************/
+int META_GPS_Open(int ATM_test)
+{
+ //int err;
+ pid_t pid;
+ int portno;
+ struct sockaddr_in serv_addr;
+ META_LOG("META_GPS_Open() 1\n");
+ if (setup_signal_handler()) {
+ META_LOG("setup_signal_handler: %d (%s)\n", errno, strerror(errno));
+ exit(1);
+ }
+ // power on GPS chip
+ //err = mnl_write_attr("/sys/class/gpsdrv/gps/pwrctl", 4);
+ //if (err != 0) {
+ // META_LOG("META_GPS_Open: GPS power-on error: %d\n", err);
+ //}
+
+ if(0 != ATM_test) {
+ META_LOG("ATM test, hidl start gps\n");
+ hidl_request_gps(true);
+ } else {
+ // run gps driver
+ if ((pid = fork()) < 0) {
+ META_LOG("META_GPS_Open: fork fails: %d (%s)\n", errno, strerror(errno));
+ return (-2);
+ }
+ else if (pid == 0) { /*child process*/
+ int err;
+ err = execl("vendor/bin/mnld", "mnld", "1Hz=y", "meta", NULL);
+ if (err == -1) {
+ MND_MSG("execl error: %s\n", strerror(errno));
+ return -1;
+ }
+ return 0;
+ } else { /*parent process*/
+ mnl_pid = pid;
+ META_LOG("META_GPS_Open: mnl_pid = %d\n", pid);
+ }
+ }
+ // create socket connection to gps driver
+ portno = 7000;
+ /* Create a socket point */
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ META_LOG("META_GPS_Open: ERROR opening socket");
+ return (-4);
+ }
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = htons(INADDR_ANY);
+ serv_addr.sin_port = htons(portno);
+
+ int try_time = 10;
+ do {
+ META_LOG("META_GPS_Open: try connecting,try_time = %d, %s(%d)",try_time, strerror(errno), errno);
+ sleep(1); // sleep 10 sec for libmnl to finish initialization
+ } while (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0 && --try_time);
+ if (try_time == 0) {
+ META_LOG("META_GPS_Open: ERROR connecting");
+ return (-6);
+ }
+
+ // run GPS_MetaThread
+ if (pthread_create(&gps_meta_thread_handle, NULL, GPS_MetaThread, NULL)) {
+ META_LOG("META_GPS_Open: error creating dsp thread \n");
+ return (-7);
+ }
+ META_LOG("META_GPS_Open() 2\n");
+
+ return 0;
+}
+
+void META_GPS_Close(int ATM_test) {
+ int err;
+ int cnt = 0, max = 10;
+
+ META_LOG("META_GPS_Close() 1\n");
+ // disconnect to gps driver
+ if (sockfd != C_INVALID_SOCKET) {
+ close(sockfd);
+ sockfd = C_INVALID_SOCKET;
+ }
+ META_LOG("META_GPS_Close() 4\n");
+
+ if(0 != ATM_test) {
+ META_LOG("ATM test, hidl stop gps\n");
+ hidl_request_gps(false);
+ } else {
+ if (mnl_pid != C_INVALID_PID) {
+ META_LOG("GPS_Close() 5\n");
+ // kill(mnl_pid, SIGKILL);
+ // usleep(500000);
+
+ kill(mnl_pid, SIGTERM);
+ while (!mnld_terminated) {
+ if (cnt++ < max) {
+ /*timeout: 1 sec;
+ notice that libmnlp needs
+ some sleep time after MTK_PARAM_CMD_RESET_DSP*/
+ usleep(100000);
+ continue;
+ } else {
+ kill(mnl_pid, SIGKILL);
+ usleep(100000);
+ }
+ }
+ META_LOG("waiting counts: %d\n", cnt);
+ mnl_pid = wait(&err);
+
+ if (mnl_pid == -1)
+ MND_MSG("wait error: %s\n",strerror(errno));
+ MND_MSG("mnld process : %d is killed\n", mnl_pid);
+ mnld_terminated = 1;
+ }
+ }
+ unlink(GPS_DATA_PATH"mtkgps.dat");
+ // power off GPS chip
+ //err = mnl_write_attr("/sys/class/gpsdrv/gps/pwrctl", 0);
+ //if (err != 0) {
+ // META_LOG("GPS power-off error: %d\n", err);
+ //}
+ META_LOG("META_GPS_Close() 6\n");
+
+ unlink(GPS_PROPERTY);
+ META_LOG("META_GPS_Close() 7\n");
+ return;
+}
+
+
+void META_GPS_OP(GPS_REQ *req, char *peer_buff, unsigned short peer_len, int ATM_test)
+{
+ memset(&gps_cnf1, 0, sizeof(GPS_CNF));
+ gps_cnf1.header.id = FT_GPS_CNF_ID;
+ gps_cnf1.header.token = req->header.token;
+ gps_cnf1.op = req->op;
+ memset(&gps_cnf2, 0, sizeof(GPS_CNF));
+ gps_cnf2.header.id = FT_GPS_CNF_ID;
+ gps_cnf2.header.token = req->header.token;
+ gps_cnf2.op = req->op;
+
+ META_LOG("META_GPS_OP() 1, (%d),(%s),(%u)\n", req->op, peer_buff, peer_len);
+ switch (req->op) {
+ case GPS_OP_OPEN:
+ META_LOG("META_GPS_OP(), GPS_OP_OPEN 1\n");
+ if (META_GPS_Open(ATM_test) != 0) { // open fail
+ META_LOG("META_GPS_OP(), GPS_OP_OPEN fail\n");
+ META_GPS_Close(ATM_test);
+ META_LOG("Can't open gps driver \r\n");
+ gps_cnf1.gps_status = FALSE;
+ gps_cnf1.status = META_FAILED;
+ }
+ else {
+ META_LOG("META_GPS_OP(), GPS_OP_OPEN OK\n");
+ gps_cnf1.gps_status = TRUE;
+ gps_cnf1.status = META_SUCCESS;
+ }
+ WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+ META_LOG("META_GPS_OP(), GPS_OP_OPEN 2\n");
+ break;
+
+ case GPS_OP_CLOSE:
+ META_LOG("META_GPS_OP(), GPS_OP_CLOSE 1\n");
+ META_GPS_Close(ATM_test);
+ gps_cnf1.gps_status = TRUE;
+ gps_cnf1.status = META_SUCCESS;
+ WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+ META_LOG("META_GPS_OP(), GPS_OP_CLOSE 2\n");
+ break;
+
+ case GPS_OP_SEND_CMD:
+ META_LOG("META_GPS_OP(), GPS_OP_SEND_CMD\n");
+ if (sockfd != C_INVALID_SOCKET) {
+ int n = write(sockfd, req->cmd.buff, req->cmd.len);
+ if (n < 0) {
+ META_LOG("ERROR writing to socket\r\n");
+ }
+ META_LOG("META_GPS_OP(), GPS_OP_SEND_CMD: %s\r\n", req->cmd.buff);
+ }
+
+ gps_cnf1.gps_status = TRUE;
+ gps_cnf1.status = META_SUCCESS;
+ META_LOG("GPS_OP_SEND_CMD, gps_cnf.status:%d\r\n", gps_cnf1.status);
+ WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+
+ break;
+
+ default:
+ META_LOG("META_GPS_OP(), default 1\n");
+ gps_cnf1.gps_status = FALSE;
+ gps_cnf1.status = META_FAILED;
+ WriteDataToPC(&gps_cnf1, sizeof(GPS_CNF), NULL, 0);
+ META_LOG("META_GPS_OP(), default 2\n");
+ break;
+ }
+ META_LOG("META_GPS_OP() 2\n");
+}
+
+void *GPS_MetaThread(void *arg)
+{
+ int read_leng = 0;
+ int cnt = 0;
+ int cnt_tmp = 0;
+ char *ptr;
+ char buf[ACK_BUF_SIZE*10];
+ UNUSED(arg);
+
+ cnt = 0;
+
+ while (1) {
+ memset(buf, 0, sizeof(buf));
+ read_leng = 0;
+ read_leng = read(sockfd, buf, sizeof(buf) - 1);
+ if (read_leng < 0) {
+ META_LOG("ERROR reading from socket");
+ return (void *)(-1);
+ } else if (read_leng > 0) {
+ buf[ACK_BUF_SIZE*10-1] = '\0';
+ ptr=strtok(buf, "\r\n");
+ if (ptr == NULL) {
+ continue;
+ }
+
+ do {
+ cnt_tmp = strlen(ptr);
+ if (cnt_tmp + BUF_TAIL_LENGTH > ACK_BUF_SIZE || ptr[0] == '#') {
+ continue;
+ }
+ META_LOG("GPS_MetaThread: [%d]/[%d]\n", cnt_tmp, cnt);
+ if ((cnt != 0) && ((cnt + cnt_tmp + BUF_TAIL_LENGTH) >= ACK_BUF_SIZE)) {
+ gps_cnf2.gps_ack.len = cnt;
+ gps_cnf2.gps_status = TRUE;
+ gps_cnf2.status = META_SUCCESS;
+ META_LOG("GPS_MetaThread, status:%d, gps_cnf.gps_ack.len:%d\r\n",
+ gps_cnf2.status, gps_cnf2.gps_ack.len);
+ WriteDataToPC(&gps_cnf2, sizeof(GPS_CNF), NULL, 0);
+ cnt = 0;
+ }
+ META_LOG("GPS_MetaThread: %s", ptr);
+ strncpy((char*)&gps_cnf2.gps_ack.buff[cnt], ptr, (sizeof(gps_cnf2.gps_ack.buff) - cnt));
+ cnt += cnt_tmp;
+ if(cnt > 0 && cnt < (sizeof(gps_cnf2.gps_ack.buff) - 3)) {
+ gps_cnf2.gps_ack.buff[cnt++] = '\r';
+ gps_cnf2.gps_ack.buff[cnt++] = '\n';
+ } else {
+ META_LOG("gps_ack buffer full(%d)", cnt);
+ }
+ } while ((ptr = strtok(NULL, "\r\n")) != NULL);
+ if (cnt > 0) {
+ gps_cnf2.gps_ack.len = cnt;
+ gps_cnf2.gps_status = TRUE;
+ gps_cnf2.status = META_SUCCESS;
+ META_LOG("GPS_MetaThread, status:%d, last gps_cnf.gps_ack.len:%d\r\n",
+ gps_cnf2.status, gps_cnf2.gps_ack.len);
+ WriteDataToPC(&gps_cnf2, sizeof(GPS_CNF), NULL, 0);
+ cnt = 0;
+ }
+ }
+ }
+
+ return (void *)0;
+}
diff --git a/src/devtools/meta/src/adaptor/gps/meta_gps_para.h b/src/devtools/meta/src/adaptor/gps/meta_gps_para.h
new file mode 100644
index 0000000..925bb29
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/gps/meta_gps_para.h
@@ -0,0 +1,121 @@
+/*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2008
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * meta_gps_para.h
+ *
+ * Project:
+ * --------
+ * DUMA
+ *
+ * Description:
+ * ------------
+ * define the struct for Meta
+ *
+ * Author:
+ * -------
+ * LiChunhui (MTK80143)
+ *
+ *============================================================================
+ * HISTORY
+ * Below this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * $Revision:$
+ * $Modtime:$
+ * $Log:$
+ *
+ * Mar 20 2009 mtk80143
+ * [DUMA00111323] [GPS] modify for GPS META
+ * Add for GPS META
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+#ifndef __META_GPS_PARA_H_
+#define __META_GPS_PARA_H_
+
+#include "MetaPub.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* The TestCase Enum define of GPS_module */
+typedef enum {
+ GPS_OP_OPEN = 0,
+ GPS_OP_CLOSE,
+ GPS_OP_SEND_CMD,
+ GPS_OP_END
+} GPS_OP;
+
+/* The PMTK command struct */
+typedef struct {
+ unsigned int len;
+ unsigned char buff[1024];
+} GPS_CMD;
+
+/* The PMTK command ACK struct */
+typedef struct {
+ unsigned int len;
+ unsigned char buff[1024];
+} GPS_ACK_BUF;
+
+typedef struct {
+ FT_H header; // module do not need care it
+ GPS_OP op;
+ GPS_CMD cmd;
+} GPS_REQ;
+
+typedef struct {
+ FT_H header; // module do not need care it
+ GPS_OP op;
+ unsigned int gps_status; // gps->FT
+ GPS_ACK_BUF gps_ack;
+ unsigned char status;
+} GPS_CNF;
+
+
+void META_GPS_OP(GPS_REQ *req, char *peer_buff, unsigned short peer_len, int ATM_test);
+void *GPS_MetaThread(void *arg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/gps/type.h b/src/devtools/meta/src/adaptor/gps/type.h
new file mode 100644
index 0000000..4d6a885
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/gps/type.h
@@ -0,0 +1,83 @@
+/*******************************************************************************
+** Copyright (c) 2005 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+#ifndef _TYPE_H
+#define _TYPE_H
+
+#define ULONG unsigned long
+#define UINT unsigned int
+#define USHORT unsigned short
+#define UCHAR unsigned char
+
+#define LONG long
+#define INT int
+#define SHORT short
+#define CHAR char
+
+#define UINT32 unsigned long
+#define UINT16 unsigned short
+#define UINT8 unsigned char
+
+#define PUINT32 unsigned long*
+#define PUINT16 unsigned short*
+#define PUINT8 unsigned char*
+
+#define UINT_64 unsigned long long
+#define UINT_32 unsigned long
+#define UINT_16 unsigned short
+#define UINT_8 unsigned char
+
+#define INT32 long
+#define INT16 short
+#define INT8 char
+
+#define PINT32 long*
+#define PINT16 short*
+#define PINT8 char*
+#define PVOID void*
+
+#define INT_32 long
+#define INT_16 short
+#define INT_8 char
+
+#define PULONG ULONG*
+#define PUCHAR UCHAR*
+
+#define DWORD ULONG
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#define BOOL bool
+#define BOOLEAN bool
+
+
+#define TRUE true
+#define FALSE false
+
+#define IN
+#define OUT
+
+#define TCHAR char
+
+#define CString char*
+
+#define LPSTR char*
+#define LPCTSTR char*
+
+#define DLL_FUNC
+
+#define TEXT
+
+#define BIT(n) ((UINT_32) 1 << (n))
+#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n)))
+
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/wifi/README b/src/devtools/meta/src/adaptor/wifi/README
new file mode 100644
index 0000000..dbbea42
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/README
@@ -0,0 +1,33 @@
+This directory contains WIFI Tool library
+
+
+WHAT IT DOES?
+=============
+It provide WIFI editing feature on PC side, which allow read and modify WIFI items as GUI.
+
+
+HOW IT WAS BUILT?
+==================
+It needs the following libs from AOSP:
+1. libc.so
+
+and the following libs from MediaTek:
+1. libmeta_wifi.a
+2. libft.so
+
+All source/dependency modules of this module are already put in
+'vendor/mediatek/proprietary/platform/${CHIP_NAME}/external/meta/wifi' folder.
+
+
+HOW TO USE IT?
+==============
+Files in this directory is used to generate a library which's name is 'libmeta_wifi'
+
+
+WIFI Tool
+The lib 'libmeta_wifi' is loaded when SP WIFI tool and related libs,
+all WIFI GUI opertations will call META_WIFI_xxx API, then it calls WIFI native API to access WIFI driver data.
+
+
+All the source code of this library were written by MediaTek co..
+
diff --git a/src/devtools/meta/src/adaptor/wifi/iwlibstub.c b/src/devtools/meta/src/adaptor/wifi/iwlibstub.c
new file mode 100644
index 0000000..648db21
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/iwlibstub.c
@@ -0,0 +1,338 @@
+/*******************************************************************************
+** Copyright (c) 2006 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <math.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+//#include <net/ethernet.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <linux/socket.h>
+#include <linux/if.h>
+#include <net/if_arp.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <linux/types.h>
+#ifndef __user
+#define __user
+#endif
+#include <linux/wireless.h>
+#include "iwlibstub.h"
+#include "meta_wifi_para.h"
+
+int openNetHandle(void)
+{
+ int sock; /* generic raw socket desc. */
+
+
+ /* Try to open the socket, if success returns it */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+ if (sock >= 0)
+ return sock;
+ else
+ return -1;
+}
+
+void closeNetHandle(int skfd)
+{
+ /* Close the socket. */
+ close(skfd);
+}
+
+int enumNetIf(int skfd, _enum_handler fn, void* argc)
+{
+ struct ifconf ifc;
+ char buff[1024];
+ struct ifreq *ifr;
+ int i, num = 0;
+
+ ifc.ifc_len = sizeof(buff);
+ ifc.ifc_buf = buff;
+
+ if (ioctl(skfd, SIOCGIFCONF, &ifc) < 0)
+ {
+ fprintf(stderr, "SIOCGIFCONF: %s\n", strerror(errno));
+ return num;
+ }
+
+ ifr = ifc.ifc_req;
+
+ for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++)
+ {
+ (*fn)(skfd, ifr->ifr_name, argc);
+ num ++;
+ }
+
+ return num;
+}
+
+
+int setIWreq(int skfd, char* if_name,
+ unsigned int ndisOid,
+ unsigned char* ndisData,
+ unsigned int bufLen,
+ unsigned int* outputBufLen)
+{
+ struct iwreq wrq;
+ unsigned char *buffer = NULL;
+ unsigned int reqBufLen = 0;
+ NDIS_TRANSPORT_STRUCT* reqStruct_p = NULL;
+ int result;
+
+ reqBufLen = bufLen + sizeof(*reqStruct_p) -
+ sizeof(reqStruct_p->ndisOidContent);
+
+ if (reqBufLen >= 0)
+ {
+ buffer = (unsigned char *)malloc(reqBufLen);
+ }
+
+ if (buffer == NULL)
+ {
+ printf("%s malloc(%d) fail\n", __func__, reqBufLen);
+ return -1;
+ }
+
+ reqStruct_p = (NDIS_TRANSPORT_STRUCT*)buffer;
+
+ reqStruct_p->ndisOidCmd = ndisOid;
+ reqStruct_p->inNdisOidlength = bufLen;
+
+ if (bufLen != 0)
+ {
+ memcpy(reqStruct_p->ndisOidContent, ndisData, bufLen);
+ }
+
+ /* Try to read the results */
+ wrq.u.data.pointer = buffer;
+ wrq.u.data.flags = PRIV_CMD_OID;
+ wrq.u.data.length = reqBufLen;
+
+#if 0
+ printf("%s: buffer(0x%p), flags(%d), length(%d)\n",
+ __FUNCTION__,
+ buffer, PRIV_CMD_OID, reqBufLen
+ );
+#endif
+
+ /* Set device name */
+ strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+ /* Do the request */
+ result = ioctl(skfd, IOCTL_SET_STRUCT, &wrq);
+
+ if (result < 0)
+ {
+ if(fprintf(stderr, "result %d %s\n", result, strerror(errno)) < 0)
+ return -1;
+ }
+
+ *outputBufLen = reqStruct_p->outNdisOidLength;
+
+ free(buffer);
+
+ if (result == 0)
+ return 0;
+
+ return -1;
+}
+
+int getIWreq(int skfd, char* if_name,
+ unsigned int ndisOid,
+ unsigned char* ndisData,
+ unsigned int bufLen,
+ unsigned int* outputBufLen)
+{
+ struct iwreq wrq;
+ unsigned char *buffer = NULL;
+ unsigned int reqBufLen = 0;
+ NDIS_TRANSPORT_STRUCT* reqStruct_p = NULL;
+ int result;
+
+ //printf("%s\n", __FUNCTION__);
+
+ reqBufLen = bufLen + sizeof(*reqStruct_p) -
+ sizeof(reqStruct_p->ndisOidContent);
+
+ if (reqBufLen >= 0)
+ {
+ buffer = (unsigned char *)malloc(reqBufLen);
+ }
+
+ if (buffer == NULL)
+ {
+ printf("%s malloc(%d) fail\n", __func__, reqBufLen);
+ return -1;
+ }
+
+ reqStruct_p = (NDIS_TRANSPORT_STRUCT*)buffer;
+
+ reqStruct_p->ndisOidCmd = ndisOid;
+ reqStruct_p->inNdisOidlength = bufLen;
+
+ /* IMPORTANT!! copy input data to buffer (ex. mcr index) */
+ memcpy(reqStruct_p->ndisOidContent, ndisData, bufLen);
+
+ /* Try to read the results */
+ wrq.u.data.pointer = buffer;
+ wrq.u.data.flags = PRIV_CMD_OID;
+ wrq.u.data.length = reqBufLen;
+
+ /* Set device name */
+ strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+ /* Do the request */
+ result = ioctl(skfd, IOCTL_GET_STRUCT, &wrq);
+
+ if (result < 0)
+ if(fprintf(stderr, "getIWreq result %s %d %s\n", if_name, result, strerror(errno)) < 0)
+ return -1;
+
+ if (result == 0)
+ {
+ memcpy(ndisData, reqStruct_p->ndisOidContent, reqStruct_p->outNdisOidLength);
+ }
+
+ *outputBufLen = reqStruct_p->outNdisOidLength;
+
+ free(buffer);
+
+ if (result == 0)
+ return 0;
+
+ return -1;
+}
+
+/**
+ * Function:
+ * Send the parsed command to driver
+ * for example : set_mcr 0x820F4020 0x14141414
+ *
+ * Parameters:
+ * IN int skfd: socket handle
+ * IN char* if_name: network device name, wlan0
+ * IN char* pDataCmd: command string from script file
+ * IN int bufLen: strlen of command string
+ * OUT int outputBufLen: length of output buffer
+ *
+ * Return:
+ * -1 means error, 0 is success
+ */
+int driverIWreq(int skfd, char* if_name,
+ char* pDataCmd,
+ unsigned int bufLen,
+ unsigned int* outputBufLen)
+{
+ struct iwreq wrq;
+ char *buffer = NULL;
+
+ int result;
+
+
+ buffer = (char *)malloc(WIFI_SCRIPT_TOTAL_BUF_LEN);
+
+ if (buffer == NULL)
+ return -1;
+
+ /*copy driver command*/
+ memcpy(buffer, pDataCmd, bufLen);
+ buffer[bufLen] = '\0';
+
+ /* Try to read the results */
+ wrq.u.data.pointer = buffer;
+ wrq.u.data.length = bufLen; /*available data length*/
+
+ DBG("input (%d) >> %s\n", wrq.u.data.length, wrq.u.data.pointer);
+
+ /* Set device name */
+ strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+ /* Do the request */
+ result = ioctl(skfd, IOCTL_GET_DRIVER, &wrq);
+
+ if (wrq.u.data.length > WIFI_SCRIPT_TOTAL_BUF_LEN)
+ wrq.u.data.length = WIFI_SCRIPT_TOTAL_BUF_LEN;
+
+ if (result < 0)
+ DBG("driverIWreq result %s %d %s\n", if_name, result, strerror(errno));
+ else if (result == 0)
+ {
+ memcpy(pDataCmd, buffer, wrq.u.data.length);
+ pDataCmd[wrq.u.data.length] = '\0';
+
+ DBG("output (%d) >> %s\n", wrq.u.data.length, pDataCmd);
+ *outputBufLen = wrq.u.data.length;
+ }
+
+ free(buffer);
+
+ if (result == 0)
+ return 0;
+
+ return -1;
+}
+
+int HQAIWreq(int skfd, char* if_name,
+ char* pDataCmd,
+ unsigned int bufLen,
+ unsigned int* outputBufLen)
+{
+ struct iwreq wrq;
+ int result, intI, dataLen;
+
+ /* Try to read the results */
+ wrq.u.data.pointer = pDataCmd;
+ wrq.u.data.length = bufLen; /*available data length*/
+
+ dataLen = (pDataCmd[8] << 8) + pDataCmd[9];
+ DBG("Cmd Type: %02x%02x, Cmd ID: %02x%02x Length: %d\n", pDataCmd[4], pDataCmd[5], pDataCmd[6], pDataCmd[7], dataLen);
+
+ for (intI = 0; intI < dataLen;)
+ {
+ DBG("Content [%d~%d]: %x %x %x %x ", intI, intI + 3, pDataCmd[12 + intI], pDataCmd[13 + intI], pDataCmd[14 + intI], pDataCmd[15 + intI]); /* content start index in pDataCmd[8], pDataCmd[6,7] is Seq */
+ intI = intI + 4;
+ }
+
+ /* Set device name */
+ strncpy(wrq.ifr_name, if_name, IFNAMSIZ - 1);
+ /* Do the request */
+#ifdef PETRUS_META_WORKAROUND
+ result = ioctl(skfd, IOCTL_QA_TOOL_DAEMON_NEW, &wrq);
+#else
+ result = ioctl(skfd, IOCTL_QA_TOOL_DAEMON, &wrq);
+#endif
+
+ if (wrq.u.data.length > bufLen)
+ wrq.u.data.length = bufLen;
+
+ if (result < 0)
+ DBG("HQAIWreq result %s %d %s\n", if_name, result, strerror(errno));
+ else if (result == 0)
+ {
+ for (intI = 0; intI < wrq.u.data.length;)
+ {
+ DBG("Content [%d~%d]: %x %x %x %x ", intI, intI + 3, pDataCmd[intI], pDataCmd[1 + intI], pDataCmd[2 + intI], pDataCmd[3 + intI]);
+ intI = intI + 4;
+ }
+ *outputBufLen = wrq.u.data.length;
+ }
+
+ if (result == 0)
+ return 0;
+
+ return -1;
+}
\ No newline at end of file
diff --git a/src/devtools/meta/src/adaptor/wifi/iwlibstub.h b/src/devtools/meta/src/adaptor/wifi/iwlibstub.h
new file mode 100644
index 0000000..51a2b1c
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/iwlibstub.h
@@ -0,0 +1,134 @@
+#ifndef _IWLIB_STUB_H
+#define _IWLIB_STUB_H
+
+/*******************************************************************************
+** Copyright (c) 2005 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+
+#include "type.h"
+
+#define PETRUS_META_WORKAROUND 1
+
+#if WIRELESS_EXT >= 12
+/* New wireless extensions API - SET/GET convention (even ioctl numbers are
+ * root only)
+ */
+#define IOCTL_SET_INT (SIOCIWFIRSTPRIV + 0)
+#define IOCTL_GET_INT (SIOCIWFIRSTPRIV + 1)
+#define IOCTL_SET_ADDRESS (SIOCIWFIRSTPRIV + 2)
+#define IOCTL_GET_ADDRESS (SIOCIWFIRSTPRIV + 3)
+#define IOCTL_SET_STR (SIOCIWFIRSTPRIV + 4)
+#define IOCTL_GET_STR (SIOCIWFIRSTPRIV + 5)
+#define IOCTL_SET_KEY (SIOCIWFIRSTPRIV + 6)
+#define IOCTL_GET_KEY (SIOCIWFIRSTPRIV + 7)
+#define IOCTL_SET_STRUCT (SIOCIWFIRSTPRIV + 8)
+#define IOCTL_GET_STRUCT (SIOCIWFIRSTPRIV + 9)
+#define IOCTL_GET_DRIVER (SIOCIWFIRSTPRIV + 15)
+#define IOCTL_QA_TOOL_DAEMON (SIOCIWFIRSTPRIV + 16)
+#define IOCTL_QA_TOOL_DAEMON_NEW (SIOCDEVPRIVATE + 2)
+#endif /* WIRELESS_EXT >= 12 */
+
+#if 1
+/* MT5921 Glue Layer Private IOCTL IDs */
+#define PRIV_CMD_REG_DOMAIN 0
+#define PRIV_CMD_BEACON_PERIOD 1
+#define PRIV_CMD_ADHOC_MODE 2
+
+#define PRIV_CMD_CSUM_OFFLOAD 3
+
+#define PRIV_CMD_ROAMING 4
+#define PRIV_CMD_VOIP_DELAY 5
+#define PRIV_CMD_POWER_MODE 6
+
+#define PRIV_CMD_WMM_PS 7
+#define PRIV_CMD_BT_COEXIST 8
+#define PRIV_GPIO2_MODE 9
+
+#define PRIV_CUSTOM_SET_PTA 10
+#define PRIV_CUSTOM_CONTINUOUS_POLL 11
+#define PRIV_CUSTOM_SINGLE_ANTENNA 12
+#define PRIV_CUSTOM_BWCS_CMD 13
+#define PRIV_CUSTOM_DISABLE_BEACON_DETECTION 14 // later
+#define PRIV_CMD_OID 15
+#define PRIV_CMD_MAX 16
+
+#else
+/* MT5911/12 Glue Layer Private IOCTL IDs */
+#define PRIV_CMD_OID 0
+#define PRIV_CMD_CHIPID 1
+#define PRIV_CMD_MCR 2
+#define PRIV_CMD_BBCR 3
+#define PRIV_CMD_EEPROM 4
+#define PRIV_CMD_EEPROM_SIZE 5
+#define PRIV_CMD_EEPROM_MAC 6
+#define PRIV_CMD_EEPROM_CHKSUM 7
+#define PRIV_CMD_EEPROM_COUNTRY 8
+#define PRIV_CMD_EEPROM_SET_POWER 9
+#define PRIV_CMD_RFTEST_MODE 10
+#define PRIV_CMD_RFTEST_TX 11
+#define PRIV_CMD_RFTEST_RX 12
+#define PRIV_CMD_RFTEST_RST_RX_CNT 13
+#define PRIV_CMD_RFTEST_CNT_POWER 14
+#define PRIV_CMD_RFTEST_LOCAL_FREQ 15
+#define PRIV_CMD_RFTEST_CAR_SUP 16
+#define PRIV_CMD_RFTEST_LOW_POWER 17
+#define PRIV_CMD_QOS_UAPSD 18
+#define PRIV_CMD_QOS_UAPSD_TEST 19
+#define PRIV_CMD_PSP_PROFILE 20
+#define PRIV_CMD_PM_TX_TIMEOUT 21
+#define PRIV_CMD_PM_ASSOC_TIMEOUT 22
+#define PRIV_CMD_PM_DTIM_PERIOD 23
+#define PRIV_CMD_CONN_KEEP_PERIOD 24
+#define PRIV_CMD_CONN_TX_NULL 25
+#define PRIV_CMD_MAX 26
+#endif
+
+#define WIFI_SCRIPT_TOTAL_BUF_LEN 2000
+#define RA_CFG_HLEN 14 /* Length of Racfg header*/
+
+typedef int (*_enum_handler)(int skfd,
+ char *ifname,
+ void *arg);
+
+typedef struct _NDIS_TRANSPORT_STRUCT
+{
+ unsigned int ndisOidCmd;
+ unsigned int inNdisOidlength;
+ unsigned int outNdisOidLength;
+ unsigned char ndisOidContent[16];
+} NDIS_TRANSPORT_STRUCT;
+
+
+int openNetHandle(void);
+void closeNetHandle(int skfd);
+int enumNetIf(int skfd, _enum_handler fn, void* argc);
+
+int setIWreq(int skfd, char* if_name,
+ unsigned int ndisOid,
+ unsigned char* ndisData,
+ unsigned int bufLen,
+ unsigned int* outputBufLen);
+
+int getIWreq(int skfd, char* if_name,
+ unsigned int ndisOid,
+ unsigned char* ndisData,
+ unsigned int bufLen,
+ unsigned int* outputBufLen);
+
+int driverIWreq(int skfd, char* if_name,
+ char* pDataCmd,
+ unsigned int bufLen,
+ unsigned int* outputBufLen);
+
+int HQAIWreq(int skfd, char* if_name,
+ char* pDataCmd,
+ unsigned int bufLen,
+ unsigned int* outputBufLen);
+
+#endif
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi.c b/src/devtools/meta/src/adaptor/wifi/meta_wifi.c
new file mode 100644
index 0000000..aed7c1d
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi.c
@@ -0,0 +1,3083 @@
+#include "meta_wifi.h"
+
+#include <cutils/properties.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <net/if_arp.h> /* For ARPHRD_ETHER */
+#include <sys/socket.h> /* For AF_INET & struct sockaddr */
+#include <netinet/in.h> /* For struct sockaddr_in */
+#include <netinet/if_ether.h>
+#include <linux/wireless.h>
+
+#include "cutils/misc.h"
+#include "iwlibstub.h"
+
+
+#include "libnvram.h"
+#include <Custom_NvRam_LID.h>
+
+#include "type.h"
+
+#ifndef WIFI_DRV_MOD_PATH
+#define WIFI_DRV_MOD_PATH "/system/lib/modules/wlan.ko"
+#endif
+#ifndef WIFI_DRV_MOD_NAME
+#define WIFI_DRV_MOD_NAME "wlan"
+#endif
+#ifndef WIFI_DRV_MOD_ARG
+#define WIFI_DRV_MOD_ARG ""
+#endif
+#ifndef WIFI_TYPE_NAME
+#define WIFI_TYPE_NAME "wlan"
+#endif
+
+#define WIFI_POWER_PATH "/dev/wmtWifi"
+
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+#define MAX_NVRAM_ACCESS_SIZE 256
+#define NVRAM_G_BAND_TSSI_CH_GROUP_NUM 14
+#define NVRAM_A_BAND_TSSI_CH_GROUP_NUM 32
+#define NVRAM_G_BAND_TSSI_CH_OFS_SIZE (sizeof(WIFI_NVRAM_TSSI_CH_OFS_T)*NVRAM_G_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_TSSI_CH_OFS_SIZE (sizeof(WIFI_NVRAM_TSSI_CH_OFS_T)*NVRAM_A_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.rTssiChOfs[0].ucTssiChOfsGT2))
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.rTssiChOfs[0].ucTssiChOfsGT2))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rTssiChOfs[0].ucTssiChOfsGT2))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rTssiChOfs[0].ucTssiChOfsGT2))
+
+#if (CFG_DNL_CAL == 1)
+#define NVRAM_G_BAND_TSSI_DNL_GROUP_NUM 14
+#define NVRAM_A_BAND_TSSI_DNL_GROUP_NUM 8
+#define NVRAM_G_BAND_TSSI_DNL_OFS_SIZE (sizeof(WIFI_NVRAM_TX_DNL_T)*NVRAM_G_BAND_TSSI_DNL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_TSSI_DNL_OFS_SIZE (sizeof(WIFI_NVRAM_TX_DNL_T)*NVRAM_A_BAND_TSSI_DNL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.rTxDnl[0].ucTxDnlCckGT0))
+#define NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.rTxDnl[0].ucTxDnlCckGT0))
+#define NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rTxDnl[0].ucTxDnlCckGT0))
+#define NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rTxDnl[0].ucTxDnlCckGT0))
+#endif
+
+#define NVRAM_G_BAND_LNA_GAIN_CAL_GROUP_NUM 1
+#define NVRAM_A_BAND_LNA_GAIN_CAL_GROUP_NUM 8
+#define NVRAM_G_BAND_LNA_GAIN_CAL_OFS_SIZE (sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T)*NVRAM_G_BAND_LNA_GAIN_CAL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_LNA_GAIN_CAL_OFS_SIZE (sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T)*NVRAM_A_BAND_LNA_GAIN_CAL_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.rLnaGainCal[0].ucRxCal1))
+#define NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.rLnaGainCal[0].ucRxCal1))
+#define NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rLnaGainCal[0].ucRxCal1))
+#define NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rLnaGainCal[0].ucRxCal1))
+#else
+#define MAX_NVRAM_ACCESS_SIZE 256
+#define NVRAM_G_BAND_TSSI_CH_GROUP_NUM 14
+#define NVRAM_A_BAND_TSSI_CH_GROUP_NUM 32
+#define NVRAM_G_BAND_TSSI_CH_OFS_SIZE (sizeof(UINT_8)*NVRAM_G_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_A_BAND_TSSI_CH_OFS_SIZE (sizeof(UINT_8)*NVRAM_A_BAND_TSSI_CH_GROUP_NUM) /*unit: 1 byte*/
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF0path.aucTx2G4TssiChannelOffsetLowCh[0]))
+#define NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r2G4WF1path.aucTx2G4TssiChannelOffsetLowCh[0]))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF0path.rTxTssiChannelOffset[0].ucTxPowerOffsetLow))
+#define NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1 (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, r5GWF1path.rTxTssiChannelOffset[0].ucTxPowerOffsetLow))
+
+#define NVRAM_TSSI_STEP_OFSET (OFFSET_OF(WIFI_CFG_PARAM_STRUCT, rSys.u1TssiStep))
+#endif /*#if (WIFI_GEN_VER == CONNAC_SOC3_0)*/
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+#define MAX_PL_INPUT_ARG_NUM 32
+#define POLLING_RECAL_RETRY_CNT 10
+#define QUERY_RECAL_RETRY_CNT 3
+
+#define GET_A_BAND_RF_GROUP(group) (((group % 2) == 0) ? (group / 2) : ((group - 1) / 2))
+
+//static const char DRIVER_MODULE_NAME[] = WIFI_DRV_MOD_NAME;
+//static const char DRIVER_MODULE_TAG[] = WIFI_DRV_MOD_NAME " ";
+//static const char DRIVER_MODULE_ARG[] = WIFI_DRV_MOD_ARG;
+//static const char DRIVER_MODULE_PATH[] = WIFI_DRV_MOD_PATH;
+//static const char MODULE_FILE[] = "/proc/modules";
+
+static int wifi_init = 0;
+static int wifi_skfd = -1;
+//static int wifi_rfkill_id = -1;
+//static char *wifi_rfkill_state_path = NULL;
+static WIFI_CNF_CB cnf_cb = NULL;
+
+//extern int init_module(void *, unsigned long, const char *);
+//extern int delete_module(const char *, unsigned int);
+extern int sched_yield(void);
+extern int ifc_init();
+extern int ifc_up(const char *name);
+extern int ifc_down(const char *name);
+extern void ifc_close();
+
+static F_INFO gNvInfo;
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+static HQA_PARA_INFO gHqaParaInfo;
+static CH_GROUP_CLASS _arChGroupTbl[][BAND_NUM] =
+{
+ { /* 2G channel group (COMMON) */
+ {
+ CH_GROUP_ITEM_COMMON,
+ NVRAM_COMMON_CATEGORY_G_BAND_CH_GROUP_NUM,
+ {
+ CH_GROUP_COMMON_G_BAND_BOUNDARY_00, CH_GROUP_COMMON_G_BAND_BOUNDARY_01, CH_GROUP_COMMON_G_BAND_BOUNDARY_02, CH_GROUP_COMMON_G_BAND_BOUNDARY_03,
+ CH_GROUP_COMMON_G_BAND_BOUNDARY_04, CH_GROUP_COMMON_G_BAND_BOUNDARY_05, CH_GROUP_COMMON_G_BAND_BOUNDARY_06, CH_GROUP_COMMON_G_BAND_BOUNDARY_07,
+ CH_GROUP_COMMON_G_BAND_BOUNDARY_08, CH_GROUP_COMMON_G_BAND_BOUNDARY_09, CH_GROUP_COMMON_G_BAND_BOUNDARY_10, CH_GROUP_COMMON_G_BAND_BOUNDARY_11,
+ CH_GROUP_COMMON_G_BAND_BOUNDARY_12, CH_GROUP_COMMON_G_BAND_BOUNDARY_13, CH_GROUP_COMMON_G_BAND_BOUNDARY_14, CH_GROUP_COMMON_G_BAND_BOUNDARY_15
+ }
+ },
+ /* 5G channel group (COMMON) */
+ {
+ CH_GROUP_ITEM_COMMON,
+ NVRAM_COMMON_CATEGORY_A_BAND_CH_GROUP_NUM,
+ {
+ CH_GROUP_COMMON_A_BAND_BOUNDARY_00, CH_GROUP_COMMON_A_BAND_BOUNDARY_01, CH_GROUP_COMMON_A_BAND_BOUNDARY_02, CH_GROUP_COMMON_A_BAND_BOUNDARY_03,
+ CH_GROUP_COMMON_A_BAND_BOUNDARY_04, CH_GROUP_COMMON_A_BAND_BOUNDARY_05, CH_GROUP_COMMON_A_BAND_BOUNDARY_06, CH_GROUP_COMMON_A_BAND_BOUNDARY_07,
+ CH_GROUP_COMMON_A_BAND_BOUNDARY_08, CH_GROUP_COMMON_A_BAND_BOUNDARY_09, CH_GROUP_COMMON_A_BAND_BOUNDARY_10, CH_GROUP_COMMON_A_BAND_BOUNDARY_11,
+ CH_GROUP_COMMON_A_BAND_BOUNDARY_12, CH_GROUP_COMMON_A_BAND_BOUNDARY_13, CH_GROUP_COMMON_A_BAND_BOUNDARY_14, CH_GROUP_COMMON_A_BAND_BOUNDARY_15
+ }
+ }
+ },
+ { /* 2G channel group (TSSI_CH) */
+ {
+ CH_GROUP_ITEM_TSSI_CH,
+ NVRAM_TSSI_CH_OFFSET_G_BAND_CH_GROUP_NUM,
+ {
+ CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_00, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_01, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_02, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_03,
+ CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_04, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_05, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_06, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_07,
+ CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_08, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_09, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_10, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_11,
+ CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_12, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_13, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_14, CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_15
+ }
+ },
+ /* 5G channel group (TSSI_CH) */
+ {
+ CH_GROUP_ITEM_TSSI_CH,
+ NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM,
+ {
+ CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_00, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_01, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_02, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_03,
+ CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_04, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_05, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_06, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_07,
+ CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_08, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_09, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_10, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_11,
+ CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_12, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_13, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_14, CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_15
+ }
+ }
+ },
+};
+static CH_SUB_GROUP_CLASS _arSubGroupTbl[][BAND_NUM] =
+{
+ { /* 2G channel group (TX) */
+ {
+ CH_SUB_GROUP_TSSI_CH,
+ CH_SUB_GROUP_2G4_ITEM_NUM, CH_SUB_GROUP_G_BAND_NOT_ORDERED_NUM,
+ {
+ CH_SUB_GROUP_G_BAND_BOUNDARY_00, CH_SUB_GROUP_G_BAND_BOUNDARY_01, CH_SUB_GROUP_G_BAND_BOUNDARY_02, CH_SUB_GROUP_G_BAND_BOUNDARY_03,
+ CH_SUB_GROUP_G_BAND_BOUNDARY_04, CH_SUB_GROUP_G_BAND_BOUNDARY_05, CH_SUB_GROUP_G_BAND_BOUNDARY_06, CH_SUB_GROUP_G_BAND_BOUNDARY_07,
+ CH_SUB_GROUP_G_BAND_BOUNDARY_08, CH_SUB_GROUP_G_BAND_BOUNDARY_09, CH_SUB_GROUP_G_BAND_BOUNDARY_10, CH_SUB_GROUP_G_BAND_BOUNDARY_11,
+ CH_SUB_GROUP_G_BAND_BOUNDARY_12, CH_SUB_GROUP_G_BAND_BOUNDARY_13, CH_SUB_GROUP_G_BAND_BOUNDARY_14, CH_SUB_GROUP_G_BAND_BOUNDARY_15
+ }
+ },
+ /* 5G channel group (TX) */
+ {
+ CH_SUB_GROUP_TSSI_CH,
+ CH_SUB_GROUP_5G_ITEM_NUM, CH_SUB_GROUP_A_BAND_NOT_ORDERED_NUM,
+ {
+ CH_SUB_GROUP_A_BAND_BOUNDARY_00, CH_SUB_GROUP_A_BAND_BOUNDARY_01, CH_SUB_GROUP_A_BAND_BOUNDARY_02, CH_SUB_GROUP_A_BAND_BOUNDARY_03,
+ CH_SUB_GROUP_A_BAND_BOUNDARY_04, CH_SUB_GROUP_A_BAND_BOUNDARY_05, CH_SUB_GROUP_A_BAND_BOUNDARY_06, CH_SUB_GROUP_A_BAND_BOUNDARY_07,
+ CH_SUB_GROUP_A_BAND_BOUNDARY_08, CH_SUB_GROUP_A_BAND_BOUNDARY_09, CH_SUB_GROUP_A_BAND_BOUNDARY_10, CH_SUB_GROUP_A_BAND_BOUNDARY_11,
+ CH_SUB_GROUP_A_BAND_BOUNDARY_12, CH_SUB_GROUP_A_BAND_BOUNDARY_13, CH_SUB_GROUP_A_BAND_BOUNDARY_14, CH_SUB_GROUP_A_BAND_BOUNDARY_15
+ }
+ }
+ }
+};
+
+#define CH_GROUP_CLASS_TBL_ITEM_NUM (sizeof(_arChGroupTbl)) / (sizeof(CH_GROUP_CLASS)) / (BAND_NUM)
+#define CH_SUB_GROUP_CLASS_TBL_ITEM_NUM (sizeof(_arSubGroupTbl)) / (sizeof(CH_SUB_GROUP_CLASS)) / (BAND_NUM)
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+static void wifi_send_resp(FT_WM_WIFI_CNF *cnf, void *buf, unsigned int size)
+{
+ if (cnf_cb)
+ cnf_cb(cnf, buf, size);
+ else
+ WriteDataToPC(cnf, sizeof(FT_WM_WIFI_CNF), buf, size);
+}
+
+int write_data_to_driver(char *data, size_t length)
+{
+ int sz;
+ int fd = -1;
+ int ret = -1;
+ int retry_cont;
+
+ if (!data || !length)
+ return ret;
+
+ for (retry_cont = 0; retry_cont < 5; retry_cont++)
+ {
+ DBG("open retry_cont = (%d)", retry_cont);
+ fd = open(WIFI_POWER_PATH, O_WRONLY);
+
+ if (fd < 0)
+ {
+ usleep(1000000);
+ }
+ else
+ break;
+ }
+
+ if (fd < 0)
+ {
+ DBG("open(%s) for write failed: %s (%d)", WIFI_POWER_PATH,
+ strerror(errno), errno);
+ goto out;
+ }
+
+ for (retry_cont = 0; retry_cont < 5; retry_cont++)
+ {
+ DBG("write retry_cont = (%d)", retry_cont);
+ sz = write(fd, data, length);
+
+ if (sz < 0)
+ {
+#if 0
+ DBG("write(%s) failed: %s (%d)", WIFI_POWER_PATH, strerror(errno),
+ errno);
+ goto out;
+#endif
+
+ usleep(1000000);
+ }
+ else
+ break;
+ }
+
+ if (sz > 0)
+ ret = 0;
+ else
+ {
+ DBG("write(%s) failed: %s (%d)", WIFI_POWER_PATH, strerror(errno),
+ errno);
+ }
+
+out:
+
+ if (fd >= 0)
+ close(fd);
+
+ return ret;
+}
+/*----------------------------------------------------------------------------*/
+/**
+* @brief wifi nvram control: read nvram and wirte nvram
+*
+* @param[in] fgSet, (true:write, false:read)
+*
+* @return new command size
+*/
+/*----------------------------------------------------------------------------*/
+int wifiNVRAMCtrl(bool fgSet, PNVRAM_ACCESS_STRUCT pnvram)
+{
+
+ int ret = -1;
+ int iFD;
+ int readByteLen = -1;
+
+ if (pnvram == NULL)
+ {
+
+ return -1;
+ }
+
+ DBG("[META_WIFI] NVRAMCtrl fg(%d) len(%d)\n", fgSet, pnvram->dataLen);
+
+
+ if (fgSet)
+ {
+ DBG("[META_WIFI] write offset:%d (0x%04X)\n", pnvram->dataOffset, pnvram->dataOffset);
+ iFD = open(gNvInfo.cFileName, O_WRONLY | O_CREAT, S_IRUSR | S_IRGRP);
+
+ if (iFD >= 0)
+ {
+ if (lseek(iFD, pnvram->dataOffset, SEEK_SET) < 0)
+ {
+ ERR("[META_WIFI] read fail!");
+ close(iFD);
+ return -1;
+ }
+
+ write(iFD, pnvram->data, pnvram->dataLen);
+ close(iFD);
+
+ /* invoke protect data file mechanism */
+ if (NVM_ProtectDataFile(AP_CFG_RDEB_FILE_WIFI_LID, 1) != 1)
+ {
+ ERR("[META_WIFI] NVM_ProtectDataFile(): set failed\n");
+ ret = -1;
+ }
+ else
+ {
+ // invoke auto backup mechanism
+ NVM_AddBackupFileNum(AP_CFG_RDEB_FILE_WIFI_LID);
+ ret = 0;
+ }
+ }
+ else
+ {
+ ERR("[META_WIFI] open file :%s fail!, iFD=%d", gNvInfo.cFileName, iFD);
+ return -1;
+ }
+
+
+ }
+ else
+ {
+ /* post-check for read access */
+ DBG("[META_WIFI] read offset:%d (0x%04X)\n", pnvram->dataOffset, pnvram->dataOffset);
+
+ if (NVM_ProtectDataFile(AP_CFG_RDEB_FILE_WIFI_LID, 0) != 1)
+ {
+ ERR("[META_WIFI] NVM_ProtectDataFile(): get failed\n");
+ return -1;
+ }
+
+ iFD = open(gNvInfo.cFileName, O_RDONLY | O_CREAT, S_IRUSR | S_IRGRP);
+
+ if (iFD >= 0)
+ {
+ if (lseek(iFD, pnvram->dataOffset, SEEK_SET) < 0)
+ {
+ ERR("[META_WIFI] lseek fail!");
+ close(iFD);
+ return -1;
+ }
+
+ readByteLen = read(iFD, pnvram->data, pnvram->dataLen);
+
+ if (readByteLen <= 0)
+ {
+ ERR("[META_WIFI] read fail! ,readByteLen :%d", readByteLen);
+ close(iFD);
+ return -1;
+ }
+
+ close(iFD);
+
+ ret = readByteLen;
+ }
+ else
+ {
+ ERR("[META_WIFI] open file :%s fail!", gNvInfo.cFileName);
+ return -1;
+ }
+
+
+ }
+
+ return ret;
+}
+
+void wifwNVRAMWriteDataToDriver(void)
+{
+ char *pCmdNvram;
+ int ret = -1;
+ PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+ int readLen = -1;
+ int cmdLen = -1;
+ char *pBuf = NULL;
+
+ pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(gNvInfo.i4RecSize + sizeof(NVRAM_ACCESS_STRUCT));
+
+ if (!pQueryNv)
+ {
+ DBG("out of memory in allocating pQueryNv\n");
+ return ;
+ }
+
+ /*read NVRAM contant*/
+ pQueryNv->dataLen = gNvInfo.i4RecSize;
+ pQueryNv->dataOffset = 0; /*read NVRAM range[0~ dataLen]*/
+ readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+ pBuf = (char *)&pQueryNv->data[0];
+
+
+ /*Fill wmtWifi command buffer*/
+ cmdLen = gNvInfo.i4RecSize + 12;
+ pCmdNvram = (char *)malloc(cmdLen);
+
+ if (!pCmdNvram)
+ {
+ DBG("out of memory in allocating acnvram\n");
+ goto exit;
+ }
+
+ memset(pCmdNvram, 0, cmdLen);
+ strncpy(pCmdNvram, "WR-BUF:NVRAM", 12);
+ memcpy(pCmdNvram + 12, pBuf, gNvInfo.i4RecSize);
+
+ /*write cmd to wifi driver*/
+ ret = write_data_to_driver(pCmdNvram, cmdLen);
+
+ DBG("[META_WIFI] write NVRAM[%d] to driver done! ret =%d \n", readLen, ret);
+
+exit:
+ FREEIF(pCmdNvram);
+ FREEIF(pQueryNv);
+
+}
+
+/*
+* Control Wi-Fi power by RFKILL interface is deprecated.
+* Use character device to control instead.
+*/
+#if 0
+static int wifi_init_rfkill(void)
+{
+ char path[128];
+ char buf[32];
+ int fd, id;
+ ssize_t sz;
+
+ for (id = 0; id < 10 ; id++)
+ {
+ snprintf(path, sizeof(path), "/sys/class/rfkill/rfkill%d/type", id);
+ fd = open(path, O_RDONLY);
+
+ if (fd < 0)
+ {
+ printf("open(%s) failed: %s (%d)\n", path, strerror(errno), errno);
+ return -1;
+ }
+
+ sz = read(fd, &buf, sizeof(buf));
+ close(fd);
+
+ if (sz >= (ssize_t)strlen(WIFI_TYPE_NAME) &&
+ memcmp(buf, WIFI_TYPE_NAME, strlen(WIFI_TYPE_NAME)) == 0)
+ {
+ wifi_rfkill_id = id;
+ break;
+ }
+ }
+
+ if (id == 10)
+ return -1;
+
+ asprintf(&wifi_rfkill_state_path, "/sys/class/rfkill/rfkill%d/state",
+ wifi_rfkill_id);
+
+ return 0;
+}
+
+static int wifi_check_power(void)
+{
+ int sz;
+ int fd = -1;
+ int ret = -1;
+ char buf;
+ char *path = wifi_rfkill_state_path;
+
+ if ((wifi_rfkill_id == -1) && wifi_init_rfkill())
+ goto out;
+
+ fd = open(path, O_RDONLY);
+
+ if (fd < 0)
+ {
+ printf("open(%s) failed: %s (%d)", path, strerror(errno),
+ errno);
+ goto out;
+ }
+
+ sz = read(fd, &buf, 1);
+
+ if (sz != 1)
+ {
+ printf("read(%s) failed: %s (%d)", path, strerror(errno),
+ errno);
+ goto out;
+ }
+
+ switch (buf)
+ {
+ case '1':
+ ret = 1;
+ break;
+
+ case '0':
+ ret = 0;
+ break;
+ }
+
+out:
+
+ if (fd >= 0)
+ close(fd);
+
+ return ret;
+}
+
+static int wifi_set_power(int on)
+{
+ int sz;
+ int fd = -1;
+ int ret = -1;
+ const char buf = (on ? '1' : '0');
+
+ if (wifi_rfkill_id == -1)
+ {
+ if (wifi_init_rfkill()) goto out;
+ }
+
+ fd = open(wifi_rfkill_state_path, O_WRONLY);
+
+ if (fd < 0)
+ {
+ printf("open(%s) for write failed: %s (%d)", wifi_rfkill_state_path,
+ strerror(errno), errno);
+ goto out;
+ }
+
+ sz = write(fd, &buf, 1);
+
+ if (sz < 0)
+ {
+ printf("write(%s) failed: %s (%d)", wifi_rfkill_state_path, strerror(errno),
+ errno);
+ goto out;
+ }
+
+ ret = 0;
+
+out:
+
+ if (fd >= 0) close(fd);
+
+ return ret;
+}
+#else
+
+
+static int wifi_set_power(int on)
+{
+ int ret = -1;
+ const char buf = (on ? '1' : '0');
+
+ if (on)
+ wifwNVRAMWriteDataToDriver();
+
+ ret = write_data_to_driver((char *)&buf, sizeof(buf));
+
+ return ret;
+}
+#endif
+
+#if 0
+static int wifi_insmod(const char *filename, const char *args)
+{
+ void *module;
+ unsigned int size;
+ int ret;
+
+ module = load_file(filename, &size);
+
+ if (!module)
+ return -1;
+
+ ret = init_module(module, size, args);
+
+ free(module);
+
+ return ret;
+}
+
+static int wifi_rmmod(const char *modname)
+{
+ int ret = -1;
+ int maxtry = 10;
+
+ while (maxtry-- > 0)
+ {
+ ret = delete_module(modname, O_NONBLOCK | O_EXCL);
+
+ if (ret < 0 && errno == EAGAIN)
+ usleep(500000);
+ else
+ break;
+ }
+
+ if (ret != 0)
+ ERR("Unable to unload driver \"%s\": %s\n", modname, strerror(errno));
+
+ return ret;
+}
+
+static int wifi_is_loaded(void)
+{
+ FILE *proc;
+ char line[sizeof(DRIVER_MODULE_TAG) + 10];
+
+ if ((proc = fopen(MODULE_FILE, "r")) == NULL)
+ {
+ ERR("Could not open %s: %s", MODULE_FILE, strerror(errno));
+ return 0;
+ }
+
+ while ((fgets(line, sizeof(line), proc)) != NULL)
+ {
+ if (strncmp(line, DRIVER_MODULE_TAG, strlen(DRIVER_MODULE_TAG)) == 0)
+ {
+ fclose(proc);
+ return 1;
+ }
+ }
+
+ fclose(proc);
+ return 0;
+}
+#endif
+
+void removeSubstring(char *s, const char *toremove)
+{
+ while ((s = strstr(s, toremove)) != NULL)
+ memmove(s, s + strlen(toremove), 1 + strlen(s + strlen(toremove)));
+
+}
+/*----------------------------------------------------------------------------*/
+/**
+* @brief remove Script's head command, inclue: adb, shell, iwpriv,wlan0,driver
+*
+* @param[in] pStr, input string
+*
+* @return new command size
+*/
+/*----------------------------------------------------------------------------*/
+
+#define WIFI_REMOVE_HEAD_SIZE 5
+int wifiScriptRemoveHead(char *pStr)
+{
+ int strIndex = 0;
+ char *removeStrArray[WIFI_REMOVE_HEAD_SIZE] =
+ {
+ "adb ",
+ "shell ",
+ "iwpriv ",
+ "wlan0 ",
+ "driver ",
+ };
+
+ if (!pStr)
+ return FALSE;
+
+ for (strIndex = 0 ; strIndex < WIFI_REMOVE_HEAD_SIZE ; strIndex++)
+ {
+ if (strncmp(pStr, removeStrArray[strIndex], strlen(removeStrArray[strIndex])) == 0)
+ removeSubstring(pStr, removeStrArray[strIndex]);
+ }
+
+ return strlen(pStr);
+}
+
+WLAN_STATUS wifiNVRAMWirteByte(unsigned int offset, unsigned char value)
+{
+ PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+ pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(unsigned char));
+ if (!pSetNv)
+ {
+ DBG("out of memory in allocating pSetNv\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+ pSetNv->dataLen = sizeof(unsigned char);
+ pSetNv->dataOffset = offset;
+ memcpy(&pSetNv->data[0], &value, sizeof(value));
+ wifiNVRAMCtrl(NVRAM_WRITE, pSetNv);
+ FREEIF(pSetNv);
+
+ return META_WIFI_STATUS_SUCCESS;
+}
+
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+unsigned char wifiNVRAMGetSubChGroup(
+ ENUM_BAND_T eBand,
+ unsigned char u1CenterCh,
+ unsigned char u1ChGroupIdx,
+ ENUM_CH_SUB_GROUP_ITEM eChSubGroupItem
+)
+{
+ unsigned char u1Idx = 0;
+ unsigned char u1ChBand;
+ unsigned char u1SubGroupIdx = 0;
+ unsigned char u1GroupIdx = 0;
+ unsigned char u1BoundaryNum = 0;
+ P_CH_SUB_GROUP_CLASS prChSubGroup = NULL;
+
+ /* get channel band */
+ u1ChBand = (BAND_2G4 == eBand) ? (G_BAND) : (A_BAND);
+
+ /* get pointer of channel power offset sub-group table entry */
+ for (u1Idx = 0 ; u1Idx < CH_SUB_GROUP_CLASS_TBL_ITEM_NUM ; u1Idx++)
+ {
+ if (_arSubGroupTbl[u1Idx][u1ChBand].eGroupId == eChSubGroupItem)
+ {
+ prChSubGroup = &(_arSubGroupTbl[u1Idx][u1ChBand]);
+ break;
+ }
+ }
+
+ if (prChSubGroup == NULL)
+ {
+ DBG("Can't find Channel Sub Group mapping Band:%d,item:%d\n", eBand, eChSubGroupItem);
+ return META_WIFI_STATUS_INVALID_PARA;
+ }
+
+
+ /* get boundary number for each group */
+ u1BoundaryNum = prChSubGroup->u1ChSubGroupCategoryNum - 1;
+
+ /* search channel power offset sub-group index for specific channel */
+ for (u1GroupIdx = (u1ChGroupIdx * u1BoundaryNum); u1GroupIdx < ((u1ChGroupIdx + 1) * u1BoundaryNum); u1GroupIdx++)
+ {
+ /* increment channel group index when exceed channel group boundary */
+ if (u1CenterCh > prChSubGroup->u1ChSubGroupBoundary[u1GroupIdx])
+ u1SubGroupIdx++;
+ }
+
+ /* special case (channel number not in order) handler for 5G band channel group 0 */
+ if ((0 == u1ChGroupIdx) && (BAND_5G == eBand))
+ {
+ /* cyclic left shift sub-group index by Non-ordered subgroup number */
+ u1SubGroupIdx += prChSubGroup->u1ChSubGroupNotOrderedNum;
+ u1SubGroupIdx %= prChSubGroup->u1ChSubGroupCategoryNum;
+ }
+
+ return u1SubGroupIdx;
+}
+unsigned char wifiNVRAMGetChGroup(ENUM_BAND_T eBand, unsigned char u1CenterCh, ENUM_CH_GROUP_ITEM eChGroupItem)
+{
+ unsigned char u1Idx;
+ unsigned char u1ChGroupIdx = 0;
+ unsigned char u1GroupIdx = 0;
+ P_CH_GROUP_CLASS prChGroup = NULL;
+ unsigned char u1ChBand;
+
+ /* get channel band */
+ u1ChBand = (BAND_2G4 == eBand) ? (G_BAND) : (A_BAND);
+
+ /* search Channel group class table entry */
+ for (u1Idx = 0 ; u1Idx < CH_GROUP_CLASS_TBL_ITEM_NUM ; u1Idx++)
+ {
+ if (_arChGroupTbl[u1Idx][u1ChBand].eGroupId == eChGroupItem)
+ {
+ prChGroup = &(_arChGroupTbl[u1Idx][u1ChBand]);
+ break;
+ }
+ }
+
+ if (prChGroup == NULL)
+ {
+ DBG("Can't find Channel Group mapping Band:%d,item:%d\n", eBand, eChGroupItem);
+ return META_WIFI_STATUS_INVALID_PARA;
+ }
+
+ /* search class index for specific channel */
+ for (u1GroupIdx = 0; u1GroupIdx < prChGroup->u1ChGroupSupportNum; u1GroupIdx++)
+ {
+ /* increment channel group index when exceed channel group boundary */
+ if (u1CenterCh > prChGroup->u1ChGroupBoundary[u1GroupIdx])
+ u1ChGroupIdx++;
+ }
+
+ /* cyclic channel group process for high channel number in group 0 */
+ if (prChGroup->u1ChGroupSupportNum != 1)
+ u1ChGroupIdx %= prChGroup->u1ChGroupSupportNum;
+
+ DBG("GetCh:%d ,ID:%d ,Group Idx:%d\n", u1CenterCh, eChGroupItem, u1ChGroupIdx);
+
+ return u1ChGroupIdx;
+
+
+}
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+/*Thrshold bound is defined */
+unsigned char wifiNVRAMTssiChGainTableSelect(int pwr)
+{
+ unsigned char table_ofs = 0;
+
+ if (pwr >= TSSI_CH_OFFSET_TH_GT7)
+ table_ofs = NVRAM_GT7_OFFSET;
+ else if ((TSSI_CH_OFFSET_TH_GT7 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT6))
+ table_ofs = NVRAM_GT6_OFFSET;
+ else if ((TSSI_CH_OFFSET_TH_GT6 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT5))
+ table_ofs = NVRAM_GT5_OFFSET;
+ else if ((TSSI_CH_OFFSET_TH_GT5 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT4))
+ table_ofs = NVRAM_GT4_OFFSET;
+ else if ((TSSI_CH_OFFSET_TH_GT4 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT3))
+ table_ofs = NVRAM_GT3_OFFSET;
+ else if ((TSSI_CH_OFFSET_TH_GT3 > pwr) && (pwr >= TSSI_CH_OFFSET_TH_GT2))
+ table_ofs = NVRAM_GT2_OFFSET;
+ else
+ DBG("out of Gain Table thrshold :%d\n", pwr);
+
+ /* Low Bound <= pwr < Upper Bound*/
+ DBG("GT7[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT7, 127);
+ DBG("GT6[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT6, TSSI_CH_OFFSET_TH_GT7);
+ DBG("GT5[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT5, TSSI_CH_OFFSET_TH_GT6);
+ DBG("GT4[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT4, TSSI_CH_OFFSET_TH_GT5);
+ DBG("GT3[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT3, TSSI_CH_OFFSET_TH_GT4);
+ DBG("GT2[%d ~ %d]\n", TSSI_CH_OFFSET_TH_GT2, TSSI_CH_OFFSET_TH_GT3);
+ DBG("Pwr:%d is filled in GT%d\n", pwr, (table_ofs + 2));
+
+ return table_ofs;
+}
+#endif
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+WLAN_STATUS wifiNVRAMTssiChGainTableAllTheSame(unsigned int nvOfs, unsigned char value)
+{
+ unsigned int gtOfsArray[TSSI_CH_OFS_GT_NUM] = {NVRAM_GT2_OFFSET, NVRAM_GT3_OFFSET,
+ NVRAM_GT4_OFFSET, NVRAM_GT5_OFFSET, NVRAM_GT6_OFFSET, NVRAM_GT7_OFFSET
+ };
+ int idx = 0;
+
+ unsigned int gtNvOfs = 0;
+
+ for (idx = 0 ; idx < TSSI_CH_OFS_GT_NUM ; idx++)
+ {
+ gtNvOfs = nvOfs + gtOfsArray[idx];
+ wifiNVRAMWirteByte(gtNvOfs, value);
+ DBG("GT%d [0x%x]=0x%x\n", (idx + 2), gtNvOfs, value);
+ }
+
+ return META_WIFI_STATUS_SUCCESS;
+}
+#endif
+
+unsigned int wifiNVRAMTssiChGetNVRAMOfs(unsigned int wf,
+ ENUM_BAND_T eBand, unsigned int ch, unsigned int *pOfs)
+{
+
+ unsigned int u4NvramOffset = 0;
+
+ unsigned char groupId = wifiNVRAMGetChGroup(eBand, ch, CH_GROUP_ITEM_TSSI_CH);
+ unsigned char subGroupId = wifiNVRAMGetSubChGroup(eBand, ch, groupId, CH_SUB_GROUP_TSSI_CH);
+
+ if (ch <= 0)
+ {
+ DBG("Tssi Ch error:%d\n", ch);
+ return META_WIFI_STATUS_INVALID_PARA;
+ }
+
+ if (wf >= WF_NUM)
+ {
+ DBG("Tssi wf error:%d\n", wf);
+ return META_WIFI_STATUS_INVALID_PARA;
+ }
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+
+ if (eBand == BAND_2G4)
+ {
+ u4NvramOffset = (wf == WF0) ? (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+ u4NvramOffset += sizeof(WIFI_NVRAM_TSSI_CH_OFS_T) * groupId;
+
+ }
+ else
+ {
+ u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+ u4NvramOffset += (groupId * (CH_SUB_GROUP_5G_ITEM_NUM) + subGroupId) * sizeof(WIFI_NVRAM_TSSI_CH_OFS_T);
+ }
+
+#else
+
+ if (eBand == BAND_2G4)
+ {
+ u4NvramOffset = (wf == WF0) ? (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+ u4NvramOffset += sizeof(UINT_8) * groupId;
+
+ }
+ else
+ {
+ u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+ u4NvramOffset += (groupId * (CH_SUB_GROUP_5G_ITEM_NUM) + subGroupId) * sizeof(UINT_8);
+ }
+
+#endif
+ *pOfs = u4NvramOffset;
+
+ return META_WIFI_STATUS_SUCCESS;
+
+}
+WLAN_STATUS wifiNVRAMTssiChOfsRfGroupTheSame(unsigned int wf, ENUM_BAND_T eBand,
+ unsigned int ch, unsigned int chGroup, char nvCompVal)
+{
+
+ unsigned char rfGroup = 0, subGroup = 0;
+ unsigned int u4NvramOffset = 0;
+ unsigned int chInter = 0;
+
+ if (eBand != BAND_5G)
+ {
+ DBG("only Support 5G Channel\n");
+ return META_WIFI_STATUS_INVALID_PARA;
+ }
+
+ rfGroup = GET_A_BAND_RF_GROUP(chGroup);
+ subGroup = wifiNVRAMGetSubChGroup(eBand, ch, chGroup, CH_SUB_GROUP_TSSI_CH);
+
+ DBG("group the same: ch[%d],tssiChGroup=%d,subGroup=%d,RfGroup=%d,nvCompVal=0x%02X\n",
+ ch, chGroup, subGroup, rfGroup, nvCompVal);
+
+ /*update (n) ~ (n+3) Tssi ch group in one RF Group*/
+ for (chInter = (rfGroup * PER_CH_GROUP_IN_RF_GROUP) ; chInter < ((rfGroup * PER_CH_GROUP_IN_RF_GROUP) + PER_CH_GROUP_IN_RF_GROUP); chInter++)
+ {
+ u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+ u4NvramOffset += (chInter * sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+#else
+ u4NvramOffset += (chInter * sizeof(UINT_8));
+#endif
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ DBG("update TssiChGroup[%d][%c],NvOfs=0x%08X,NvVal=0x%02X\n",
+ chInter / 2,
+ ((chInter % 2) == 0) ? ('L') : ('H'),
+ u4NvramOffset,
+ nvCompVal);
+
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+ u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+#endif
+ wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+ DBG("update TssiChGroup[%d][%c] nvOfs=0x%X,nvCompVal=0x%02X\n",
+ chInter / 2,
+ ((chInter % 2) == 0) ? ('L') : ('H'),
+ u4NvramOffset,
+ nvCompVal);
+#endif
+ }
+
+ return META_WIFI_STATUS_SUCCESS;
+
+}
+
+
+/*clear tssi channel offset*/
+WLAN_STATUS wifiNVRAMTssiChOfsClear(void)
+{
+ NVRAM_ACCESS_STRUCT raNvram[] =
+ {
+ /*2.4G WF0 Tssi Ch*/
+ {NVRAM_G_BAND_TSSI_CH_OFS_SIZE, NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0, {0}},
+ /*2.4G WF1 Tssi Ch*/
+ {NVRAM_G_BAND_TSSI_CH_OFS_SIZE, NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1, {0}},
+ /*5G WF0 Tssi Ch*/
+ {NVRAM_A_BAND_TSSI_CH_OFS_SIZE, NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0, {0}},
+ /*5G WF1 Tssi Ch*/
+ {NVRAM_A_BAND_TSSI_CH_OFS_SIZE, NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1, {0}},
+
+ };
+ PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+ char *pBuf = NULL;
+
+#if 0
+ int readLen = 0, j = 0;
+#endif
+ int i = 0;
+
+ pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+ if (pQueryNv == NULL)
+ {
+ ERR("[META_WIFI] No memory nvram\n");
+ goto error;
+ }
+
+ for (i = 0 ; i < (sizeof(raNvram) / sizeof(NVRAM_ACCESS_STRUCT)) ; i++)
+ {
+ pQueryNv->dataLen = raNvram[i].dataLen;
+ pQueryNv->dataOffset = raNvram[i].dataOffset;
+ pBuf = (char *)&pQueryNv->data[0];
+#if 0
+ /*read before clean*/
+ readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+ DBG("[META_WIFI] 1st read len= %d\n", readLen);
+
+ for (j = 0; j < readLen; j++)
+ DBG("[META_WIFI] NVofs(0x%08X)[%p] = 0x%02X\n", (pQueryNv->dataOffset + j), (pBuf + j), *(pBuf + j));
+
+#endif
+ /*clear NVRAM content*/
+ memset(pBuf, 0, MAX_NVRAM_ACCESS_SIZE);
+ wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+#if 0
+ /*read again*/
+ readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+ DBG("[META_WIFI] 2st read len= %d\n", readLen);
+
+ for (j = 0; j < readLen; j++)
+ DBG("[META_WIFI] NVofs(0x%08X)[%p] = 0x%02X\n", (pQueryNv->dataOffset + j), (pBuf + j), *(pBuf + j));
+
+#endif
+ }
+
+ DBG("Finish!\n");
+error:
+ FREEIF(pQueryNv);
+
+ return META_WIFI_STATUS_SUCCESS;
+
+}
+
+WLAN_STATUS wifiNVRAMTssiContentDumpToPC(ENUM_BAND_T eBand, P_CMD_PL_CAL pCmdPLcal, WLAN_STATUS kResult)
+{
+
+ PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+ int readLen = 0, buffIdx = 0;
+
+ pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(PNVRAM_ACCESS_STRUCT));
+
+ if (!pQueryNv)
+ {
+ DBG("out of memory in allocating pQueryNv\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+ memset(pQueryNv, 0, sizeof(PNVRAM_ACCESS_STRUCT));
+
+ /*debug flow:add response data to PC*/
+ pCmdPLcal->au4Buffer[buffIdx++] = kResult;
+
+ if (eBand == BAND_2G4)
+ {
+ pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_G_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+
+ /*read 2.4G WF0 TSSI CH OFS*/
+ pQueryNv->dataLen = NVRAM_G_BAND_TSSI_CH_OFS_SIZE;
+ pQueryNv->dataOffset = NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+ readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+ memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+ buffIdx += readLen / sizeof(unsigned int);
+
+ /*clear buffer*/
+ memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+ pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_G_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+ /*read 2.4G WF1 TSSI CH OFS*/
+ pQueryNv->dataLen = NVRAM_G_BAND_TSSI_CH_OFS_SIZE;
+ pQueryNv->dataOffset = NVRAM_G_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+ readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+ memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+ buffIdx += readLen / sizeof(unsigned int);
+
+ memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+ /*update data length*/
+ pCmdPLcal->inputLen = buffIdx;
+
+ }
+ else
+ {
+ pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_A_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+
+ /*read 5G WF0 TSSI CH OFS*/
+ pQueryNv->dataLen = NVRAM_A_BAND_TSSI_CH_OFS_SIZE;
+ pQueryNv->dataOffset = NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0;
+ readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+ memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+ buffIdx += readLen / sizeof(unsigned int);
+
+ memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+ pCmdPLcal->au4Buffer[buffIdx++] = (NVRAM_A_BAND_TSSI_CH_OFS_SIZE << 16) | NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+ /*read 5G WF1 TSSI CH OFS*/
+ pQueryNv->dataLen = NVRAM_A_BAND_TSSI_CH_OFS_SIZE;
+ pQueryNv->dataOffset = NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1;
+
+ readLen = wifiNVRAMCtrl(NVRAM_READ, pQueryNv);
+ memcpy(&pCmdPLcal->au4Buffer[buffIdx], &pQueryNv->data[0], readLen);
+ buffIdx += readLen / sizeof(unsigned int);
+
+ memset(pQueryNv, 0, MAX_NVRAM_ACCESS_SIZE);
+
+ /*update data length*/
+ pCmdPLcal->inputLen = buffIdx;
+
+ }
+
+ FREEIF(pQueryNv);
+ DBG("Band[%d] Calibration Result:%d dump done!\n", eBand, kResult);
+
+ return kResult;
+}
+
+#if (WIFI_GEN_VER != CONNAC_SOC3_0)
+unsigned int wifiNVRAMCalculateShift()
+{
+ unsigned int ret = 7;
+ UINT_8 tssiStep;
+ unsigned int readLine = 0;
+ PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+
+ /* read from NVram calculateShift */
+ pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(UINT_8));
+
+ if (!pSetNv)
+ {
+ DBG("out of memory in allocating pSetNv\n");
+ return ret;
+ }
+
+ pSetNv->dataLen = sizeof(UINT_8);
+ pSetNv->dataOffset = NVRAM_TSSI_STEP_OFSET;
+ readLine = wifiNVRAMCtrl(NVRAM_READ, pSetNv);
+ memcpy(&tssiStep, &pSetNv->data[0], sizeof(UINT_8));
+
+ DBG("calculate Shift tssiStep=[0x%X] readLen=%d\n", tssiStep, readLine);
+
+ switch (tssiStep)
+ {
+ case 0x83:
+ /* precision 0.125 translate q-format from .8 to .3 */
+ ret = 5;
+ break;
+
+ case 0x82:
+ /* precision 0.25 translate q-format from .8 to .2 */
+ ret = 6;
+ break;
+ case 0x81:
+ case 0x80:
+ default:
+ /* precision 0.5 translate q-format from .8 to .1 */
+ ret = 7;
+ }
+
+ FREEIF(pSetNv);
+ return ret;
+
+}
+#endif
+
+WLAN_STATUS wifiNVRAMTssiChOfsAdjust(unsigned int wf, ENUM_BAND_T eBand, unsigned int ch, unsigned int targetPwr, unsigned int MeanPwr)
+{
+
+ unsigned int u4NvramOffset = 0;
+ unsigned char GTofs = 0;
+ char tssiChofsValue = 0;
+ unsigned int shift = 5;
+
+ if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, ch, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("Get Ch offset fial!\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+ /*decided to gain table compensation offset*/
+ GTofs = wifiNVRAMTssiChGainTableSelect(targetPwr);
+#else
+ shift = wifiNVRAMCalculateShift();
+#endif
+
+ /*decided to tssi channel offset compensation*/
+ /*TODO*/
+ /*targetpwr = 8 bit format ,2's complement*/
+ /*MeanPwr = s23.8 format*/
+ /*tssiChofsValue format = s4.3,nvram use 2's complement firmware will covert 20 s4.3*/
+
+ tssiChofsValue = (((targetPwr << 7) - MeanPwr) >> shift) & 0xFF;
+ DBG("TargetPwr:0x%08X (%6.1fdBm), MeaPwr:0x%08X(%6.8fdBm),tssiChofsValue=0x%02X\n",
+ targetPwr,
+ ((float)targetPwr) / (2.0),
+ MeanPwr,
+ ((float)MeanPwr / (256.0)),
+ tssiChofsValue);
+
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ DBG("Tssi ch wf[%d]Band[%d]Ch[%d] GT the same\n"
+ , wf
+ , eBand
+ , ch);
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, tssiChofsValue);
+#else
+ u4NvramOffset += GTofs;
+
+ wifiNVRAMWirteByte(u4NvramOffset, tssiChofsValue);
+
+ DBG("Tssi ch wf[%d]Band[%d]Ch[%d]GT[%d] ofs:0x%08X = 0x%x\n"
+ , wf
+ , eBand
+ , ch
+ , (GTofs + 2)
+ , u4NvramOffset
+ , tssiChofsValue);
+#endif
+
+
+
+ return META_WIFI_STATUS_SUCCESS;
+}
+
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+
+WLAN_STATUS wifiNVRAMTssiChOfsInterpolation(TX_PWR_INTERPOLATION_TYPE type,
+ ENUM_BAND_T eBand, unsigned int chNum, unsigned int *pchArray)
+{
+
+ int wf = WF0;
+ unsigned int u4NvramOffset;
+ unsigned int chIdx = 0, rfIdx = 0;
+ int ch0 = 0, ch1 = 0, chInter = 0;
+ unsigned int readLine = 0;
+ int devStep = 0;
+ char nvCompVal = 0;
+ WIFI_NVRAM_TSSI_CH_OFS_T rNvVal[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+ PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+ int chOfs0 = 0, chOfs1 = 0;
+ unsigned char chGroup[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+ unsigned char rfGroup = 0;
+ INTER_ACT interAct = INTER_ACT_NOT_SUPPORT;
+ INTERPOLATION_CH_BOUND_A_BAND rfInterList[NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM] =
+ {
+ {0xFF, 0}, //RF Group 0, not support 5G Interpolation
+ {36, 48}, //RF Group 1
+ {52, 64}, //RF Group 2
+ {0xFF, 0}, //RF Group 3, not support 5G Interpolation
+ {100, 112}, //RF Group 4
+ {116, 128}, //RF Group 5
+ {132, 144}, //RF Group 6
+ {149, 165}, //RF Group 7
+ };
+
+
+
+ /*init */
+ pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+ DBG("Band[%d] chNum[%d] Type[%d] Enter\n", eBand, chNum, type);
+ memset(&rNvVal[0], 0, sizeof(WIFI_NVRAM_TSSI_CH_OFS_T) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+ memset(&chGroup[0], 0, sizeof(unsigned char) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+
+ for (wf = WF0; wf < WF_NUM; wf++)
+ {
+
+ //read GT table by channel range
+ for (chIdx = 0; chIdx < chNum; chIdx++)
+ {
+ ch0 = pchArray[chIdx];
+ chGroup[chIdx] = wifiNVRAMGetChGroup(eBand, ch0, CH_GROUP_ITEM_TSSI_CH);
+
+ if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, ch0, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("Get Ch offset fial!\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+
+ pSetNv->dataLen = sizeof(WIFI_NVRAM_TSSI_CH_OFS_T);
+ pSetNv->dataOffset = u4NvramOffset;
+ readLine = wifiNVRAMCtrl(NVRAM_READ, pSetNv);
+ memcpy(&rNvVal[chIdx], &pSetNv->data[0], sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+ DBG("Read WF[%d]chIdx[%d] = %d,Group=%d,GT=[0x%X,0x%X,0x%X,0x%X,0x%X,0x%X] readLen=%d\n",
+ wf,
+ chIdx,
+ ch0,
+ chGroup[chIdx],
+ rNvVal[chIdx].ucTssiChOfsGT2,
+ rNvVal[chIdx].ucTssiChOfsGT3,
+ rNvVal[chIdx].ucTssiChOfsGT4,
+ rNvVal[chIdx].ucTssiChOfsGT5,
+ rNvVal[chIdx].ucTssiChOfsGT6,
+ rNvVal[chIdx].ucTssiChOfsGT7,
+ readLine);
+ }
+
+
+
+ /*only 2.4G support interpolation -- start*/
+ if ((type == TYPE_INTERPOLATION) && (eBand == BAND_2G4))
+ {
+ //calcaute each step ch=0 ~ pchArray(chNum-1)
+ for (chIdx = 0; chIdx < chNum - 1; chIdx++)
+ {
+
+ ch0 = pchArray[chIdx];
+ chOfs0 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx].ucTssiChOfsGT7, 8);
+
+
+ ch1 = pchArray[(chIdx + 1)];
+ chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)].ucTssiChOfsGT7, 8);
+
+ for (chInter = ch0 + 1 ; chInter < ch1; chInter++)
+ {
+ u4NvramOffset = 0;
+
+ if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset)
+ != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("Get Ch offset fial!\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+
+ devStep = ((chOfs1 - chOfs0) * (chInter - ch0)) / (ch1 - ch0);
+
+ DBG("Interpolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+ ch0, ch1, chOfs0, chOfs1, chInter, devStep);
+
+ nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+ u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+ wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+ DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+ chInter, u4NvramOffset, nvCompVal);
+#endif
+ }
+ }
+
+ //calcaute each step pchArray(n+1) ~ ch=14
+ for (chInter = ch1 + 1 ; chInter <= 14; chInter++)
+ {
+ u4NvramOffset = 0;
+
+ if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("Get Ch offset fial!\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+
+ devStep = ((chOfs1 - chOfs0) * (chInter - ch1)) / (ch1 - ch0);
+
+ DBG("Extrapolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+ ch1 + 1, 14, chOfs0, chOfs1, chInter, devStep);
+ nvCompVal = chOfs0 + (chInter - ch0) * devStep;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+ u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+ wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+ DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+ chInter, u4NvramOffset, nvCompVal);
+#endif
+
+ }
+ }
+ else if ((type == TYPE_GROUP_THE_SAME) && (eBand == BAND_5G))
+ {
+ /* "group the same" means using meanuse tx power value to apply tssi ch ofs group
+ * in RF defined group
+ */
+ //calcaute each step ch=0 ~ pchArray(chNum)
+ for (chIdx = 0; chIdx < chNum ; chIdx++)
+ {
+ nvCompVal = rNvVal[chIdx].ucTssiChOfsGT7;
+ wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+ }
+ }
+ else if ((type == TYPE_INTERPOLATION) && (eBand == BAND_5G))
+ {
+ //calcaute each step ch=0 ~ pchArray(chNum-1)
+ for (chIdx = 0; chIdx < chNum; chIdx++)
+ {
+ interAct = INTER_ACT_NOT_SUPPORT;
+
+ //Check 5G interpolation support RF group channel bound
+ for (rfIdx = 0; rfIdx < NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM; rfIdx++)
+ {
+ DBG("ch=%d Check RFGroup[%d] bound[%d ~ %d]\n",
+ pchArray[chIdx],
+ rfIdx,
+ rfInterList[rfIdx].lowBoundCh,
+ rfInterList[rfIdx].upperBoundCh);
+
+ //if chIdx = low bound and chIdx+1 = upper bound
+ if (pchArray[chIdx] == rfInterList[rfIdx].lowBoundCh)
+ {
+ if ((chIdx < (chNum - 1)) &&
+ pchArray[chIdx + 1] == rfInterList[rfIdx].upperBoundCh)
+ {
+ interAct = INTER_ACT_INTERPOLATION;
+
+ rfGroup = GET_A_BAND_RF_GROUP(chGroup[chIdx]);
+
+ ch0 = pchArray[chIdx];
+ ch1 = pchArray[(chIdx + 1)];
+
+ chOfs0 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx].ucTssiChOfsGT7, 8);
+ chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)].ucTssiChOfsGT7, 8);
+
+ DBG("5G do Interpolation WF[%d] RF[%d] ch[%d ~ %d] Rang[%d ~ %d]\n",
+ wf,
+ rfGroup,
+ ch0,
+ ch1,
+ chOfs0,
+ chOfs1);
+
+ //Query the next RF group
+ chIdx++;
+ break;
+ }
+ else
+ {
+ interAct = INTER_ACT_GROUP_THE_SAME;
+ break;
+ }
+ }
+ else if ((pchArray[chIdx] > rfInterList[rfIdx].lowBoundCh) &&
+ (pchArray[chIdx] < rfInterList[rfIdx].upperBoundCh))
+ {
+ interAct = INTER_ACT_GROUP_THE_SAME;
+ break;
+ }
+ else
+ interAct = INTER_ACT_GROUP_THE_SAME;
+
+ }
+
+ if (interAct == INTER_ACT_GROUP_THE_SAME)
+ {
+ nvCompVal = rNvVal[chIdx].ucTssiChOfsGT7;
+ wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+ }
+ else if (interAct == INTER_ACT_INTERPOLATION)
+ {
+
+ /*update (n) ~ (n+3) Tssi ch group in one RF Group*/
+ for (chInter = (rfGroup * PER_CH_GROUP_IN_RF_GROUP) ; chInter < ((rfGroup * PER_CH_GROUP_IN_RF_GROUP) + PER_CH_GROUP_IN_RF_GROUP); chInter++)
+ {
+ u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+ u4NvramOffset += (chInter * sizeof(WIFI_NVRAM_TSSI_CH_OFS_T));
+
+ devStep = ((chOfs1 - chOfs0) * (chInter - (rfGroup * PER_CH_GROUP_IN_RF_GROUP))) / (PER_CH_GROUP_IN_RF_GROUP - 1);
+
+ nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+ DBG("Interpolation:TssiChGroup[%d][%c] + devStep=%d,NvOfs=0x%08X,NvVal=0x%02X\n",
+ chInter / 2,
+ ((chInter % 2) == 0) ? ('L') : ('H'),
+ devStep,
+ u4NvramOffset,
+ nvCompVal);
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+ u4NvramOffset += OFFSET_OF(WIFI_NVRAM_TSSI_CH_OFS_T, ucTssiChOfsGT7);
+
+ wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+#endif
+
+ }
+
+ }
+ else
+ DBG("Not Support ch[%d]!\n", pchArray[chIdx + 1]);
+
+ }
+ }
+ }
+
+ FREEIF(pSetNv);
+
+ return META_WIFI_STATUS_SUCCESS;
+}
+
+
+WLAN_STATUS wifiNVRAMTssiNDLOfsClear(void)
+{
+#if (CFG_DNL_CAL == 1)
+ NVRAM_ACCESS_STRUCT raNvram[] =
+ {
+ /*2.4G WF0 Tssi DNL*/
+ {NVRAM_G_BAND_TSSI_DNL_OFS_SIZE, NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF0, {0}},
+ /*2.4G WF1 Tssi DNL*/
+ {NVRAM_G_BAND_TSSI_DNL_OFS_SIZE, NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF1, {0}},
+ /*5G WF0 Tssi DNL*/
+ {NVRAM_A_BAND_TSSI_DNL_OFS_SIZE, NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF0, {0}},
+ /*5G WF1 Tssi DNL*/
+ {NVRAM_A_BAND_TSSI_DNL_OFS_SIZE, NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF1, {0}},
+
+ };
+ PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+ char *pBuf = NULL;
+ int i = 0;
+
+ pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+ if (pQueryNv == NULL)
+ {
+ ERR("[META_WIFI] No memory nvram\n");
+ goto error;
+ }
+
+ for (i = 0 ; i < (sizeof(raNvram) / sizeof(NVRAM_ACCESS_STRUCT)) ; i++)
+ {
+ pQueryNv->dataLen = raNvram[i].dataLen;
+ pQueryNv->dataOffset = raNvram[i].dataOffset;
+ pBuf = (char *)&pQueryNv->data[0];
+
+ /*clear NVRAM content*/
+ memset(pBuf, 0, MAX_NVRAM_ACCESS_SIZE);
+ wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+ }
+
+ DBG("Finish!\n");
+error:
+ FREEIF(pQueryNv);
+#endif
+ return META_WIFI_STATUS_SUCCESS;
+
+}
+
+WLAN_STATUS wifiNVRAMTssiDnlOfsAdjust(unsigned int dbdcbandIdx,
+ ENUM_BAND_T eBand, unsigned char inputCh)
+{
+ WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+
+#if (CFG_DNL_CAL == 1)
+ unsigned char chGroup = 0;
+ unsigned int data_cnt = 0;
+ char crOfsetIdx = 0;
+ char chIdx = 0;
+ int i = 0;
+ RECAL_INFO_T rReCalInfo;
+ WIFI_NVRAM_TX_DNL_T rDnl;
+
+ unsigned int nvramOfs = 0;
+ PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+
+ pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+ memset(&rReCalInfo, 0, sizeof(RECAL_INFO_T));
+
+ //get ch group
+ chGroup = wifiNVRAMGetChGroup(eBand, inputCh, CH_GROUP_ITEM_COMMON);
+
+ DBG("DbdcIdx=%d,Band=%d,ch=%d,Group=%d\n", dbdcbandIdx, eBand, inputCh, chGroup);
+
+ for (i = 0 ; i < QUERY_RECAL_RETRY_CNT ; i++)
+ {
+
+ //set NDL CAL by HQA CMD
+ if (wifiHqaDoCalibrationTestItem(HQA_CAL_ITEM_DNL, dbdcbandIdx) != META_WIFI_STATUS_SUCCESS)
+ DBG("Cal test item fail!\n");
+
+
+ //query NDL CAL RESULT
+ if (wifiHqaGetDumpReCal(HQA_CAL_ITEM_DNL, dbdcbandIdx, &rReCalInfo) != META_WIFI_STATUS_SUCCESS)
+ DBG("Cal query item fail!\n");
+
+
+ data_cnt = rReCalInfo.u4Count;
+
+ if (data_cnt != (DNL_WF_PATH_CR_NUM * WF_NUM))
+ {
+ DBG("Result Num dismatch!,Expect:%d Total:%d do-try(%d)!\n",
+ (DNL_WF_PATH_CR_NUM * WF_NUM),
+ data_cnt, i);
+ continue;
+ }
+ else
+ break;
+ }
+
+ if (data_cnt != (DNL_WF_PATH_CR_NUM * WF_NUM))
+ {
+ DBG("Over retry(%d)! DNL Cal Result Fail\n", QUERY_RECAL_RETRY_CNT);
+ ret = META_WIFI_STATUS_FAIL;
+ goto error;
+ }
+
+
+
+ for (i = 0 ; i < data_cnt ; i++)
+ {
+ DBG("(%d)ID=0x%X,Addr=0x%X,Val=0x%X\n", i, rReCalInfo.u4CalId[i], rReCalInfo.u4CalAddr[i], rReCalInfo.u4CalValue[i]);
+ }
+
+ for (i = 0; i < WF_NUM; i++)
+ {
+
+ crOfsetIdx = DNL_WF_PATH_CR_NUM * i;
+ memset(&rDnl, 0, sizeof(WIFI_NVRAM_TX_DNL_T));
+
+ rDnl.ucTxDnlCckGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT0 = (rReCalInfo.u4CalValue[crOfsetIdx + 1] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+ rDnl.ucTxDnlCckGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 2] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT1 = (rReCalInfo.u4CalValue[crOfsetIdx + 3] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+ rDnl.ucTxDnlCckGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 4] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT2 = (rReCalInfo.u4CalValue[crOfsetIdx + 5] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+ rDnl.ucTxDnlCckGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 6] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT3 = (rReCalInfo.u4CalValue[crOfsetIdx + 7] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+ rDnl.ucTxDnlCckGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 8] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT4 = (rReCalInfo.u4CalValue[crOfsetIdx + 9] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+ rDnl.ucTxDnlCckGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 10] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT5 = (rReCalInfo.u4CalValue[crOfsetIdx + 11] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+ rDnl.ucTxDnlCckGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 12] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT6 = (rReCalInfo.u4CalValue[crOfsetIdx + 13] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+ rDnl.ucTxDnlCckGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS0_MASK) >> NDL_OFFSET_BIAS0_SHFT;
+ rDnl.ucTxDnlLowGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS1_MASK) >> NDL_OFFSET_BIAS1_SHFT;
+ rDnl.ucTxDnlMidGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS2_MASK) >> NDL_OFFSET_BIAS2_SHFT;
+ rDnl.ucTxDnlHighGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 14] & NDL_OFFSET_BIAS3_MASK) >> NDL_OFFSET_BIAS3_SHFT;
+ rDnl.ucTxDnlUltraGT7 = (rReCalInfo.u4CalValue[crOfsetIdx + 15] & NDL_OFFSET_BIAS4_MASK) >> NDL_OFFSET_BIAS4_SHFT;
+
+
+ if (eBand == BAND_2G4)
+ {
+ //2.4G channel all the same DNL value;
+ for (chIdx = 0 ; chIdx < 14 ; chIdx++)
+ {
+ nvramOfs = (i == WF0) ? (NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_TSSI_DNL_OFS_OFSETOF_WF1);
+ //get nvram by ch group offset
+ nvramOfs += sizeof(WIFI_NVRAM_TX_DNL_T) * chIdx;
+ memset(pQueryNv, 0, sizeof(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE));
+
+ pQueryNv->dataLen = sizeof(WIFI_NVRAM_TX_DNL_T);
+ pQueryNv->dataOffset = nvramOfs;
+ memcpy(&pQueryNv->data[0], &rDnl, sizeof(WIFI_NVRAM_TX_DNL_T));
+ wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+ DBG("WF%d update B[%d] Ch=%d nvramOfs=0x%08X done!\n", i, eBand, chIdx, nvramOfs);
+ }
+ }
+ else
+ {
+ //get 5G DNL offset
+ nvramOfs = (i == WF0) ? (NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_DNL_OFS_OFSETOF_WF1);
+
+ //get nvram by ch group offset
+ nvramOfs += sizeof(WIFI_NVRAM_TX_DNL_T) * chGroup;
+ memset(pQueryNv, 0, sizeof(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE));
+
+ pQueryNv->dataLen = sizeof(WIFI_NVRAM_TX_DNL_T);
+ pQueryNv->dataOffset = nvramOfs;
+ memcpy(&pQueryNv->data[0], &rDnl, sizeof(WIFI_NVRAM_TX_DNL_T));
+ wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+ DBG("WF%d update B[%d] Ch=%d Group =%d nvramOfs=0x%08X done!\n", i, eBand, inputCh, chGroup, nvramOfs);
+
+ }
+
+
+ }
+
+ ret = META_WIFI_STATUS_SUCCESS;
+
+ DBG("DNL Adjust success!\n");
+error:
+ FREEIF(pQueryNv);
+
+#else
+ DBG("[WARNING] Adjust not-support!\n");
+#endif
+
+ return ret;
+}
+
+
+/*LNA(Rssi) Gain Calibration clear*/
+WLAN_STATUS wifiNVRAMLnaGainCalClear(void)
+{
+ NVRAM_ACCESS_STRUCT raNvram[] =
+ {
+ /*2.4G WF0 LNA(Rssi) Gain Calibration*/
+ {NVRAM_G_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0, {0}},
+ /*2.4G WF1 LNA(Rssi) Gain Calibration*/
+ {NVRAM_G_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1, {0}},
+ /*5G WF0 LNA(Rssi) Gain Calibration*/
+ {NVRAM_A_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0, {0}},
+ /*5G WF1 LNA(Rssi) Gain Calibration*/
+ {NVRAM_A_BAND_LNA_GAIN_CAL_OFS_SIZE, NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1, {0}},
+
+ };
+ PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+ char *pBuf = NULL;
+ int i = 0;
+
+ pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+ if (pQueryNv == NULL)
+ {
+ ERR("[META_WIFI] No memory nvram\n");
+ goto error;
+ }
+
+ for (i = 0 ; i < (sizeof(raNvram) / sizeof(NVRAM_ACCESS_STRUCT)) ; i++)
+ {
+ pQueryNv->dataLen = raNvram[i].dataLen;
+ pQueryNv->dataOffset = raNvram[i].dataOffset;
+ pBuf = (char *)&pQueryNv->data[0];
+
+ /*clear NVRAM content*/
+ memset(pBuf, 0, MAX_NVRAM_ACCESS_SIZE);
+ wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+ }
+
+ DBG("Finish!\n");
+error:
+ FREEIF(pQueryNv);
+
+ return META_WIFI_STATUS_SUCCESS;
+
+}
+/*LNA(Rssi) Gain Calibration Adjust*/
+WLAN_STATUS wifiNVRAMLnaGainCalAdjust(unsigned int dbdcbandIdx,
+ ENUM_BAND_T eBand, unsigned char inputCh)
+{
+
+ unsigned char chGroup = 0;
+ unsigned int data_cnt = 0;
+ char crOfsetIdx = 0;
+ int i = 0;
+ RECAL_INFO_T rReCalInfo;
+ WIFI_NVRAM_LNA_GAIN_CAL_T rLnaGain;
+ unsigned int nvramOfs = 0;
+ PNVRAM_ACCESS_STRUCT pQueryNv = NULL;
+ WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+
+ memset(&rReCalInfo, 0, sizeof(RECAL_INFO_T));
+ memset(&rLnaGain, 0, sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T));
+
+ pQueryNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE);
+
+ //get ch group
+ chGroup = wifiNVRAMGetChGroup(eBand, inputCh, CH_GROUP_ITEM_COMMON);
+
+ DBG("DbdcIdx=%d,Band=%d,ch=%d,Group=%d\n", dbdcbandIdx, eBand, inputCh, chGroup);
+
+ for (i = 0 ; i < QUERY_RECAL_RETRY_CNT ; i++)
+ {
+
+ //set Lna/Rssi Gain Cal by HQA CMD
+ if (wifiHqaDoCalibrationTestItem(HQA_CAL_ITEM_LNA_GIAN_CAL, dbdcbandIdx) != META_WIFI_STATUS_SUCCESS)
+ DBG("Cal test item fail!\n");
+
+
+ //query Lna/Rssi Gain Cal RESULT
+ if (wifiHqaGetDumpReCal(HQA_CAL_ITEM_LNA_GIAN_CAL, dbdcbandIdx, &rReCalInfo) != META_WIFI_STATUS_SUCCESS)
+ DBG("Cal test item fail!\n");
+
+
+ data_cnt = rReCalInfo.u4Count;
+
+ if (data_cnt != (LNA_GIAN_CAL_WF_PATH_CR_NUM * WF_NUM))
+ {
+ DBG("Result Num dismatch!,Expect:%d Total:%d do-try(%d)!\n",
+ (LNA_GIAN_CAL_WF_PATH_CR_NUM * WF_NUM),
+ data_cnt, i);
+ continue;
+ }
+ else
+ break;
+ }
+
+ if (data_cnt != (LNA_GIAN_CAL_WF_PATH_CR_NUM * WF_NUM))
+ {
+ DBG("Over retry(%d)! DNL Cal Result Fail\n", QUERY_RECAL_RETRY_CNT);
+ ret = META_WIFI_STATUS_FAIL;
+ goto error;
+ }
+
+ for (i = 0 ; i < data_cnt ; i++)
+ {
+ DBG("(%d)ID=0x%X,Addr=0x%X,Val=0x%X\n", i, rReCalInfo.u4CalId[i], rReCalInfo.u4CalAddr[i], rReCalInfo.u4CalValue[i]);
+ }
+
+ for (i = 0; i < WF_NUM; i++)
+ {
+
+ crOfsetIdx = LNA_GIAN_CAL_WF_PATH_CR_NUM * i;
+
+ //get Cal value
+ rLnaGain.ucRxCal1 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB0_MASK) >> LNA_GAIN_TAB0_SHFT;
+ rLnaGain.ucRxCal2 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB1_MASK) >> LNA_GAIN_TAB1_SHFT;
+ rLnaGain.ucRxCal3 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB2_MASK) >> LNA_GAIN_TAB2_SHFT;
+ rLnaGain.ucRxCal4 = (rReCalInfo.u4CalValue[crOfsetIdx + 0] & LNA_GAIN_TAB3_MASK) >> LNA_GAIN_TAB3_SHFT;
+ rLnaGain.ucRxCal5 = (rReCalInfo.u4CalValue[crOfsetIdx + 1] & LNA_GAIN_TAB4_MASK) >> LNA_GAIN_TAB4_SHFT;
+ rLnaGain.ucRxCal6 = 0; /*reserved*/
+
+ //calculate nvram offset
+ if (eBand == BAND_2G4)
+ {
+ nvramOfs = (i == WF0) ? (NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0) : (NVRAM_G_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1);
+ }
+ else
+ {
+ nvramOfs = (i == WF0) ? (NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_LNA_GAIN_CAL_OFS_OFSETOF_WF1);
+ //get nvram by ch group offset
+ nvramOfs += sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T) * chGroup;
+ }
+
+
+ memset(pQueryNv, 0, sizeof(sizeof(NVRAM_ACCESS_STRUCT) + MAX_NVRAM_ACCESS_SIZE));
+
+ pQueryNv->dataLen = sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T);
+ pQueryNv->dataOffset = nvramOfs;
+ memcpy(&pQueryNv->data[0], &rLnaGain, sizeof(WIFI_NVRAM_LNA_GAIN_CAL_T));
+ wifiNVRAMCtrl(NVRAM_WRITE, pQueryNv);
+
+ DBG("WF%d update B[%d] Ch=%d GP=%d nvramOfs=0x%08X done!\n", i, eBand, inputCh, chGroup, nvramOfs);
+ }
+
+ ret = META_WIFI_STATUS_SUCCESS;
+
+ DBG("Success!\n");
+error:
+ FREEIF(pQueryNv);
+
+ return ret;
+}
+
+#else
+
+WLAN_STATUS wifiNVRAMTssiChOfsInterpolation(TX_PWR_INTERPOLATION_TYPE type,
+ ENUM_BAND_T eBand, unsigned int chNum, unsigned int *pchArray)
+{
+
+ int wf = WF0;
+ unsigned int u4NvramOffset;
+ unsigned int chIdx = 0, rfIdx = 0;
+ int ch0 = 0, ch1 = 0, chInter = 0;
+ unsigned int readLine = 0;
+ int devStep = 0;
+ char nvCompVal = 0;
+ UINT_8 rNvVal[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+ PNVRAM_ACCESS_STRUCT pSetNv = NULL;
+ int chOfs0 = 0, chOfs1 = 0;
+ unsigned char chGroup[NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2];
+ unsigned char rfGroup = 0;
+ INTER_ACT interAct = INTER_ACT_NOT_SUPPORT;
+ INTERPOLATION_CH_BOUND_A_BAND rfInterList[NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM] =
+ {
+ {0xFF, 0}, //RF Group 0, not support 5G Interpolation
+ {36, 48}, //RF Group 1
+ {52, 64}, //RF Group 2
+ {0xFF, 0}, //RF Group 3, not support 5G Interpolation
+ {100, 112}, //RF Group 4
+ {116, 128}, //RF Group 5
+ {132, 144}, //RF Group 6
+ {149, 165}, //RF Group 7
+ };
+
+ /*init */
+ pSetNv = (PNVRAM_ACCESS_STRUCT)malloc(sizeof(NVRAM_ACCESS_STRUCT) + sizeof(UINT_8));
+ DBG("Band[%d] chNum[%d] Type[%d] Enter\n", eBand, chNum, type);
+ memset(&rNvVal[0], 0, sizeof(UINT_8) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+ memset(&chGroup[0], 0, sizeof(unsigned char) * (NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM * 2));
+
+ for (wf = WF0; wf < WF_NUM; wf++)
+ {
+
+ //read GT table by channel range
+ for (chIdx = 0; chIdx < chNum; chIdx++)
+ {
+ ch0 = pchArray[chIdx];
+ chGroup[chIdx] = wifiNVRAMGetChGroup(eBand, ch0, CH_GROUP_ITEM_TSSI_CH);
+
+ if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, ch0, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("Get Ch offset fial!\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+
+ pSetNv->dataLen = sizeof(UINT_8);
+ pSetNv->dataOffset = u4NvramOffset;
+ readLine = wifiNVRAMCtrl(NVRAM_READ, pSetNv);
+ memcpy(&rNvVal[chIdx], &pSetNv->data[0], sizeof(UINT_8));
+ DBG("Read WF[%d]chIdx[%d] = %d,Group=%d, Ofs=[0x%X] readLen=%d\n",
+ wf,
+ chIdx,
+ ch0,
+ chGroup[chIdx],
+ rNvVal[chIdx],
+ readLine);
+ }
+
+
+
+ /*only 2.4G support interpolation -- start*/
+ if ((type == TYPE_INTERPOLATION) && (eBand == BAND_2G4))
+ {
+ //calcaute each step ch=0 ~ pchArray(chNum-1)
+ for (chIdx = 0; chIdx < chNum - 1; chIdx++)
+ {
+
+ ch0 = pchArray[chIdx];
+ chOfs0 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx], 8);
+
+
+ ch1 = pchArray[(chIdx + 1)];
+ chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)], 8);
+
+ for (chInter = ch0 + 1 ; chInter < ch1; chInter++)
+ {
+ u4NvramOffset = 0;
+
+ if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset)
+ != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("Get Ch offset fial!\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+
+ devStep = ((chOfs1 - chOfs0) * (chInter - ch0)) / (ch1 - ch0);
+
+ DBG("Interpolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+ ch0, ch1, chOfs0, chOfs1, chInter, devStep);
+
+ nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+ wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+ DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+ chInter, u4NvramOffset, nvCompVal);
+#endif
+ }
+ }
+
+ //calcaute each step pchArray(n+1) ~ ch=14
+ for (chInter = ch1 + 1 ; chInter <= 14; chInter++)
+ {
+ u4NvramOffset = 0;
+
+ if (wifiNVRAMTssiChGetNVRAMOfs(wf, eBand, chInter, &u4NvramOffset) != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("Get Ch offset fial!\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+
+ devStep = ((chOfs1 - chOfs0) * (chInter - ch1)) / (ch1 - ch0);
+
+ DBG("Extrapolation ch[%d ~ %d] tssiChVal=[%d ~ %d],ch[%d] + devStep=%d\n",
+ ch1 + 1, 14, chOfs0, chOfs1, chInter, devStep);
+ nvCompVal = chOfs0 + (chInter - ch0) * devStep;
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+ wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+ DBG("ch[%d] nvOfs=0x%X,nvCompVal=0x%02X\n",
+ chInter, u4NvramOffset, nvCompVal);
+#endif
+
+ }
+ }
+ else if ((type == TYPE_GROUP_THE_SAME) && (eBand == BAND_5G))
+ {
+ /* "group the same" means using meanuse tx power value to apply tssi ch ofs group
+ * in RF defined group
+ */
+ //calcaute each step ch=0 ~ pchArray(chNum)
+ for (chIdx = 0; chIdx < chNum ; chIdx++)
+ {
+ nvCompVal = rNvVal[chIdx];
+ wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+ }
+ }
+ else if ((type == TYPE_INTERPOLATION) && (eBand == BAND_5G))
+ {
+ //calcaute each step ch=0 ~ pchArray(chNum-1)
+ for (chIdx = 0; chIdx < chNum; chIdx++)
+ {
+ interAct = INTER_ACT_NOT_SUPPORT;
+
+ //Check 5G interpolation support RF group channel bound
+ for (rfIdx = 0; rfIdx < NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM; rfIdx++)
+ {
+ DBG("ch=%d Check RFGroup[%d] bound[%d ~ %d]\n",
+ pchArray[chIdx],
+ rfIdx,
+ rfInterList[rfIdx].lowBoundCh,
+ rfInterList[rfIdx].upperBoundCh);
+
+ //if chIdx = low bound and chIdx+1 = upper bound
+ if (pchArray[chIdx] == rfInterList[rfIdx].lowBoundCh)
+ {
+ if ((chIdx < (chNum - 1)) &&
+ pchArray[chIdx + 1] == rfInterList[rfIdx].upperBoundCh)
+ {
+ interAct = INTER_ACT_INTERPOLATION;
+
+ rfGroup = GET_A_BAND_RF_GROUP(chGroup[chIdx]);
+
+ ch0 = pchArray[chIdx];
+ ch1 = pchArray[(chIdx + 1)];
+
+ chOfs0 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[chIdx], 8);
+ chOfs1 = SIGNED_CONVERT_EXTEND_BITS(rNvVal[(chIdx + 1)], 8);
+
+ DBG("5G do Interpolation WF[%d] RF[%d] ch[%d ~ %d] Rang[%d ~ %d]\n",
+ wf,
+ rfGroup,
+ ch0,
+ ch1,
+ chOfs0,
+ chOfs1);
+
+ //Query the next RF group
+ chIdx++;
+ break;
+ }
+ else
+ {
+ interAct = INTER_ACT_GROUP_THE_SAME;
+ break;
+ }
+ }
+ else if ((pchArray[chIdx] > rfInterList[rfIdx].lowBoundCh) &&
+ (pchArray[chIdx] < rfInterList[rfIdx].upperBoundCh))
+ {
+ interAct = INTER_ACT_GROUP_THE_SAME;
+ break;
+ }
+ else
+ interAct = INTER_ACT_GROUP_THE_SAME;
+
+ }
+
+ if (interAct == INTER_ACT_GROUP_THE_SAME)
+ {
+ nvCompVal = rNvVal[chIdx];
+ wifiNVRAMTssiChOfsRfGroupTheSame(wf, eBand, pchArray[chIdx], chGroup[chIdx], nvCompVal);
+ }
+ else if (interAct == INTER_ACT_INTERPOLATION)
+ {
+
+ /*update (n) ~ (n+3) Tssi ch group in one RF Group*/
+ for (chInter = (rfGroup * PER_CH_GROUP_IN_RF_GROUP) ; chInter < ((rfGroup * PER_CH_GROUP_IN_RF_GROUP) + PER_CH_GROUP_IN_RF_GROUP); chInter++)
+ {
+ u4NvramOffset = (wf == WF0) ? (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF0) : (NVRAM_A_BAND_TSSI_CH_OFS_OFSETOF_WF1);
+ u4NvramOffset += (chInter * sizeof(UINT_8));
+
+ devStep = ((chOfs1 - chOfs0) * (chInter - (rfGroup * PER_CH_GROUP_IN_RF_GROUP))) / (PER_CH_GROUP_IN_RF_GROUP - 1);
+
+ nvCompVal = (chOfs0 + devStep) & 0x000000FF;
+
+ DBG("Interpolation:TssiChGroup[%d][%c] + devStep=%d,NvOfs=0x%08X,NvVal=0x%02X\n",
+ chInter / 2,
+ ((chInter % 2) == 0) ? ('L') : ('H'),
+ devStep,
+ u4NvramOffset,
+ nvCompVal);
+
+#if (CFG_TSSI_CH_GT_SAME == 1)
+ wifiNVRAMTssiChGainTableAllTheSame(u4NvramOffset, nvCompVal);
+#else
+ wifiNVRAMWirteByte(u4NvramOffset, nvCompVal);
+#endif
+
+ }
+
+ }
+ else
+ DBG("Not Support ch[%d]!\n", pchArray[chIdx + 1]);
+
+ }
+ }
+ }
+
+ FREEIF(pSetNv);
+
+ return META_WIFI_STATUS_SUCCESS;
+}
+
+WLAN_STATUS wifiNVRAMLnaGainCalClear(void)
+{
+ return META_WIFI_STATUS_FAIL;
+}
+WLAN_STATUS wifiNVRAMLnaGainCalAdjust(unsigned int dbdcbandIdx,
+ ENUM_BAND_T eBand, unsigned char inputCh)
+{
+ return META_WIFI_STATUS_FAIL;
+}
+WLAN_STATUS wifiNVRAMTssiNDLOfsClear(void)
+{
+ return META_WIFI_STATUS_FAIL;
+}
+WLAN_STATUS wifiNVRAMTssiDnlOfsAdjust(unsigned int dbdcbandIdx,
+ ENUM_BAND_T eBand, unsigned char inputCh)
+{
+ return META_WIFI_STATUS_FAIL;
+}
+#endif /*#if (WIFI_GEN_VER == CONNAC_SOC3_0)*/
+
+WLAN_STATUS wifiProductLineCalProcess(P_CMD_PL_CAL pCmdPLcal)
+{
+ WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+ unsigned char i = 0;
+ unsigned int arg[MAX_PL_INPUT_ARG_NUM] = {0};
+ unsigned int CalStatus = META_WIFI_STATUS_FAIL;
+ unsigned int targetPwr = gHqaParaInfo.power;
+ int meanPwr = 0;
+ unsigned int ch = 0;
+ unsigned int wf_idx = -1;
+ unsigned int dbdcBandIdx = -1;
+ ENUM_BAND_T eBand = (gHqaParaInfo.chBand == 0) ? (BAND_2G4) : (BAND_5G);
+
+ unsigned int band_chNum = 0;
+ unsigned int interpolat_type = 0;
+
+
+ memset(&arg[0], 0, sizeof(unsigned int)*MAX_PL_INPUT_ARG_NUM);
+
+ if (gHqaParaInfo.eCbw == CDBW_80P80)
+ ch = gHqaParaInfo.chS2;
+ else
+ ch = gHqaParaInfo.chS1;
+
+ wf_idx = gHqaParaInfo.wf_idx;
+
+ dbdcBandIdx = gHqaParaInfo.dbdcBandIdx;
+
+ if (pCmdPLcal == NULL)
+ {
+ ERR("pCmdPLcal is null\n");
+ ret = META_WIFI_STATUS_INVALID_PARA;
+ goto error;
+ }
+
+ DBG("ID=%d Act=%d ParaNum= %d wf_idx=%d\n", pCmdPLcal->calId, pCmdPLcal->action, pCmdPLcal->inputLen, wf_idx);
+
+ for (i = 0; i < pCmdPLcal->inputLen ; i++)
+ {
+ arg[i] = pCmdPLcal->au4Buffer[i];
+ DBG("Para (%d)=%d\n", i, arg[i]);
+ }
+
+ switch (pCmdPLcal->calId)
+ {
+
+ case WIFI_PL_CAL_TX_PWR:
+ {
+ switch (pCmdPLcal->action)
+ {
+ case TX_PWR_CAL_ACT_START:
+ ret = wifiNVRAMTssiChOfsClear();
+
+ if (ret == META_WIFI_STATUS_SUCCESS)
+ {
+ wifwNVRAMWriteDataToDriver();
+ usleep(500000);
+ }
+
+ break;
+
+ case TX_PWR_CAL_ACT_ADJUST:
+ meanPwr = arg[0];
+
+ if (wf_idx & BIT(WF0))
+ ret = wifiNVRAMTssiChOfsAdjust(WF0, eBand, ch, targetPwr, meanPwr);
+
+ if (wf_idx & BIT(WF1))
+ ret = wifiNVRAMTssiChOfsAdjust(WF1, eBand, ch, targetPwr, meanPwr);
+
+ if (ret == META_WIFI_STATUS_SUCCESS)
+ {
+ wifwNVRAMWriteDataToDriver();
+ usleep(500000);
+ }
+
+ break;
+
+ case TX_PWR_CAL_ACT_END:
+ CalStatus = arg[0];
+
+ if (CalStatus == META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("[META_WIFI] TX POWER CALIBRATION PASS!\n");
+ ret = META_WIFI_STATUS_SUCCESS;
+ }
+ else
+ {
+ DBG("[META_WIFI] TX POWER CALIBRATION Fail! Clear Result!\n");
+ ret = wifiNVRAMTssiChOfsClear();
+ }
+
+ break;
+
+ case TX_PWR_CAL_ACT_INTERPOLAT:
+ if (arg[0] & BIT(0)) //BIT[0]:2.4G
+ eBand = BAND_2G4;
+ else if (arg[0] & BIT(1))//BIT[1]:5G
+ eBand = BAND_5G;
+
+ DBG("[META_WIFI] TX_PWR_CAL_ACT_INTERPOLAT Band(%d)\n", eBand);
+ interpolat_type = arg[1];
+ band_chNum = arg[2];
+ ret = wifiNVRAMTssiChOfsInterpolation(interpolat_type, eBand, band_chNum, &arg[3]);
+
+ if (ret == META_WIFI_STATUS_SUCCESS)
+ {
+ wifwNVRAMWriteDataToDriver();
+ usleep(500000);
+ }
+
+ return wifiNVRAMTssiContentDumpToPC(eBand, pCmdPLcal, ret);
+
+ default:
+ DBG("[META_WIFI] un-support act(%d)\n", pCmdPLcal->action);
+ ret = META_WIFI_STATUS_FAIL;
+ goto error;
+ }
+ }
+ break;
+
+ case WIFI_PL_CAL_EPA_FE_GAIN:
+ break;
+
+ case WIFI_PL_CAL_LNA_GAIN_CAL:
+ switch (pCmdPLcal->action)
+ {
+ case TX_PWR_CAL_ACT_START:
+ ret = wifiNVRAMLnaGainCalClear();
+
+ if (ret == META_WIFI_STATUS_SUCCESS)
+ {
+ wifwNVRAMWriteDataToDriver();
+ usleep(500000);
+ }
+
+ break;
+
+ case TX_PWR_CAL_ACT_ADJUST:
+ ret = wifiNVRAMLnaGainCalAdjust(dbdcBandIdx, eBand, ch);
+
+ if (ret == META_WIFI_STATUS_SUCCESS)
+ {
+ wifwNVRAMWriteDataToDriver();
+ usleep(500000);
+ }
+
+ break;
+
+ case TX_PWR_CAL_ACT_END:
+ CalStatus = arg[0];
+
+ if (CalStatus == META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("[META_WIFI] LNA GAIN CALIBRATION PASS!\n");
+ ret = META_WIFI_STATUS_SUCCESS;
+ }
+ else
+ {
+ DBG("[META_WIFI] LNA GAIN CALIBRATION Fail! Clear Result!\n");
+ ret = wifiNVRAMLnaGainCalClear();
+ }
+
+ break;
+
+ default:
+ DBG("[META_WIFI] un-support act(%d)\n", pCmdPLcal->action);
+ ret = META_WIFI_STATUS_FAIL;
+ goto error;
+
+ }
+
+ break;
+
+ case WIFI_PL_CAL_DNL_CAL:
+ switch (pCmdPLcal->action)
+ {
+ case TX_PWR_CAL_ACT_START:
+ ret = wifiNVRAMTssiNDLOfsClear();
+
+ if (ret == META_WIFI_STATUS_SUCCESS)
+ {
+ wifwNVRAMWriteDataToDriver();
+ usleep(500000);
+ }
+
+ break;
+
+ case TX_PWR_CAL_ACT_ADJUST:
+ ret = wifiNVRAMTssiDnlOfsAdjust(dbdcBandIdx, eBand, ch);
+
+ if (ret == META_WIFI_STATUS_SUCCESS)
+ {
+ wifwNVRAMWriteDataToDriver();
+ usleep(500000);
+ }
+
+ break;
+
+ case TX_PWR_CAL_ACT_END:
+ CalStatus = arg[0];
+
+ if (CalStatus == META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("[META_WIFI] DNL CALIBRATION PASS!\n");
+ ret = META_WIFI_STATUS_SUCCESS;
+ }
+ else
+ {
+ DBG("[META_WIFI] DNL CALIBRATION Fail! Clear Result!\n");
+ ret = wifiNVRAMTssiNDLOfsClear();
+ }
+
+ break;
+
+ default:
+ DBG("[META_WIFI] un-support act(%d)\n", pCmdPLcal->action);
+ ret = META_WIFI_STATUS_FAIL;
+ goto error;
+
+ }
+
+ break;
+
+ default:
+ ERR("Not Support Cal ID :%d\n", pCmdPLcal->calId);
+ ret = META_WIFI_STATUS_FAIL;
+ goto error;
+ }
+
+error:
+
+ //reponse Product Line calibration result
+ pCmdPLcal->inputLen = sizeof(ret);
+ pCmdPLcal->au4Buffer[0] = ret;
+
+ return ret;
+
+}
+
+WLAN_STATUS wifiProductLineScript(char* pCmd, unsigned short pCmdlen)
+{
+ CMD_PL_CAL rCmdPlCal;
+ char head[20];
+ unsigned int act;
+ unsigned int val;
+ unsigned int calId;
+
+ DBG("do Product line cmd: %s len:%d\n", pCmd, pCmdlen);
+ sscanf(pCmd, "%s %d %d %d", head, &calId, &act, &val);
+ DBG("HEAD:%s,CAL ID%d,ACT:%d,VAL:%d\n", head, calId, act, val);
+
+ rCmdPlCal.calId = calId;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.action = act;
+ rCmdPlCal.inputLen = 1;
+ rCmdPlCal.au4Buffer[0] = val;
+
+ return wifiProductLineCalProcess(&rCmdPlCal);
+
+}
+
+WLAN_STATUS wifiProductInit(void)
+{
+ memset(&gHqaParaInfo, 0, sizeof(gHqaParaInfo));
+
+ return META_WIFI_STATUS_SUCCESS;
+
+}
+
+unsigned int wifiHqaGetParaAndShiftBuf(
+ bool convert, unsigned int size, unsigned char **buf, unsigned char *out)
+{
+ if (!(*buf))
+ {
+ DBG("*buf NULL pointer with size=%u\n", size);
+ return META_WIFI_STATUS_INVALID_PARA;
+ }
+
+ if (!out)
+ {
+ DBG("out NULL pointer with size=%u\n", size);
+ return META_WIFI_STATUS_INVALID_PARA;
+ }
+
+ memcpy(out, *buf, size);
+ *buf = *buf + size;
+
+ if (!convert)
+ {
+ DBG("size=%u", size);
+ return META_WIFI_STATUS_SUCCESS;
+ }
+
+ if (size == sizeof(unsigned int))
+ {
+ unsigned int *tmp = (unsigned int *) out;
+
+ *tmp = ntohl(*tmp);
+ DBG("size=%u, val=%u\n", size, *tmp);
+ }
+ else if (size == sizeof(unsigned short))
+ {
+ unsigned short *tmp = (unsigned short *) out;
+
+ *tmp = ntohs(*tmp);
+ DBG("size=%u, val=%u\n", size, *tmp);
+ }
+ else
+ {
+ DBG("size %u not supported\n", size);
+ return META_WIFI_STATUS_NOT_SUPPORT;
+ }
+
+ return META_WIFI_STATUS_SUCCESS;
+}
+
+WLAN_STATUS wifiHqaGetDumpReCal(unsigned int item, unsigned int dbdcBandIdx, P_RECAL_INFO_T prReCalInfo)
+{
+ P_HQA_CMD_FRAME prHqaCmd = NULL;
+ WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+ unsigned char* pData = NULL;
+
+
+ unsigned int avail_sz = 0;
+ int i = 0, j = 0;
+ int u4hqaCmdLen = 0;
+
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(RECAL_INFO_T) + sizeof(RECAL_INFO_T);
+ prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+ if (!prHqaCmd)
+ {
+ DBG("out of memory in allocating prHqaCmd\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+ memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_GetDumpRecal);
+ prHqaCmd->length = htons(sizeof(unsigned int));
+ prHqaCmd->sequence = 1;
+ dbdcBandIdx = htonl(dbdcBandIdx);
+
+ memcpy(&prHqaCmd->data[0], &dbdcBandIdx, sizeof(unsigned int));
+
+ for (i = 0; i < POLLING_RECAL_RETRY_CNT; i++)
+ {
+ ret = HQAIWreq(wifi_skfd, "wlan0", (char *)prHqaCmd, u4hqaCmdLen, &avail_sz);
+
+ DBG("[HQA_CMD] dump Item:%d,BandIdx:%d,CMD:%p,len:%d,ret:%d,avail_sz:%d\n",
+ item,
+ dbdcBandIdx,
+ prHqaCmd,
+ u4hqaCmdLen,
+ ret,
+ avail_sz);
+
+ if (ret != META_WIFI_STATUS_SUCCESS)
+ {
+ DBG("[HQA_CMD] dump Item:%d fail!ret(%d)\n", item, ret);
+ break;
+ }
+
+ if (avail_sz > 0)
+ {
+ pData = (unsigned char*)&prHqaCmd->data[0];
+
+ //status 2Byte
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned short), &pData, (unsigned char *)&prReCalInfo->status);
+
+ //Count 4Byte
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4Count);
+
+ DBG("[HQA_CMD] dump Cal Item:%d,retry:%d,status:%d,Count:%d\n", item, i, prReCalInfo->status, prReCalInfo->u4Count);
+
+
+ if (prReCalInfo->u4Count == 0)
+ {
+ usleep(1 * 1000 * 1000);
+ DBG("[HQA_CMD] dump Item Sleep 1s do next query\n");
+ }
+ else if (prReCalInfo->u4Count > MAX_RECAL_DATA_NUM)
+ {
+ DBG("[HQA_CMD] prReCalInfo->u4Count out of bound!\n");
+ ret = META_WIFI_STATUS_FAIL;
+ goto error;
+ }
+ else
+ {
+
+ for (j = 0 ; j < prReCalInfo->u4Count ; j++)
+ {
+ //Recal ID 4Byte
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4CalId[j]);
+ //Offset 4Byte
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4CalAddr[j]);
+ //Value 4Byte
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&prReCalInfo->u4CalValue[j]);
+
+ DBG("[HQA_CMD] (%d)ID=0x%08X,CR=0x%08X,Value=0x%08X\n"
+ , j, prReCalInfo->u4CalId[j], prReCalInfo->u4CalAddr[j], prReCalInfo->u4CalValue[j]);
+ }
+
+ ret = META_WIFI_STATUS_SUCCESS;
+
+ break;
+ }
+ }
+
+ }
+
+error:
+ FREEIF(prHqaCmd);
+
+ DBG("finish\n");
+
+ return ret;
+}
+WLAN_STATUS wifiHqaDoCalibrationTestItem(unsigned int item, unsigned int dbdcBandIdx)
+{
+ P_HQA_CMD_FRAME prHqaCmd;
+ WLAN_STATUS ret = META_WIFI_STATUS_FAIL;
+ HQA_DO_CAL_TEST_ITEM rCalItem;
+
+ unsigned int avail_sz = 0;
+ int u4hqaCmdLen = 0;
+
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_DO_CAL_TEST_ITEM);
+ prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+ if (!prHqaCmd)
+ {
+ DBG("out of memory in allocating prHqaCmd\n");
+ return META_WIFI_STATUS_FAIL;
+ }
+ memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_DoCalibrationTestItem);
+ prHqaCmd->length = htons(sizeof(rCalItem));
+ prHqaCmd->sequence = 1;
+ rCalItem.item = htonl(item);
+ rCalItem.band_idx = htonl(dbdcBandIdx);
+
+ memcpy(&prHqaCmd->data[0], &rCalItem, sizeof(HQA_DO_CAL_TEST_ITEM));
+
+ ret = HQAIWreq(wifi_skfd, "wlan0", (char *)prHqaCmd, u4hqaCmdLen, &avail_sz);
+
+ DBG("[HQA_CMD] Do Cal Item:0x%08X,BandIdx:%d,CMD:%p,len:%d,ret:%d,avail_sz:%d\n",
+ item,
+ dbdcBandIdx,
+ prHqaCmd,
+ u4hqaCmdLen,
+ ret,
+ avail_sz);
+
+
+ FREEIF(prHqaCmd);
+ return ret;
+}
+
+WLAN_STATUS wifiHqaCmdParaMonitor(char* peer_buf, unsigned short peer_len)
+{
+ P_HQA_CMD_FRAME prHqaCmd = NULL;
+ unsigned short u2HqaCmdId = 0;
+ unsigned int u4HqaCmdExtId = 0;
+ unsigned int u4ParaNum = 0;
+ unsigned int value = 0;
+ unsigned char* pData = NULL;
+
+ if (peer_buf == NULL)
+ return META_WIFI_STATUS_INVALID_PARA;
+
+ if (peer_len <= 0)
+ return META_WIFI_STATUS_INVALID_PARA;
+
+
+ prHqaCmd = (P_HQA_CMD_FRAME)peer_buf;
+
+ if (ntohl(prHqaCmd->magicNo) != HQA_CMD_MAGIC_NO)
+ {
+ DBG("MagicNo is Not Support\n");
+ return META_WIFI_STATUS_NOT_SUPPORT;
+ }
+
+ u2HqaCmdId = ntohs(prHqaCmd->id);
+
+ pData = &prHqaCmd->data[0];
+
+ switch (u2HqaCmdId)
+ {
+ case HQA_CMD_OPEN_ADAPTER:
+ case HQA_CMD_CLOSE_ADAPTER:
+ memset(&gHqaParaInfo, 0, sizeof(gHqaParaInfo));
+ break;
+
+ case HQA_CMD_SetTxPath:
+ //tx path in bitwith
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ gHqaParaInfo.wf_idx = value;
+ //band index
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ gHqaParaInfo.dbdcBandIdx = value;
+ break;
+
+ case HQA_CMD_SetTxPowerExt:
+ //Power
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ gHqaParaInfo.power = value;
+ break;
+
+ case HQA_CMD_EXTEND:
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&u4HqaCmdExtId);
+ break;
+ }
+
+ switch (u4HqaCmdExtId)
+ {
+ case HQA_CMD_DBDCSetChannel:
+ //PARA NUM
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&u4ParaNum);
+ //DBDC IDX
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ //Center Channel Freq 0
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ gHqaParaInfo.chS1 = value;
+ //Center Channel Freq 1
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ gHqaParaInfo.chS2 = value;
+ //SystemBW
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ gHqaParaInfo.eCbw = value;
+ //PrePketBW
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ //primary select
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ //reason
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ //channel band
+ wifiHqaGetParaAndShiftBuf(TRUE, sizeof(unsigned int), &pData, (unsigned char *)&value);
+ gHqaParaInfo.chBand = value;
+ break;
+
+ case HQA_CMD_DBDCStartTx:
+ DBG("Start Tx: wf_idx[0x%x]dbdcIdx[%d]chBand[%d]pwr[%d]chS1[%d]chS2[%d]cbw[%d]\n",
+ gHqaParaInfo.wf_idx,
+ gHqaParaInfo.dbdcBandIdx,
+ gHqaParaInfo.chBand,
+ gHqaParaInfo.power,
+ gHqaParaInfo.chS1,
+ gHqaParaInfo.chS2,
+ gHqaParaInfo.eCbw);
+ break;
+
+ case HQA_CMD_DBDCStopTx:
+ break;
+
+ }
+
+ DBG("Handle cmdId = 0x%08X extId = 0x%08X\n", u2HqaCmdId, u4HqaCmdExtId);
+
+ return META_WIFI_STATUS_SUCCESS;
+
+}
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+void META_WIFI_Register(WIFI_CNF_CB callback)
+{
+ cnf_cb = callback;
+}
+
+int META_WIFI_init(void)
+{
+ int count = 100;
+
+ if (1 == wifi_init)
+ {
+ ERR("wifi is already initilized.\n");
+ return true;
+ }
+
+#if 0
+
+ if (!wifi_is_loaded())
+ {
+ ERR("[META_WIFI] loading wifi driver ... ...\n");
+
+ if (wifi_insmod(DRIVER_MODULE_PATH, DRIVER_MODULE_ARG) < 0)
+ {
+ ERR("[META_WIFI] failed to load wifi driver!!!\n");
+ goto error;
+ }
+ }
+
+#endif
+ usleep(200000);
+ /*get wifi nvram profile before wifi on */
+ gNvInfo = NVM_ReadFileVerInfo(AP_CFG_RDEB_FILE_WIFI_LID);
+ DBG("[META_WIFI] NVRAM FileVer:%s\n", gNvInfo.cFileVer);
+ DBG("[META_WIFI] NVRAM FileName:%s\n", gNvInfo.cFileName);
+ DBG("[META_WIFI] NVRAM RecSize:%d\n", gNvInfo.i4RecSize);
+ DBG("[META_WIFI] NVRAM RecNum:%d\n", gNvInfo.i4RecNum);
+ DBG("[META_WIFI] NVRAM MaxFileLid:%d\n", gNvInfo.i4MaxFileLid);
+
+ DBG("[META_WIFI] WIFI_META_VER:%s\n", WIFI_META_VER);
+
+ wifi_set_power(1);
+
+
+ sched_yield();
+
+ while (count-- > 0)
+ {
+ if (ifc_init() == 0)
+ {
+ if (ifc_up("wlan0") == 0)
+ {
+ ifc_close();
+ break;
+ }
+
+ ERR("[META_WIFI] ifc_up(wlan0) failed\n");
+ ifc_close();
+ }
+ else
+ {
+ ERR("[META_WIFI] ifc_init() failed\n");
+ }
+
+ usleep(100000);
+ }
+
+ if (count == 0)
+ goto error;
+
+ if (wifi_skfd == -1)
+ wifi_skfd = openNetHandle();
+
+ if (wifi_skfd < 0)
+ {
+ META_WIFI_deinit();
+ goto error;
+ }
+
+ wifi_init = 1;
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+ wifiProductInit();
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+ return true;
+
+error:
+ wifi_set_power(0);
+ return false;
+}
+
+void META_WIFI_deinit(void)
+{
+ //int count = 20; /* wait at most 10 seconds for completion */
+
+ DBG("[META_WIFI] WIFI_META_VER:%s\n", WIFI_META_VER);
+
+ if (0 == wifi_init)
+ {
+ ERR("wifi is already deinitilized.\n");
+ return;
+ }
+
+ if (wifi_skfd > 0)
+ {
+ closeNetHandle(wifi_skfd);
+ wifi_skfd = -1;
+ }
+
+ /* if (wifi_rmmod(DRIVER_MODULE_NAME) == 0) {
+ while (count-- > 0) {
+ if (!wifi_is_loaded())
+ break;
+ usleep(500000);
+ }
+ sched_yield();*/
+ wifi_set_power(0);
+ /* }*/
+ wifi_init = 0;
+ return;
+}
+
+void META_WIFI_OP(FT_WM_WIFI_REQ *req, char *peer_buf, unsigned short peer_len)
+{
+ unsigned int i;
+ int ret = -1;
+ FT_WM_WIFI_CNF cnf;
+ OID_STRUC *poid = NULL;
+ unsigned int avail_sz = 0;
+ NVRAM_ACCESS_STRUCT *pnvram = NULL;
+ P_CMD_PL_CAL prCmdPlCal = NULL;
+ char *pCmd = NULL;
+ int cmdLen = 0;
+ void *ret_buf = NULL, *allocated_buf = NULL;
+ unsigned int ret_size = 0;
+ int readByteLen = -1;
+
+
+//modify for wifi init/deinit flow
+// if (NULL == req || NULL == peer_buf || wifi_skfd < 0 || !wifi_init) {
+// printf("[META_WIFI] Invalid arguments or operation\n");
+// goto exit;
+// }
+
+ DBG("META_WIFI_OP OP is %d,peer_len=%d\n", req->type, peer_len);
+
+ //for the compaliance of the former meta tool
+ if (!wifi_init && WIFI_CMD_INIT != req->type)
+ {
+ if (true != META_WIFI_init())
+ {
+ ERR("!wifi_init & META_WIFI_init fail\n");
+ ret = -1;
+ goto exit;
+ }
+ else
+ DBG("Init for the compaliance of the former meta tool.\n");
+ }
+
+
+ // OID operation
+ if (WIFI_CMD_SET_OID == req->type
+ || WIFI_CMD_QUERY_OID == req->type)
+ {
+ if ((peer_len <= 0) || NULL == (poid = (OID_STRUC *)malloc(peer_len)))
+ {
+ ERR("[META_WIFI] No memory, %d\n", peer_len);
+ goto exit;
+ }
+
+ // for later freeing
+ allocated_buf = (void *)poid;
+ memcpy(poid, peer_buf, peer_len);
+
+ if (WIFI_CMD_SET_OID == req->type)
+ {
+ for (i = 0; i < poid->SetOidPara.dataLen; i++)
+ {
+ DBG("[META_WIFI] OIDReq : data[%d] = 0x%x\n",
+ i, poid->SetOidPara.data[i]);
+ }
+
+ ret = setIWreq(wifi_skfd, "wlan0", poid->SetOidPara.oid,
+ poid->SetOidPara.data, poid->SetOidPara.dataLen, &avail_sz);
+ DBG("[META_WIFI] SET_OID, OID: 0x%x, len: %d, ret: %d\n",
+ poid->SetOidPara.oid, poid->SetOidPara.dataLen, ret);
+ }
+ else if (WIFI_CMD_QUERY_OID == req->type)
+ {
+ ret = getIWreq(wifi_skfd, "wlan0", poid->QueryOidPara.oid,
+ poid->QueryOidPara.data, poid->QueryOidPara.dataLen, &avail_sz);
+ DBG("[META_WIFI] QUERY_OID, OID: 0x%x, len: %d, ret: %d\n",
+ poid->QueryOidPara.oid, poid->QueryOidPara.dataLen, ret);
+ }
+
+ if (ret == 0 && WIFI_CMD_QUERY_OID == req->type)
+ {
+ ret_buf = (void *)poid;
+ ret_size = avail_sz + 8;
+ }
+ }
+ // NVRAM access
+ else if (WIFI_CMD_NVRAM_WRITE_ACCESS == req->type
+ || WIFI_CMD_NVRAM_READ_ACCESS == req->type)
+ {
+
+ if ((peer_len <= 0) || NULL == (pnvram = (NVRAM_ACCESS_STRUCT *)malloc(peer_len)))
+ {
+ ERR("[META_WIFI] No memory, %d\n", peer_len);
+ goto exit;
+ }
+
+ // for later freeing
+ allocated_buf = (void *)pnvram;
+ memcpy(pnvram, peer_buf, peer_len);
+
+ if (peer_len < (offsetof(NVRAM_ACCESS_STRUCT, data) + pnvram->dataLen))
+ {
+ ERR("[META_WIFI] Mimatched NVRAM content length: (%d / %u)\n", peer_len,
+ (unsigned int)(offsetof(NVRAM_ACCESS_STRUCT, data) + pnvram->dataLen));
+ goto exit;
+ }
+
+ if (WIFI_CMD_NVRAM_READ_ACCESS == req->type)
+ {
+ readByteLen = wifiNVRAMCtrl(NVRAM_READ, pnvram);
+
+ if (readByteLen > 0)
+ {
+ ret_buf = (void *)pnvram;
+ ret_size = offsetof(NVRAM_ACCESS_STRUCT, data) + ret;
+ ret = 0;
+ }
+ else
+ ret = -1;
+ }
+ else if (WIFI_CMD_NVRAM_WRITE_ACCESS == req->type)
+ {
+ ret = wifiNVRAMCtrl(NVRAM_WRITE, pnvram);
+ }
+ }
+ else if (WIFI_CMD_INIT == req->type)
+ {
+ if (true != META_WIFI_init())
+ ret = -1;
+ else
+ ret = 0;
+ }
+
+ else if (WIFI_CMD_DEINIT == req->type)
+ {
+ META_WIFI_deinit();
+ ret = 0;
+ }
+
+ else if (WIFI_CMD_SCRIPT == req->type)
+ {
+
+ /*Do sanity check*/
+ if (peer_len <= 0)
+ goto exit;
+
+ /*memory allocate for saving driver's command result*/
+ if (NULL == (pCmd = (char *)malloc(WIFI_SCRIPT_TOTAL_BUF_LEN)))
+ {
+ goto exit;
+ }
+
+ memcpy(pCmd, peer_buf, peer_len);
+ pCmd[peer_len] = '\0';
+
+ /*parse User command and remove iwpriv driver command head, for example : adb shell ipwriv driver*/
+ cmdLen = wifiScriptRemoveHead(pCmd);
+
+ if (cmdLen > 0)
+ {
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+
+ /*Support Product Line Calibration script*/
+ /*format : PL <ID> <ACT> <VALUE>*/
+ if (pCmd[0] == 'P' && pCmd[1] == 'L')
+ {
+ ret = wifiProductLineScript(pCmd, cmdLen);
+ }
+ else
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+ {
+ ret = driverIWreq(wifi_skfd, "wlan0", pCmd, cmdLen, &avail_sz);
+ DBG("[META_WIFI] DRIVER CMD:%s,len:%d,ret:%d,avail_sz:%d\n", peer_buf, peer_len, ret, avail_sz);
+ }
+
+ if (ret == 0 && WIFI_CMD_SCRIPT == req->type)
+ {
+ ret_buf = (void *)pCmd;
+ ret_size = avail_sz;
+ }
+
+ }
+
+ }
+
+ else if (WIFI_CMD_HQA == req->type)
+ {
+
+ if ((peer_len <= 0) || NULL == (pCmd = (char *)malloc(WIFI_SCRIPT_TOTAL_BUF_LEN)))
+ {
+ ERR("[HQA_CMD] No memory, %d\n", peer_len);
+ goto exit;
+ }
+
+ memcpy(pCmd, peer_buf, peer_len);
+ pCmd[peer_len] = '\0';
+ cmdLen = peer_len; // + RA_CFG_HLEN
+
+ ret = HQAIWreq(wifi_skfd, "wlan0", pCmd, cmdLen, &avail_sz);
+
+ DBG("[HQA_CMD] CMD:%p,len:%d,ret:%d,avail_sz:%d\n", peer_buf, peer_len, ret, avail_sz);
+
+ if (ret == 0 && WIFI_CMD_HQA == req->type)
+ {
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+ wifiHqaCmdParaMonitor(peer_buf, peer_len);
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+ ret_buf = (void *)pCmd;
+ ret_size = avail_sz;
+ }
+ }
+
+#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)
+
+ else if (WIFI_CMD_PL_CALIBRATION == req->type)
+ {
+ if ((peer_len <= 0) || NULL == (prCmdPlCal = (P_CMD_PL_CAL)malloc(sizeof(CMD_PL_CAL))))
+ {
+ ERR("[META_WIFI] No memory, %d\n", peer_len);
+ goto exit;
+ }
+
+ //init
+ memset(prCmdPlCal, 0, sizeof(CMD_PL_CAL));
+
+ // for later freeing
+ memcpy(prCmdPlCal, peer_buf, peer_len);
+ ret = wifiProductLineCalProcess(prCmdPlCal);
+
+ ret_buf = (void *)prCmdPlCal;
+ ret_size = sizeof(CMD_PL_CAL);
+
+ DBG("[PL_CAL] ID:%d,ACT:%d,ret:%d,ret_size:%d done!\n", prCmdPlCal->calId, prCmdPlCal->action, ret, ret_size);
+ }
+
+#endif /*#if (META_SUPPORT_PRODUCT_LINE_CAL == 1)*/
+
+exit:
+ memset(&cnf, 0, sizeof(FT_WM_WIFI_CNF));
+ cnf.header.token = req->header.token;
+ cnf.header.id = FT_WIFI_CNF_ID;
+ cnf.type = req->type;
+ cnf.status = META_SUCCESS;
+
+ /* CHECKME!! Need to confirm the value of drv_status */
+ cnf.drv_status = (ret == 0) ? (int)true : (int)false;
+
+ wifi_send_resp(&cnf, ret_buf, ret_size);
+
+ FREEIF(poid);
+ FREEIF(pnvram);
+ FREEIF(pCmd);
+ FREEIF(prCmdPlCal);
+ return;
+}
+
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi.h b/src/devtools/meta/src/adaptor/wifi/meta_wifi.h
new file mode 100644
index 0000000..2aa5dc6
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi.h
@@ -0,0 +1,10 @@
+#ifndef __META_WIFI_H__
+#define __META_WIFI_H__
+#include "meta_wifi_para.h"
+
+typedef void (*WIFI_CNF_CB)(FT_WM_WIFI_CNF *cnf, void *buf, unsigned int size);
+
+extern void META_WIFI_Register(WIFI_CNF_CB callback);
+
+#endif
+
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi_para.h b/src/devtools/meta/src/adaptor/wifi/meta_wifi_para.h
new file mode 100644
index 0000000..83ecd12
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi_para.h
@@ -0,0 +1,675 @@
+/*****************************************************************************
+* Copyright Statement:
+* --------------------
+* This software is protected by Copyright and the information contained
+* herein is confidential. The software may not be copied and the information
+* contained herein may not be used or disclosed except with the written
+* permission of MediaTek Inc. (C) 2008
+*
+* BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+* THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+* RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
+* AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
+* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
+* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
+* NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
+* SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
+* SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
+* THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
+* NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
+* SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
+*
+* BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
+* LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
+* AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
+* OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
+* MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+*
+* THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
+* WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
+* LAWS PRINCIPLES. ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
+* RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
+* THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
+*
+*****************************************************************************/
+
+//
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+//
+// Use of this source code is subject to the terms of the Microsoft end-user
+// license agreement (EULA) under which you licensed this SOFTWARE PRODUCT.
+// If you did not accept the terms of the EULA, you are not authorized to use
+// this source code. For a copy of the EULA, please see the LICENSE.RTF on your
+// install media.
+//
+
+/*****************************************************************************
+ *
+ * Filename:
+ * ---------
+ * meta_wifi_para.h
+ *
+ * Project:
+ * --------
+ * DUMA
+ *
+ * Description:
+ * ------------
+ * the defination of Wi-Fi wrapper interface for META FT task.
+ *
+ * Author:
+ * -------
+ * Renbang Jiang (MTK80150)
+ *
+ *============================================================================
+ * HISTORY
+ * Below this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *------------------------------------------------------------------------------
+ * $Revision:$
+ * $Modtime:$
+ * $Log:$
+ *
+ * Mar 6 2009 mtk80150
+ * [DUMA00110922] [Wi-Fi] Wi-Fi driver for META initial timeout
+ * Add Timeout for driver initializing
+ *
+ * Mar 6 2009 mtk80150
+ * [DUMA00110922] [Wi-Fi] Wi-Fi driver for META initial timeout
+ * Add timeout for Wi-Fi driver initialize
+ *
+ * Feb 22 2009 mtk80150
+ * [DUMA00109732] [Wi-Fi] Driver version update to 1.13
+ *
+ *
+ *
+ *------------------------------------------------------------------------------
+ * Upper this line, this part is controlled by CC/CQ. DO NOT MODIFY!!
+ *============================================================================
+ ****************************************************************************/
+
+#ifndef _META_WIFI_PARA_H_
+#define _META_WIFI_PARA_H_
+
+#include <sys/types.h>
+#include "MetaPub.h"
+#include <cutils/log.h>
+#include <type.h>
+
+#include "CFG_Wifi_File.h"
+
+#define WIFI_GEN_VER (WIFI_NVRAM_VERSION & 0xF000)
+#define CONNAC_SOC3_0 0x3000
+#define CONNAC_SOC2_0 0x2000
+#define SUPPORT_SOC3_0_DNL_VER 0x3030
+
+#if (WIFI_GEN_VER == CONNAC_SOC3_0)
+#define CFG_TSSI_CH_GT_SAME 1 // all gt table apply the same value
+#else
+#define CFG_TSSI_CH_GT_SAME 0 // all gt table apply the same value
+#endif
+
+#if (WIFI_NVRAM_VERSION >= SUPPORT_SOC3_0_DNL_VER)
+#define CFG_DNL_CAL 1
+#else
+#define CFG_DNL_CAL 0
+#endif
+
+#define DRIVER_INIT_TIMEOUT 1000
+
+#define ZONE_ERROR 1
+#define ZONE_FUNC 0
+
+
+#define FUNCTION_CODE_QUERY_OID_VALUE 0x201
+#define FUNCTION_CODE_SET_OID_VALUE 0x205
+#define FUNCTION_CODE_POSTINIT_VALUE 0x209
+#define NVRAM_READ FALSE
+#define NVRAM_WRITE TRUE
+#define G_BAND 0
+#define A_BAND 1
+#define BAND_NUM 2
+
+#define WF0 0
+#define WF1 1
+#define WF_NUM 2
+
+#define META_WIFI_STATUS_SUCCESS 0
+#define META_WIFI_STATUS_FAIL -1
+#define META_WIFI_STATUS_INVALID_PARA -2
+#define META_WIFI_STATUS_NOT_SUPPORT -3
+
+
+#define _META_CTL_CODE(_Function, _Method, _Access) \
+ CTL_CODE(FILE_DEVICE_NETWORK, _Function, _Method, _Access)
+
+#define IOCTL_META_SET_OID_VALUE \
+ _META_CTL_CODE(FUNCTION_CODE_SET_OID_VALUE, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define IOCTL_META_QUERY_OID_VALUE \
+ _META_CTL_CODE(FUNCTION_CODE_QUERY_OID_VALUE, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+
+#define IOCTL_META_WIFI_POSTINIT \
+ _META_CTL_CODE(FUNCTION_CODE_POSTINIT_VALUE, \
+ METHOD_BUFFERED, \
+ FILE_READ_ACCESS | FILE_WRITE_ACCESS)
+
+#define FREEIF(p) do { if(p) free(p); p = NULL; } while(0)
+
+
+
+#define WIFI_DEV_NAME (L"NDL1:")
+#define WIFI_READY_EVENT_NAME (L"OEM/WiFiDriverReady")
+
+
+#define HQA_CMD_MAGIC_NO 0x18142880
+#define HQA_CMD_OPEN_ADAPTER 0x1000
+#define HQA_CMD_CLOSE_ADAPTER 0x1001
+#define HQA_CMD_SetTxPath 0x100B
+#define HQA_CMD_DoCalibrationTestItem 0x150A
+#define HQA_CMD_GetDumpRecal 0x1581
+
+#define HQA_CMD_SetTxPowerExt 0x1011
+#define HQA_CMD_EXTEND 0x1600
+#define HQA_CMD_DBDCSetChannel 0x01
+#define HQA_CMD_DBDCStartTx 0x03
+#define HQA_CMD_DBDCStopTx 0x05
+
+#define HQA_CAL_ITEM_DNL 0x00004000
+#define DNL_WF_PATH_CR_NUM 16 /* CR:32*(WF0+WF1)*/
+
+#define HQA_CAL_ITEM_LNA_GIAN_CAL 0x00008000
+#define LNA_GIAN_CAL_WF_PATH_CR_NUM 2 /*CR:2 *(WF0+WF1)*/
+
+#define TSSI_CH_OFS_GT_NUM 6
+#define PER_CH_GROUP_IN_RF_GROUP 4 /* 2x(low channel+high channel) */
+
+#define MAX_RECAL_DATA_NUM 64
+
+/** chanle group support max num */
+#define CH_GROUP_SUPPORT_MAX_NUM 16
+#define CH_SUB_GROUP_SUPPORT_MAX_NUM 16
+
+/** common category channel group info */
+#define NVRAM_COMMON_CATEGORY_G_BAND_CH_GROUP_NUM 14
+#define NVRAM_COMMON_CATEGORY_A_BAND_CH_GROUP_NUM 8
+
+/** wf path module channel group info (Tssi Ch offset) */
+#define NVRAM_TSSI_CH_OFFSET_G_BAND_CH_GROUP_NUM 14
+#define NVRAM_TSSI_CH_OFFSET_A_BAND_CH_GROUP_NUM 16
+#define NVRAM_TSSI_CH_OFFSET_A_BAND_RF_GROUP_NUM 8
+
+
+/** channel group boundary (common category) */
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_00 1
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_01 2
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_02 3
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_03 4
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_04 5
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_05 6
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_06 7
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_07 8
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_08 9
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_09 10
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_10 11
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_11 12
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_12 13
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_13 14
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_14 255
+#define CH_GROUP_COMMON_G_BAND_BOUNDARY_15 255
+
+
+/** channel group boundary (common category) */
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_00 34
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_01 50
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_02 66
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_03 98
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_04 114
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_05 130
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_06 147
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_07 182
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_08 255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_09 255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_10 255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_11 255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_12 255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_13 255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_14 255
+#define CH_GROUP_COMMON_A_BAND_BOUNDARY_15 255
+
+/** channel group boundary (Tssi Ch offset for G-Band) */
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_00 1
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_01 2
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_02 3
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_03 4
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_04 5
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_05 6
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_06 7
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_07 8
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_08 9
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_09 10
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_10 11
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_11 12
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_12 13
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_13 14
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_14 255
+#define CH_GROUP_TSSI_CH_OFS_G_BAND_BOUNDARY_15 255
+
+/** channel group boundary (Tssi Ch offset for A-Band) */
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_00 5
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_01 34
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_02 40
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_03 50
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_04 56
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_05 66
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_06 80
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_07 98
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_08 104
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_09 114
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_10 120
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_11 130
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_12 136
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_13 144
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_14 157
+#define CH_GROUP_TSSI_CH_OFS_A_BAND_BOUNDARY_15 182
+
+
+/** sub-group boundary (TX for G-Band) */
+#define CH_SUB_GROUP_G_BAND_NOT_ORDERED_NUM 0
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_00 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_01 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_02 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_03 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_04 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_05 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_06 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_07 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_08 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_09 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_10 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_11 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_12 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_13 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_14 255
+#define CH_SUB_GROUP_G_BAND_BOUNDARY_15 255
+
+/** channel power offset sub-group boundary (TX for A-Band) */
+#define CH_SUB_GROUP_A_BAND_NOT_ORDERED_NUM 0
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_00 190
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_01 17
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_02 37
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_03 45
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_04 53
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_05 61
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_06 75
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_07 89
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_08 102
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_09 110
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_10 118
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_11 125
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_12 134
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_13 142
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_14 153
+#define CH_SUB_GROUP_A_BAND_BOUNDARY_15 163
+
+
+#define NVRAM_GT2_OFFSET 0x00
+#define NVRAM_GT3_OFFSET 0x01
+#define NVRAM_GT4_OFFSET 0x02
+#define NVRAM_GT5_OFFSET 0x03
+#define NVRAM_GT6_OFFSET 0x04
+#define NVRAM_GT7_OFFSET 0x05
+
+#define NDL_OFFSET_BIAS0_MASK 0xFF000000
+#define NDL_OFFSET_BIAS0_SHFT 24
+
+#define NDL_OFFSET_BIAS1_MASK 0x00FF0000
+#define NDL_OFFSET_BIAS1_SHFT 16
+
+#define NDL_OFFSET_BIAS2_MASK 0x0000FF00
+#define NDL_OFFSET_BIAS2_SHFT 8
+
+#define NDL_OFFSET_BIAS3_MASK 0x000000FF
+#define NDL_OFFSET_BIAS3_SHFT 0
+
+#define NDL_OFFSET_BIAS4_MASK 0xFF000000
+#define NDL_OFFSET_BIAS4_SHFT 24
+
+#define NDL_OFFSET_BIAS5_MASK 0x00FF0000
+#define NDL_OFFSET_BIAS5_SHFT 16
+
+
+#define LNA_GAIN_TAB0_MASK 0x7F000000 //[30..24]
+#define LNA_GAIN_TAB0_SHFT 24
+
+#define LNA_GAIN_TAB1_MASK 0x007F0000 //[22..16]
+#define LNA_GAIN_TAB1_SHFT 16
+
+#define LNA_GAIN_TAB2_MASK 0x00007F00 //[14..8]
+#define LNA_GAIN_TAB2_SHFT 8
+
+#define LNA_GAIN_TAB3_MASK 0x0000007F //[6..0]
+#define LNA_GAIN_TAB3_SHFT 0
+
+#define LNA_GAIN_TAB4_MASK 0x7F000000 //[30..24]
+#define LNA_GAIN_TAB4_SHFT 24
+
+
+/* This macro returns the byte offset of a named field in a known structure
+ * type.
+ * _type - structure name,
+ * _field - field name of the structure
+ */
+#ifndef OFFSET_OF
+#define OFFSET_OF(_type, _field) offsetof(_type, _field)
+#endif /* OFFSET_OF */
+#define SIGNED_CONVERT_EXTEND_BITS(data,ori_res) ((unsigned)(data) >= (unsigned)BIT((ori_res) - 1) ? (signed)((data)- BIT((ori_res))) : (signed)(data))
+
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "WIFI_META "
+#define WIFI_META_VER "20191021_0"
+
+#define WIFI_META_TEST_DEBUG 0
+#if (WIFI_META_TEST_DEBUG == 1)
+#define DBG(f, ...) printf(f, ##__VA_ARGS__)
+#define TRC(f, ...) printf(f, ##__VA_ARGS__)
+#define ERR(f, ...) printf(f, ##__VA_ARGS__)
+#define WAN(f, ...) printf(f, ##__VA_ARGS__)
+#else
+#define DBG(f, ...) ALOGD("%s: " f, __func__, ##__VA_ARGS__)
+#define TRC(f) ALOGW("%s #%d", __func__, __LINE__)
+#define ERR(f, ...) ALOGE("%s: " f, __func__, ##__VA_ARGS__)
+#define WAN(f, ...) ALOGW("%s: " f, __func__, ##__VA_ARGS__)
+#endif
+
+
+typedef enum
+{
+ WIFI_CMD_SET_OID = 0,
+ WIFI_CMD_QUERY_OID = 1,
+ WIFI_CMD_NVRAM_WRITE_ACCESS = 2,
+ WIFI_CMD_NVRAM_READ_ACCESS = 3,
+ WIFI_CMD_INIT = 4,
+ WIFI_CMD_DEINIT = 5,
+ WIFI_CMD_SCRIPT = 6,
+ WIFI_CMD_HQA = 7,
+ WIFI_CMD_PL_CALIBRATION = 8,
+ WIFI_CMD_NUM
+} WIFI_CMD_TYPE;
+
+typedef enum
+{
+ WIFI_PL_CAL_TX_PWR = 1,
+ WIFI_PL_CAL_EPA_FE_GAIN = 2,
+ WIFI_PL_CAL_LNA_GAIN_CAL = 3, /*RSSI GAIN CAL*/
+ WIFI_PL_CAL_DNL_CAL = 4,
+ WIFI_PL_CAL_NUM
+} WIFI_PL_CAL_TYPE;
+
+typedef enum
+{
+ TX_PWR_CAL_ACT_START = 0,
+ TX_PWR_CAL_ACT_ADJUST = 1,
+ TX_PWR_CAL_ACT_END = 2,
+ TX_PWR_CAL_ACT_INTERPOLAT = 3, //Interpolation
+ TX_PWR_CAL_ACT_NUM
+} TX_PWR_CAL_ACT;
+
+
+typedef enum
+{
+ TYPE_INTERPOLATION = 0,
+ TYPE_GROUP_THE_SAME = 1,
+ TX_PWR_INTERPOLATION_NUM
+} TX_PWR_INTERPOLATION_TYPE;
+
+typedef enum
+{
+ INTER_ACT_INTERPOLATION = 0,
+ INTER_ACT_GROUP_THE_SAME = 1,
+ INTER_ACT_NOT_SUPPORT = 2,
+ INTER_ACT_NUM
+} INTER_ACT;
+
+
+/* This starting freq of the band is unit of kHz */
+typedef enum _ENUM_BAND_T
+{
+ BAND_NULL = 0000000,
+ BAND_2G4 = 2407000,
+ BAND_5G = 5000000,
+ BAND_4G9375 = 4937500,
+ BAND_4G89 = 4890000,
+ BAND_4G85 = 4850000,
+ BAND_4G = 4000000,
+ BAND_5G0025 = 5002500,
+ BAND_4G0025 = 4002500
+} ENUM_BAND_T, *P_ENUM_BAND_T;
+
+/* The following macro to translate channel number to its center freq
+ * in unit of kHz
+ */
+#define CHNL_FREQ_2G(n) (((n) == 14) ? 2484000 : \
+ (BAND_2G4 + 5000 * (n)))
+#define CHNL_FREQ_5G(n) (BAND_5G + 5000 * (n))
+#define CHNL_FREQ_4G9375(n) (BAND_4G9375 + 5000 * (n))
+#define CHNL_FREQ_4G89(n) (BAND_4G89 + 5000 * (n))
+#define CHNL_FREQ_4G85(n) (BAND_4G85 + 5000 * (n))
+#define CHNL_FREQ_4G(n) (BAND_4G + 5000 * (n))
+#define CHNL_FREQ_5G0025(n) (BAND_5G0025 + 5000 * (n))
+#define CHNL_FREQ_4G0025(n) (BAND_4G0025 + 5000 * (n))
+
+#define CHNL_FREQ(_eBand, _u1Chnl) \
+ (((_eBand) == BAND_2G4 && (_u1Chnl) == 14) ? 2484000 : \
+ ((_eBand) + 5000 * (_u1Chnl)))
+
+#define FREQ_BAND(_u4Freq) \
+ ((_u4Freq) < BAND_4G ? BAND_2G4 : BAND_5G) /* To do: support more bands */
+
+#define FREQ_CHNL(_eBand, _u4Freq) \
+ ((unsigned char)(((_eBand) == BAND_2G4 && (_u4Freq) == 2484000) ? 14 : \
+ (((_u4Freq) - (_eBand)) / 5000)))
+
+/** channel group category item */
+typedef enum _ENUM_CH_GROUP_ITEM
+{
+ CH_GROUP_ITEM_COMMON = 0x00,
+ CH_GROUP_ITEM_TSSI_CH = 0x01,
+ CH_GROUP_ITEM_NUM
+} ENUM_CH_GROUP_ITEM, *P_ENUM_CH_GROUP_ITEM;
+
+/** channel sub-group category item */
+typedef enum _ENUM_CH_SUB_GROUP_ITEM
+{
+ CH_SUB_GROUP_TSSI_CH = 0,
+ CH_SUB_GROUP_ITEM_NUM
+} ENUM_CH_SUB_GROUP_ITEM, *P_ENUM_CH_SUB_GROUP_ITEM;
+
+
+typedef enum _ENUM_CH_SUB_GROUP_2G4_ITEM
+{
+ CH_SUB_GROUP_2G4_LOW = 0,
+ CH_SUB_GROUP_2G4_MID,
+ CH_SUB_GROUP_2G4_HIGH,
+ CH_SUB_GROUP_2G4_ITEM_NUM
+} ENUM_CH_SUB_GROUP_2G4_ITEM, *P_ENUM_CH_SUB_GROUP_2G4_ITEM;
+
+typedef enum _ENUM_CH_SUB_GROUP_5G_ITEM
+{
+ CH_SUB_GROUP_5G_LOW = 0,
+ CH_SUB_GROUP_5G_HIGH,
+ CH_SUB_GROUP_5G_ITEM_NUM
+} ENUM_CH_SUB_GROUP_5G_ITEM, *P_ENUM_CH_SUB_GROUP_5G_ITEM;
+
+typedef enum _ENUM_CBW_DBW_T
+{
+ CDBW_20,
+ CDBW_40,
+ CDBW_80,
+ CDBW_160,
+ CDBW_80P80,
+ CDBW_5,
+ CDBW_10,
+ CDBW_NUM
+} ENUM_CBW_DBW_T, *P_ENUM_CBW_DBW_T;
+
+/** channel group info structure */
+typedef struct _CH_GROUP_CLASS
+{
+ ENUM_CH_GROUP_ITEM eGroupId;
+ unsigned char u1ChGroupSupportNum;
+ unsigned char u1ChGroupBoundary[CH_GROUP_SUPPORT_MAX_NUM];
+} CH_GROUP_CLASS, *P_CH_GROUP_CLASS;
+
+/** channel power offset group info structure */
+typedef struct _CH_SUB_GROUP_CLASS
+{
+ ENUM_CH_SUB_GROUP_ITEM eGroupId;
+ unsigned char u1ChSubGroupCategoryNum;
+ unsigned char u1ChSubGroupNotOrderedNum;
+ unsigned char u1ChSubGroupBoundary[CH_SUB_GROUP_SUPPORT_MAX_NUM];
+} CH_SUB_GROUP_CLASS, *P_CH_SUB_GROUP_CLASS;
+
+typedef struct
+{
+ FT_H header;
+ WIFI_CMD_TYPE type;
+ int dummy;
+} FT_WM_WIFI_REQ;
+
+typedef struct
+{
+ FT_H header;
+ WIFI_CMD_TYPE type;
+ int drv_status;
+ unsigned char status;
+} FT_WM_WIFI_CNF;
+typedef struct _INTERPOLATION_CH_BOUND_A_BAND
+{
+ unsigned char lowBoundCh;
+ unsigned char upperBoundCh;
+} INTERPOLATION_CH_BOUND_A_BAND, *P_INTERPOLATION_CH_BOUND_A_BAND;
+
+
+typedef struct _CMD_PL_CAL
+{
+ unsigned int calId;
+ unsigned int action;
+ unsigned int flags;
+ unsigned int inputLen;
+ unsigned int au4Buffer[100];
+} CMD_PL_CAL, *P_CMD_PL_CAL;
+
+typedef struct _SET_OID_STRUC
+{
+ unsigned int oid;
+ unsigned int dataLen;
+ unsigned char data[1];
+
+} SET_OID_STRUC, *PSET_OID_STRUC;
+
+
+typedef struct _QUERY_OID_STRUC
+{
+ unsigned int oid;
+ unsigned int dataLen;
+ unsigned char data[1];
+
+} QUERY_OID_STRUC, *PQUERY_OID_STRUC;
+
+typedef struct _NVRAM_ACCESS_STRUCT
+{
+ unsigned int dataLen;
+ unsigned int dataOffset;
+ unsigned char data[1];
+} NVRAM_ACCESS_STRUCT, *PNVRAM_ACCESS_STRUCT;
+
+typedef union
+{
+ SET_OID_STRUC SetOidPara;
+ QUERY_OID_STRUC QueryOidPara;
+} OID_STRUC, *POID_STRUC;
+
+typedef struct _HQA_CMD_FRAME
+{
+ unsigned int magicNo;
+ unsigned short type;
+ unsigned short id;
+ unsigned short length;
+ unsigned short sequence;
+ unsigned char data[1];
+} HQA_CMD_FRAME, *P_HQA_CMD_FRAME;
+
+typedef struct _HQA_SET_TX_PATH
+{
+ unsigned int tx_path;
+ unsigned int band_idx;
+} HQA_SET_TX_PATH, *P_HQA_SET_TX_PATH;
+
+typedef struct _HQA_SET_TX_POWER
+{
+ unsigned int power;
+ unsigned int band_idx;
+ unsigned int channel;
+ unsigned int channel_band;
+ unsigned int ant_idx;
+} HQA_SET_TX_POWER, *P_HQA_SET_TX_POWER;
+
+
+typedef struct _HQA_DO_CAL_TEST_ITEM
+{
+ unsigned int item;
+ unsigned int band_idx;
+} HQA_DO_CAL_TEST_ITEM, *P_HQA_DO_CAL_TEST_ITEM;
+
+typedef struct _RECAL_INFO_T
+{
+ unsigned short status;
+ unsigned int u4Count;
+ unsigned int u4CalId[MAX_RECAL_DATA_NUM];
+ unsigned int u4CalAddr[MAX_RECAL_DATA_NUM];
+ unsigned int u4CalValue[MAX_RECAL_DATA_NUM];
+} RECAL_INFO_T, *P_RECAL_INFO_T;
+
+typedef struct _HQA_SET_CH
+{
+ unsigned int ext_id;
+ unsigned int num_param;
+ unsigned int band_idx;
+ unsigned int central_ch0;
+ unsigned int central_ch1;
+ unsigned int sys_bw;
+ unsigned int perpkt_bw;
+ unsigned int pri_sel;
+ unsigned int reason;
+ unsigned int ch_band;
+ unsigned int out_band_freq;
+} HQA_SET_CH, *P_HQA_SET_CH;
+
+
+typedef struct _HQA_PARA_INFO
+{
+ unsigned int wf_idx; /* bit[0]:WF0,bit[1]:WF1,bit[2]:WF0/WF1 */
+ unsigned int dbdcBandIdx;
+ unsigned int chBand; /*0:2,4G , 1:5G*/
+ unsigned int chS1; /* Channel Number in unit of kHz - 20/40/80/160 */
+ unsigned int chS2; /* Channel Number in unit of kHz - 80+80*/
+ ENUM_CBW_DBW_T eCbw;
+ unsigned int power; /* In unit of 0.5 dBm */
+} HQA_PARA_INFO, *P_HQA_PARA_INFO;
+
+WLAN_STATUS wifiNVRAMTssiChOfsAdjust(unsigned int wf, ENUM_BAND_T eBand, unsigned int ch, unsigned int targetPwr, unsigned int MeanPwr);
+int META_WIFI_init(void);
+void META_WIFI_deinit(void);
+void META_WIFI_OP(FT_WM_WIFI_REQ *req, char *peer_buf, unsigned short peer_len);
+WLAN_STATUS wifiHqaGetDumpReCal(unsigned int item, unsigned int dbdcBandIdx, P_RECAL_INFO_T prReCalInfo);
+WLAN_STATUS wifiHqaDoCalibrationTestItem(unsigned int item, unsigned int dbdcBandIdx);
+#endif
diff --git a/src/devtools/meta/src/adaptor/wifi/meta_wifi_test.c b/src/devtools/meta/src/adaptor/wifi/meta_wifi_test.c
new file mode 100644
index 0000000..0c1c47c
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/meta_wifi_test.c
@@ -0,0 +1,759 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include "meta_wifi.h"
+#include <cutils/log.h>
+#include <arpa/inet.h>
+#include <unistd.h>
+
+#ifdef LOG_TAG
+#undef LOG_TAG
+#endif
+#define LOG_TAG "WIFI_META "
+
+static void wifi_info_callback(FT_WM_WIFI_CNF *cnf, void *buf, unsigned int size)
+{
+ unsigned int i;
+ char *type[] = { "WIFI_CMD_SET_OID", "WIFI_CMD_QUERY_OID", "WIFI_CMD_NVRAM_WRITE_ACCESS", "WIFI_CMD_NVRAM_READ_ACCESS"
+ , "WIFI_CMD_INIT", "WIFI_CMD_DEINIT", "WIFI_CMD_SCRIPT", "WIFI_CMD_HQA", "WIFI_CMD_PL_CALIBRATION"
+ };
+ OID_STRUC *poid;
+
+ P_CMD_PL_CAL prCmdPlCal;
+
+ if (buf == NULL)
+ {
+ printf("[META_WIFI] %s is Null!\n", __func__);
+ return;
+ }
+
+ printf("[META_WIFI] <CNF> %s, Drv Status: %d, Status: %d\n", type[cnf->type],
+ cnf->drv_status, cnf->status);
+
+ switch (cnf->type)
+ {
+ case WIFI_CMD_SET_OID:
+ case WIFI_CMD_QUERY_OID:
+ {
+ poid = (OID_STRUC *)buf;
+ printf("META_WIFI] <CNF> OID: %d, data len: %d\n",
+ poid->QueryOidPara.oid, poid->QueryOidPara.dataLen);
+
+ for (i = 0; i < poid->QueryOidPara.dataLen; i++)
+ {
+ printf("META_WIFI] <CNF> Data[%d] = 0x%x\n",
+ i, poid->QueryOidPara.data[i]);
+ }
+
+ break;
+ }
+
+ case WIFI_CMD_SCRIPT:
+ {
+ printf("[META_WIFI] <CNF> DataBuf(%d)= %s\n", size, buf);
+ break;
+ }
+
+ case WIFI_CMD_PL_CALIBRATION:
+ {
+ prCmdPlCal = (P_CMD_PL_CAL)buf;
+ printf("[META_WIFI] <WIFI_CMD_PL_CALIBRATION> id=%d,act=%d,Len=%d\n",
+ prCmdPlCal->calId,
+ prCmdPlCal->action,
+ prCmdPlCal->inputLen);
+
+ for (i = 0; i < prCmdPlCal->inputLen; i++)
+ {
+ printf("META_WIFI] Data[%d] = 0x%08x\n",
+ i, prCmdPlCal->au4Buffer[i]);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ printf("[META_WIFI] %s is Null!\n", __func__);
+ return;
+ }
+ }
+}
+
+void DoTestTssiChOffset()
+{
+ FT_WM_WIFI_REQ req;
+
+ CMD_PL_CAL rCmdPlCal;
+ P_HQA_CMD_FRAME prHqaCmd;
+ HQA_SET_TX_PATH rSetTxPath;
+ HQA_SET_TX_POWER rSetTxPower;
+ HQA_SET_CH rSetCh;
+ int u4hqaCmdLen = 0;
+ int ext_id = 0;
+
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_SET_CH);
+ prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+
+ memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+ memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_OPEN_ADAPTER); //OPEN ADAPTER
+ prHqaCmd->length = 0;
+ prHqaCmd->sequence = 1;
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================HQA OPEN ADAPTER DONE====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_TX_PWR;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_START;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL TXPWR -START DONE====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+ prHqaCmd->length = htons(sizeof(rSetTxPath));
+ prHqaCmd->sequence = 1;
+ rSetTxPath.tx_path = htonl(0x01);
+ rSetTxPath.band_idx = htonl(0x00);
+ memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA Set Tx Path DONE====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_SetTxPowerExt);
+ prHqaCmd->length = htons(sizeof(rSetTxPath));
+ prHqaCmd->sequence = 2;
+ rSetTxPower.power = htonl(0x1E);
+ rSetTxPower.band_idx = htonl(0x00);
+ rSetTxPower.channel = htonl(0x00);
+ rSetTxPower.channel_band = htonl(0x00);
+ rSetTxPower.ant_idx = htonl(0x00);
+ memcpy(&prHqaCmd->data[0], &rSetTxPower, sizeof(rSetTxPower));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPower);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA Set Tx Power DONE====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(7); //channel 7
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+ prHqaCmd->length = htons(sizeof(unsigned int));
+ prHqaCmd->sequence = 4;
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+ ext_id = htonl(HQA_CMD_DBDCStartTx); //HQA_DBDCSetChannel
+ memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA START TX DONE====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+ prHqaCmd->length = htons(sizeof(unsigned int));
+ prHqaCmd->sequence = 4;
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+ ext_id = htonl(HQA_CMD_DBDCStopTx); //HQA_DBDCSetChannel
+ memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA STOP TX DONE====================\n");
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_TX_PWR;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 1;
+ rCmdPlCal.au4Buffer[0] = 0x1000; //Tool Measurement(S23.8)
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL ADJUST DONE====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+ prHqaCmd->length = htons(sizeof(rSetTxPath));
+ prHqaCmd->sequence = 1;
+ rSetTxPath.tx_path = htonl(0x01);
+ rSetTxPath.band_idx = htonl(0x00);
+ memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R2:HQA Set Tx Path DONE====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_SetTxPowerExt);
+ prHqaCmd->length = htons(sizeof(rSetTxPath));
+ prHqaCmd->sequence = 2;
+ rSetTxPower.power = htonl(0x16);
+ rSetTxPower.band_idx = htonl(0x00);
+ rSetTxPower.channel = htonl(0x00);
+ rSetTxPower.channel_band = htonl(0x00);
+ rSetTxPower.ant_idx = htonl(0x00);
+ memcpy(&prHqaCmd->data[0], &rSetTxPower, sizeof(rSetTxPower));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPower);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R2:HQA Set Tx Power DONE====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(6); //channel 6
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R2:HQA DBDC Set Channel DONE====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+ prHqaCmd->length = htons(sizeof(unsigned int));
+ prHqaCmd->sequence = 4;
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+ ext_id = htonl(HQA_CMD_DBDCStartTx); //HQA_DBDCSetChannel
+ memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R2:HQA START TX DONE====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND); //OPEN ADAPTER
+ prHqaCmd->length = htons(sizeof(unsigned int));
+ prHqaCmd->sequence = 4;
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+ ext_id = htonl(HQA_CMD_DBDCStopTx); //HQA_DBDCSetChannel
+ memcpy(&prHqaCmd->data[0], &ext_id, sizeof(ext_id));
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R2:HQA STOP TX DONE====================\n");
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_TX_PWR;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_END;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 1;
+ rCmdPlCal.au4Buffer[0] = 0; /*success*/
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL TXPWR -FINISH DONE====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_CLOSE_ADAPTER); //CLOSE ADAPTER
+ prHqaCmd->length = 0;
+ prHqaCmd->sequence = 2;
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================CLOSE ADAPTER Done====================\n");
+
+
+#if 1
+ int inputCh[] = {3, 0, 4, 1, 4, 7, 13};
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_TX_PWR;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_INTERPOLAT;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = sizeof(inputCh) / sizeof(int);
+ rCmdPlCal.au4Buffer[0] = 0; /*success*/
+ memcpy(&rCmdPlCal.au4Buffer[0], &inputCh[0], sizeof(inputCh));
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL TXPWR - Interpolation ====================\n");
+#endif
+
+ FREEIF(prHqaCmd);
+
+}
+void DoTest2G4Interpolation()
+{
+
+ FT_WM_WIFI_REQ req;
+
+ CMD_PL_CAL rCmdPlCal;
+ memset(&rCmdPlCal, 0, sizeof(rCmdPlCal));
+
+ int inputCh[] = {3, 0, 4, 1, 4, 7, 13};
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_TX_PWR;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_INTERPOLAT;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = sizeof(inputCh) / sizeof(int);
+ rCmdPlCal.au4Buffer[0] = 0; /*success*/
+ memcpy(&rCmdPlCal.au4Buffer[0], &inputCh[0], sizeof(inputCh));
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL TXPWR - 2.4G Interpolation ====================\n");
+
+}
+void DoTest5GInterpolation()
+{
+
+ FT_WM_WIFI_REQ req;
+
+ CMD_PL_CAL rCmdPlCal;
+ memset(&rCmdPlCal, 0, sizeof(rCmdPlCal));
+
+ int inputCh[] = {2, 0, 14, 36, 48, 52, 64, 100, 112, 116, 128, 132, 144, 149, 165, 184, 192};
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_TX_PWR;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_INTERPOLAT;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = sizeof(inputCh) / sizeof(int);
+ rCmdPlCal.au4Buffer[0] = 0; /*success*/
+ memcpy(&rCmdPlCal.au4Buffer[0], &inputCh[0], sizeof(inputCh));
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL TXPWR - 5G Interpolation ====================\n");
+}
+void DoTestDNLCal()
+{
+
+ FT_WM_WIFI_REQ req;
+ P_HQA_CMD_FRAME prHqaCmd;
+ HQA_SET_CH rSetCh;
+ HQA_SET_TX_PATH rSetTxPath;
+ CMD_PL_CAL rCmdPlCal;
+
+ int u4hqaCmdLen = 0;
+
+ printf("====================DoTestDNLCal====================\n");
+
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_SET_CH);
+ prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+
+
+ memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+ memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_OPEN_ADAPTER); //OPEN ADAPTER
+ prHqaCmd->length = 0;
+ prHqaCmd->sequence = 1;
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================HQA OPEN ADAPTER DONE====================\n");
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_DNL_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_START;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL DNL -START DONE====================\n");
+
+
+#if 1
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+ prHqaCmd->length = htons(sizeof(rSetTxPath));
+ prHqaCmd->sequence = 1;
+ rSetTxPath.tx_path = htonl(0x01);
+ rSetTxPath.band_idx = htonl(0x00);
+ memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA Set Tx Path DONE====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(7); //channel 6
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_DNL_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================DNL adjust done!====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(192); //channel 8
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_DNL_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================DNL adjust done!====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(100); //channel 100
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_DNL_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================DNL adjust done!====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_DNL_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_END;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================DNL END done!====================\n");
+
+
+#endif
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_CLOSE_ADAPTER); //CLOSE ADAPTER
+ prHqaCmd->length = 0;
+ prHqaCmd->sequence = 2;
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================CLOSE ADAPTER Done====================\n");
+
+
+ FREEIF(prHqaCmd);
+
+}
+void DoTestLnaGainCal()
+{
+
+ FT_WM_WIFI_REQ req;
+ P_HQA_CMD_FRAME prHqaCmd;
+ HQA_SET_CH rSetCh;
+ HQA_SET_TX_PATH rSetTxPath;
+ CMD_PL_CAL rCmdPlCal;
+
+ int u4hqaCmdLen = 0;
+
+ printf("====================DoTestLnaGainCal====================\n");
+
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(HQA_SET_CH);
+ prHqaCmd = (P_HQA_CMD_FRAME)malloc(u4hqaCmdLen);
+
+
+ memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+ memset(prHqaCmd, 0, u4hqaCmdLen);
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_OPEN_ADAPTER); //OPEN ADAPTER
+ prHqaCmd->length = 0;
+ prHqaCmd->sequence = 1;
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================HQA OPEN ADAPTER DONE====================\n");
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_LNA_GAIN_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_START;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================PL LNA GAIN CAL -START DONE====================\n");
+
+
+#if 1
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_SetTxPath);
+ prHqaCmd->length = htons(sizeof(rSetTxPath));
+ prHqaCmd->sequence = 1;
+ rSetTxPath.tx_path = htonl(0x01);
+ rSetTxPath.band_idx = htonl(0x00);
+ memcpy(&prHqaCmd->data[0], &rSetTxPath, sizeof(rSetTxPath));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetTxPath);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA Set Tx Path DONE====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(7); //channel 6
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(0); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_LNA_GAIN_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================LNA GAIN CAL adjust done!====================\n");
+
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(192); //channel 8
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_LNA_GAIN_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================LNA GAIN CAL adjust done!====================\n");
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_EXTEND);
+ prHqaCmd->length = htons(sizeof(rSetCh));
+ prHqaCmd->sequence = 3;
+ rSetCh.ext_id = htonl(HQA_CMD_DBDCSetChannel); //HQA_DBDCSetChannel
+ rSetCh.num_param = htonl(0x06);
+ rSetCh.band_idx = htonl(0x00);
+ rSetCh.central_ch0 = htonl(100); //channel 100
+ rSetCh.central_ch1 = htonl(0x00);
+ rSetCh.sys_bw = htonl(0);
+ rSetCh.perpkt_bw = htonl(0);
+ rSetCh.ch_band = htonl(1); //0:2.4G,1:5G
+ memcpy(&prHqaCmd->data[0], &rSetCh, sizeof(rSetCh));
+ u4hqaCmdLen = sizeof(HQA_CMD_FRAME) + sizeof(rSetCh);
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================R1:HQA DBDC Set Channel DONE====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_LNA_GAIN_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_ADJUST;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================LNA GAIN CAL adjust done!====================\n");
+
+
+ req.type = WIFI_CMD_PL_CALIBRATION;
+ rCmdPlCal.calId = WIFI_PL_CAL_LNA_GAIN_CAL;
+ rCmdPlCal.action = TX_PWR_CAL_ACT_END;
+ rCmdPlCal.flags = FALSE;
+ rCmdPlCal.inputLen = 0;
+ META_WIFI_OP(&req, (char *)&rCmdPlCal, sizeof(rCmdPlCal));
+ printf("====================LNA GAIN CAL END done!====================\n");
+
+
+#endif
+
+ req.type = WIFI_CMD_HQA;
+ prHqaCmd->magicNo = htonl(HQA_CMD_MAGIC_NO);
+ prHqaCmd->type = 0;
+ prHqaCmd->id = htons(HQA_CMD_CLOSE_ADAPTER); //CLOSE ADAPTER
+ prHqaCmd->length = 0;
+ prHqaCmd->sequence = 2;
+ META_WIFI_OP(&req, (char *)prHqaCmd, u4hqaCmdLen);
+ printf("====================CLOSE ADAPTER Done====================\n");
+
+
+ FREEIF(prHqaCmd);
+
+}
+
+
+void doScript(void)
+{
+ FT_WM_WIFI_REQ req;
+
+ memset(&req, 0, sizeof(FT_WM_WIFI_REQ));
+
+ req.type = WIFI_CMD_SCRIPT;
+
+ char *cmd2 = "adb shell iwpriv driver set_mcr 2011 2011";
+ printf("[META_WIFI] WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd2, strlen(cmd2));
+ META_WIFI_OP(&req, cmd2, strlen(cmd2));
+
+ char *cmd3 = "adb shell iwpriv driver get_mcr 0x820F4020";
+ printf("[META_WIFI] WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd3, strlen(cmd3));
+ META_WIFI_OP(&req, cmd3, strlen(cmd3));
+
+
+ char *cmd4 = "adb shell iwpriv driver set_mcr 0x820F4020 0x14141414";
+ printf("[META_WIFI] WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd4, strlen(cmd4));
+ META_WIFI_OP(&req, cmd4, strlen(cmd4));
+
+
+ char *cmd5 = "adb shell iwpriv driver get_mcr 0x820F4020";
+ printf("[META_WIFI] WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd5, strlen(cmd5));
+ META_WIFI_OP(&req, cmd5, strlen(cmd5));
+
+ //GET_NOISE
+ char *cmd6 = "adb shell iwpriv driver get_noise";
+ printf("[META_WIFI] WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd6, strlen(cmd6));
+ META_WIFI_OP(&req, cmd6, strlen(cmd6));
+
+ //GET_NOISE
+ char *cmd7 = "adb shell iwpriv get_noise";
+ printf("[META_WIFI] WIFI_CMD_SCRIPT execute:%s sizeof(%lu)\n", cmd7, strlen(cmd7));
+ META_WIFI_OP(&req, cmd7, strlen(cmd7));
+
+
+}
+int main()
+{
+
+ META_WIFI_Register(wifi_info_callback);
+
+ if (META_WIFI_init() == false)
+ {
+ printf("WLAN init failed\n");
+ return -1;
+ }
+
+ /*Test Case: TSSI DNL OFFSET CALIBRATION*/
+ //DoTestDNLCal();
+
+ /*Test Case: TSSI Channel offset compensation*/
+ //DoTestTssiChOffset();
+
+ /*Test Case: LNA GAIN CAL*/
+ //DoTestLnaGainCal();
+
+ DoTest2G4Interpolation();
+
+
+ /*Test Case: Tssi 5G RF Group Interpolation*/
+ DoTest5GInterpolation();
+
+ printf("Sleep 1s\n");
+ usleep(1 * 1000 * 1000);
+
+ META_WIFI_deinit();
+ META_WIFI_Register(NULL);
+
+ return 0;
+}
+
diff --git a/src/devtools/meta/src/adaptor/wifi/type.h b/src/devtools/meta/src/adaptor/wifi/type.h
new file mode 100644
index 0000000..3b34a44
--- /dev/null
+++ b/src/devtools/meta/src/adaptor/wifi/type.h
@@ -0,0 +1,52 @@
+/*******************************************************************************
+** Copyright (c) 2005 MediaTek Inc.
+**
+** All rights reserved. Copying, compilation, modification, distribution
+** or any other use whatsoever of this material is strictly prohibited
+** except in accordance with a Software License Agreement with
+** MediaTek Inc.
+********************************************************************************
+*/
+#ifndef _TYPE_H
+#define _TYPE_H
+
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+
+#if !defined(TRUE)
+#define TRUE true
+#endif
+
+#if !defined(FALSE)
+#define FALSE false
+#endif
+
+#define IN
+#define OUT
+
+#define DLL_FUNC
+
+#define TEXT
+
+#define BIT(n) ((unsigned int) 1 << (n))
+#define BITS(m,n) (~(BIT(m)-1) & ((BIT(n) - 1) | BIT(n)))
+
+/* Type definition for WLAN STATUS */
+#define WLAN_STATUS unsigned int
+#define P_WLAN_STATUS unsigned int*
+
+#ifndef RX_ANT_
+#define RX_ANT_
+typedef enum
+{
+ AGC_RX_ANT_SEL,
+ MPDU_RX_ANT_SEL,
+ FIXED_0,
+ FIXED_1
+} RX_ANT_SEL;
+#endif
+
+#endif
diff --git a/src/devtools/meta/src/common/inc/CmdTarget.h b/src/devtools/meta/src/common/inc/CmdTarget.h
new file mode 100644
index 0000000..d0549be
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/CmdTarget.h
@@ -0,0 +1,51 @@
+#ifndef _CMD_TARGET_H_
+#define _CMD_TARGET_H_
+
+#include "Frame.h"
+
+class CmdTarget
+{
+public:
+ CmdTarget(unsigned short);
+ virtual ~CmdTarget(void);
+
+public:
+ virtual void exec(Frame*);
+
+ unsigned short getId() const
+ {
+ return m_myId;
+ }
+
+ unsigned short getToken() const
+ {
+ return m_token;
+ }
+
+ void setToken(unsigned short token)
+ {
+ m_token = token;
+ }
+
+ int getInitState() const
+ {
+ return m_isInited;
+ }
+protected:
+ virtual int init(Frame*);
+ virtual void deinit();
+
+private:
+ unsigned short m_myId;
+ int m_isInited;
+ unsigned short m_token;
+};
+/*
+template <typename _Tx>
+_Tx *getInstance()
+{
+ static _Tx _inst;
+ return &_inst;
+}
+*/
+#endif // _CMD_TARGET_H_
diff --git a/src/devtools/meta/src/common/inc/Context.h b/src/devtools/meta/src/common/inc/Context.h
new file mode 100644
index 0000000..de56af9
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Context.h
@@ -0,0 +1,135 @@
+#ifndef _CONETXT_H_
+#define _CONETXT_H_
+
+#include "MetaPub.h"
+
+
+#define MD1_INDEX 0x01
+#define MD2_INDEX 0x02
+#define MD3_INDEX 0x04
+#define MD5_INDEX 0x10
+
+
+typedef enum
+{
+ MODEM_AP_TST = 0,
+ MODEM_DHL = 1,
+ MODEM_6292 = 2,
+ MODEM_6293 = 3,
+ MODEM_6295 = 4,
+ MODEM_END = 5,
+}Modem_Hw_Version;
+
+
+//#define BOOTMODE_PATH "/sys/class/BOOT/BOOT/boot/boot_mode"
+#define BOOTMODE_PATH "/proc/device-tree/chosen/atag,boot" //for common kernel
+//struct tag_bootmode {
+//u32 size;
+//u32 tag;
+//u32 bootmode;
+//u32 boottype;
+//};
+
+#define UNKNOWN_BOOT -1
+#define NORMAL_BOOT 0
+#define META_BOOT 1
+
+//Jade
+//#define FLAG_PATH "/dev/block/platform/mtk-msdc.0/11230000.msdc0/by-name/proinfo"
+//Bianco
+#define FLAG_PATH "/dev/block/platform/bootdevice/by-name/proinfo"
+#define OFFSET_ATM (64+4*10+170+64+4+8)
+#define OFFSET_METALOG (349)
+#define KEY1 12345678
+#define KEY2 23131123
+#define ENCRYPT_LENTH 8
+
+#define USBONLINE_STATUS_PATH "/sys/class/power_supply/usb/online"
+
+class Modem;
+class CmdTarget;
+class UsbRxWatcher;
+class MSocket;
+
+Modem * createModem(const char *ccci, unsigned short id);
+Modem * createModem(unsigned short id);
+void destroyModem(Modem *p);
+
+Modem * getModem(unsigned short id);
+CmdTarget * getModule(unsigned short id);
+unsigned int getMdmType();
+unsigned int getActiveMdmId();
+unsigned int getMdmNumber();
+signed int getModemHandle(unsigned short id);
+
+unsigned int dumpData(const unsigned char* con, int length);
+unsigned int dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow=16);
+unsigned int getFileSize(int fd);
+const char* makepath(unsigned char file_ID);
+void createModemThread(unsigned short modemIndex,int usbUsb);
+void destroyModemThread(unsigned short modemIndex);
+void createSerPortThread();
+void destroySerPortThread();
+void createAllModemThread();
+void destroyAllModemThread();
+
+void setLogLevel(unsigned int level);
+unsigned int getLogLevel();
+
+int getModemProtocol(unsigned short modemIndex, void* modem_capa);
+int getMDChType(unsigned short modemIndex);
+
+unsigned int getMDMode(void);
+void setMDMode(unsigned int modem_boot_mode);
+
+void setActiveATModem(unsigned int activeATModemId);
+unsigned int getActiveATModem();
+int getIOCPort(unsigned int nModemIndex,int & bDataDevice);
+int getBootMode();
+void queryNormalModeTestFlag();
+int getNormalModeTestFlag();
+int setNormalModeTestFlag(int flag);
+
+int setProductInfo(int type, int flag, int offset);
+int getProductInfo(int type, int offset);
+
+
+int getPropValue(const char *key);
+int getDataChannelType();
+
+void queryWifiPara(int argc, char** argv);
+WIFI_PARA getWifiPara();
+
+void destroyVirtualRxThread();
+void createVirtualRxThread();
+void setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher);
+
+MSocket * createSocket(unsigned int type);
+MSocket * getSocket(unsigned int type);
+void delSocket(unsigned int type);
+
+void destroyContext();
+
+int getLoadType();
+int getModemHwVersion(unsigned short modemIndex);
+
+void setATRespFlag(int atFlag);
+int getATRespFlag();
+
+int notifyModemDoRFByATCI();
+int ChangeModemMode(int mode);
+
+void writeBootprof(char * str);
+int writePortIndex();
+
+int readSys_int(char const * path);
+unsigned int checkMdStatus();
+
+void SetDataCompressStatus(unsigned int enable);
+unsigned int GetDataCompressStatus();
+
+void HandleSocketCmd(char* socket_cmd);
+void setCurrentMdMode(int mdMode);
+
+
+#endif // _CONETXT_H_
diff --git a/src/devtools/meta/src/common/inc/Device.h b/src/devtools/meta/src/common/inc/Device.h
new file mode 100644
index 0000000..1590c5e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Device.h
@@ -0,0 +1,50 @@
+#pragma once
+
+#include <pthread.h>
+#include "MetaPub.h"
+
+
+#define NULL_FILE_DESCRIPTOR (-1) // 0 or -1 ???
+
+class IDevWatcher
+{
+public:
+ virtual signed int onReceived(
+ unsigned char*, unsigned int) = 0;
+ virtual ~IDevWatcher(void) = 0;
+};
+
+class Device
+{
+public:
+ Device(void);
+ virtual ~Device(void);
+
+public:
+ virtual signed int read(unsigned char*, unsigned int);
+ virtual signed int write(const unsigned char*, unsigned int);
+ virtual void update();
+ virtual void close();
+ void waitForThreadExit();
+ void setExitFlag(unsigned int exitFlag);
+
+ signed int pump(IDevWatcher*);
+ signed int pumpAsync(IDevWatcher*);
+ signed int getDevHandle() const
+ {
+ return m_fd;
+ }
+
+
+private:
+ static void *ThreadProc(void*);
+ unsigned int m_exitFlag;
+ unsigned char *m_buf;
+
+protected:
+ signed int m_fd;
+ pthread_t m_thread;
+ IDevWatcher *m_pWatcher;
+ pthread_mutex_t m_wMutex;
+
+};
diff --git a/src/devtools/meta/src/common/inc/DriverInterface.h b/src/devtools/meta/src/common/inc/DriverInterface.h
new file mode 100644
index 0000000..9c093fe
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/DriverInterface.h
@@ -0,0 +1,1439 @@
+
+#ifndef _FT_DRIVERINTERFACE_H_
+#define _FT_DRIVERINTERFACE_H_
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+
+#include "MetaPub.h"
+
+//WCN
+
+#ifdef FT_WIFI_FEATURE
+#include "meta_wifi_para.h"
+#endif
+
+#ifdef FT_GPS_FEATURE
+#include "meta_gps_para.h"
+#endif
+
+#ifdef FT_NFC_FEATURE
+#include "meta_nfc_para.h"
+#endif
+
+#ifdef FT_BT_FEATURE
+#include "meta_bt_para.h"
+#endif
+#ifdef FT_FM_FEATURE
+#include "meta_fm_para.h"
+#endif
+
+#ifdef FT_RAT_FEATURE
+#include "meta_rat_para.h"
+#endif
+
+#ifdef FT_MSIM_FEATURE
+#include "meta_msim_para.h"
+#endif
+
+//MM
+#ifdef FT_AUDIO_FEATURE
+#include "meta_audio_para.h"
+#endif
+
+#ifdef FT_MATV_FEATURE
+#include "meta_matv_para.h"
+#endif
+
+#ifdef FT_DRM_KEY_MNG_FEATURE
+#include "meta_drmkey_install_para.h"
+#endif
+
+#ifdef FT_GAMMA_FEATURE
+#include "meta_gamma_para.h"
+#endif
+
+#ifdef FT_ATTESTATION_KEY_FEATURE
+#include "kmsetkey.h"
+#endif
+
+#ifdef IS_SUPPORT_SP
+//NVRAM
+#include "libfile_op.h"
+#endif
+
+#ifdef FT_NVRAM_FEATURE
+#include "libfile_op.h"
+#include "Meta_APEditor_Para.h"
+#endif
+
+#ifdef FT_SYSENV_SUPPORT
+#include "sysenv_utils.h"
+#endif
+
+typedef struct
+{
+ unsigned int file_size;
+ unsigned char file_ID;
+ unsigned char stage;
+} FT_STREAM_BLOCK;
+
+typedef struct
+{
+ FT_H header;
+ char buffer[1024];
+ int count;
+ int mode;
+} FT_NVRAM_BACKUP_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_STREAM_BLOCK block;
+ unsigned char status;
+} FT_NVRAM_BACKUP_CNF;
+
+typedef struct
+{
+ FT_H header;
+ FT_STREAM_BLOCK block;
+} FT_NVRAM_RESTORE_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char status;
+} FT_NVRAM_RESTORE_CNF;
+
+
+//Basic
+typedef struct
+{
+ FT_H header;
+ unsigned int dummy;
+} FT_IS_ALIVE_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned int dummy;
+} FT_IS_ALIVE_CNF;
+
+typedef struct
+{
+ FT_H header;
+} FT_VER_INFO_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char bb_chip[64];
+ unsigned char eco_ver[4];
+ unsigned char sw_time[64];
+ unsigned char dsp_fw[64];
+ unsigned char rsc_ver[64];
+ unsigned char sw_ver[64];
+ unsigned char hw_ver[64];
+ unsigned char melody_ver[64];
+ unsigned char status;
+} FT_VER_INFO_CNF;
+
+typedef struct
+{
+ FT_H header; //ft header
+} FT_VER_INFO_V2_REQ;
+
+typedef struct
+{
+ FT_H header; //ft header
+ unsigned char bb_chip[64];
+ unsigned char eco_ver[4];
+ unsigned char sw_time[64];
+ unsigned char dsp_fw[64];
+ unsigned char dsp_patch[64];
+ unsigned char sw_ver[64];
+ unsigned char hw_ver[64];
+ unsigned char melody_ver[64];
+ unsigned char build_disp_id[64];
+ unsigned char status; //ft status: 0 is success
+} FT_VER_INFO_V2_CNF;
+
+
+typedef enum {
+ FT_SHUTDOWN_OP_POWEROFF = 0,
+ FT_SHUTDOWN_OP_REBOOT,
+ FT_SHUTDOWN_OP_ATMDISCONNECT,
+ FT_SHUTDOWN_OP_WAITUSB,
+ FT_SHUTDOWN_OP_END = 0x0fffffff
+} FT_SHUTDOWN_OP;
+
+
+typedef struct
+{
+ FT_H header;
+ unsigned int dummy;
+}FT_POWER_OFF_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned int delay;
+ unsigned int dummy;
+} FT_META_REBOOT_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char tag[64];
+}FT_BUILD_PROP_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char content[128];
+ int status;
+}FT_BUILD_PROP_CNF;
+
+typedef struct
+{
+ FT_H header;
+ unsigned int dummy;
+} FT_GET_CHIPID_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char chipId[17];
+ unsigned char status;
+} FT_GET_CHIPID_CNF;
+
+//Sensor
+#ifdef FT_GSENSOR_FEATURE
+#include "meta_gsensor_para.h"
+#endif
+#ifdef FT_MSENSOR_FEATURE
+#include "meta_msensor_para.h"
+#endif
+#ifdef FT_ALSPS_FEATURE
+#include "meta_alsps_para.h"
+#endif
+#ifdef FT_GYROSCOPE_FEATURE
+#include "meta_gyroscope_para.h"
+#endif
+
+
+typedef struct
+{
+ FT_H header;
+ unsigned int dummy;
+} FT_MSENSOR_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char status;
+} FT_MSENSOR_CNF;
+
+typedef struct
+{
+ FT_H header;
+ unsigned int dummy;
+} FT_ALSPS_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char status;
+} FT_ALSPS_CNF;
+
+//Modem
+typedef enum
+{
+ FT_MODEM_OP_QUERY_INFO = 0,
+ FT_MODEM_OP_CAPABILITY_LIST = 1,
+ FT_MODEM_OP_SET_MODEMTYPE = 2,
+ FT_MODEM_OP_GET_CURENTMODEMTYPE = 3,
+ FT_MODEM_OP_QUERY_MDIMGTYPE = 4,
+ FT_MODEM_OP_QUERY_MDDOWNLOADSTATUS = 5,
+ FT_MODEM_OP_TRIGGER_NATIVE_DOWNLOAD = 6,
+ FT_MODEM_OP_REBOOT_MODEM = 7,
+ FT_MODEM_OP_GET_MODEMMODE = 8,
+ FT_MODEM_OP_QUERY_MDDBPATH = 9,
+ FT_MODEM_OP_SUPPORT_COMPRESS = 10,
+ FT_MODEM_END = 0x0fffffff
+}FT_MODEM_OP;
+
+typedef struct
+{
+ unsigned int modem_id; //no use
+}MODEM_QUERY_MDDBPATH_REQ;
+
+typedef struct
+{
+ unsigned char mddb_path[64];
+}MODEM_QUERY_MDDBPATH_CNF;
+
+typedef struct
+{
+ unsigned char modem_index;
+ unsigned char mode;
+}MODEM_REBOOT_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}MODEM_REBOOT_CNF;
+
+
+typedef struct
+{
+ unsigned char modem_index;
+}MODEM_GET_MODEMMODE_REQ;
+
+typedef struct
+{
+ unsigned char mode;
+}MODEM_GET_MODEMMODE_CNF;
+
+typedef struct
+{
+ unsigned char reserved;
+}MODEM_QUERY_DOWNLOAD_STATUS_REQ;
+
+typedef struct
+{
+ unsigned int percentage;
+ unsigned int status_code;
+}MODEM_QUERY_DOWNLOAD_STATUS_CNF;
+
+typedef struct
+{
+ unsigned char reserved;
+}MODEM_QUERY_INFO_REQ;
+
+typedef struct
+{
+ unsigned int modem_number;
+ unsigned int modem_id;
+}MODEM_QUERY_INFO_CNF;
+
+typedef enum
+{
+ FT_MODEM_SRV_INVALID = 0,
+ FT_MODEM_SRV_TST = 1,
+ FT_MODEM_SRV_DHL = 2,
+ FT_MODEM_SRV_ETS = 3,
+ FT_MODEM_SRV_END = 0x0fffffff
+}FT_MODEM_SRV;
+
+typedef enum
+{
+ FT_MODEM_CH_NATIVE_INVALID = 0,
+ FT_MODEM_CH_NATIVE_TST = 1,
+ FT_MODEM_CH_TUNNELING = 2,
+ FT_MODEM_CH_TUNNELING_IGNORE_CKSM = 3,
+ FT_MODEM_CH_NATIVE_ETS = 4,
+ FT_MODEM_CH_END = 0x0fffffff
+}FT_MODEM_CH_TYPE;
+
+typedef struct
+{
+ FT_MODEM_SRV md_service;
+ FT_MODEM_CH_TYPE ch_type;
+ unsigned char reserved;
+}MODEM_CAPABILITY;
+
+typedef struct
+{
+ unsigned char reserved;
+}MODEM_CAPABILITY_LIST_REQ;
+
+typedef struct
+{
+ MODEM_CAPABILITY modem_cap[8];
+}MODEM_CAPABILITY_LIST_CNF;
+
+typedef struct
+{
+ unsigned int modem_id;
+ unsigned int modem_type;
+}MODEM_SET_MODEMTYPE_REQ;
+
+typedef struct
+{
+ unsigned char reserved;
+}MODEM_SET_MODEMTYPE_CNF;
+
+typedef struct
+{
+ unsigned int modem_id;
+}MODEM_GET_CURRENTMODEMTYPE_REQ;
+
+typedef struct
+{
+ unsigned int current_modem_type;
+}MODEM_GET_CURENTMODEMTYPE_CNF;
+
+typedef struct
+{
+ unsigned int modem_id;
+}MODEM_QUERY_MDIMGTYPE_REQ;
+
+typedef struct
+{
+ unsigned int mdimg_type[16];
+}MODEM_QUERY_MDIMGTYPE_CNF;
+
+typedef struct
+{
+ unsigned int action; //0:disable; 1:enable
+} MODEM_SUPPORT_COMPRESS_REQ;
+
+typedef struct
+{
+ unsigned int result; //0:fail; 1:success
+} MODEM_SUPPORT_COMPRESS_CNF;
+
+typedef union
+{
+ MODEM_QUERY_INFO_REQ query_modem_info_req;
+ MODEM_CAPABILITY_LIST_REQ query_modem_cap_req;
+ MODEM_SET_MODEMTYPE_REQ set_modem_type_req;
+ MODEM_GET_CURRENTMODEMTYPE_REQ get_currentmodem_type_req;
+ MODEM_QUERY_MDIMGTYPE_REQ query_modem_imgtype_req;
+ MODEM_QUERY_DOWNLOAD_STATUS_REQ query_modem_download_status_req;
+ MODEM_REBOOT_REQ reboot_modem_req;
+ MODEM_GET_MODEMMODE_REQ get_modem_mode_req;
+ MODEM_QUERY_MDDBPATH_REQ query_mddbpath_req;
+ MODEM_SUPPORT_COMPRESS_REQ set_compress_req;
+}FT_MODEM_CMD;
+
+typedef union
+{
+ MODEM_QUERY_INFO_CNF query_modem_info_cnf;
+ MODEM_CAPABILITY_LIST_CNF query_modem_cap_cnf;
+ MODEM_SET_MODEMTYPE_CNF set_modem_type_cnf;
+ MODEM_GET_CURENTMODEMTYPE_CNF get_currentmodem_type_cnf;
+ MODEM_QUERY_MDIMGTYPE_CNF query_modem_imgtype_cnf;
+ MODEM_QUERY_DOWNLOAD_STATUS_CNF query_modem_download_status_cnf;
+ MODEM_REBOOT_CNF reboot_modem_cnf;
+ MODEM_GET_MODEMMODE_CNF get_modem_mode_cnf;
+ MODEM_QUERY_MDDBPATH_CNF query_mddbpath_cnf;
+ MODEM_SUPPORT_COMPRESS_CNF set_compress_cnf;
+}FT_MODEM_RESULT;
+
+typedef struct
+{
+ FT_H header;
+ FT_MODEM_OP type;
+ FT_MODEM_CMD cmd;
+}FT_MODEM_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_MODEM_OP type;
+ unsigned char status;
+ FT_MODEM_RESULT result;
+}FT_MODEM_CNF;
+
+typedef enum
+{
+ FT_GET_SIM_NUM = 0,
+ FT_MISC_WCN_END = 0x0fffffff
+}FT_GET_SIM_OP;
+
+
+typedef struct
+{
+ FT_H header;
+ FT_GET_SIM_OP type;
+}FT_GET_SIM_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_GET_SIM_OP type;
+ unsigned char status;
+ unsigned int number;
+}FT_GET_SIM_CNF;
+
+//Baseband
+#ifdef FT_LCDBK_FEATURE
+#include "meta_lcdbk_para.h"
+#endif
+
+#ifdef FT_KEYPADBK_FEATURE
+#include "meta_keypadbk_para.h"
+#endif
+
+#ifdef FT_LCD_FEATURE
+#include "meta_lcdft_para.h"
+#endif
+
+#ifdef FT_VIBRATOR_FEATURE
+#include "meta_vibrator_para.h"
+#endif
+
+typedef enum
+{
+ FT_UTILCMD_CHECK_IF_FUNC_EXIST = 0
+ ,FT_UTILCMD_CHECK_IF_ISP_SUPPORT
+ ,FT_UTILCMD_QUERY_BT_MODULE_ID
+ ,FT_UTILCMD_ENABLE_WATCHDOG_TIMER
+ ,FT_UTILCMD_CHECK_IF_ACOUSTIC16_SUPPORT
+ ,FT_UTILCMD_CHECK_IF_AUDIOPARAM45_SUPPORT
+ ,FT_UTILCMD_CHECK_IF_LOW_COST_SINGLE_BANK_FLASH
+ ,FT_UTILCMD_QUERY_PMIC_ID
+ ,FT_UTILCMD_BT_POWER_ON
+ ,FT_UTILCMD_KEYPAD_LED_ONOFF
+ ,FT_UTILCMD_VIBRATOR_ONOFF //10
+ ,FT_UTILCMD_QUERY_LOCAL_TIME
+ ,FT_UTILCMD_CHECK_IF_WIFI_ALC_SUPPORT
+ ,FT_UTILCMD_RF_ITC_PCL
+ ,FT_UTILCMD_CHECK_IF_DRC_SUPPORT
+ ,FT_UTILCMD_CHECK_IF_BT_POWERON
+ ,FT_UTILCMD_MAIN_SUB_LCD_LIGHT_LEVEL
+ ,FT_UTILCMD_SIGNAL_INDICATOR_ONOFF
+ ,FT_UTILCMD_SET_CLEAN_BOOT_FLAG
+ ,FT_UTILCMD_LCD_COLOR_TEST
+ ,FT_UTILCMD_SAVE_MOBILE_LOG //20
+ ,FT_UTILCMD_GET_EXTERNAL_SD_CARD_PATH
+ ,FT_UTILCMD_SET_LOG_LEVEL
+ ,FT_UTILCMD_SDIO_AUTO_CALIBRATION
+ ,FT_UTILCMD_QUERY_WCNDRIVER_READY
+ ,FT_UTILCMD_SDIO_CHECK_CALIBRATION
+ ,FT_UTILCMD_SWITCH_WIFI_USB
+ ,FT_UTILCMD_SET_ATM_FLAG
+ ,FT_UTILCMD_SET_PRODUCT_INFO
+ ,FT_UTILCMD_PRINTF_CUSLOG
+ ,FT_UTILCMD_END //30
+} FtUtilCmdType;
+
+typedef struct
+{
+ unsigned int query_ft_msg_id;
+ unsigned int query_op_code;
+}FtUtilCheckIfFuncExist;
+
+typedef struct
+{
+ int Notused;
+ unsigned char BackupTime[64];
+} SetCleanBootFlag_REQ;
+
+typedef struct
+{
+ BOOL drv_statsu; //inidicate the result of setting clean boot
+} SetCleanBootFlag_CNF;
+
+typedef struct
+{
+ int reserved;
+} SAVE_MOBILE_LOG_REQ;
+
+typedef struct
+{
+ BOOL drv_status;
+} SAVE_MOBILE_LOG_CNF;
+
+typedef struct
+{
+ unsigned int level;
+}SET_LOG_LEVEL_REQ;
+
+typedef struct
+{
+ int reserved;
+}SET_LOG_LEVEL_CNF;
+
+typedef struct
+{
+ unsigned int result;
+}QUERY_WCNDRIVER_READY_CNF;
+
+typedef struct
+{
+ unsigned short interval;
+} WatchDog_REQ;
+
+typedef struct
+{
+ unsigned short rtc_sec;
+ unsigned short rtc_min;
+ unsigned short rtc_hour;
+ unsigned short rtc_day;
+ unsigned short rtc_mon;
+ unsigned short rtc_wday;
+ unsigned short rtc_year;
+ unsigned short status;
+} WatchDog_CNF;
+
+typedef struct
+{
+ unsigned int flag; //0: wifi to usb, 1: usb to wifi
+}SWITCH_WIFI_USB_REQ;
+
+typedef struct
+{
+ unsigned int result;
+}SWITCH_WIFI_USB_CNF;
+
+typedef struct
+{
+ unsigned int flag;
+}SET_ATM_FLAG_REQ;
+
+typedef struct
+{
+ int reserved;
+}SET_ATM_FLAG_CNF;
+
+typedef struct
+{
+ unsigned int type; //0: ATM flag 1: meta log flag
+ unsigned int flag;
+}SET_PRODUCT_INFO_REQ;
+
+typedef struct
+{
+ int reserved;
+}SET_PRODUCT_INFO_CNF;
+
+typedef struct
+{
+ unsigned char log[256];
+}PRINTF_LOG_REQ;
+
+typedef struct
+{
+ int reserved;
+}PRINTF_LOG_CNF;
+
+
+typedef union
+{
+ FtUtilCheckIfFuncExist CheckIfFuncExist;
+ WatchDog_REQ m_WatchDogReq; // whether use
+#ifdef IS_SUPPORT_SP
+ KeypadBK_REQ m_KeypadBKReq;
+ LCDLevel_REQ m_LCDReq;
+ NLED_REQ m_NLEDReq;
+ LCDFt_REQ m_LCDColorTestReq;
+#endif
+ SetCleanBootFlag_REQ m_SetCleanBootFlagReq;
+ SAVE_MOBILE_LOG_REQ m_SaveMobileLogReq;
+ SET_LOG_LEVEL_REQ m_SetLogLevelReq;
+ SWITCH_WIFI_USB_REQ m_SwitchWiFiUSBReq;
+ SET_ATM_FLAG_REQ m_SetATMFlagReq;
+ SET_PRODUCT_INFO_REQ m_SetProductInfo;
+ PRINTF_LOG_REQ m_PrintCusLogReq;
+ unsigned int dummy;
+} FtUtilCmdReq_U;
+
+typedef union
+{
+ FtUtilCheckIfFuncExist CheckIfFuncExist;
+ WatchDog_CNF m_WatchDogCnf;
+#ifdef IS_SUPPORT_SP
+ KeypadBK_CNF m_KeypadBKCnf;
+ LCDLevel_CNF m_LCDCnf;
+ NLED_CNF m_NLEDCnf;
+ LCDFt_CNF m_LCDColorTestCNF;
+#endif
+ SetCleanBootFlag_CNF m_SetCleanBootFlagCnf;
+ SAVE_MOBILE_LOG_CNF m_SaveMobileLogCnf;
+ SET_LOG_LEVEL_CNF m_SetLogLevelCnf;
+ QUERY_WCNDRIVER_READY_CNF m_QueryWCNDriverReadyCnf;
+ SWITCH_WIFI_USB_CNF m_SwitchWiFiUSBCnf;
+ SET_ATM_FLAG_CNF m_SetATMFlagCnf;
+ SET_PRODUCT_INFO_CNF m_SetProductInfoCnf;
+ PRINTF_LOG_CNF m_PrintCusLogCnf;
+ unsigned int dummy;
+} FtUtilCmdCnf_U;
+
+
+typedef struct
+{
+ FT_H header; //ft header
+ FtUtilCmdType type; //cmd type
+ FtUtilCmdReq_U cmd; //cmd parameter
+} FT_UTILITY_COMMAND_REQ;
+
+typedef struct
+{
+ FT_H header; //ft header
+ FtUtilCmdType type; //cmd type
+ FtUtilCmdCnf_U result; //module cmd result
+ unsigned char status; //ft status: 0 is success
+} FT_UTILITY_COMMAND_CNF;
+
+//File system
+#ifdef FT_EMMC_FEATURE
+#include "meta_clr_emmc_para.h"
+#endif
+#ifdef FT_NAND_FEATURE
+#include "meta_clr_emmc_para.h"
+#endif
+#ifdef FT_CRYPTFS_FEATURE
+#include "meta_cryptfs_para.h"
+#endif
+
+//Misc
+#ifdef FT_ADC_FEATURE
+#include "meta_adc_para.h"
+#endif
+
+
+#ifdef FT_TOUCH_FEATURE
+#include "meta_touch_para.h"
+#endif
+
+
+#ifdef FT_GPIO_FEATURE
+#include "Meta_GPIO_Para.h"
+#endif
+
+
+
+typedef enum
+{
+ FT_CUSTOMER_OP_BASIC = 0
+ ,FT_CUSTOMER_OP_END
+
+} META_CUSTOMER_CMD_TYPE;
+
+typedef union
+{
+ unsigned char m_u1Dummy;
+} META_CUSTOMER_CMD_U;
+
+typedef union
+{
+ unsigned char m_u1Dummy;
+} META_CUSTOMER_CNF_U;
+
+typedef struct
+{
+ FT_H header;
+ META_CUSTOMER_CMD_TYPE type;
+ META_CUSTOMER_CMD_U cmd;
+} FT_CUSTOMER_REQ;
+
+typedef struct
+{
+ FT_H header;
+ META_CUSTOMER_CMD_TYPE type;
+ unsigned char status;
+ META_CUSTOMER_CNF_U result;
+} FT_CUSTOMER_CNF;
+
+typedef enum
+{
+ FT_SPECIALTEST_OP_HUGEDATA = 0,
+ FT_SPECIALTEST_END = 0x0fffffff
+}SPECIALTEST_OP;
+
+typedef struct
+{
+ int reserved;
+}SPECIALTEST_HUGEDATA_REQ;
+
+typedef struct
+{
+ unsigned char result;
+}SPECIALTEST_HUGEDATA_CNF;
+
+
+typedef union
+{
+ SPECIALTEST_HUGEDATA_REQ specialtest_hugedata_req;
+}FT_SPECIALTEST_CMD;
+
+typedef union
+{
+ SPECIALTEST_HUGEDATA_CNF specialtest_hugedata_cnf;
+}FT_SPECIALTEST_RESULT;
+
+typedef struct
+{
+ FT_H header;
+ SPECIALTEST_OP type;
+ FT_SPECIALTEST_CMD cmd;
+}FT_SPECIALTEST_REQ;
+
+
+typedef struct
+{
+ FT_H header;
+ SPECIALTEST_OP type;
+ unsigned char status;
+ FT_SPECIALTEST_RESULT result;
+}FT_SPECIALTEST_CNF;
+
+
+struct FT_RAWDATATEST_REQ
+{
+ FT_H header;
+};
+
+struct FT_RAWDATATEST_CNF
+{
+ FT_H header;
+ unsigned char status;
+};
+
+typedef struct
+{
+ FT_H header;
+} FT_CHIP_INFO_REQ;
+
+typedef struct
+{
+ FT_H header;
+ unsigned char code_func[64];
+ unsigned char code_proj[64];
+ unsigned char code_date[64];
+ unsigned char code_fab[64];
+ unsigned char status;
+} FT_CHIP_INFO_CNF;
+
+//////////////////////////////////////////////////////////////////////
+
+typedef enum{
+ FT_SIM_DETECT_OP_EXTMOD = 0,
+ FT_SIM_DETECT_OP_PRJTYPE,
+ FT_SIM_DETECT_OP_MDIDXSET,
+ FT_SIM_DETECT_OP_SWITCH,
+ FT_SIM_DETECT_OP_GETSSW,
+ FT_SIM_DETECT_END = 0x0fffffff
+}FT_SIM_DETECT_OP;
+
+typedef struct
+{
+ unsigned int reserved;
+}SIM_QUERY_MDTYPE_REQ;
+
+typedef struct
+{
+ unsigned int md_type;
+}SIM_QUERY_MDTYPE_CNF;
+
+typedef struct
+{
+ unsigned int reserved;
+}SIM_QUERY_PRJTYPE_REQ;
+
+typedef struct
+{
+ unsigned int prj_type;
+}SIM_QUERY_PRJTYPE_CNF;
+
+typedef struct
+{
+ unsigned int mode_cmd;
+}SIM_SET_SWITCHER_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}SIM_SET_SWITCHER_CNF;
+
+typedef struct
+{
+ unsigned int reserved;
+}SIM_QUERY_MDIDXSET_REQ;
+
+typedef struct
+{
+ unsigned int md_idxset;
+}SIM_QUERY_MDIDXSET_CNF;
+
+typedef struct
+{
+ unsigned int reserved;
+}SIM_QUERY_SSW_REQ;
+
+typedef struct
+{
+ unsigned int ssw_val;
+}SIM_QUERY_SSW_CNF;
+
+typedef union
+{
+ SIM_QUERY_MDTYPE_CNF sim_query_mdtype_cnf;
+ SIM_QUERY_PRJTYPE_CNF sim_query_prjtype_cnf;
+ SIM_QUERY_MDIDXSET_CNF sim_query_mdidxset_cnf;
+ SIM_SET_SWITCHER_CNF sim_set_switcher_cnf;
+ SIM_QUERY_SSW_CNF sim_query_ssw_cnf;
+
+} FT_SIM_DETECT_RESULT;
+
+
+typedef union
+{
+ SIM_QUERY_MDTYPE_REQ sim_query_mdtype_req;
+ SIM_QUERY_PRJTYPE_REQ sim_query_prjtype_req;
+ SIM_QUERY_MDIDXSET_REQ sim_query_mdidxset_req;
+ SIM_SET_SWITCHER_REQ sim_set_switcher_req;
+ SIM_QUERY_SSW_REQ sim_query_ssw_req;
+
+} FT_SIM_DETECT_CMD;
+
+
+typedef struct
+{
+ FT_H header;
+ FT_SIM_DETECT_OP type;
+ FT_SIM_DETECT_CMD cmd;
+}FT_SIM_DETECT_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_SIM_DETECT_OP type;
+ FT_SIM_DETECT_RESULT result;
+ unsigned char status;
+}FT_SIM_DETECT_CNF;
+
+
+typedef enum{
+ FT_FILE_OP_PARSE = 0,
+ FT_FILE_OP_GETFILEINFO,
+ FT_FILE_OP_SENDFILE,
+ FT_FILE_OP_RECEIVEFILE,
+ FT_FILE_OP_END = 0x0fffffff
+}FT_FILE_OPERATION_OP;
+
+typedef struct
+{
+ unsigned char path_name[256];
+ unsigned char filename_substr[256];
+}FILE_OPERATION_PARSE_REQ;
+
+typedef enum
+{
+ FT_FILE_TYPE_INVALID = 0,
+ FT_FILE_TYPE_FILE = 1,
+ FT_FILE_TYPE_FOLDER = 2,
+ FT_FILE_TYPE_END = 0x0fffffff
+}FT_FILE_TYPE;
+
+typedef struct
+{
+ FT_FILE_TYPE file_type;
+ unsigned int file_size;
+ unsigned char file_name[256];
+}FT_FILE_INFO;
+
+typedef struct
+{
+ unsigned int file_count;
+}FILE_OPERATION_PARSE_CNF;
+
+typedef struct
+{
+ unsigned int index; // [ 0, file_count )
+}FILE_OPERATION_GETFILEINFO_REQ;
+
+
+typedef struct
+{
+ FT_FILE_INFO file_info;
+}FILE_OPERATION_GETFILEINFO_CNF;
+
+typedef struct
+{
+ unsigned int file_size; // Total size of the current file. Only available on EOF
+ unsigned char stage; // CREATE, WRITE, EOF
+}FILEOPERATION_STREAM_BLOCK;
+
+typedef struct
+{
+ unsigned char dest_file_name[256];
+ FILEOPERATION_STREAM_BLOCK stream_block;
+}FILE_OPERATION_SENDFILE_REQ;
+
+typedef struct
+{
+ unsigned int send_result;
+}FILE_OPERATION_SENDFILE_CNF;
+
+typedef struct
+{
+ unsigned char source_file_name[256];
+}FILE_OPERATION_RECEIVEFILE_REQ;
+
+typedef struct
+{
+ FILEOPERATION_STREAM_BLOCK stream_block;
+ unsigned int receive_result;
+}FILE_OPERATION_RECEIVEFILE_CNF;
+
+typedef union
+{
+ FILE_OPERATION_PARSE_CNF parse_cnf;
+ FILE_OPERATION_GETFILEINFO_CNF getfileinfo_cnf;
+ FILE_OPERATION_SENDFILE_CNF sendfile_cnf;
+ FILE_OPERATION_RECEIVEFILE_CNF receivefile_cnf;
+
+}FT_FILE_OPERATION_RESULT;
+
+
+typedef union
+{
+ FILE_OPERATION_PARSE_REQ parse_req;
+ FILE_OPERATION_GETFILEINFO_REQ getfileinfo_req;
+ FILE_OPERATION_SENDFILE_REQ sendfile_req;
+ FILE_OPERATION_RECEIVEFILE_REQ receivefile_req;
+
+}FT_FILE_OPERATION_CMD;
+
+
+typedef struct
+{
+ FT_H header;
+ FT_FILE_OPERATION_OP type;
+ FT_FILE_OPERATION_CMD cmd;
+}FT_FILE_OPERATION_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_FILE_OPERATION_OP type;
+ FT_FILE_OPERATION_RESULT result;
+ unsigned char status;
+}FT_FILE_OPERATION_CNF;
+
+
+#ifdef FT_SDCARD_FEATURE
+#include "meta_sdcard_para.h"
+#endif
+
+////////////////////Target log ctrl///////////////////////////
+typedef enum{
+ FT_MDLOGGER_OP_SWITCH_TYPE = 0,
+ FT_MDLOGGER_OP_QUERY_STATUS = 1,
+ FT_MDLOGGER_OP_QUERY_NORMALLOG_PATH = 2,
+ FT_MDLOGGER_OP_QUERY_EELOG_PATH = 3,
+ FT_MOBILELOG_OP_SWITCH_TYPE = 4,
+ FT_MOBILELOG_OP_QUERY_LOG_PATH = 5,
+ FT_TARGETLOG_OP_PULL = 6,
+ FT_TARGETLOG_OP_PULLING_STATUS = 7,
+ FT_MDLOGGER_OP_SET_FILTER = 8,
+ FT_CONNSYSLOG_OP_SWITCH_TYPE = 9,
+ FT_TARGET_OP_CONNSYSLOG_LEVEL = 10,
+ FT_GPSLOGGER_OP_SWITCH_TYPE = 11,
+ FT_TARGETLOG_CTRL_OP_END = 0x0fffffff
+}FT_TARGETLOG_CTRL_OP;
+
+typedef struct
+{
+ unsigned int mode; //1: usb, 2:SD
+ unsigned int action; //0: stop, 1: start
+}MDLOGGER_CTRL_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}MDLOGGER_CTRL_CNF;
+
+typedef struct
+{
+ unsigned int reserved;
+}MDLOGGER_QUERY_STATUS_REQ;
+
+typedef struct
+{
+ unsigned int status; //0: stop 1:logging
+}MDLOGGER_QUERY_STATUS_CNF;
+
+typedef struct
+{
+ unsigned int reserved;
+}MDLOGGER_QUERY_LOGPATH_REQ;
+
+typedef struct
+{
+ unsigned char path[256];
+}MDLOGGER_QUERY_LOGPATH_CNF;
+
+typedef struct
+{
+ unsigned int type; //0:default filter 1:customization filter
+}MDLOGGER_SET_FILTER_REQ;
+
+
+// for mobilelog ctrl
+typedef struct
+{
+ unsigned int mode; //reserved, in the future maybe->1: usb, 2:SD
+ unsigned int action; //0: stop, 1: start
+}MOBILELOG_SWITCH_MODE_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}MOBILELOG_SWITCH_MODE_CNF;
+
+typedef struct
+{
+ unsigned int reserved;
+}MOBILELOG_QUERY_LOGPATH_REQ;
+
+typedef struct
+{
+ unsigned char path[256];
+}MOBILELOG_QUERY_LOGPATH_CNF;
+
+typedef struct
+{
+ unsigned int type; //0:modemlog 1:mobilelog 2:connsysLog 3:mddb 4:gpslog
+ unsigned int action; //0:stop 1:start
+}TARGET_LOG_PULL_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}TARGET_LOG_PULL_CNF;
+
+typedef struct
+{
+ unsigned int type; //0:modemlog 1:mobilelog 2:modem EE log 3:connsyslog 4:mddb 5:gpslog
+}TARGET_LOG_PULL_STATUS_REQ;
+
+typedef struct
+{
+ unsigned int status; //0:pulling 1:done
+}TARGET_LOG_PULL_STATUS_CNF;
+
+
+typedef enum{
+ CONSYS_WIFI = 0,
+ CONSYS_BT = 1,
+ CONSYS_GPS = 2,
+ CONSYS_MCU = 3, // reserved
+ CONSYS_END = 4,
+}CONSYS_TYPE;
+
+typedef struct
+{
+ CONSYS_TYPE type;
+ unsigned int level;
+}CONNSYS_SET_LOG_LEVEL_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}CONNSYS_SET_LOG_LEVEL_CNF;
+
+// for connsyslog ctrl
+typedef struct
+{
+ unsigned int mode; //reserved, in the future maybe->1: usb, 2:SD
+ unsigned int action; //0: stop, 1: start
+}CONNSYSLOG_SWITCH_MODE_REQ, GPSLOG_SWITCH_MODE_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}CONNSYSLOG_SWITCH_MODE_CNF, GPSLOG_SWITCH_MODE_CNF;
+
+
+typedef union
+{
+ MDLOGGER_CTRL_CNF mdlogger_ctrl_cnf;
+ MDLOGGER_QUERY_STATUS_CNF mdlogger_status_cnf;
+ MDLOGGER_QUERY_LOGPATH_CNF mdlogger_logpath_cnf;
+ MOBILELOG_SWITCH_MODE_CNF mobilelog_ctrl_cnf;
+ MOBILELOG_QUERY_LOGPATH_CNF mobilelog_logpath_cnf;
+ CONNSYSLOG_SWITCH_MODE_CNF connsyslog_ctrl_cnf;
+ TARGET_LOG_PULL_CNF targetlog_pull_cnf;
+ TARGET_LOG_PULL_STATUS_CNF targetlog_pulling_status_cnf;
+ GPSLOG_SWITCH_MODE_CNF gpslog_ctrl_cnf;
+ CONNSYS_SET_LOG_LEVEL_CNF connsyslog_set_level_cnf;
+} FT_TARGETLOG_CTRL_RESULT;
+
+
+typedef union
+{
+ MDLOGGER_CTRL_REQ mdlogger_ctrl_req;
+ MDLOGGER_QUERY_STATUS_REQ mdlogger_status_req;
+ MDLOGGER_QUERY_LOGPATH_REQ mdlogger_logpath_req;
+ MDLOGGER_SET_FILTER_REQ mdlogger_setfilter_req;
+ MOBILELOG_SWITCH_MODE_REQ mobilelog_ctrl_req;
+ MOBILELOG_QUERY_LOGPATH_REQ mobilelog_logpath_req;
+ CONNSYSLOG_SWITCH_MODE_REQ connsyslog_ctrl_req;
+ TARGET_LOG_PULL_REQ targetlog_pull_req;
+ TARGET_LOG_PULL_STATUS_REQ targetlog_pulling_status_req;
+ GPSLOG_SWITCH_MODE_REQ gpslog_ctrl_req;
+ CONNSYS_SET_LOG_LEVEL_REQ connsyslog_set_level_req;
+} FT_TARGETLOG_CTRL_CMD;
+
+typedef struct
+{
+ FT_H header;
+ FT_TARGETLOG_CTRL_OP type;
+ FT_TARGETLOG_CTRL_CMD cmd;
+}FT_TARGETLOG_CTRL_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_TARGETLOG_CTRL_OP type;
+ FT_TARGETLOG_CTRL_RESULT result;
+ unsigned char status;
+}FT_TARGETLOG_CTRL_CNF;
+
+
+////////////////////APDB function///////////////////////////
+typedef enum
+{
+ FT_APDB_OP_QUERYPATH = 0,
+ FT_APDB_OP_END = 0x0fffffff
+}FT_APDB_OP;
+
+typedef struct
+{
+ unsigned int reserved; //reserved, no use
+}QUERY_APDBPATH_REQ;
+
+typedef struct
+{
+ unsigned char apdb_path[128];
+}QUERY_APDBPATH_CNF;
+
+typedef union
+{
+ QUERY_APDBPATH_CNF query_apdbpath_cnf;
+} FT_APDB_RESULT;
+
+
+typedef union
+{
+ QUERY_APDBPATH_REQ query_apdbpath_req;
+} FT_APDB_CMD;
+
+typedef struct
+{
+ FT_H header;
+ FT_APDB_OP type;
+ FT_APDB_CMD cmd;
+}FT_APDB_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_APDB_OP type;
+ FT_APDB_RESULT result;
+ unsigned int status;
+}FT_APDB_CNF;
+
+
+////////////////////Attestation Key///////////////////////////
+typedef enum
+{
+ FT_ATTESTATIONKEY_INSTALL_SET = 0,
+ FT_ATTESTATIONKEY_INSTALL_END = 0x0fffffff
+}FT_ATTESTATIONKEY_INSTALL_OP;
+
+typedef struct
+{
+ unsigned int file_size;
+ unsigned char stage;
+}ATTESTATIONKEY_INSTALL_SET_REQ;
+
+typedef struct
+{
+ unsigned int result;
+}ATTESTATIONKEY_INSTALL_SET_CNF;
+
+typedef union
+{
+ ATTESTATIONKEY_INSTALL_SET_REQ set_req;
+}FT_ATTESTATIONKEY_INSTALL_CMD;
+
+typedef union
+{
+ ATTESTATIONKEY_INSTALL_SET_CNF set_cnf;
+}FT_ATTESTATIONKEY_INSTALL_RESULT;
+
+typedef struct
+{
+ FT_H header;
+ FT_ATTESTATIONKEY_INSTALL_OP type;
+ FT_ATTESTATIONKEY_INSTALL_CMD cmd;
+}FT_ATTESTATIONKEY_INSTALL_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_ATTESTATIONKEY_INSTALL_OP type;
+ FT_ATTESTATIONKEY_INSTALL_RESULT result;
+ unsigned char status;
+}FT_ATTESTATIONKEY_INSTALL_CNF;
+
+////////////////////SysEnv///////////////////////////
+typedef enum{
+ FT_SYSENV_SET = 0,
+ FT_SYSENV_GET = 1,
+ FT_SYSENV_END = 0x0fffffff
+}FT_SYSENV_OP;
+
+typedef struct
+{
+ unsigned char name[256];
+ unsigned char value[256];
+}SYS_ENV_SET_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}SYS_ENV_SET_CNF;
+
+typedef struct
+{
+ unsigned char name[256];
+}SYS_ENV_GET_REQ;
+
+typedef struct
+{
+ unsigned char value[256];
+}SYS_ENV_GET_CNF;
+
+
+typedef union
+{
+ SYS_ENV_SET_CNF sysenv_set_cnf;
+ SYS_ENV_GET_CNF sysenv_get_cnf;
+} FT_SYS_ENV_RESULT;
+
+
+typedef union
+{
+ SYS_ENV_SET_REQ sysenv_set_req;
+ SYS_ENV_GET_REQ sysenv_get_req;
+} FT_SYS_ENV_CMD;
+
+typedef struct
+{
+ FT_H header;
+ FT_SYSENV_OP type;
+ FT_SYS_ENV_CMD cmd;
+}FT_SYS_ENV_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_SYSENV_OP type;
+ FT_SYS_ENV_RESULT result;
+ unsigned int status;
+}FT_SYS_ENV_CNF;
+
+
+typedef enum
+{
+ FT_CLOCK_SET = 0,
+ FT_CLOCK_GET = 1,
+ FT_CLOCK_END = 0x0fffffff
+}FT_TARGETCLOCK_OP;
+
+typedef struct
+{
+ unsigned int year;
+ unsigned int mon;
+ unsigned int day;
+ unsigned int hour;
+ unsigned int min;
+ unsigned int sec;
+ unsigned int ms;
+}SET_TARGET_CLOCK_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}SET_TARGET_CLOCK_CNF;
+
+typedef union
+{
+ SET_TARGET_CLOCK_REQ set_clock_req;
+}FT_TARGET_CLOCK_CMD;
+
+typedef union
+{
+ SET_TARGET_CLOCK_CNF set_clock_cnf;
+}FT_TARGET_CLOCK_RESULT;
+
+typedef struct
+{
+ FT_H header;
+ FT_TARGETCLOCK_OP type;
+ FT_TARGET_CLOCK_CMD cmd;
+}FT_TARGETCLOCK_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_TARGETCLOCK_OP type;
+ FT_TARGET_CLOCK_RESULT result;
+ unsigned int status;
+}FT_TARGETCLOCK_CNF;
+
+typedef enum
+{
+ FT_CTRL_POWEROFF,
+ FT_CTRL_REBOOT,
+ FT_CTRL_REBOOT_RECOVERY,
+ FT_CTRL_REBOOT_BYDELAY,
+ FT_CTRL_DISCONN_ATM,
+ FT_CTRL_CHECKUSB_POWEROFF,
+ FT_CTRL_DONOTHING,
+ FT_CTRL_TARGET_OP_END = 0x0fffffff
+}FT_DISCONN_TARGET_OP;
+
+typedef struct
+{
+ unsigned int delay;
+ unsigned int reserved;
+}FT_TARGET_DISCONNECT_REQ;
+
+typedef struct
+{
+ unsigned int reserved;
+}FT_TARGET_DISCONNECT_CNF;
+
+typedef union
+{
+ FT_TARGET_DISCONNECT_REQ disconnect_req;
+}FT_DISCONNECT_CMD;
+
+typedef union
+{
+ FT_TARGET_DISCONNECT_CNF disconnect_cnf;
+}FT_DISCONNECT_RESULT;
+
+typedef struct
+{
+ FT_H header;
+ FT_DISCONN_TARGET_OP type;
+ FT_DISCONNECT_CMD cmd;
+}FT_DISCONNECT_REQ;
+
+typedef struct
+{
+ FT_H header;
+ FT_DISCONN_TARGET_OP type;
+ FT_DISCONNECT_RESULT result;
+ unsigned int status;
+}FT_DISCONNECT_CNF;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+
+
+
diff --git a/src/devtools/meta/src/common/inc/Frame.h b/src/devtools/meta/src/common/inc/Frame.h
new file mode 100644
index 0000000..2af9b95
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Frame.h
@@ -0,0 +1,74 @@
+#ifndef _FRAME_H_
+#define _FRAME_H_
+
+#include <stdlib.h>
+#include "MetaPub.h"
+
+class CmdTarget;
+
+class Frame
+{
+public:
+ Frame(const META_RX_DATA&, CmdTarget*);
+ Frame();
+ ~Frame(void);
+
+public:
+ void exec();
+
+ META_FRAME_TYPE type() const
+ {
+ return m_frmData.eFrameType;
+ }
+
+ unsigned char *localBuf() const
+ {
+ return m_frmData.pData;
+ }
+ unsigned char *peerBuf() const
+ {
+ if (m_frmData.PeerLen > 8)
+ {
+ return m_frmData.pData + m_frmData.LocalLen + 8; //skip the header of peer buffer
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+ unsigned short localLen() const
+ {
+ return m_frmData.LocalLen;
+ }
+ unsigned short peerLen() const
+ {
+ if (m_frmData.PeerLen > 8)
+ {
+ return m_frmData.PeerLen - 8;//skip the header of peer buffer
+ }
+ else
+ {
+ return 0;
+ }
+ }
+ unsigned char getIsValid()
+ {
+ return m_isValid;
+ }
+
+ CmdTarget * getCmdTarget() const
+ {
+ return m_myMod;
+ }
+
+protected:
+ void decode();
+
+private:
+ CmdTarget *m_myMod;
+ META_RX_DATA m_frmData;
+ unsigned char m_isValid;
+};
+
+#endif // _FRAME_H_
\ No newline at end of file
diff --git a/src/devtools/meta/src/common/inc/FtModule.h b/src/devtools/meta/src/common/inc/FtModule.h
new file mode 100644
index 0000000..76cd47e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/FtModule.h
@@ -0,0 +1,643 @@
+#ifndef _FT_MODULE_H_
+#define _FT_MODULE_H_
+#include "DriverInterface.h"
+#include "CmdTarget.h"
+#include "mlist.h"
+#include <vector>
+
+
+class FtModWifi : public CmdTarget
+{
+public:
+ FtModWifi(void);
+ virtual ~FtModWifi(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModGPS : public CmdTarget
+{
+public:
+ FtModGPS(void);
+ virtual ~FtModGPS(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+class FtModNFC : public CmdTarget
+{
+public:
+ FtModNFC(void);
+ virtual ~FtModNFC(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+};
+
+
+class FtModBT : public CmdTarget
+{
+public:
+ FtModBT(void);
+ virtual ~FtModBT(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModFM : public CmdTarget
+{
+public:
+ FtModFM(void);
+ virtual ~FtModFM(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+};
+
+class FtModAudio : public CmdTarget
+{
+public:
+ FtModAudio(void);
+ virtual ~FtModAudio(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+};
+
+class FtModCCAP : public CmdTarget
+{
+public:
+ FtModCCAP(void);
+ virtual ~FtModCCAP(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+class FtModDRM : public CmdTarget
+{
+public:
+ FtModDRM(void);
+ virtual ~FtModDRM(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModGAMMA : public CmdTarget
+{
+public:
+ FtModGAMMA(void);
+ virtual ~FtModGAMMA(void);
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModAttestationKey : public CmdTarget
+{
+public:
+ FtModAttestationKey(void);
+ virtual ~FtModAttestationKey(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+#ifdef FT_NVRAM_FEATURE
+class FtModNvramBackup : public CmdTarget
+{
+public:
+ FtModNvramBackup(void);
+ virtual ~FtModNvramBackup(void);
+ void covertArray2Vector(const char* in, int len, std::vector<uint8_t>& out);
+ void covertVector2Array(std::vector<uint8_t> in, char* out);
+
+private:
+ bool SendNVRAMFile(unsigned char file_ID, FT_NVRAM_BACKUP_CNF* pft_cnf);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModNvramRestore : public CmdTarget
+{
+public:
+ FtModNvramRestore(void);
+ virtual ~FtModNvramRestore(void);
+
+public:
+ virtual void exec(Frame*);
+
+};
+
+class FtModNvramReset : public CmdTarget
+{
+public:
+ FtModNvramReset(void);
+ virtual ~FtModNvramReset(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModNvramRead : public CmdTarget
+{
+public:
+ FtModNvramRead(void);
+ virtual ~FtModNvramRead(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+class FtModNvramWrite : public CmdTarget
+{
+public:
+ FtModNvramWrite(void);
+ virtual ~FtModNvramWrite(void);
+
+public:
+ virtual void exec(Frame*);
+};
+#endif
+
+class FtModTestAlive : public CmdTarget
+{
+public:
+ FtModTestAlive(void);
+ virtual ~FtModTestAlive(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModVersionInfo : public CmdTarget
+{
+public:
+ FtModVersionInfo(void);
+ virtual ~FtModVersionInfo(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+
+class FtModVersionInfo2 : public CmdTarget
+{
+public:
+ FtModVersionInfo2(void);
+ virtual ~FtModVersionInfo2(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+class FtModChipInfo : public CmdTarget
+{
+public:
+ FtModChipInfo(void);
+ virtual ~FtModChipInfo(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+class FtModPowerOff : public CmdTarget
+{
+public:
+ FtModPowerOff(void);
+ virtual ~FtModPowerOff(void);
+
+public:
+ virtual void exec(Frame*);
+ void checkUSBOnline();
+ void rebootToRecovery();
+ void closeUSB();
+
+};
+
+
+class FtModReboot : public CmdTarget
+{
+public:
+ FtModReboot(void);
+ virtual ~FtModReboot(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModMetaDisconnect : public CmdTarget
+{
+public:
+ FtModMetaDisconnect(void);
+ virtual ~FtModMetaDisconnect(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+class FtModBuildProp : public CmdTarget
+{
+public:
+ FtModBuildProp(void);
+ virtual ~FtModBuildProp(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+
+
+class FtModGSensor : public CmdTarget
+{
+public:
+ FtModGSensor(void);
+ virtual ~FtModGSensor(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+
+};
+
+class FtModMSensor : public CmdTarget
+{
+public:
+ FtModMSensor(void);
+ virtual ~FtModMSensor(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+
+private:
+ FT_MSENSOR_CNF m_ft_cnf;
+};
+
+class FtModALSPS : public CmdTarget
+{
+public:
+ FtModALSPS(void);
+ virtual ~FtModALSPS(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+
+private:
+ FT_ALSPS_CNF m_ft_cnf;
+};
+
+class FtModGyroSensor : public CmdTarget
+{
+public:
+ FtModGyroSensor(void);
+ virtual ~FtModGyroSensor(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+
+};
+
+
+class FtModModemInfo : public CmdTarget
+{
+public:
+ FtModModemInfo(void);
+ virtual ~FtModModemInfo(void);
+ int getModemCapability(MODEM_CAPABILITY_LIST_CNF* modem_capa);
+ void rebootModem(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd);
+ int getModemMode(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd);
+ int getModemIndex(FT_MODEM_REQ *req);
+ int getModemState(int *modem_state, int fd);
+ int getModemType(int *modem_type, int fd);
+ int setModemType(int modem_type, int fd);
+#ifdef MTK_SINGLE_BIN_MODEM_SUPPORT
+ int CopyMDDBFile(unsigned int nModemId);
+#endif
+
+public:
+ virtual void exec(Frame*);
+
+};
+
+
+class FtModSIMNum : public CmdTarget
+{
+public:
+ FtModSIMNum(void);
+ virtual ~FtModSIMNum(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModSDcard : public CmdTarget
+{
+public:
+ FtModSDcard(void);
+ virtual ~FtModSDcard(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+
+};
+
+class FtModEMMC : public CmdTarget
+{
+public:
+ FtModEMMC(void);
+ virtual ~FtModEMMC(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModCRYPTFS : public CmdTarget
+{
+public:
+ FtModCRYPTFS(void);
+ virtual ~FtModCRYPTFS(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModADC : public CmdTarget
+{
+public:
+ FtModADC(void);
+ virtual ~FtModADC(void);
+
+public:
+ virtual void exec(Frame*);
+};
+#if 0
+class FtModAUXADC : public CmdTarget
+{
+public:
+ FtModAUXADC(void);
+ virtual ~FtModAUXADC(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ virtual void init();
+ virtual void deinit();
+};
+
+
+
+class FtModCPURegR : public CmdTarget
+{
+public:
+ FtModCPURegR(void);
+ virtual ~FtModCPURegR(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ virtual void init();
+ virtual void deinit();
+};
+
+class FtModCPURegW : public CmdTarget
+{
+public:
+ FtModCPURegW(void);
+ virtual ~FtModCPURegW(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ virtual void init();
+ virtual void deinit();
+};
+
+#endif
+
+
+class FtModChipID : public CmdTarget
+{
+public:
+ FtModChipID(void);
+ virtual ~FtModChipID(void);
+
+public:
+ virtual void exec(Frame*);
+
+};
+
+#ifdef FT_TOUCH_FEATURE
+class FtModCTP : public CmdTarget
+{
+public:
+ FtModCTP(void);
+ virtual ~FtModCTP(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+
+private:
+ Touch_CNF m_ft_cnf;
+};
+#endif
+
+class FtModGPIO : public CmdTarget
+{
+public:
+ FtModGPIO(void);
+ virtual ~FtModGPIO(void);
+
+public:
+ virtual void exec(Frame*);
+
+protected:
+ int init(Frame*);
+};
+
+class FtModFileOperation : public CmdTarget
+{
+public:
+ FtModFileOperation(void);
+ virtual ~FtModFileOperation(void);
+
+public:
+ virtual void exec(Frame*);
+
+private:
+ mlist<FT_FILE_INFO*> m_fileInfoList;
+ unsigned m_nFileCount;
+ unsigned int GetFileLen(char *pFilePath);
+ int ListPath(unsigned char *pPath,unsigned char *pFileNameSubStr);
+ void ClearFileInfoList(void);
+ FT_FILE_INFO* GetFileInfo(unsigned int id);
+ int SaveSendData(FILE_OPERATION_SENDFILE_REQ *req, char *peer_buff, unsigned short peer_len);
+ int SetReceiveData(FILE_OPERATION_RECEIVEFILE_REQ *req, FT_FILE_OPERATION_CNF* pft_cnf);
+};
+
+class FtModRAT : public CmdTarget
+{
+public:
+ FtModRAT(void);
+ virtual ~FtModRAT(void);
+
+public:
+ void exec(Frame*);
+protected:
+ int init(Frame*);
+
+};
+
+class FtModMSIM : public CmdTarget
+{
+public:
+ FtModMSIM(void);
+ virtual ~FtModMSIM(void);
+
+public:
+ void exec(Frame*);
+protected:
+ int init(Frame*);
+
+};
+
+
+class FtModUtility : public CmdTarget
+{
+public:
+ FtModUtility(void);
+ virtual ~FtModUtility(void);
+#ifdef FT_NVRAM_FEATURE
+ void covertArray2Vector(unsigned char* in, int len, std::vector<uint8_t>& out);
+ void covertVector2Array(std::vector<uint8_t> in, char* out);
+#endif
+public:
+ void exec(Frame*);
+
+};
+
+
+class FtModCustomer : public CmdTarget
+{
+public:
+ FtModCustomer(void);
+ virtual ~FtModCustomer(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModSpecialTest : public CmdTarget
+{
+public:
+ FtModSpecialTest(void);
+ virtual ~FtModSpecialTest(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModTargetloggerCtrl : public CmdTarget
+{
+public:
+ FtModTargetloggerCtrl(void);
+ virtual ~FtModTargetloggerCtrl(void);
+
+public:
+ virtual void exec(Frame*);
+
+private:
+ unsigned int SwitchMdloggerMode(FT_TARGETLOG_CTRL_REQ *req);
+ unsigned int SwitchMobilelogMode(FT_TARGETLOG_CTRL_REQ *req);
+ unsigned int SwitchConnsyslogMode(FT_TARGETLOG_CTRL_REQ *req);
+ unsigned int TargetLogPulling(FT_TARGETLOG_CTRL_REQ *req);
+ unsigned int GetTargetLogPullingStatus(FT_TARGETLOG_CTRL_REQ *req, FT_TARGETLOG_CTRL_CNF &cnf);
+ unsigned int QueryMdloggerStatus(FT_TARGETLOG_CTRL_CNF &cnf);
+ unsigned int GetLogPropValue(char *key);
+ unsigned int SetModemLogFilter(FT_TARGETLOG_CTRL_REQ *req);
+ void* GetLoggerSocket(unsigned int type, const char * service);
+ unsigned int QueryMdNormalLogPath(FT_TARGETLOG_CTRL_CNF &cnf);
+ unsigned int QueryMdEELogPath(FT_TARGETLOG_CTRL_CNF &cnf);
+ unsigned int QueryMBLogPath(FT_TARGETLOG_CTRL_CNF &cnf);
+ unsigned int SwitchGPSlogMode(FT_TARGETLOG_CTRL_REQ *req);
+ unsigned int SetConnsysLogLevel(FT_TARGETLOG_CTRL_REQ *req);
+
+};
+
+class FtModAPDB : public CmdTarget
+{
+public:
+ FtModAPDB(void);
+ virtual ~FtModAPDB(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModSysEnv : public CmdTarget
+{
+public:
+ FtModSysEnv(void);
+ virtual ~FtModSysEnv(void);
+
+public:
+ virtual void exec(Frame*);
+};
+
+class FtModTargetClock : public CmdTarget
+{
+public:
+ FtModTargetClock(void);
+ virtual ~FtModTargetClock(void);
+
+public:
+ virtual void exec(Frame*);
+
+private:
+ unsigned int SetSysClock(SET_TARGET_CLOCK_REQ *req);
+ unsigned int IsValidDate(SET_TARGET_CLOCK_REQ *req);
+
+};
+
+
+#endif // _FT_MODULE_H_
diff --git a/src/devtools/meta/src/common/inc/LogDefine.h b/src/devtools/meta/src/common/inc/LogDefine.h
new file mode 100644
index 0000000..120e08e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/LogDefine.h
@@ -0,0 +1,31 @@
+#ifndef _LOG_DEFINE_H_
+#define _LOG_DEFINE_H_
+
+
+#undef LOG_TAG
+#define LOG_TAG "META"
+
+#ifdef IS_SUPPORT_SP
+#include <log/log.h>
+
+#define META_LOG(...) \
+ do { \
+ ALOGD(__VA_ARGS__); \
+ } while (0)
+
+#else
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#define META_LOG(...) {\
+ syslog(LOG_DEBUG, ## __VA_ARGS__);}
+#endif
+
+//#define LOGD(...) {\
+// syslog(LOG_DEBUG, ## __VA_ARGS__);}
+
+#define TEXT(__a) __a
+
+
+
+#endif /* _LOG_DEFINE_H__ */
diff --git a/src/devtools/meta/src/common/inc/MSocket.h b/src/devtools/meta/src/common/inc/MSocket.h
new file mode 100644
index 0000000..ec62ad0
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/MSocket.h
@@ -0,0 +1,127 @@
+#ifndef _METASOCKET_H_
+#define _METASOCKET_H_
+
+#include <string>
+using namespace std;
+
+typedef enum
+{
+ SOCKET_MDLOGGER = 0,
+ SOCKET_MOBILELOG = 1,
+ SOCKET_ATCI_CLIENT = 2,
+ SOCKET_ATCI_SERVER = 3,
+ SOCKET_ATM_COMM = 4,
+ SOCKET_CONNSYSLOG = 5,
+ SOCKET_GPSLOGGER = 6,
+ SOCKET_END = 7
+}SOCKET_TYPE;
+
+
+class MSocket
+{
+
+public:
+ MSocket();
+ virtual ~MSocket(void);
+ int initClient(const char * socket_name, int namespaceId, int bListen=1);
+ int initServer(const char * socket_name, int namespaceId, int bListen=1);
+ void deinit();
+ int connect();
+ void disconnect();
+ int getClientSocketID() const
+ {
+ return m_clientID;
+ }
+ int getServerSocketID() const
+ {
+ return m_serverID;
+ }
+ virtual void send_msg(const char *msg);
+
+private:
+ static void* ThreadFunc(void*);
+ virtual void wait_msg() = 0;
+
+public:
+ SOCKET_TYPE m_type;
+ bool m_bClientConnected;
+
+protected:
+ int m_clientID;
+ int m_serverID;
+ int m_threadID;
+ int m_stop;
+ pthread_t m_thread;
+};
+
+//////////////////////////////////////////////MATCIClientSocket////////////////////////////////////////////////////
+//ATCI is socket client
+class MATCIClientSocket : public MSocket
+{
+public:
+ MATCIClientSocket();
+ MATCIClientSocket(SOCKET_TYPE type);
+ virtual ~MATCIClientSocket();
+
+private:
+ virtual void wait_msg();
+};
+
+//////////////////////////////////////////////MATCIServerSocket////////////////////////////////////////////////////
+//ATCI is socket server
+class MATCIServerSocket : public MSocket
+{
+public:
+ MATCIServerSocket();
+ MATCIServerSocket(SOCKET_TYPE type);
+ virtual ~MATCIServerSocket();
+
+private:
+ virtual void wait_msg();
+};
+
+
+//////////////////////////////////////////////MLogSocket////////////////////////////////////////////////////
+
+class MLogSocket : public MSocket
+{
+public:
+ MLogSocket();
+ MLogSocket(SOCKET_TYPE type);
+ virtual ~MLogSocket();
+ int recv_rsp(char *buf);
+ void send_msg(const char *msg, bool ignore);
+ int getLogPullingStatus(int type);
+ void setLogPullingStatus(int type, int value);
+
+private:
+ string m_strCmd;
+ string m_strRsp;
+ int m_mdlogpulling;
+ int m_mblogpulling;
+ int m_connsyslogpulling;
+ int m_mddbpulling;
+ int m_gpslogpulling;
+ pthread_mutex_t m_Mutex;
+
+private:
+ virtual void wait_msg();
+};
+
+
+//////////////////////////////////////////////MATMSocket////////////////////////////////////////////////////
+
+class MATMSocket : public MSocket
+{
+public:
+ MATMSocket();
+ MATMSocket(SOCKET_TYPE type);
+ virtual ~MATMSocket();
+
+private:
+ virtual void wait_msg();
+};
+
+#endif
+
+
diff --git a/src/devtools/meta/src/common/inc/MdRxWatcher.h b/src/devtools/meta/src/common/inc/MdRxWatcher.h
new file mode 100644
index 0000000..f860210
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/MdRxWatcher.h
@@ -0,0 +1,55 @@
+#ifndef _MD_RX_WATCHER_H_
+#define _MD_RX_WATCHER_H_
+
+#include "Frame.h"
+#include "Device.h"
+#include "MetaPub.h"
+#include "DriverInterface.h"
+
+typedef struct
+{
+ unsigned int data_len;
+ char preserve_head_buf[MD_FRAME_HREADER_LENGTH*2]; // Double the buffer space to preserve extension for escape translation
+ char data[MAX_TST_RECEIVE_BUFFER_LENGTH];
+ char preserve_tail_buf[TST_CHECKSUM_SIZE*2];// Double the buffer space to preserve extension for escape translation
+} TST_MD_RECV_BUF;
+
+
+class MdRxWatcher : public IDevWatcher
+{
+public:
+ MdRxWatcher(int index);
+ virtual ~MdRxWatcher(void);
+
+public:
+ virtual signed int onReceived(
+ unsigned char*, unsigned int);
+
+private:
+ void process(
+ const unsigned char *buf,
+ unsigned int len);
+
+ void processMDConfirm(
+ char *pdata, unsigned short len);
+
+
+ int fillDataToTSTBufferReverse(unsigned char data, char **buffer_ptr);
+ int fillDataToTSTBuffer(unsigned char data, char **buffer_ptr);
+ void processTunnelData(unsigned char *pdata, unsigned int len);
+ bool compress(char *pdata, unsigned short len, char *compressed, size_t *compressed_len);
+
+private:
+ unsigned short m_bufLen;
+ unsigned short m_frmLen;
+ unsigned char m_frmBuf[FRAME_MAX_LEN];
+ unsigned char m_frmStat;
+ unsigned char m_frmStat0;
+ unsigned char m_chkSum;
+ int m_bL1Header; //0:PS dta 1:L1 Data
+ TST_MD_RECV_BUF *m_recv_buf;
+
+ int nModemIndex;
+};
+
+#endif // _MD_RX_WATCHER_H_
diff --git a/src/devtools/meta/src/common/inc/MetaPub.h b/src/devtools/meta/src/common/inc/MetaPub.h
new file mode 100644
index 0000000..85fd982
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/MetaPub.h
@@ -0,0 +1,466 @@
+#ifndef _META_PUB_H_
+#define _META_PUB_H_
+
+#include <stdbool.h>
+#include "PortHandle.h"
+#define MAX_PATH 1024
+
+typedef enum
+{
+ META_SUCCESS = 0,
+ META_FAILED
+} META_RESULT;
+
+
+typedef enum
+{
+ META_STATUS_FAILED = 0,
+ META_STATUS_SUCCESS
+} META_STATUS;
+
+
+//////////////////////////////////////////////////////////////////////////
+//define the MD frame
+#define MD_FRAME_TREACE_OFFSITE 3
+#define MD_FRAME_HREADER_LENGTH 4
+#define MAX_TST_RECEIVE_BUFFER_LENGTH (4096*16)//2048
+#define TST_CHECKSUM_SIZE (1)
+#define MD_FRAME_TST_INJECT_PRIMITIVE_LENGTH 10
+#define MD_FRAME_FAILED_TST_LOG_PRIMITIVE_LENGTH 20
+#define MD_FRAME_SUCCESS_TST_LOG_PRIMITIVE_LENGTH 102
+#define MD_FRAME_REF_LENGTH 2
+#define MD_FRAME_MSG_LEN_LENGTH 2
+#define MD_FRAME_MAX_LENGTH 256
+#define MD_FRAME_FAILED_CHECEK_SIM_OFFISTE 76
+#define MD_FRAME_SUCCESS_CHECEK_SIM_OFFISTE 116
+#define MD_FRAME_DS269_OFFSITE 8
+
+//the define of the type of meta frame
+#define RS232_LOGGED_PRIMITIVE_TYPE 0x60
+#define RS232_PS_TRACE_TYPE 0x61
+#define RS232_PS_PROMPT_TRACE_TYPE 0x62
+#define RS232_COMMAND_TYPE_OCTET 0x63
+#define RS232_INJECT_PRIMITIVE_OCTET 0x64
+#define RS232_INJECT_UT_PRIMITIVE 0x65
+#define RS232_INJECT_APPRIMITIVE_OCTET 0x66
+
+#define RS232_INJECT_PRIMITIVE_OCTETMODEM2 0xA0
+#define RS232_INJECT_PRIMITIVE_OCTETMODEM2_END 0xA7
+#define RS232_COMMAND_TYPE_MD2_MEMORY_DUMP 0xC0
+#define RS232_COMMAND_TYPE_MD2_MEMORY_DUMP_END 0xC7
+
+//TST tunneling
+#define RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START 0xD0
+#define RS232_COMMAND_TYPE_MD_DATA_TUNNEL_END 0xD7
+#define RS232_RESPONSE_MD_DATA_TUNNEL_START 0xD8
+#define RS232_RESPONSE_MD_DATA_TUNNEL_END 0xDF
+//TST tunneling + compression
+#define RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START 0xF0
+#define RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_END 0xF7
+#define RS232_RESPONSE_MD_DATA_TUNNEL_COMP_START 0xF8
+#define RS232_RESPONSE_MD_DATA_TUNNEL_COMP_END 0xFF
+
+
+//the maximum size of frame
+#define FRAME_MAX_LEN 1024*64
+//the size of peer buf header
+#define PEER_HEADER_LEN 8
+// the maximum size of peer buf
+#define PEER_BUF_MAX_LEN 1024*60
+// the maximum size of peer buf + local buf
+#define FT_MAX_LEN (FRAME_MAX_LEN -PEER_HEADER_LEN - 9)
+
+/* teh define of escape key */
+#define STX_OCTET 0x55
+#define MUX_KEY_WORD 0x5A
+#define SOFT_FLOW_CTRL_BYTE 0x77
+#define STX_L1HEADER 0xA5
+
+
+//CCB: Mux Header size
+/***************************************************
+Mux Header Format
+ 0 1 2 3
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+ | mux header magic (4B) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-
+ | len (2B) |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-
+
+ mux header magic:
+ 0 1 2 3
+ 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ | 0xAC | 0xCA | 0x00 | 0xFF |
+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+
+****************************************************/
+#define META_CCB_MUX_HEADER_LEN 6
+#define META_CCB_TX_MAX_RETRY 10
+#define META_CCB_INIT_MAX_RETRY 10
+#define META_CCB_POOL_BITMASK 1 //For Meta, the bitmask is fixed
+#define META_CCB_BUFFER_ID 0 //For Meta, the buffer id is fixed.
+
+/* Define the rs232 frame phase states */
+#define RS232_FRAME_STX 0
+#define RS232_FRAME_LENHI 1
+#define RS232_FRAME_LENLO 2
+#define RS232_FRAME_TYPE 3
+#define RS232_FRAME_LOCAL_LENHI 4
+#define RS232_FRAME_LOCAL_LENLO 5
+#define RS232_FRAME_PEER_LENHI 6
+#define RS232_FRAME_PEER_LENLO 7
+#define RS232_FRAME_COMMAND_DATA 8
+#define RS232_FRAME_COMMAND_HEADER 9
+#define RS232_FRAME_UT_DATA 10
+#define RS232_FRAME_MD_DATA 11
+#define RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER 12
+#define RS232_FRAME_AP_PRIM_LOCAL_PARA_DATA 13
+#define RS232_FRAME_AP_PRIM_PEER_DATA 14
+#define RS232_FRAME_CHECKSUM 15
+#define RS232_FRAME_KEYWORD 16
+#define RS232_FRAME_SOFT_CTRL 17
+#define RS232_FRAME_MD_CONFIRM_DATA 18
+#define RS232_FRAME_MD_TUNNELING_DATA 19
+#define RS232_FRAME_MD_TUNNELING_CHECKSUM 20
+#define RS232_FRAME_MD_TUNNELING_COMPRESS_DATA 21
+
+
+#define UART1_PATH_TTYS "/dev/ttyS0"
+#define UART2_PATH_TTYS "/dev/ttyS1"
+#define UART3_PATH_TTYS "/dev/ttyS2"
+#define UART4_PATH_TTYS "/dev/ttyS3"
+
+#define UART1_PATH_TTYMT "/dev/ttyMT0"
+#define UART2_PATH_TTYMT "/dev/ttyMT1"
+#define UART3_PATH_TTYMT "/dev/ttyMT2"
+#define UART4_PATH_TTYMT "/dev/ttyMT3"
+
+
+////////////////////////////log ctrl///////////////////////////////////
+
+#define MDLOG_SOCKET_NAME "/dev/mdlogger_socket1"
+#define MBLOG_SOCKET_NAME "/dev/log_controld"
+#define CONNSYSLOG_SOCKET_NAME "ConnsysFWHidlServer"
+#define GPSLOG_SOCKET_NAME "mtk_meta2mnld_logctrl"
+
+#define MDLOG_START "meta_start,%d"
+#define MDLOG_STOP "meta_pause"
+#define MDLOG_PULL_START "pull_mdlog_start,1"
+#define MDLOG_PULL_STOP "pull_mdlog_stop"
+#define MDLOG_QUERY_STATUS "get_running_state"
+#define MDLOG_QUERY_NORMALLOG_PATH "get_run_folder"
+#define MDLOG_QUERY_EELOG_PATH "get_ee_folder"
+#define MDLOG_PULL_STATUS "get_pullmdlog_state"
+#define MDLOG_EE_DONE_STATUS "get_ee_done_state"
+#define MDLOG_SET_FILTER "meta_mdfilter,%d"
+
+#define MBLOG_START "meta_aplog_rec_start"
+#define MBLOG_STOP "meta_aplog_rec_stop"
+#define MBLOG_PULL_START "meta_aplog_pull_start"
+#define MBLOG_PULL_STOP "meta_aplog_pull_stop"
+
+#define MBLOG_QUERY_NORMALLOG_PATH "get_run_mbfolder"
+#define MBLOG_PULL_STATUS "get_pullmblog_state"
+
+#define CONNLOG_START "meta_connsys_start"
+#define CONNLOG_STOP "meta_connsys_stop"
+#define CONNLOG_PULL_START "pull_FWlog_start"
+#define CONNLOG_PULL_STOP "pull_FWlog_stop"
+#define CONNLOG_PULL_STATUS "pull_FWlog_status"
+#define CONNLOG_QUERY_STATUS "log_running_status"
+
+#define GPSLOG_START "meta_gpslog_start"
+#define GPSLOG_STOP "meta_gpslog_stop"
+#define GPSLOG_PULL_START "pull_gpslog_start"
+#define GPSLOG_PULL_STOP "pull_gpslog_stop"
+
+#define SET_FWLOG_LEVEL "meta_set_fwlog_level,%d,%d"
+#define MDDB_PULL_START "pull_MDDB"
+//////////////////////////////////////////////////////////////////////////
+
+//-------------------------------------
+// define com mask parameter
+//-------------------------------------
+#define DEFAULT_COM_MASK (EV_RXCHAR | EV_RLSD | EV_ERR | EV_BREAK | EV_RING)
+
+//////////////////////////////////////////////////////////////////////////
+
+typedef signed short int16;
+typedef signed int int32;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+typedef unsigned int uint32;
+
+
+
+//*****************************************************************************
+//
+// META Driver data structure def
+//
+//*****************************************************************************
+
+
+
+// defie the type of frame.
+typedef enum
+{
+ AP_FRAME =0, //ap side
+ MD_FRAME //modem side
+} META_FRAME_TYPE;
+
+
+// the data pass between FT and TST
+typedef struct
+{
+ META_FRAME_TYPE eFrameType; //frame type
+ unsigned char *pData;
+ unsigned short LocalLen; //local len
+ unsigned short PeerLen; //peer len
+} META_RX_DATA;
+
+typedef enum
+{
+ META_UNKNOWN_COM=0,
+ META_UART_COM,
+ META_USB_COM,
+ META_SOCKET,
+ META_PCIE_COM
+}META_COM_TYPE;
+
+typedef struct
+{
+ unsigned short token;
+ unsigned short id;
+}FT_H;
+
+typedef struct
+{
+ char* ip_addr;
+ unsigned int port;
+}WIFI_PARA;
+
+
+//the ID define of ft req and cnf, it is used to ananlyze the different module.
+typedef enum
+{
+ /* RF */
+ FT_RF_TEST_REQ_ID = 0 ,/*0*/
+ FT_RF_TEST_CNF_ID = 1 ,
+ /* BaseBand */
+ FT_REG_READ_ID = 2 ,
+ FT_REG_READ_CNF_ID = 3 ,
+ FT_REG_WRITE_ID = 4 ,
+ FT_REG_WRITE_CNF_ID = 5 ,/*5*/
+ FT_ADC_GETMEADATA_ID = 6 ,
+ FT_ADC_GETMEADATA_CNF_ID = 7 ,
+ /* test alive */
+ FT_IS_ALIVE_REQ_ID = 8 ,
+ FT_IS_ALIVE_CNF_ID = 9 ,
+ /* power off */
+ FT_POWER_OFF_REQ_ID = 10 ,/*10*/
+ /* unused */
+ FT_RESERVED04_ID = 11 ,
+ /* required META_DLL version */
+ FT_CHECK_META_VER_REQ_ID = 12 ,
+ FT_CHECK_META_VER_CNF_ID = 13 ,
+ /* utility command */
+ FT_UTILITY_COMMAND_REQ_ID = 14 ,
+ FT_UTILITY_COMMAND_CNF_ID = 15 ,/*15*/
+ /* for NVRAM */
+ FT_NVRAM_GET_DISK_INFO_REQ_ID = 16 ,
+ FT_NVRAM_GET_DISK_INFO_CNF_ID = 17 ,
+ FT_NVRAM_RESET_REQ_ID = 18 ,
+ FT_NVRAM_RESET_CNF_ID = 19 ,
+ FT_NVRAM_LOCK_CNF_ID = 20 ,/*20*/
+ FT_NVRAM_LOCK_REQ_ID = 21 ,
+ FT_NVRAM_READ_REQ_ID = 22 ,
+ FT_NVRAM_READ_CNF_ID = 23 ,
+ FT_NVRAM_WRITE_REQ_ID = 24 ,
+ FT_NVRAM_WRITE_CNF_ID = 25 ,/*25*/
+ /* FAT */
+ FT_FAT_OPERATION_ID = 26 ,/* 26 ~ 40 */
+ /* L4 Audio */
+ FT_L4AUD_REQ_ID = 41 ,/* 41 ~ 50 */
+ FT_L4AUD_CNF_ID ,
+ /* Version Info */
+ FT_VER_INFO_REQ_ID = 51 ,/* 51 */
+ FT_VER_INFO_CNF_ID ,
+ /* CCT */
+ FT_CCT_REQ_ID = 53 ,/* 53 */
+ FT_CCT_CNF_ID ,
+ /* WiFi */
+ FT_WIFI_WNDRV_SET_REQ_ID = 55 ,/* 55 */
+ FT_WIFI_WNDRV_SET_CNF_ID ,
+ FT_WIFI_WNDRV_QUERY_REQ_ID = 57 ,/* 57 */
+ FT_WIFI_WNDRV_QUERY_CNF_ID ,
+ FT_WIFI_REQ_ID = 59 ,/* 59 */
+ FT_WIFI_CNF_ID ,
+ FT_BT_REQ_ID = 61 ,
+ FT_BT_CNF_ID ,
+ FT_PMIC_REG_READ_ID = 63 ,
+ FT_PMIC_REG_READ_CNF_ID ,
+ FT_PMIC_REG_WRITE_ID = 65 ,
+ FT_PMIC_REG_WRITE_CNF_ID ,
+ FT_URF_TEST_REQ_ID = 67 , /* 67 */
+ FT_URF_TEST_CNF_ID ,
+ FT_FM_REQ_ID = 69 , /* 69 */
+ FT_FM_CNF_ID = 70 ,
+ FT_TDMB_REQ_ID = 71 , /* 71 */
+ FT_TDMB_CNF_ID = 72 , /* 72 */
+ /* This is a special message defined to handle L1 report. */
+ FT_DISPATCH_REPORT_ID ,
+ FT_WM_METATEST_REQ_ID , /* 74 */
+ FT_WM_METATEST_CNF_ID ,
+ // for battery dfi
+ FT_WM_BAT_REQ_ID , /* 76 */
+ FT_WM_BAT_CNF_ID ,
+ //for dvbt test
+ FT_WM_DVB_REQ_ID , /* 78 */
+ FT_WM_DVB_CNF_ID ,
+ FT_BATT_READ_INFO_REQ_ID=80 ,
+ FT_BATT_READ_INFO_CNF_ID,
+ FT_GPS_REQ_ID = 82 ,
+ FT_GPS_CNF_ID ,
+ FT_BAT_CHIPUPDATE_REQ_ID = 84 ,
+ FT_BAT_CHIPUPDATE_CNF_ID ,
+ FT_SDCARD_REQ_ID = 86 ,
+ FT_SDCARD_CNF_ID ,
+ FT_LOW_POWER_REQ_ID = 88,
+ FT_LOW_POWER_CNF_ID ,
+ FT_GPIO_REQ_ID = 90,
+ FT_GPIO_CNF_ID ,
+ // For NVRAM backup & restore
+ FT_NVRAM_BACKUP_REQ_ID = 94,
+ FT_NVRAM_BACKUP_CNF_ID,
+ FT_NVRAM_RESTORE_REQ_ID = 96,
+ FT_NVRAM_RESTORE_CNF_ID,
+ // For G-Sensor
+ FT_GSENSOR_REQ_ID = 114,
+ FT_GSENSOR_CNF_ID ,
+ FT_META_MODE_LOCK_REQ_ID = 116,
+ FT_META_MODE_LOCK_CNF_ID,
+ // Reboot
+ FT_REBOOT_REQ_ID = 118,
+ // For MATV
+ FT_MATV_CMD_REQ_ID = 119,
+ FT_MATV_CMD_CNF_ID,
+ // Customer API
+ FT_CUSTOMER_REQ_ID = 121,
+ FT_CUSTOMER_CNF_ID = 122,
+ // Get chip ID
+ FT_GET_CHIPID_REQ_ID = 123,
+ FT_GET_CHIPID_CNF_ID = 124,
+ // M-Sensor
+ FT_MSENSOR_REQ_ID = 125,
+ FT_MSENSOR_CNF_ID = 126,
+ // Touch panel
+ FT_CTP_REQ_ID = 127,
+ FT_CTP_CNF_ID = 128,
+ // ALS_PS
+ FT_ALSPS_REQ_ID = 129,
+ FT_ALSPS_CNF_ID = 130,
+ //Gyroscope
+ FT_GYROSCOPE_REQ_ID = 131,
+ FT_GYROSCOPE_CNF_ID = 132,
+ // Get version info V2
+ FT_VER_INFO_V2_REQ_ID = 133,
+ FT_VER_INFO_V2_CNF_ID = 134,
+ //CMMB
+ FT_CMMB_REQ_ID = 135,
+ FT_CMMB_CNF_ID = 136,
+
+ FT_BUILD_PROP_REQ_ID = 137,
+ FT_BUILD_PROP_CNF_ID = 138,
+
+ // NFC
+ FT_NFC_REQ_ID = 139,
+ FT_NFC_CNF_ID = 140,
+
+ FT_ADC_REQ_ID = 141,
+ FT_ADC_CNF_ID = 142,
+
+ FT_EMMC_REQ_ID = 143,
+ FT_EMMC_CNF_ID = 144,
+
+ FT_CRYPTFS_REQ_ID = 145,
+ FT_CRYPTFS_CNF_ID = 146,
+
+ FT_MODEM_REQ_ID = 147,
+ FT_MODEM_CNF_ID = 148,
+
+ FT_SIM_NUM_REQ_ID = 149,
+ FT_SIM_NUM_CNF_ID = 150,
+
+ // DFO
+ FT_DFO_REQ_ID = 151,
+ FT_DFO_CNF_ID = 152,
+
+ //DRMKey
+ FT_DRMKEY_REQ_ID = 153,
+ FT_DRMKEY_CNF_ID = 154,
+
+ //FT_HDCP_REQ_ID = 155,
+ //FT_HDCP_CNF_ID = 156,
+
+ //SPECIALTEST
+ FT_SPECIALTEST_REQ_ID = 157,
+ FT_SPECIALTEST_CNF_ID = 158,
+
+ FT_CHIP_INFO_REQ_ID = 159,
+ FT_CHIP_INFO_CNF_ID = 160,
+
+ FT_SIM_DETECT_REQ_ID = 161,
+ FT_SIM_DETECT_CNF_ID = 162,
+
+ FT_FILE_OPERATION_REQ_ID = 163,
+ FT_FILE_OPERATION_CNF_ID = 164,
+ FT_GAMMA_REQ_ID = 165,
+ FT_GAMMA_CNF_ID = 166,
+
+ FT_RATCONFIG_REQ_ID = 167,
+ FT_RATCONFIG_CNF_ID = 168,
+
+ FT_MSIM_REQ_ID = 169,
+ FT_MSIM_CNF_ID = 170,
+
+ //MD logger ctrl
+ FT_TARGETLOG_CTRL_REQ_ID = 171,
+ FT_TARGETLOG_CTRL_CNF_ID = 172,
+
+ FT_APDB_REQ_ID = 173,
+ FT_APDB_CNF_ID = 174,
+
+ FT_ATTESTATIONKEY_REQ_ID = 175,
+ FT_ATTESTATIONKEY_CNF_ID = 176,
+
+ FT_SYSENV_REQ_ID = 177,
+ FT_SYSENV_CNF_ID = 178,
+
+ FT_TARGETCLOCK_REQ_ID = 179,
+ FT_TARGETCLOCK_CNF_ID = 180,
+
+ FT_DISCONNECT_REQ_ID = 181,
+ FT_DISCONNECT_CNF_ID = 182,
+
+ FT_MSG_LAST_ID
+} FT_MESSAGE_ID;
+
+
+
+#ifndef FALSE
+#define FALSE 0
+#define TRUE 1
+#endif
+
+#ifndef BOOL
+#define BOOL bool
+#endif
+
+#ifndef META_BOOL
+#define META_BOOL bool
+#endif
+
+typedef unsigned char BYTE;
+
+#endif // _META_PUB_H_
diff --git a/src/devtools/meta/src/common/inc/Meta_mipc.h b/src/devtools/meta/src/common/inc/Meta_mipc.h
new file mode 100644
index 0000000..70dc88e
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Meta_mipc.h
@@ -0,0 +1,26 @@
+#ifndef _CMD_METAMIPC_H_
+#define _CMD_METAMIPC_H_
+
+class MetaMIPC
+{
+public:
+ MetaMIPC(void);
+ ~MetaMIPC(void);
+
+public:
+ void Init();
+ bool Send_at_cmd(const char* cmd, char *res);
+ bool IsModemReady()
+ {
+ return m_bReady;
+ }
+
+ void SetModemReady(bool bStatus)
+ {
+ m_bReady = bStatus;
+ }
+private:
+ bool m_bReady;
+};
+
+#endif
diff --git a/src/devtools/meta/src/common/inc/Modem.h b/src/devtools/meta/src/common/inc/Modem.h
new file mode 100644
index 0000000..ea3a262
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/Modem.h
@@ -0,0 +1,32 @@
+#ifndef _MODEM_H_
+#define _MODEM_H_
+
+#include "CmdTarget.h"
+#include "SerPort.h"
+
+class IDevWatcher;
+
+class Modem : public CmdTarget
+{
+public:
+ Modem(const char*, unsigned short);
+ Modem(unsigned short id);
+ virtual ~Modem(void);
+
+public:
+ virtual void exec(Frame*);
+ virtual void exec(const unsigned char *p, unsigned int len );
+
+ signed int pumpAsync(IDevWatcher*);
+ signed int getDevHandle();
+ void popUpAsync();
+
+protected:
+ int init(Frame*);
+ void deinit();
+
+private:
+ Device *m_pDev;
+};
+
+#endif // _MODEM_H_
diff --git a/src/devtools/meta/src/common/inc/PortHandle.h b/src/devtools/meta/src/common/inc/PortHandle.h
new file mode 100644
index 0000000..b4eaca7
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/PortHandle.h
@@ -0,0 +1,20 @@
+#ifndef _PORTHANDLE_H_
+#define _PORTHANDLE_H_
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // _PORTHANDLE_H_
+
+
+
+
+
diff --git a/src/devtools/meta/src/common/inc/PortInterface.h b/src/devtools/meta/src/common/inc/PortInterface.h
new file mode 100644
index 0000000..a0f72bc
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/PortInterface.h
@@ -0,0 +1,22 @@
+
+#ifndef _PORTINTERFACE_H_
+#define _PORTINTERFACE_H_
+
+#include "MetaPub.h"
+
+class SerPort;
+
+void destroyPortHandle();
+META_COM_TYPE getComType();
+void setComType(META_COM_TYPE comType);
+SerPort * createSerPort();
+SerPort * getSerPort();
+void querySerPortStatus();
+void destroySerPort();
+void usbMutexLock(bool bLock);
+
+
+
+#endif // _PORTINTERFACE_H_
+
+
diff --git a/src/devtools/meta/src/common/inc/SerPort.h b/src/devtools/meta/src/common/inc/SerPort.h
new file mode 100644
index 0000000..5127856
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/SerPort.h
@@ -0,0 +1,105 @@
+#pragma once
+#include "Device.h"
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <poll.h>
+#include <dirent.h>
+#include <errno.h>
+
+
+class CCCI : public Device
+{
+public:
+ CCCI(const char*);
+ virtual signed int read(unsigned char *buf, unsigned int len);
+ virtual signed int write(const unsigned char *p, unsigned int len);
+
+private:
+ static signed int open(const char*);
+};
+
+class CCB : public Device
+{
+public:
+ CCB();
+
+private:
+ int init();
+ void *ccb_memcpy(void *dst,void *src, size_t n);
+ void ccb_data_copy(void* dst, void* src, unsigned int length, void* alignment_addr);
+public:
+ virtual signed int read(unsigned char*, unsigned int);
+ virtual signed int write(const unsigned char*, unsigned int);
+};
+
+class SerPort : public Device
+{
+public:
+ SerPort(const char*);
+ SerPort();
+ ~SerPort();
+ virtual void setSerPortExitFlag();
+
+protected:
+ virtual signed int open(const char*);
+ static void initTermIO(int portFd);
+};
+
+
+class UartPort : public SerPort
+{
+public:
+ UartPort(const char*);
+};
+
+class UsbPort : public SerPort
+{
+public:
+ UsbPort(const char*);
+ ~UsbPort();
+
+public:
+ virtual signed int read(unsigned char*, unsigned int);
+ virtual signed int write(const unsigned char*, unsigned int);
+ virtual void update();
+
+
+private:
+ void close();
+ int isReady();
+ void initUeventSocket();
+ void deinitUeventSocket();
+ void handleUsbUevent(const char *buff, int len);
+ int getUsbState() const;
+
+private:
+ const char *m_devPath;
+ int m_usbMutexFlag;
+ int m_usbConnected;
+ int m_ueventSocket;
+ bool m_getUsbUvent;
+};
+
+class MetaSocket : public SerPort
+{
+public:
+ MetaSocket(const char*);
+ ~MetaSocket();
+public:
+ virtual signed int open(const char*);
+ virtual signed int read(unsigned char*, unsigned int);
+ virtual signed int write(const unsigned char*, unsigned int);
+ virtual void close();
+ virtual void setSerPortExitFlag();
+private:
+ signed int connect();
+ void disconnect();
+
+private:
+ int m_nClientFd;
+ bool m_bConnect;
+ int m_nSocketConnectExitFlag;
+
+};
diff --git a/src/devtools/meta/src/common/inc/UsbRxWatcher.h b/src/devtools/meta/src/common/inc/UsbRxWatcher.h
new file mode 100644
index 0000000..d021dac
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/UsbRxWatcher.h
@@ -0,0 +1,92 @@
+#ifndef _USB_RX_WATCHER_H_
+#define _USB_RX_WATCHER_H_
+
+#include "Device.h"
+#include "Frame.h"
+#include "MetaPub.h"
+#include "DriverInterface.h"
+
+#define FrameMaxSize 4096*16//2048
+
+typedef struct
+{
+ unsigned short local_len;
+ unsigned short peer_len;
+} PRIM_HEADER;
+
+/* the define of buf of meta type */
+typedef struct
+{
+ PRIM_HEADER inject_prim; //lenght of peer buf and local buf
+ unsigned short received_prig_header_length; //recieved header count
+ unsigned short received_buf_para_length; //recieved buf count
+ unsigned char *header_ptr; //header pointer
+ unsigned char *buf_ptr; //buf pointer
+} PRIM_FRAME;
+
+
+typedef struct
+{
+ unsigned short frame_len;
+ unsigned char frame_state;
+ unsigned char frame_cksm;
+ unsigned char frame_md_index;
+ unsigned char frame_buf[FrameMaxSize]; // Must be 4-byte aligned
+ unsigned char* frame_data_ptr; // this is a frame type dependent data pointer
+} TST_FRMAE_INTERNAL_STRUCT;
+
+class UsbRxWatcher : public IDevWatcher
+{
+public:
+ UsbRxWatcher(void);
+ virtual ~UsbRxWatcher(void);
+
+public:
+ virtual signed int onReceived(
+ unsigned char*, unsigned int);
+
+private:
+ Frame *decode(unsigned char*, unsigned int, unsigned short&);
+ Frame *decodeMDFrame(void *pdata, unsigned int len, unsigned char frmType,unsigned short&);
+ Frame *decodeAPFrame(unsigned int input_len,unsigned char * src,unsigned short&);
+ Frame *decodeLTE_C2KFrame(unsigned int input_len,unsigned char * src,unsigned char frmType,unsigned short &u16Length);
+ Frame *sendFtTask();
+
+ Frame * sendMdTask(void *pdata, unsigned int len,unsigned char frmType);
+
+ unsigned char transferFrame(unsigned char * ch);
+ unsigned char checkEscape(unsigned char ch);
+
+ Frame * dispatchFrame(unsigned char ch, unsigned char *buf_ptr, unsigned int input_len, unsigned char *src,unsigned short& );
+
+ unsigned char *reallocFrameBuf(unsigned int len);
+
+ unsigned int flowControl(
+ void *pdata, unsigned int len);
+
+ unsigned char getUARTEsc(unsigned char &ch);
+
+ bool uncompress(void *pdata, int len, char *uncompressed, int *uncompressed_len);
+ unsigned int nRemainLen;
+ unsigned char szRemainBuf[FrameMaxSize*2];
+ char m_uncompressed[FrameMaxSize];
+private:
+ unsigned char m_checksum;
+ unsigned short m_uFrameLength;
+
+ char m_cTstFrameState;
+ char m_cOldTstFrameState;
+
+ unsigned short m_frame_buf_len;
+ PRIM_FRAME m_sRs232Frame;
+
+ char m_flow_ctrl_flag;
+
+ unsigned char m_md_index;//Only LTE modem use
+
+ unsigned char m_frm_len_byte; //frame length take up to bytes
+ unsigned int m_nStartByteLen;
+
+};
+
+#endif // _USB_RX_WATCHER_H_
diff --git a/src/devtools/meta/src/common/inc/mlist.h b/src/devtools/meta/src/common/inc/mlist.h
new file mode 100644
index 0000000..a8414db
--- /dev/null
+++ b/src/devtools/meta/src/common/inc/mlist.h
@@ -0,0 +1,160 @@
+#ifndef _M_LIST_
+#define _M_LIST_
+
+#include <stddef.h>
+
+template <typename _Tx>
+struct mlist_item
+{
+ _Tx data;
+ struct mlist_item<_Tx> *next;
+};
+
+template <typename _Tx>
+class mlist_iter
+{
+public:
+ typedef mlist_item<_Tx> nodetype;
+ typedef mlist_iter<_Tx> self;
+
+ mlist_iter() : node(NULL)
+ {
+ }
+
+ mlist_iter(nodetype *p) : node(p)
+ {
+ }
+
+public:
+ self &operator++()
+ {
+ // assert(node != NULL);
+ node = node->next;
+ return *this;
+ }
+
+ _Tx &operator*()
+ {
+ // assert(node != NULL);
+ return node->data;
+ }
+
+ _Tx *operator->()
+ {
+ // assert(node != NULL);
+ return &(node->data);
+ }
+
+ bool operator==(const self &ref) const
+ {
+ return (node == ref.node);
+ }
+
+ bool operator!=(const self &ref) const
+ {
+ return (node != ref.node);
+ }
+
+private:
+ nodetype *node;
+};
+
+template <typename _Tx>
+class mlist
+{
+public:
+ typedef mlist_iter<_Tx> iterator;
+ typedef mlist_item<_Tx> nodetype;
+
+ mlist()
+ {
+ head = NULL;
+ tail = NULL;
+ }
+
+ ~mlist()
+ {
+ nodetype *tmp = NULL;
+
+ while (head != NULL)
+ {
+ tmp = head->next;
+ delete head;
+ head = tmp;
+ }
+ }
+
+public:
+ void push_back(const _Tx &x)
+ {
+ if (tail != NULL)
+ {
+ tail->next = new nodetype;
+ tail = tail->next;
+ }
+ else
+ {
+ tail = new nodetype;
+ head = tail;
+ }
+ tail->data = x;
+ tail->next = NULL;
+ }
+
+ void destroy_node(const _Tx &x)
+ {
+ nodetype *tmp = NULL;
+ nodetype *delete_node =NULL;
+
+ if(head->data == x)
+ {
+ delete_node = head;
+ head = head->next;
+ }
+ else
+ {
+ tmp = head;
+ while(tmp->next->data != x)
+ {
+ tmp = tmp->next;
+ }
+ delete_node = tmp->next;
+ tmp->next = tmp->next->next;
+ }
+
+ if(head == NULL)
+ tail = NULL;
+
+ if(delete_node != NULL)
+ delete delete_node;
+ }
+
+ iterator begin() const
+ {
+ return iterator(head);
+ }
+
+ iterator end() const
+ {
+ return iterator(NULL);
+ }
+
+ void clear()
+ {
+ nodetype *tmp = NULL;
+ while (head != NULL)
+ {
+ tmp = head->next;
+ delete head;
+ head = tmp;
+ }
+ head = NULL;
+ tail = NULL;
+ }
+
+private:
+ nodetype *head;
+ nodetype *tail;
+};
+
+#endif // _M_LIST_
diff --git a/src/devtools/meta/src/common/src/CmdTarget.cpp b/src/devtools/meta/src/common/src/CmdTarget.cpp
new file mode 100644
index 0000000..0aeebb3
--- /dev/null
+++ b/src/devtools/meta/src/common/src/CmdTarget.cpp
@@ -0,0 +1,37 @@
+#include "CmdTarget.h"
+#include "LogDefine.h"
+
+CmdTarget::CmdTarget(unsigned short id)
+ : m_myId(id), m_isInited(false)
+{
+ META_LOG("[Meta] id = %d", m_myId);
+ m_token = 0;
+}
+
+CmdTarget::~CmdTarget(void)
+{
+ if (m_isInited)
+ {
+ deinit();
+ m_isInited = false;
+ }
+}
+
+void CmdTarget::exec(Frame* pFrame)
+{
+ if (!m_isInited)
+ {
+ if(init(pFrame))
+ m_isInited = true;
+ }
+}
+
+
+int CmdTarget::init(Frame*)
+{
+ return true;
+}
+
+void CmdTarget::deinit()
+{
+}
diff --git a/src/devtools/meta/src/common/src/Context.cpp b/src/devtools/meta/src/common/src/Context.cpp
new file mode 100644
index 0000000..31988f7
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Context.cpp
@@ -0,0 +1,2169 @@
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <stdint.h>
+#include <string.h>
+
+
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#include "CFG_PRODUCT_INFO_File.h"
+#include "Custom_NvRam_LID.h"
+#include "libnvram.h"
+#endif
+
+#include <unistd.h>
+#include "mlist.h"
+#include "Modem.h"
+#include "MdRxWatcher.h"
+#include "UsbRxWatcher.h"
+#include "MSocket.h"
+
+#include "FtModule.h"
+#include "Context.h"
+#include "LogDefine.h"
+//#include "hardware/ccci_intf.h"
+#include <sys/time.h>
+#include "ccci_intf.h"
+
+#include "Meta_mipc.h"
+#include "PortInterface.h"
+
+#ifdef TST_C2K_SUPPORT
+#ifndef MTK_ECCCI_C2K
+#include "c2kutils.h"
+#endif
+#endif
+
+#define CCCI_ONE_PATH "/dev/ttyC1"
+#define CCCI_TWO_PATH "/dev/ccci2_tty1"
+#define CCCI_FIVE_PATH "/dev/eemcs_md_log"
+#define USB_EXTERNAL_PATH "/dev/ttyACM0"
+
+UsbRxWatcher hostSerPortRx;
+
+class Context
+{
+private:
+ Context(void);
+public:
+ ~Context(void);
+
+public:
+ static Context *instance();
+
+ Modem * createModem(const char *ccci, unsigned short id);
+ Modem * createModem(unsigned short id);
+ void destroyModem(Modem *p);
+ Modem * getModem(unsigned short id);
+
+ CmdTarget *getModule(unsigned short id);
+
+ unsigned int dumpData(const unsigned char* con, int length);
+ unsigned int dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow);
+
+ unsigned int getFileSize(int fd);
+ const char* makepath(unsigned char file_ID);
+
+ unsigned getMdmInfo();
+
+ unsigned int getMdmType();
+ unsigned int getActiveMdmId();
+ unsigned int getMdmNumber();
+ signed int getModemHandle(unsigned short id);
+ void createModemThread(unsigned short modemIndex,int usbUsb);
+ void createSerPortThread();
+ void destroySerPortThread();
+ void destroyModemThread(unsigned short modemIndex);
+ void createAllModemThread();
+ void destroyAllModemThread();
+
+ void setLogLevel(unsigned int level);
+ unsigned int getLogLevel();
+ int queryModemProtocol(unsigned short modemIndex);
+ int getModemProtocol(unsigned short modemIndex, MODEM_CAPABILITY_LIST_CNF* modem_capa);
+ FT_MODEM_CH_TYPE getMDChType(unsigned short modemIndex);
+ unsigned int getPropValue(const char *key);
+ unsigned int getMDMode(void);
+ void setMDMode(unsigned int modem_boot_mode);//normal= 1 meta=2
+ void setActiveATModem(unsigned int activeATModemId);
+ unsigned int getActiveATModem();
+ int getIOCPort(unsigned int nModemIndex, int & bDataDevice);
+ void destroy();
+ void setMDThreadFlag(int modemThreadFlag);
+ int getMDThreadFlag();
+ void destroyVirtualRxThread();
+ void createVirtualRxThread();
+ UsbRxWatcher * getVirtualRxWatcher() const;
+ void setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher);
+ int readSys_int(char const * path);
+ int getBootMode();
+ int getDataChannelType();
+ MSocket * createSocket(SOCKET_TYPE type);
+ MSocket * getSocket(SOCKET_TYPE type);
+ void delSocket(SOCKET_TYPE type);
+
+ int encrypt(int plainText, int key){return plainText^key;}
+ int decrypt(int cipherText, int key){return cipherText^key;}
+ void queryNormalModeTestFlag();
+ int getNormalModeTestFlag();
+ int setNormalModeTestFlag(int flag);
+
+ int setProductInfo(int type, int flag, int offset);
+ int getProductInfo(int type, int offset);
+ int modifyProductInfo(int type, int flag, int offset);
+
+ void queryWifiPara(int argc, char** argv);
+ WIFI_PARA getWifiPara();
+
+ int getLoadType();
+ void queryModemHwVersion(unsigned short modemIndex);
+ int getModemHwVersion(unsigned short modemIndex);
+
+ void setATRespFlag(int atFlag);
+ int getATRespFlag();
+
+ void setCurrentMdMode(int mdMode);
+
+ int notifyModemDoRFByATCI();
+ int ChangeModemMode(int mode);
+
+ void writeBootprof(char * str);
+
+ int writePortIndex();
+
+ int getModemModeSwitching();
+
+ void setModemModeSwitching(int modemModeSwitching);
+
+ void switchComType(META_COM_TYPE targetComType);
+ unsigned int checkMdStatus();
+
+ void SetDataCompressStatus(unsigned int enable);
+ unsigned int GetDataCompressStatus();
+
+ void HandleSocketCmd(char* socket_cmd);
+
+private:
+ void initModuleList();
+ bool IsModemSupport(int idx);
+ int notifyModemDoRF(int mdIdx);
+ void waitMdResponse(int fd, const char *rsp);
+
+private:
+ mlist<Modem*> m_mdmList;
+ mlist<CmdTarget*> m_modList;
+ SerPort * m_serPort;
+ UsbRxWatcher * m_virtualRxWatcher;
+ MSocket * m_socket[SOCKET_END];
+
+ MODEM_CAPABILITY_LIST_CNF m_modem_cap_list;
+
+ static Context * m_myInst;
+
+ unsigned int m_mdmNumber;
+ unsigned int m_activeMdmId;
+ unsigned int m_activeATModemId;
+ unsigned int m_mdmType;
+ unsigned int m_logLevel;
+ unsigned int m_modem_boot_mode;
+ unsigned int m_modemThreadFlag;
+ unsigned int m_virtualRxThreadFlag;
+ unsigned int m_mdDataChannel; //0: CCCI, 1:CCB
+
+ Modem_Hw_Version m_modem_hw_version;
+ char m_modemProtocol[16];
+
+ int m_normalModeTestFlag;
+ int m_bootMode;
+
+ WIFI_PARA m_WifiPara;
+
+ int m_atFlag;
+ int m_currentMdMode;
+ unsigned int m_dataCompressStatus;
+};
+
+Context *Context::m_myInst = NULL;
+
+
+Context::Context(void)
+ :m_serPort(NULL),m_virtualRxWatcher(NULL)
+{
+ initModuleList();
+ META_LOG("[Meta] initModuleList");
+ getMdmInfo();
+ memset(&m_modem_cap_list,0,sizeof(m_modem_cap_list));
+ m_logLevel = 0;
+ m_modemThreadFlag = 0;
+ m_modem_boot_mode = 0;
+ m_virtualRxThreadFlag = 0;
+ m_activeATModemId = 0;
+ m_mdDataChannel = 0;
+ m_normalModeTestFlag = 0;
+ m_bootMode = UNKNOWN_BOOT;
+
+ m_modem_hw_version = MODEM_END;
+ memset(m_modemProtocol, 0, sizeof(m_modemProtocol));
+
+ m_WifiPara.ip_addr = (char *)"0.0.0.0";
+ m_WifiPara.port = 0;
+
+ for(int i=0; i<SOCKET_END; i++)
+ {
+ m_socket[i] = NULL;
+ }
+
+ m_atFlag = 0;
+ m_currentMdMode = 0;
+ m_dataCompressStatus = 0;
+}
+
+Context::~Context(void)
+{
+ mlist<Modem*>::iterator it0 = m_mdmList.begin();
+
+ while (it0 != m_mdmList.end())
+ {
+ delete (*it0);
+ ++ it0;
+ }
+
+ mlist<CmdTarget*>::iterator it1 = m_modList.begin();
+
+ while (it1 != m_modList.end())
+ {
+ delete (*it1);
+ ++ it1;
+ }
+
+ if (m_serPort != NULL)
+ {
+ delete m_serPort;
+ }
+}
+
+Context *Context::instance()
+{
+ return (m_myInst==NULL) ? ((m_myInst=new Context)) : m_myInst;
+}
+
+void Context::destroy()
+{
+ delete m_myInst;
+ m_myInst = NULL;
+}
+
+bool Context::IsModemSupport(int idx)
+{
+
+// char szVal[128] = {0};
+// char szProperty[128] = {0};
+ int ret = 0;
+
+#ifdef IS_SUPPORT_SP
+ sprintf(szProperty, "ro.vendor.mtk_md%d_support", idx);
+ property_get(szProperty, szVal, "0");
+ ret = atoi(szVal);
+#else
+ if(idx == 1)
+ ret = 1;
+#endif
+
+ if(ret > 0)
+ return true;
+
+ return false;
+}
+
+int Context::getLoadType() //eng : 1 or user : 2
+{
+ char szVal[128] = {0};
+ int ret = 0;
+
+#ifdef IS_SUPPORT_SP
+ property_get("ro.build.type", szVal, NULL);
+
+ if(strcmp(szVal,"eng")==0)
+ {
+ ret = 1;
+ }
+ else if(strcmp(szVal,"user")==0)
+ {
+ ret = 2;
+ }
+ else if(strcmp(szVal,"userdebug")==0)
+ {
+ ret = 3;
+ }
+#else
+ ret = 1;
+#endif
+
+ META_LOG("[Meta] ro.build.type = %s ret = %d.",szVal,ret);
+ return ret;
+
+}
+
+void Context::destroyModem(Modem *p)
+{
+ if(p!=NULL)
+ {
+ m_mdmList.destroy_node(p);
+ delete p; //close handle
+ META_LOG("[Meta] Delete modem success.");
+ }
+ else
+ {
+ META_LOG("[Meta] Delete modem fail.");
+ }
+}
+
+Modem * Context::createModem(const char *ccci, unsigned short id)
+{
+ Modem *p = new Modem(ccci, id);
+
+ if(p!=NULL)
+ {
+ m_mdmList.push_back(p);
+ META_LOG("[Meta] Create modem%d success.",id+1);
+ }
+ else
+ {
+ META_LOG("[Meta] Create modem%d fail.",id+1);
+ }
+ return p;
+}
+
+Modem * Context::createModem(unsigned short id)
+{
+ Modem *p = new Modem(id);
+
+ if(p == NULL)
+ {
+ return NULL;
+ }
+
+ if(p->getDevHandle()> 0)
+ {
+ m_mdmList.push_back(p);
+ META_LOG("[Meta] Create modem%d success.",id+1);
+ }
+ else
+ {
+ delete(p);
+ META_LOG("[Meta] Create modem%d failed.",id+1);
+ return NULL;
+ }
+ return p;
+}
+
+
+CmdTarget * Context::getModule(unsigned short id)
+{
+ mlist<CmdTarget*>::iterator it = m_modList.begin();
+
+ while (it != m_modList.end())
+ {
+ //META_LOG("[Meta] it->id = %d",(*it)->getId());
+ if ((*it)->getId() == id)
+ {
+ return (*it);
+ }
+ ++ it;
+ }
+ return NULL;
+}
+
+int Context::readSys_int(char const * path)
+{
+ int fd;
+ if (path == NULL)
+ return -1;
+
+ fd = open(path, O_RDONLY);
+ if (fd >= 0)
+ {
+ int buffer[8] = {0};
+ int len = read(fd, &buffer, sizeof(int)*8);
+ META_LOG("[Meta] read boot mode struct len = %d\n", len);
+ if(len > 0)
+ {
+ META_LOG("[Meta] boot mode size = %d, tag = %d, mode = %d\n", buffer[0], buffer[1], buffer[2]);
+ close(fd);
+ return buffer[2];
+ }
+ close(fd);
+ }
+ META_LOG("[Meta] read boot mode failed to open %s\n", path);
+ return -1;
+
+}
+
+int Context::getBootMode()
+{
+ if(UNKNOWN_BOOT == m_bootMode)
+ {
+ m_bootMode = readSys_int(BOOTMODE_PATH);
+
+ if(NORMAL_BOOT== m_bootMode)
+ {
+ META_LOG("[Meta] Normal mode boot!");
+ }
+ else if(META_BOOT== m_bootMode)
+ {
+ META_LOG("[Meta] Meta mode boot!");
+ }
+ else
+ {
+ META_LOG("[Meta] Not Support boot mode! BootMode=%d",m_bootMode);
+ m_bootMode = UNKNOWN_BOOT;
+ }
+ }
+
+ return m_bootMode;
+}
+
+Modem * Context::getModem(unsigned short id)
+{
+ mlist<Modem*>::iterator it = m_mdmList.begin();
+
+ while (it != m_mdmList.end())
+ {
+ META_LOG("[Meta] modem it->id = %d",(*it)->getId());
+ if ((*it)->getId() == id)
+ {
+ return (*it);
+ }
+ ++ it;
+ }
+ return NULL;
+}
+
+void Context::initModuleList()
+{
+ META_LOG("[Meta] Enter initModuleList");
+
+//#ifdef FT_WIFI_FEATURE
+ m_modList.push_back(new FtModWifi);
+//#endif
+
+#ifdef FT_GPS_FEATURE
+ m_modList.push_back(new FtModGPS);
+#endif
+
+#ifdef FT_NFC_FEATURE
+ m_modList.push_back(new FtModNFC);
+#endif
+
+#ifdef FT_BT_FEATURE
+ m_modList.push_back(new FtModBT);
+#endif
+
+#ifdef FT_FM_FEATURE
+ m_modList.push_back(new FtModFM);
+#endif
+
+#ifdef FT_AUDIO_FEATURE
+ m_modList.push_back(new FtModAudio);
+#endif
+
+#ifdef FT_CCAP_FEATURE
+ m_modList.push_back(new FtModCCAP);
+#endif
+
+#ifdef FT_DRM_KEY_MNG_FEATURE
+ m_modList.push_back(new FtModDRM);
+#endif
+
+#ifdef FT_GAMMA_FEATURE
+ m_modList.push_back(new FtModGAMMA);
+#endif
+
+#ifdef FT_ATTESTATION_KEY_FEATURE
+ m_modList.push_back(new FtModAttestationKey);
+#endif
+
+#ifdef FT_NVRAM_FEATURE
+ m_modList.push_back(new FtModNvramBackup);
+ m_modList.push_back(new FtModNvramRestore);
+ m_modList.push_back(new FtModNvramReset);
+ m_modList.push_back(new FtModNvramRead);
+ m_modList.push_back(new FtModNvramWrite);
+ m_modList.push_back(new FtModAPDB);
+#endif
+
+#ifdef FT_GSENSOR_FEATURE
+ m_modList.push_back(new FtModGSensor);
+#endif
+
+#ifdef FT_MSENSOR_FEATURE
+ m_modList.push_back(new FtModMSensor);
+#endif
+
+#ifdef FT_ALSPS_FEATURE
+ m_modList.push_back(new FtModALSPS);
+#endif
+
+#ifdef FT_GYROSCOPE_FEATURE
+ m_modList.push_back(new FtModGyroSensor);
+#endif
+
+#ifdef FT_SDCARD_FEATURE
+ m_modList.push_back(new FtModSDcard);
+#endif
+
+#ifdef FT_EMMC_FEATURE
+ m_modList.push_back(new FtModEMMC);
+#endif
+
+#ifdef FT_NAND_FEATURE
+ m_modList.push_back(new FtModEMMC);
+#endif
+
+#ifdef FT_CRYPTFS_FEATURE
+ m_modList.push_back(new FtModCRYPTFS);
+#endif
+
+#ifdef FT_ADC_FEATURE
+ m_modList.push_back(new FtModADC);
+#endif
+
+#ifdef FT_TOUCH_FEATURE
+ m_modList.push_back(new FtModCTP);
+#endif
+
+#ifdef FT_GPIO_FEATURE
+ m_modList.push_back(new FtModGPIO);
+#endif
+
+#ifdef FT_RAT_FEATURE
+ m_modList.push_back(new FtModRAT);
+#endif
+
+#ifdef FT_MSIM_FEATURE
+ m_modList.push_back(new FtModMSIM);
+#endif
+
+ m_modList.push_back(new FtModCustomer);
+ m_modList.push_back(new FtModChipID);
+ m_modList.push_back(new FtModTestAlive);
+ m_modList.push_back(new FtModVersionInfo);
+ m_modList.push_back(new FtModVersionInfo2);
+ m_modList.push_back(new FtModPowerOff);
+ m_modList.push_back(new FtModReboot);
+ m_modList.push_back(new FtModBuildProp);
+ m_modList.push_back(new FtModModemInfo);
+ m_modList.push_back(new FtModSIMNum);
+ m_modList.push_back(new FtModUtility);
+ m_modList.push_back(new FtModSpecialTest);
+ m_modList.push_back(new FtModChipInfo);
+ m_modList.push_back(new FtModFileOperation);
+ m_modList.push_back(new FtModTargetloggerCtrl);
+ m_modList.push_back(new FtModTargetClock);
+ m_modList.push_back(new FtModMetaDisconnect);
+
+#ifdef MTK_META_SYSENV_SUPPORT
+ m_modList.push_back(new FtModSysEnv);
+#endif
+
+
+}
+
+unsigned int Context::getMdmInfo()
+{
+ unsigned int modem_number =0;
+ unsigned int active_modem_id = 0;
+ unsigned int modem_type = 0;
+ bool isactive = false;
+
+ if(IsModemSupport(3))
+ {
+ modem_type |= MD3_INDEX;
+ modem_number++;
+ META_LOG("[Meta] modem[3] is enable");
+ }
+
+ if(IsModemSupport(1))
+ {
+ modem_type |= MD1_INDEX;
+ modem_number++;
+ if(!isactive)
+ {
+ active_modem_id = 1;
+ isactive = true;
+ }
+ META_LOG("[Meta] modem[1] is enable");
+ }
+
+ if(IsModemSupport(2))
+ {
+ modem_type |= MD2_INDEX;
+ modem_number++;
+ if(!isactive)
+ {
+ active_modem_id = 2;
+ isactive = true;
+ }
+ META_LOG("[Meta] modem[2] is enable");
+ }
+
+ if(IsModemSupport(5))
+ {
+ modem_type |= MD5_INDEX;
+ modem_number++;
+ if(!isactive)
+ {
+ active_modem_id = 5;
+ isactive = true;
+ }
+ META_LOG("[Meta] modem[5] is enable");
+ }
+
+ META_LOG("[Meta] modem_type = %d, modem_number = %d, active_modem_id = %d", modem_type, modem_number, active_modem_id);
+
+ m_mdmType = modem_type;
+ m_mdmNumber = modem_number;
+ m_activeMdmId = active_modem_id;
+
+ return modem_number;
+}
+
+
+void Context::setLogLevel(unsigned int level)
+{
+ m_logLevel = level;
+}
+unsigned int Context::getLogLevel()
+{
+ return m_logLevel;
+}
+
+unsigned int Context::getMdmType()
+{
+ return m_mdmType;
+}
+
+
+unsigned int Context::getActiveMdmId()
+{
+ return m_activeMdmId;
+}
+
+
+unsigned int Context::getMdmNumber()
+{
+ return m_mdmNumber;
+}
+
+signed int Context::getModemHandle(unsigned short id)
+{
+ Modem *md = getModem(id);
+ if(md != NULL)
+ return md->getDevHandle();
+
+ return -1;
+}
+
+int Context::getDataChannelType()
+{
+ return m_mdDataChannel;
+}
+
+unsigned int Context::dumpData(const unsigned char* con, int length)
+{
+ META_LOG("[Meta] Dump data is: ");
+ int i = 0;
+ for(i = 0; i < length; i++)
+ printf(" (%02x) ",con[i]);
+ META_LOG("[Meta] Dump finished!");
+ return 0;
+
+
+}
+
+unsigned int Context::dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow)
+{
+
+// if(getLogLevel() || getPropValue("persist.vendor.meta.dumpdata") == 1)
+ {
+ int i = 0;
+ unsigned int j = 0;
+ unsigned int rowLength = 3 * bytesPerRow + 1;
+ unsigned char hex[rowLength];
+ unsigned char high;
+ unsigned char low;
+ META_LOG("[Meta] Dump begin!");
+ for(i = 0; i < length; i++)
+ {
+ high = (con[i] >> 4);
+ low = (con[i] & 0x0f);
+
+ if(high < 0x0a)
+ high += 0x30;
+ else
+ high += 0x37;
+
+ if(low < 0x0a)
+ low += 0x30;
+ else
+ low += 0x37;
+
+ hex[j++] = high;
+ hex[j++] = low;
+ hex[j++] = ' ';
+
+ if (j == rowLength - 1 || i == length - 1)
+ {
+ hex[j] = '\0';
+ j = 0;
+ META_LOG("%s", hex);
+ }
+ }
+
+ META_LOG("[Meta] Dump finished!");
+ }
+
+ return 0;
+}
+
+
+unsigned int Context::getFileSize(int fd)
+{
+ struct stat file_stat;
+ if(fstat(fd, &file_stat) < 0)
+ {
+ return 0;
+ }
+ else
+ {
+ return (unsigned int)file_stat.st_size;
+ }
+}
+
+
+const char* Context::makepath(unsigned char file_ID)
+{
+ if(access("/data/nvram/AllMap",F_OK)==0)
+ {
+ META_LOG("[Meta] /data/nvram/AllMap exist");
+ if(file_ID == 0)
+ {
+ return "/data/nvram/AllMap";
+ }
+ else if(file_ID == 1)
+ {
+ return "/data/nvram/AllFile";
+ }
+ else
+ {
+ META_LOG("[Meta] makepath error: invalid file_ID %d! ", file_ID);
+ return "";
+ }
+ }
+ else
+ {
+ META_LOG("[Meta] /data/nvram/AllMap not exist");
+ if(file_ID == 0)
+ {
+ return "/mnt/vendor/nvdata/AllMap";
+ }
+ else if(file_ID == 1)
+ {
+ return "/mnt/vendor/nvdata/AllFile";
+ }
+ else
+ {
+ META_LOG("[Meta] makepath error: invalid file_ID %d! ", file_ID);
+ return "";
+ }
+ }
+}
+
+void Context::destroyAllModemThread()
+{
+ if(getMDThreadFlag()==1)
+ {
+ setMDThreadFlag(0);
+ }
+ else
+ {
+ META_LOG("[Meta] No MD thread!");
+ return;
+ }
+ unsigned int modemType = getMdmType();
+
+ if((modemType & MD1_INDEX) == MD1_INDEX)
+ {
+ META_LOG("[Meta] DestroyModemThread 0");
+ destroyModemThread(0);
+ }
+
+ if((modemType & MD2_INDEX) == MD2_INDEX)
+ {
+ META_LOG("[Meta] DestroyModemThread 1");
+ destroyModemThread(1);
+ }
+
+#ifdef TST_C2K_SUPPORT
+ if((modemType & MD3_INDEX) == MD3_INDEX)
+ {
+ META_LOG("[Meta] DestroyModemThread 2");
+ destroyModemThread(2);
+ }
+#endif
+
+ if((modemType & MD5_INDEX) == MD5_INDEX)
+ {
+ META_LOG("[Meta] DestroyModemThread 4");
+ destroyModemThread(4);
+ }
+
+}
+void Context::createSerPortThread()
+{
+ SerPort *pPort = NULL;
+
+ pPort = createSerPort();
+
+ if (pPort != NULL)
+ {
+ pPort->pumpAsync(&hostSerPortRx);
+ }
+ else
+ {
+ META_LOG("[Meta] Enter meta_tst normal mode init fail");
+ }
+
+}
+void Context::destroySerPortThread()
+{
+ SerPort *pPort = NULL;
+ pPort = getSerPort();
+ pPort->setExitFlag(1);
+ destroySerPort();
+}
+void Context::createAllModemThread()
+{
+ if(getMDThreadFlag()==0)
+ {
+ setMDThreadFlag(1);
+ }
+ else
+ {
+ META_LOG("[Meta] Alread created MD thread");
+ return;
+ }
+ unsigned int modemType = getMdmType();
+
+ META_LOG("[Meta] createAllModemThread - modemtype = %d", modemType);
+ if((modemType & MD1_INDEX) == MD1_INDEX)
+ {
+ META_LOG("[Meta] CreateAllModemThread 0");
+ createModemThread(0,0);
+ Modem *p = getModem(0);
+ if(p!=NULL)
+ {
+ META_LOG("[Meta] P is not NULL");
+ }
+ else
+ {
+ META_LOG("[Meta] P is NULL");
+ }
+ }
+
+ if((modemType & MD2_INDEX) == MD2_INDEX)
+ {
+ META_LOG("[Meta] CreateAllModemThread 1");
+ createModemThread(1,0);
+ }
+
+#ifdef TST_C2K_SUPPORT
+ if((modemType & MD3_INDEX) == MD3_INDEX)
+ {
+ META_LOG("[Meta] CreateAllModemThread 3");
+ createModemThread(2,0);
+ }
+#endif
+
+ if((modemType & MD5_INDEX) == MD5_INDEX)
+ {
+ META_LOG("[Meta] CreateAllModemThread 4");
+ createModemThread(4,0);
+ }
+}
+
+void Context::destroyModemThread(unsigned short modemIndex)
+{
+ Modem *p = getModem(modemIndex);
+
+ if(p!=NULL)
+ {
+ p->popUpAsync();
+ destroyModem(p);
+ META_LOG("[Meta] DestroyModemThread success modemIndex = %d" ,modemIndex);
+ }
+ else
+ {
+ META_LOG("[Meta] DestroyModemThread fail");
+ }
+}
+
+void Context::createModemThread(unsigned short modemIndex, int usbUsb)
+{
+
+ Modem *pMdHandle = NULL;
+ MdRxWatcher *pRxWatcher = NULL;
+ pRxWatcher = new MdRxWatcher(modemIndex);
+
+ getModemProtocol(modemIndex, &m_modem_cap_list);
+ if((m_mdDataChannel == 1) && (modemIndex == 0))
+ {
+ notifyModemDoRF(modemIndex);
+ pMdHandle = createModem(modemIndex);
+ }
+
+ if(pMdHandle != NULL)
+ {
+ pMdHandle->pumpAsync(pRxWatcher);
+ }
+ else
+ {
+ delete pRxWatcher;
+ }
+}
+
+void Context::setActiveATModem(unsigned int activeATModemId)
+{
+ m_activeATModemId = activeATModemId;
+}
+
+unsigned int Context::getActiveATModem()
+{
+ return m_activeATModemId;
+}
+
+int Context::getModemHwVersion(unsigned short modemIndex)
+{
+ if(MODEM_END == m_modem_hw_version)
+ {
+ if(-1 != queryModemProtocol(modemIndex))
+ {
+ META_LOG("[Meta][Protocol] get MD%d protocol, modem_protocol:%s",(modemIndex+1),m_modemProtocol);
+ if(strcmp(m_modemProtocol,"AP_TST") == 0)
+ {
+ m_modem_hw_version = MODEM_AP_TST;
+ }
+ else if(strcmp(m_modemProtocol,"DHL") == 0)
+ {
+ m_modem_hw_version = MODEM_DHL;
+ }
+ else if(strcmp(m_modemProtocol,"6292") == 0)
+ {
+ m_modem_hw_version = MODEM_6292;
+ }
+ else if(strcmp(m_modemProtocol,"6293") == 0)
+ {
+ m_modem_hw_version = MODEM_6293;
+ }
+ else if(strcmp(m_modemProtocol,"6295") == 0)
+ {
+ m_modem_hw_version = MODEM_6295;
+ }
+ }
+ }
+
+ return m_modem_hw_version;
+}
+
+int Context::getModemProtocol(unsigned short modemIndex, MODEM_CAPABILITY_LIST_CNF* modem_capa)
+{
+ int nRet = 1;
+ modem_capa->modem_cap[modemIndex].md_service = FT_MODEM_SRV_DHL;
+ modem_capa->modem_cap[modemIndex].ch_type = FT_MODEM_CH_TUNNELING;
+ m_mdDataChannel = 1;
+
+ META_LOG("[Meta][Protocol] modem_cap[%d]%d,%d",modemIndex,modem_capa->modem_cap[modemIndex].md_service,modem_capa->modem_cap[modemIndex].ch_type);
+
+ return nRet;
+}
+
+FT_MODEM_CH_TYPE Context::getMDChType(unsigned short modemIndex)
+{
+ return m_modem_cap_list.modem_cap[modemIndex].ch_type;
+}
+
+unsigned int Context::getPropValue(const char *key)
+{
+#ifdef IS_SUPPORT_SP
+ char tempstr[128]={0};
+ property_get(key,tempstr,"0");
+ if(tempstr[0] == '1')
+ return 1;
+ else
+ return 0;
+#else
+ return 0;
+#endif
+
+}
+
+unsigned int Context::getMDMode(void)
+{
+ return m_modem_boot_mode;
+}
+void Context::setMDMode(unsigned int modem_boot_mode)
+{
+ m_modem_boot_mode = modem_boot_mode;
+}
+
+int Context::getIOCPort(unsigned int nModemIndex,int & bDataDevice)
+{
+ int fd = -1;
+ char dev_node[32] = {0};
+
+ if((nModemIndex == 0) || (nModemIndex == 1) || (nModemIndex == 4 && ccci_get_version() == EDSDA))
+ {
+ snprintf(dev_node, 32, "%s", "/dev/ccci_ioctl4");
+ fd = open(dev_node, O_RDWR|O_NOCTTY|O_NDELAY );
+ bDataDevice = 0;
+ }
+ else
+ {
+ unsigned short id = getActiveMdmId() - 1;
+ fd= getModemHandle(id);
+ bDataDevice = 1;
+ }
+
+ if(fd< 0)
+ {
+ META_LOG("[Meta]Open MD%d device note %s fail errno = %d",(nModemIndex+1),dev_node,errno);
+ }
+
+ return fd;
+}
+
+int Context::queryModemProtocol(unsigned short modemIndex)
+{
+ int fd = -1;
+ int nRet = -1;
+
+
+ META_LOG("[META] m_modemProtocol[0] = %c",m_modemProtocol[0]);
+ if(0 == m_modemProtocol[0])
+ {
+ int bDataDevice = 0;
+
+ fd = getIOCPort(modemIndex,bDataDevice);
+
+ if(fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_PROTOCOL_TYPE, m_modemProtocol))
+ {
+ META_LOG("[Meta][Protocol] get MD%d protocol, modem_protocol:%s",(modemIndex+1),m_modemProtocol);
+ nRet = 0;
+ }
+
+ if(bDataDevice == FALSE)
+ {
+ if(fd != -1)
+ {
+ close(fd);
+ META_LOG("[Meta][FT]Close fd");
+ fd = -1;
+ }
+ }
+ }
+ else
+ {
+ nRet = 0;
+ }
+
+ return nRet;
+}
+
+void Context::setMDThreadFlag(int modemThreadFlag)
+{
+ m_modemThreadFlag = modemThreadFlag;
+ META_LOG("[Meta] Set MD Thread Flag = %d",m_modemThreadFlag);
+}
+
+int Context::getMDThreadFlag()
+{
+ return m_modemThreadFlag;
+}
+
+unsigned int Context::checkMdStatus()
+{
+ int ret = 0;
+#ifdef IS_SUPPORT_SP
+ char status[128]={0};
+ property_get("vendor.mtk.md1.status",status, "0");
+ META_LOG("[Meta] modem status = %s", status);
+ if(0 == strncmp(status, "ready", 5)) //ccb owner tell us to check this property.
+ ret = 1;
+ else if(0 == strncmp(status, "exception", 9))
+ ret = 2;
+#else
+/* int count = 0;
+ struct md_status_event status_buf;
+
+ META_LOG("[Meta] begin to open [/dev/ccci_md1_sta]");
+ int md_status_fd = open("/dev/ccci_md1_sta", O_RDWR);
+ META_LOG("[Meta] end open [/dev/ccci_md1_sta]");
+ if (md_status_fd < 0)
+ {
+ META_LOG("[Meta] failed to open [/dev/ccci_md1_sta]");
+ return ret;
+ }
+
+ META_LOG("[Meta] begin to read [/dev/ccci_md1_sta]");
+ count = read(md_status_fd, &status_buf, sizeof(struct md_status_event));
+ if (count > 0)
+ {
+ META_LOG("[Meta] modem status = %d", status_buf.event_type);
+ if (status_buf.event_type == MD_STA_EV_READY)
+ ret = 1;
+ else if(status_buf.event_type == MD_STA_EV_EXCEPTION)
+ ret = 2;
+ }
+*/
+ ret = 1; //ccci module not ready, so set default value.
+#endif
+ return ret;
+}
+
+void Context::setATRespFlag(int atFlag)
+{
+ m_atFlag = atFlag;
+}
+
+int Context::getATRespFlag()
+{
+ return m_atFlag;
+}
+
+void Context::setCurrentMdMode(int mdMode)
+{
+ m_currentMdMode = mdMode;
+}
+
+int Context::notifyModemDoRFByATCI()
+{
+ META_LOG("[Meta] notifyModemDoRFByATCI");
+ if(0 == ChangeModemMode(2))
+ {
+ setMDMode(2);//normal= 1 meta=2
+ }
+ return 0;
+}
+
+int Context::ChangeModemMode(int mode) // 1:modem to normal 2:modem to meta
+{
+ unsigned int nRetry = 0;
+ int nMdStatus = 0;
+
+ META_LOG("[Meta] Enter ChangeModemMode");
+ META_LOG("[Meta] To wait modem ready");
+ do
+ {
+ nMdStatus = checkMdStatus();
+ if( 2 == nMdStatus) //Modem exception, return -1 immediatly
+ {
+ return -1;
+ }
+ usleep(100*1000);
+ nRetry++;
+ if(nRetry > 100) //return if it takes more than 10 seconds
+ return -1;
+ }while(0 == nMdStatus);
+
+
+ MSocket *pSocket = getSocket(SOCKET_ATCI_SERVER);
+ if(pSocket == NULL)
+ {
+ pSocket = createSocket(SOCKET_ATCI_SERVER);
+ if(pSocket != NULL)
+ {
+ int bInit = pSocket->initClient("adb_atci_socket", 0);
+ if(bInit == 0)
+ {
+ delSocket(SOCKET_ATCI_SERVER);
+ return -1;
+ }
+ }
+ else
+ return -1;
+ }
+
+ META_LOG("[META] Check Modem ready by send AT");
+
+ setATRespFlag(1);
+ pSocket->send_msg("AT\r");
+ nRetry = 0;
+ while(getATRespFlag()!=0)
+ {
+ usleep(100*1000);
+ if(getATRespFlag()==-1)
+ pSocket->send_msg("AT\r");
+ nRetry++;
+ if(nRetry > 100) //return if it takes more than 10 seconds
+ return -1;
+ }
+/*
+ META_LOG("[META] Check sim status");
+ char strSimStatus[128] = {0};
+ property_get("persist.vendor.radio.simswitch",strSimStatus,"unknown");
+ nRetry = 0;
+ if((strcmp(strSimStatus,"1") == 0) || (strcmp(strSimStatus,"unknown") == 0))
+ {
+ META_LOG("[META] Sim1 is the main slot, need to send AT+ESUO=4 first");
+ setATRespFlag(1);
+ pSocket->send_msg("AT+ESUO=4\r");
+
+ while(getATRespFlag()!=0)
+ {
+ usleep(100*1000);
+ nRetry++;
+ if(nRetry > 100) //return if it takes more than 10 seconds
+ return -1;
+ }
+ }
+ else if(strcmp(strSimStatus,"2") == 0)
+ {
+ META_LOG("[META] Sim2 is the main slot, need to send AT+ESUO=5 first");
+ setATRespFlag(1);
+ pSocket->send_msg("AT+ESUO=5\r");
+
+ while(getATRespFlag()!=0)
+ {
+ usleep(100*1000);
+ nRetry++;
+ if(nRetry > 100) //return if it takes more than 10 seconds
+ return -1;
+ }
+ }
+*/
+ META_LOG("[Meta] Query current modem mode");
+ setCurrentMdMode(0);
+ pSocket->send_msg("AT+EMETACFG?\r");
+ nRetry = 0;
+ while(1)
+ {
+ if(1 == m_currentMdMode || 2 == m_currentMdMode)
+ break;
+ usleep(100*1000);
+ nRetry++;
+ if(nRetry > 100) //return if it takes more than 10 seconds
+ return -1;
+ }
+ META_LOG("[Meta] Current modem mode = %d", m_currentMdMode);
+ if(m_currentMdMode == mode) //No need to switch modem mode, return 0 directly
+ {
+ META_LOG("[Meta] No need to switch modem mode");
+ return 0;
+ }
+
+ META_LOG("[META] Switch modem mode to %d", mode);
+ setATRespFlag(1);
+ if(mode == 1)
+ {
+ pSocket->send_msg("AT+EMETACFG=0\r");
+ META_LOG("[Meta] Send AT+EMETACFG=0");
+ }
+ else if(mode == 2)
+ {
+ pSocket->send_msg("AT+EMETACFG=1\r");
+ META_LOG("[Meta] Send AT+EMETACFG=1");
+ }
+ else
+ {
+ META_LOG("[Meta]Invalid mode = %d",mode);
+ return -1;
+ }
+ nRetry = 0;
+ while(getATRespFlag()!=0)
+ {
+ usleep(100*1000);
+ nRetry++;
+ if(nRetry > 100) //return if it takes more than 10 seconds
+ return -1;
+ }
+
+ META_LOG("[META]AT+EMETACFG return OK, switch modem success");
+ return 0;
+}
+
+void Context::writeBootprof(char * str)
+{
+ FILE *pBootProfFile = NULL;
+ pBootProfFile = fopen("proc/bootprof","w");
+ if(pBootProfFile!=NULL)
+ {
+ fputs(str,pBootProfFile);
+ fclose(pBootProfFile);
+ pBootProfFile = NULL;
+ META_LOG("[META] write proc/bootprof success");
+ }
+ else
+ {
+ META_LOG("[META] open proc/bootprof fail!");
+ }
+}
+
+int Context::notifyModemDoRF(int mdIdx)
+{
+
+ META_LOG("[Meta] To wait modem ready");
+#ifdef IS_SUPPORT_SP
+ char dev_node[32] = {0};
+ const char *cmd = "AT+EMETACFG=1\r";
+ const char *cmdClearURC = "AT+EURCRPT=0\r";
+ const char *urc = "+EIND: 128";
+ const char *rsp = "OK";
+
+ while(0 == checkMdStatus())
+ {
+ META_LOG("[Meta] To check modem status before open USR_MUXD_DATA");
+ usleep(100*1000);
+ }
+
+ //write bootprof
+ writeBootprof((char *)"[META] checkMdStatus mtk.md1.status=ready.");
+
+ snprintf(dev_node, 32, "%s", ccci_get_node_name(USR_MUXD_DATA,(CCCI_MD)mdIdx));
+ signed int fd = open(dev_node, O_RDWR|O_NOCTTY);
+ if(fd < 0)
+ {
+ META_LOG("[Meta] Can't open CCCI MUXD channel: %s", dev_node);
+ return 0;
+ }
+
+ META_LOG("[Meta] open CCCI MUXD channel: %s", dev_node);
+ META_LOG("[Meta] To read modem URC");
+ waitMdResponse(fd, urc);
+
+ writeBootprof((char *)"[META] Wait Modem urc +EIND: 128");
+
+ //Send AT command to modem
+ int len = write(fd, cmd, strlen(cmd));
+ META_LOG("[Meta] Send AT command - len = %d, cmd = %s", len, cmd);
+ META_LOG("[Meta] To read AT response");
+ waitMdResponse(fd, rsp);
+
+ writeBootprof((char *)"[META] AT+EMETACFG=1 return OK.");
+
+ int lenClearURC = write(fd, cmdClearURC, strlen(cmdClearURC));
+ META_LOG("[Meta] Send AT command - lenClearURC = %d, cmdClearURC = %s", lenClearURC, cmdClearURC);
+
+ close(fd);
+ META_LOG("[Meta] Close CCCI MUXD channel. fd = %d", fd);
+#else
+/* while(0 == checkMdStatus())
+ {
+ META_LOG("[Meta] To check modem status before read URC");
+ usleep(100*1000);
+ }
+
+*/ MetaMIPC ipc;
+ const char *cmd = "AT+EMETACFG=1\r";
+ char rsp[1024] = {0};
+
+ ipc.Init();
+/*
+ while(!ipc.IsModemReady())
+ {
+ META_LOG("[Meta] [META] Wait Modem urc [+EIND: 128]");
+ usleep(500*1000);
+ }
+*/
+ if(ipc.Send_at_cmd(cmd, rsp))
+ {
+ if(NULL != strstr(rsp, "OK"))
+ {
+ META_LOG("[Meta] modem seamless switch successful");
+ }
+ else
+ {
+ META_LOG("[Meta] modem seamless switch failed");
+ }
+ }
+#endif
+
+ return 0;
+}
+
+void Context::waitMdResponse(int fd, const char *rsp)
+{
+ char szbuf[1024] = {0};
+ char data[33] = {0};
+ int len = 0;
+ int totalLen = 0;
+
+ while(1)
+ {
+ len = ::read(fd, data, 32);
+ if(len > 0)
+ {
+ data[len] = '\0';
+ META_LOG("[Meta] read data from AT channel: len= %d, %s", len, data);
+ dumpDataInHexString((const unsigned char*)data,len, 16);
+ strncpy(szbuf+totalLen, data, len);
+ totalLen += len;
+ if(totalLen >= 1024)
+ {
+ totalLen = 0;
+ META_LOG("[Meta] Modem response too long");
+ }
+
+ if( NULL != strstr(szbuf, rsp))
+ break;
+ }
+ memset(data, 0, 33);
+ }
+ META_LOG("[Meta] Read AT response sucess");
+}
+
+MSocket* Context::createSocket(SOCKET_TYPE type)
+{
+ for(int i=0; i<SOCKET_END; i++)
+ {
+ if(m_socket[i] == NULL)
+ {
+ switch(type)
+ {
+ case SOCKET_MDLOGGER:
+ case SOCKET_MOBILELOG:
+ case SOCKET_CONNSYSLOG:
+ case SOCKET_GPSLOGGER:
+ m_socket[i] = (MSocket*)new MLogSocket(type);
+ break;
+ case SOCKET_ATCI_CLIENT:
+ m_socket[i] = (MSocket*)new MATCIClientSocket(type);
+ break;
+ case SOCKET_ATCI_SERVER:
+ m_socket[i] = (MSocket*)new MATCIServerSocket(type);
+ break;
+ case SOCKET_ATM_COMM:
+ m_socket[i] = (MSocket*)new MATMSocket(type);
+ break;
+ default:
+ return NULL;
+ }
+
+ if(m_socket[i] != NULL)
+ {
+ //META_LOG("[Meta][Socket] Create socket success. idx=%d, pSocket=0x%08x, type=%d", i, m_socket[i], m_socket[i]->m_type);
+ return m_socket[i];
+ }
+ else
+ {
+ META_LOG("[Meta][Socket] Create socket fail.");
+ return NULL;
+ }
+ }
+ }
+
+ META_LOG("[Meta][Socket] no empty socket object!");
+ return NULL;
+
+}
+
+MSocket* Context::getSocket(SOCKET_TYPE type)
+{
+
+ META_LOG("[Meta][Socket] To get socket object!");
+ for(int i=0; i<SOCKET_END; i++)
+ {
+ if(m_socket[i] != NULL)
+ {
+ //META_LOG("[Meta][Socket] Get socket, idx=%d, pSocket=0x%08x, type=%d", i, m_socket[i], m_socket[i]->m_type);
+ if(m_socket[i]->m_type == type)
+ return m_socket[i];
+ }
+ }
+
+ META_LOG("[Meta][Socket] Can not find socket object!");
+ return NULL;
+}
+
+void Context::delSocket(SOCKET_TYPE type)
+{
+ META_LOG("[Meta][Socket] To delete socket object!");
+ for(int i=0; i<SOCKET_END; i++)
+ {
+ if(m_socket[i] != NULL)
+ {
+ //META_LOG("[Meta][Socket] Get socket, idx=%d, pSocket=0x%08x, type=%d", i, m_socket[i], m_socket[i]->m_type);
+ if(m_socket[i]->m_type == type)
+ {
+ free(m_socket[i]);
+ m_socket[i] = NULL;
+ }
+ }
+ }
+
+ return;
+}
+void Context::destroyVirtualRxThread()
+{
+ SerPort *pPort = getSerPort();
+ if(pPort!=NULL)
+ {
+ pPort->setExitFlag(1);
+ pPort->setSerPortExitFlag(); //Stop socket connect while loop
+ pPort->waitForThreadExit(); //Sync virtual rx thread with main thread before destroy
+ //destroyPortHandle();
+ destroySerPort();
+ META_LOG("[Meta] destroyVirtualRxThread success" );
+ }
+ else
+ {
+ META_LOG("[Meta] destroyVirtualRxThread fail");
+ }
+}
+
+//For USB,UART,SOCKET, etc.
+void Context::createVirtualRxThread()
+{
+ SerPort *pPort = createSerPort();
+ UsbRxWatcher *pVirtualRxWatcher = getVirtualRxWatcher();
+
+ if (pPort != NULL && pVirtualRxWatcher != NULL)
+ {
+ META_LOG("[Meta] createVirtualRxThread success");
+ pPort->pumpAsync(pVirtualRxWatcher);
+ }
+ else
+ {
+ META_LOG("[Meta] createVirtualRxThread fail");
+ }
+}
+
+UsbRxWatcher * Context::getVirtualRxWatcher() const
+{
+ return m_virtualRxWatcher;
+}
+
+void Context::setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher)
+{
+ m_virtualRxWatcher = virtualRxWatcher;
+}
+
+void Context::queryNormalModeTestFlag()
+{
+ m_normalModeTestFlag = getProductInfo(0, OFFSET_ATM);
+}
+
+int Context::getNormalModeTestFlag()
+{
+ return m_normalModeTestFlag;
+}
+
+int Context::setNormalModeTestFlag(int flag)
+{
+ return modifyProductInfo(0, flag, OFFSET_ATM);
+}
+
+int Context::modifyProductInfo(int type, int flag, int offset)
+{
+ int fd = -1;
+ int result = 0;
+ int cipherText = 0;
+ char write_buf[1024] = {0};
+ char log_flag = 0;
+
+ META_LOG("[Meta][FT] setProductInfo flag = %d", flag);
+
+ if(type == 0) //ATM flag
+ {
+ cipherText = encrypt((KEY1+flag), KEY2);
+ META_LOG("[Meta][FT] setProductInfo after encrypt, flag = %d", cipherText);
+ sprintf(write_buf, "%d", cipherText);
+ }
+
+ fd = open(FLAG_PATH, O_RDWR);
+ if(fd < 0)
+ {
+ META_LOG("[Meta][FT] setProductInfo open /proinfo fail, errno = %d", errno);
+ return -1;
+ }
+ else
+ {
+ if(lseek(fd, offset, SEEK_SET) < 0)
+ {
+ META_LOG("[Meta][FT] setProductInfo lseek failed.");
+ close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return -1;
+ }
+
+ if(type == 0) //ATM flag
+ result = write(fd, write_buf, ENCRYPT_LENTH);
+ else if(type == 1) //meta log
+ {
+ log_flag = (char)flag;
+ result = write(fd, &log_flag, 1);
+ }
+
+ if(result > 0)
+ {
+ META_LOG("[Meta][FT] setProductInfo write /proinfo success");
+ close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return 0;
+ }
+ else
+ {
+ META_LOG("[Meta][FT] setProductInfo write /proinfo fail, errno = %d", errno);
+ close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return -1;
+ }
+ }
+}
+
+int Context::setProductInfo(int type, int flag, int offset)
+{
+ return modifyProductInfo(type, flag, offset);
+}
+
+int Context::getProductInfo(int type, int offset)
+{
+ int fd = -1;
+ char read_buf[1024] = {0};
+ int result = 0;
+ int val = -1;
+ char log_val = -1;
+ int ret = 0;
+
+ fd = open(FLAG_PATH,O_RDWR);
+ if(fd < 0)
+ {
+ META_LOG("[Meta][FT] queryProductInfo open /proinfo fail, errno = %d", errno);
+ return val;
+ }
+ ret = lseek(fd, offset, SEEK_SET);
+ if(ret == -1)
+ {
+ close(fd);
+ return -1;
+ }
+
+ if(type == 0)
+ {
+ result = read(fd, read_buf, ENCRYPT_LENTH);
+ META_LOG("[Meta][FT] queryProductInfo read /proinfo success");
+ META_LOG("[Meta][FT] queryProductInfo before decrypt, flag = %d", atoi(read_buf));
+ if(result > 0)
+ val = decrypt(atoi(read_buf), KEY2) - KEY1;
+ }
+ else if(type == 1)
+ {
+ result = read(fd, &log_val, 1);
+ val = log_val;
+ }
+
+ if(result > 0)
+ {
+
+ META_LOG("[Meta][FT] queryProductInfo flag = %d", val);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] queryProductInfo read /proinfo fail, errno = %d", errno);
+ }
+
+ close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+
+ return val;
+}
+
+void Context::queryWifiPara(int argc, char** argv)
+{
+ META_LOG("[Meta] Enter queryWifiPara");
+ const char* wifi_opt = "a:p:";
+ int opt = 0;
+
+ while( (opt = getopt(argc, argv, wifi_opt)) != -1)
+ {
+ META_LOG("[Meta] queryWifiPara opt = %d", opt);
+ switch(opt)
+ {
+ case 'a':
+ m_WifiPara.ip_addr = optarg;
+ META_LOG("[Meta] queryWifiPara get ip address: %s", m_WifiPara.ip_addr);
+ break;
+ case 'p':
+ m_WifiPara.port = atoi(optarg);
+ META_LOG("[Meta] queryWifiPara get port: %d", m_WifiPara.port);
+ break;
+ default:
+ META_LOG("[Meta] queryWifiPara invalid option!");
+ break;
+ }
+ }
+
+ META_LOG("[Meta] Exit queryWifiPara");
+}
+
+WIFI_PARA Context::getWifiPara()
+{
+#ifdef IS_SUPPORT_SP
+ char strIpAddr[128] = {0};
+ property_get("persist.vendor.atm.ipaddress", strIpAddr, "0,0,0,0");
+ m_WifiPara.ip_addr = strIpAddr;
+ m_WifiPara.port = 9000;
+#endif
+
+ return m_WifiPara;
+}
+
+int Context::writePortIndex()
+{
+ int res = 0;
+ int fd = ::open("/sys/class/android_usb/android0/f_acm/port_index", O_WRONLY);
+ if (fd != -1)
+ {
+ res = ::write(fd,"1,4",4);
+ if(res>0)
+ {
+ META_LOG("[Meta] writePortIndex /sys/class/android_usb/android0/f_acm/port_index 1,4 Success");
+ close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return 0;
+ }
+ else
+ {
+ META_LOG("[Meta] writePortIndex /sys/class/android_usb/android0/f_acm/port_index 1,4 Failed");
+ close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return -1;
+ }
+ }
+ else
+ {
+ META_LOG("[Meta] Failed to open:/sys/class/android_usb/android0/f_acm/port_index");
+ return -1;
+ }
+
+}
+
+void Context::switchComType(META_COM_TYPE targetComType)
+{
+ if(getComType() != targetComType)
+ {
+ usbMutexLock(true);
+ destroyVirtualRxThread();
+ usleep(100*1000); //sleep 100 ms
+ setComType(targetComType);
+#ifndef MTK_ATM_METAWIFIONLY
+ createVirtualRxThread();
+#else
+ if(META_SOCKET == targetComType)
+ {
+ createVirtualRxThread();
+ }
+#endif
+ META_LOG("[Meta] Change connect type to %d", (int)targetComType);
+ usbMutexLock(false);
+ }
+ else
+ {
+ META_LOG("[Meta] Connect type is already %d, no need to switch", (int)targetComType);
+ }
+}
+
+void Context::SetDataCompressStatus(unsigned int enable)
+{
+ m_dataCompressStatus = enable;
+}
+unsigned int Context::GetDataCompressStatus()
+{
+ return m_dataCompressStatus;
+}
+
+void Context::HandleSocketCmd(char* socket_cmd)
+{
+
+#ifdef IS_SUPPORT_SP
+ if(sizeof(socket_cmd) > 32) {
+ META_LOG("[Meta] HandleSocketCmd: Invalid socket command: %s", socket_cmd);
+ return;
+ }
+ META_LOG("[Meta] HandleSocketCmd: command: %s", socket_cmd);
+
+ if(strstr(socket_cmd, "ATM_WIFI_INFO_IP_ADDRESS") != NULL)
+ {
+ string strcmd = string(socket_cmd);
+ string strIP = strcmd.erase(0, strcmd.find_last_of(':')+1);
+ property_set("persist.vendor.atm.ipaddress", strIP.c_str());
+ META_LOG("[Meta] HandleSocketCmd: ipaddr: %s", strIP.c_str());
+ }
+ else
+ {
+ if(0 == strcmp(socket_cmd, "ATM_SWITCH_META_TO_WIFI")) {
+ switchComType(META_SOCKET);
+ property_set("persist.vendor.meta.connecttype", "wifi");
+ } else if(0 == strcmp(socket_cmd, "ATM_SWITCH_META_TO_USB")) {
+ switchComType(META_USB_COM);
+ property_set("persist.vendor.meta.connecttype", "usb");
+ } else if(0 == strcmp(socket_cmd, "ATM_SWITCH_MODEM_TO_META")) {
+ if(0 == ChangeModemMode(2))
+ {
+ META_LOG("[Meta] HandleSocketCmd: switch modem to META mode success");
+ setMDMode(2);
+ property_set("persist.vendor.atm.mdmode", "meta");
+ }
+ else
+ {
+ META_LOG("[Meta] HandleSocketCmd: switch modem to META mode fail");
+ }
+ } else if(0 == strcmp(socket_cmd, "ATM_SWITCH_MODEM_TO_NORMAL")) {
+ if(0 == ChangeModemMode(1))
+ {
+ META_LOG("[Meta] HandleSocketCmd: switch modem to normal mode success");
+ setMDMode(1);
+ property_set("persist.vendor.atm.mdmode", "normal");
+ }
+ else
+ {
+ META_LOG("[Meta] HandleSocketCmd: switch modem to normal mode fail");
+ }
+ } else if(0 == strcmp(socket_cmd, "ATM_DESTORY_WIFI_SOCKET")) {
+ destroyVirtualRxThread();
+ setComType(META_UNKNOWN_COM);
+ } else if(0 == strcmp(socket_cmd, "ATM_NEW_WIFI_SOCKET")) {
+ setComType(META_SOCKET);
+ createVirtualRxThread();
+ } else if(0 == strcmp(socket_cmd, "ATM_REBOOT_MODEM")) {
+ int bDataDevice = 0;
+ int fd = getIOCPort(0, bDataDevice);
+ if(fd >= 0)
+ {
+ if(0 == ioctl(fd, CCCI_IOC_MD_RESET))
+ {
+ setMDMode(1);
+ property_set("persist.vendor.atm.mdmode", "normal");
+ META_LOG("[Meta] HandleSocketCmd: reboot modem to normal mode success");
+ }
+ else
+ {
+ META_LOG("[Meta] HandleSocketCmd: reboot modem to normal mode fail");
+ }
+ if(FALSE == bDataDevice)
+ {
+ close(fd);
+ META_LOG("[Meta] HandleSocketCmd: close fd: %d", fd);
+ fd = -1;
+ }
+ }
+ }
+
+ }
+#endif
+}
+//////////////////////////////////////////////////////////////////////////
+
+void destroyModem(Modem *p)
+{
+ return Context::instance()->destroyModem(p);
+}
+
+Modem * createModem(const char *ccci, unsigned short id)
+{
+ return Context::instance()->createModem(ccci, id);
+}
+
+Modem * createModem(unsigned short id)
+{
+ return Context::instance()->createModem(id);
+}
+
+CmdTarget * getModule(unsigned short id)
+{
+ return Context::instance()->getModule(id);
+}
+
+Modem * getModem(unsigned short id)
+{
+ return Context::instance()->getModem(id);
+}
+
+unsigned int dumpData(const unsigned char* con, int length)
+{
+ return Context::instance()->dumpData(con,length);
+}
+
+unsigned int dumpDataInHexString(const unsigned char* con, int length, unsigned int bytesPerRow)
+{
+ return Context::instance()->dumpDataInHexString(con,length,bytesPerRow);
+}
+
+unsigned int getFileSize(int fd)
+{
+ return Context::instance()->getFileSize(fd);
+}
+
+const char* makepath(unsigned char file_ID)
+{
+ return Context::instance()->makepath(file_ID);
+}
+
+void destroyContext()
+{
+ return Context::instance()->destroy();
+}
+
+unsigned int getMdmType()
+{
+ return Context::instance()->getMdmType();
+}
+
+unsigned int getActiveMdmId()
+{
+ return Context::instance()->getActiveMdmId();
+}
+
+unsigned int getMdmNumber()
+{
+ return Context::instance()->getMdmNumber();
+}
+
+signed int getModemHandle(unsigned short id)
+{
+ return Context::instance()->getModemHandle(id);
+}
+
+void setLogLevel(unsigned int level)
+{
+ return Context::instance()->setLogLevel(level);
+}
+unsigned int getLogLevel()
+{
+ return Context::instance()->getLogLevel();
+}
+
+void destroyModemThread(unsigned short modemIndex)
+{
+ return Context::instance()->destroyModemThread(modemIndex);
+}
+
+void destroyAllModemThread()
+{
+ return Context::instance()->destroyAllModemThread();
+}
+
+void createAllModemThread()
+{
+ return Context::instance()->createAllModemThread();
+}
+
+
+void createModemThread(unsigned short modemIndex,int usbUsb)
+{
+ return Context::instance()->createModemThread(modemIndex,usbUsb);
+}
+
+void createSerPortThread()
+{
+ return Context::instance()->createSerPortThread();
+}
+
+void destroySerPortThread()
+{
+ return Context::instance()->destroySerPortThread();
+}
+
+
+int getModemProtocol(unsigned short modemIndex, void* modem_capa)
+{
+ return Context::instance()->getModemProtocol(modemIndex, (MODEM_CAPABILITY_LIST_CNF*)modem_capa);
+}
+
+int getMDChType(unsigned short modemIndex)
+{
+ return Context::instance()->getMDChType(modemIndex);
+}
+
+unsigned int getMDMode(void)
+{
+ return Context::instance()->getMDMode();;
+}
+
+void setMDMode(unsigned int modem_boot_mode)
+{
+ return Context::instance()->setMDMode(modem_boot_mode);
+}
+
+void setActiveATModem(unsigned int activeATModemId)
+{
+ return Context::instance()->setActiveATModem(activeATModemId);
+}
+
+unsigned int getActiveATModem()
+{
+ return Context::instance()->getActiveATModem();
+}
+
+int getIOCPort(unsigned int nModemIndex,int & bDataDevice)
+{
+ return Context::instance()->getIOCPort(nModemIndex,bDataDevice);
+}
+
+int getBootMode()
+{
+ return Context::instance()->getBootMode();
+}
+
+void queryNormalModeTestFlag()
+{
+ return Context::instance()->queryNormalModeTestFlag();
+}
+
+int getNormalModeTestFlag()
+{
+ return Context::instance()->getNormalModeTestFlag();
+}
+
+int setNormalModeTestFlag(int flag)
+{
+ return Context::instance()->setNormalModeTestFlag(flag);
+}
+
+int setProductInfo(int type, int flag, int offset)
+{
+ return Context::instance()->setProductInfo(type, flag, offset);
+}
+
+int getProductInfo(int type, int offset)
+{
+ return Context::instance()->getProductInfo(type, offset);
+}
+
+int getDataChannelType()
+{
+ return Context::instance()->getDataChannelType();
+}
+
+int getPropValue(const char *key)
+{
+ return Context::instance()->getPropValue(key);
+}
+
+MSocket * createSocket(unsigned int type)
+{
+ return Context::instance()->createSocket((SOCKET_TYPE)type);
+}
+
+MSocket * getSocket(unsigned int type)
+{
+ return Context::instance()->getSocket((SOCKET_TYPE)type);
+}
+
+void delSocket(unsigned int type)
+{
+ return Context::instance()->delSocket((SOCKET_TYPE)type);
+}
+void destroyVirtualRxThread()
+{
+ return Context::instance()->destroyVirtualRxThread();
+}
+
+void createVirtualRxThread()
+{
+ return Context::instance()->createVirtualRxThread();
+}
+
+void setVirtualRxWatcher(UsbRxWatcher * virtualRxWatcher)
+{
+ return Context::instance()->setVirtualRxWatcher(virtualRxWatcher);
+}
+
+int getLoadType()
+{
+ return Context::instance()->getLoadType();
+}
+
+int getModemHwVersion(unsigned short modemIndex)
+{
+ return Context::instance()->getModemHwVersion(modemIndex);
+}
+
+void queryWifiPara(int argc, char** argv)
+{
+ return Context::instance()->queryWifiPara(argc, argv);
+}
+
+WIFI_PARA getWifiPara()
+{
+ return Context::instance()->getWifiPara();
+}
+
+void setATRespFlag(int atFlag)
+{
+ return Context::instance()->setATRespFlag(atFlag);
+}
+
+int getATRespFlag()
+{
+ return Context::instance()->getATRespFlag();
+}
+
+int notifyModemDoRFByATCI()
+{
+ return Context::instance()->notifyModemDoRFByATCI();
+}
+
+int ChangeModemMode(int mode)
+{
+ return Context::instance()->ChangeModemMode(mode);
+}
+
+int writePortIndex()
+{
+ return Context::instance()->writePortIndex();
+}
+
+void writeBootprof(char * str)
+{
+ return Context::instance()->writeBootprof(str);
+}
+
+
+void setCurrentMdMode(int mdMode)
+{
+ return Context::instance()->setCurrentMdMode(mdMode);
+}
+
+void HandleSocketCmd(char* socket_cmd)
+{
+ return Context::instance()->HandleSocketCmd(socket_cmd);
+}
+
+int readSys_int(char const * path)
+{
+ return Context::instance()->readSys_int(path);
+}
+
+unsigned int checkMdStatus()
+{
+ return Context::instance()->checkMdStatus();
+
+}
+
+void SetDataCompressStatus(unsigned int enable)
+{
+ return Context::instance()->SetDataCompressStatus(enable);
+}
+unsigned int GetDataCompressStatus()
+{
+ return Context::instance()->GetDataCompressStatus();
+}
+
+
diff --git a/src/devtools/meta/src/common/src/Device.cpp b/src/devtools/meta/src/common/src/Device.cpp
new file mode 100644
index 0000000..df6d0c5
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Device.cpp
@@ -0,0 +1,150 @@
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+
+#include "Context.h"
+#include "Device.h"
+#include "LogDefine.h"
+
+#define BUF_SIZE (64+12)*1024+6
+IDevWatcher::~IDevWatcher(void){}
+
+Device::Device(void)
+ : m_exitFlag(0), m_fd(NULL_FILE_DESCRIPTOR), m_pWatcher(NULL)
+{
+ m_wMutex = PTHREAD_MUTEX_INITIALIZER;
+ memset(&m_thread, 0, sizeof(pthread_t));
+ m_buf = (unsigned char *)malloc(BUF_SIZE);
+ if(m_buf != NULL)
+ memset(m_buf, 0, BUF_SIZE);
+}
+
+Device::~Device(void)
+{
+ if (m_fd != NULL_FILE_DESCRIPTOR)
+ {
+ ::close(m_fd);
+ m_fd = NULL_FILE_DESCRIPTOR;
+ }
+
+ if(m_buf != NULL)
+ {
+ free(m_buf);
+ m_buf = NULL;
+ }
+
+ if(m_pWatcher != NULL)
+ {
+ delete(m_pWatcher);
+ m_pWatcher = NULL;
+ }
+
+}
+
+void Device::close()
+{
+ META_LOG("[Meta] Close Handle m_fd = %d",m_fd);
+ if(m_fd != NULL_FILE_DESCRIPTOR)
+ {
+ int result = ::close(m_fd);
+ META_LOG("[Meta] Close handle success result = %d",result);
+ m_fd = NULL_FILE_DESCRIPTOR;
+ }
+}
+
+signed int Device::read(unsigned char *buf, unsigned int len)
+{
+ int tmpLen = 0;
+
+ if(m_fd < 0)
+ sleep(1);
+ else
+ tmpLen = ::read(m_fd, buf, len);
+ //META_LOG("[Meta] read data from device: len =%d , m_fd = %d", tmpLen, m_fd);
+ return tmpLen;
+}
+
+signed int Device::write(const unsigned char *p, unsigned int len)
+{
+ int bytes_written = -1;
+ int remain_size = len;
+ pthread_mutex_lock(&m_wMutex);
+ while(remain_size > 0)
+ {
+ bytes_written = ::write(m_fd, p, remain_size);
+ if (bytes_written < 0)
+ {
+ META_LOG("[Meta] Write data to device failed, return %d, errno=%d, m_fd=%d", bytes_written, errno, m_fd);
+ pthread_mutex_unlock(&m_wMutex);
+ return bytes_written;
+ }
+ else
+ {
+ META_LOG("[Meta] Write %d bytes to device: m_fd = %d, ", bytes_written, m_fd);
+ }
+ remain_size -= bytes_written;
+ p += bytes_written;
+ }
+ pthread_mutex_unlock(&m_wMutex);
+ return (len - remain_size);
+}
+
+signed int Device::pump(IDevWatcher *p)
+{
+ //unsigned char buf[65*1024+6]={0};
+// unsigned char buf[(64+12)*1024+6]={0};
+ int len = 0;
+
+ assert (p != NULL);
+ if(m_buf == NULL)
+ {
+ META_LOG("[Meta] failed to malloc rx buf");
+ return 0;
+ }
+
+ while (m_exitFlag == 0)
+ {
+ len = read(m_buf, BUF_SIZE);
+
+ if (len > 0)
+ {
+ p->onReceived(m_buf, len);
+ }
+ }
+ return 0;
+}
+
+void Device::setExitFlag(unsigned int exitFlag)
+{
+ m_exitFlag = exitFlag;
+}
+
+signed int Device::pumpAsync(IDevWatcher *p)
+{
+ m_pWatcher = p;
+ pthread_create(&m_thread, NULL, ThreadProc, this);
+ return 0;
+}
+
+void *Device::ThreadProc(void *p)
+{
+ Device *inst = (Device*)p;
+ inst->pump(inst->m_pWatcher);
+ return NULL;
+}
+
+void Device::waitForThreadExit()
+{
+ pthread_join(m_thread, NULL);
+}
+
+void Device::update()
+{
+}
+
+
+
+
diff --git a/src/devtools/meta/src/common/src/Frame.cpp b/src/devtools/meta/src/common/src/Frame.cpp
new file mode 100644
index 0000000..dd496ec
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Frame.cpp
@@ -0,0 +1,33 @@
+#include <stddef.h>
+#include <string.h>
+#include "Frame.h"
+#include "CmdTarget.h"
+#include "LogDefine.h"
+
+Frame::Frame(const META_RX_DATA &data, CmdTarget *mod)
+ : m_myMod(mod), m_frmData(data),m_isValid(1)
+{
+}
+Frame::Frame()
+ : m_isValid(0)
+{
+ m_myMod = NULL;
+ memset(&m_frmData, 0, sizeof(META_RX_DATA));
+}
+
+
+Frame::~Frame(void)
+{
+}
+
+void Frame::exec()
+{
+ if (m_myMod != NULL)
+ {
+ m_myMod->exec(this);
+ }
+ else
+ {
+ META_LOG("[Meta] No module assigned; data discarded.");
+ }
+}
diff --git a/src/devtools/meta/src/common/src/FtModule.cpp b/src/devtools/meta/src/common/src/FtModule.cpp
new file mode 100644
index 0000000..4cc838f
--- /dev/null
+++ b/src/devtools/meta/src/common/src/FtModule.cpp
@@ -0,0 +1,4594 @@
+#ifdef IS_SUPPORT_SP
+#ifdef FT_DRM_KEY_MNG_FEATURE
+#ifdef FT_DRM_KEY_MNG_TEE_FEATURE
+#include "Keymanage.h"
+#include <vendor/mediatek/hardware/keymanage/1.0/IKeymanage.h>
+using namespace vendor::mediatek::hardware::keymanage::V1_0;
+#else
+#include "Keyinstall.h"
+#include <vendor/mediatek/hardware/keyinstall/1.0/IKeyinstall.h>
+using namespace vendor::mediatek::hardware::keyinstall::V1_0;
+#endif
+#endif
+#include <vendor/mediatek/hardware/nvram/1.1/INvram.h>
+
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+//#include "sysenv_utils.h"
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/reboot.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <time.h>
+
+#include "FtModule.h"
+#include "LogDefine.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "PortHandle.h"
+#include <sys/time.h>
+#include "ccci_intf.h"
+
+#include "MSocket.h"
+
+
+#define SIM_SWITCH_MODE_FILE "/sys/mtk_ssw/mode"
+#define SIM_SWITCH_MODE_STR_LEN 8
+
+#define MTK_MDDB_PATH "vendor/etc/mddb"
+#define MTK_APDB_PATH "vendor/etc/apdb"
+
+#ifndef FT_CNF_OK
+#define FT_CNF_OK 0
+#endif
+#ifndef FT_CNF_FAIL
+#define FT_CNF_FAIL 1
+#endif
+
+#if defined(__LP64__)
+#define CCAP_LIB_PATH "/system/lib64/libccap.so"
+#else
+#define CCAP_LIB_PATH "/system/lib/libccap.so"
+#endif
+
+
+FtModWifi::FtModWifi(void)
+ :CmdTarget(FT_WIFI_REQ_ID)
+{
+}
+
+FtModWifi::~FtModWifi(void)
+{
+}
+
+void FtModWifi::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_WIFI_OP ");
+
+#ifdef FT_WIFI_FEATURE
+ META_WIFI_OP((FT_WM_WIFI_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+#else
+ //write fake for DataCard
+ FT_TARGETLOG_CTRL_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_TARGETLOG_CTRL_CNF));
+ FT_TARGETLOG_CTRL_REQ *req = (FT_TARGETLOG_CTRL_REQ *)pFrm->localBuf();
+ ft_cnf.status = META_FAILED;
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type= req->type;
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_TARGETLOG_CTRL_CNF),NULL, 0);
+#endif
+
+
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_GPS_FEATURE
+
+FtModGPS::FtModGPS(void)
+ :CmdTarget(FT_GPS_REQ_ID)
+{
+}
+
+FtModGPS::~FtModGPS(void)
+{
+}
+
+void FtModGPS::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_GPS_OP ");
+
+ int ATM_Test = ((NORMAL_BOOT == getBootMode()) && (1 == getNormalModeTestFlag()))? 1:0;
+ META_GPS_OP((GPS_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen(), 1);
+}
+
+#endif
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef FT_NFC_FEATURE
+FtModNFC::FtModNFC(void)
+ :CmdTarget(FT_NFC_REQ_ID)
+{
+}
+
+FtModNFC::~FtModNFC(void)
+{
+}
+
+void FtModNFC::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_NFC_OP ");
+
+ if(getInitState())
+ META_NFC_OP((NFC_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+int FtModNFC::init(Frame*)
+{
+ if (META_NFC_init() != 0)
+ {
+ META_NFC_deinit();
+ return false;
+ }
+ return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_FM_FEATURE
+
+FtModFM::FtModFM(void)
+ :CmdTarget(FT_FM_REQ_ID)
+{
+}
+
+FtModFM::~FtModFM(void)
+{
+
+}
+
+void FtModFM::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_FM_OP ");
+ META_FM_OP((FM_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+int FtModFM::init(Frame*)
+{
+ META_FM_init();
+ return true;
+
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_BT_FEATURE
+
+FtModBT::FtModBT(void)
+ :CmdTarget(FT_BT_REQ_ID)
+{
+}
+
+FtModBT::~FtModBT(void)
+{
+}
+
+void FtModBT::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_BT_OP ");
+
+ META_BT_OP((BT_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_AUDIO_FEATURE
+
+FtModAudio::FtModAudio(void)
+ :CmdTarget(FT_L4AUD_REQ_ID)
+{
+}
+
+FtModAudio::~FtModAudio(void)
+{
+}
+
+void FtModAudio::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_Audio_OP ");
+
+ META_Audio_OP((FT_L4AUD_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+int FtModAudio::init(Frame*)
+{
+ META_Audio_init();
+ return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_CCAP_FEATURE
+
+FtModCCAP::FtModCCAP(void)
+ :CmdTarget(FT_CCT_REQ_ID)
+{
+}
+
+FtModCCAP::~FtModCCAP(void)
+{
+}
+
+void FtModCCAP::exec(Frame *pFrm)
+{
+ static void *CcapHwhndl = NULL;
+
+ static int (*func_ccap_init)() = NULL;
+ static void (*func_ccap_op)(const void*, void*, void**, unsigned short*, void**, unsigned short*) = NULL;
+ static void (*func_ccap_const)(int*, int*, int*, int*, int*) = NULL;
+ static void (*func_ccap_set_error)(const void*, void*) = NULL;
+ static int (*func_ccap_get_req_op)(const void*) = NULL;
+
+ static int cnf_size = 0;
+ static int FT_CCT_OP_SUBPREVIEW_LCD_START = 0;
+ static int FT_CCT_OP_SUBPREVIEW_LCD_STOP = 0;
+
+ if(CcapHwhndl == NULL)
+ {
+ CcapHwhndl = dlopen(CCAP_LIB_PATH, RTLD_NOW);
+
+ if(CcapHwhndl == NULL)
+ {
+ META_LOG("[Meta][FT] link libccap.so fail ");
+ return;
+ }
+ else
+ {
+ func_ccap_init = (int(*)()) dlsym(CcapHwhndl, "intf_ccap_init");
+ func_ccap_op = (void(*)(const void*, void*, void**, unsigned short*, void**, unsigned short*)) dlsym(CcapHwhndl, "intf_ccap_op");
+ func_ccap_const = (void(*)(int*, int*, int*, int*, int*)) dlsym(CcapHwhndl, "intf_ccap_const");
+ func_ccap_set_error = (void(*)(const void*, void*)) dlsym(CcapHwhndl, "intf_ccap_set_error");
+ func_ccap_get_req_op = (int(*)(const void*)) dlsym(CcapHwhndl, "intf_ccap_get_req_op");
+ if (func_ccap_init == NULL || func_ccap_op == NULL ||
+ func_ccap_const == NULL || func_ccap_set_error == NULL ||
+ func_ccap_get_req_op == NULL )
+ {
+ META_LOG("[Meta][FT] link libccap.so function pointers fail ");
+ dlclose(CcapHwhndl);
+ CcapHwhndl = NULL;
+ return;
+ }
+
+ func_ccap_const(NULL, &cnf_size, NULL, &FT_CCT_OP_SUBPREVIEW_LCD_START, &FT_CCT_OP_SUBPREVIEW_LCD_STOP);
+ }
+ }
+
+ CmdTarget::exec(pFrm);
+
+ void *req = (void*)pFrm->localBuf();
+ int req_op = func_ccap_get_req_op( req );
+ if ((req_op != FT_CCT_OP_SUBPREVIEW_LCD_START) && (req_op !=FT_CCT_OP_SUBPREVIEW_LCD_STOP))
+ {
+ META_LOG("[Meta][FT] META_CCAP_init ");
+ if (func_ccap_init() == 0)
+ {
+ void *cnf = malloc(cnf_size);
+ if(cnf == NULL)
+ {
+ META_LOG("[Meta][FT] FT_CCAP_OP META_CCT_init Fail, malloc Fail. ");
+ return;
+ }
+ memset(cnf, 0, cnf_size);
+
+ func_ccap_set_error(req, cnf);
+ WriteDataToPC(cnf, cnf_size, NULL, 0);
+
+ free(cnf);
+
+ META_LOG("[Meta][FT] FT_CCAP_OP META_CCT_init Fail ");
+ return;
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] Now is sub Camera, init will be do later");
+ }
+
+ META_LOG("[Meta][FT] FT_CCAP_OP ");
+
+#if 0
+ func_ccap_op( (const void*)req, (void*)pFrm->peerBuf() );
+#else
+ //sned data & free buffer in meta
+ void *localBuf = NULL, *peerBuf = NULL;
+ unsigned short localBufLen = 0, peerBufLen = 0;
+
+ func_ccap_op( (const void*)req, (void*)pFrm->peerBuf(), &localBuf, &localBufLen, &peerBuf, &peerBufLen );
+ WriteDataToPC(localBuf, localBufLen, peerBuf, peerBufLen);
+ free(localBuf);
+ free(peerBuf);
+#endif
+
+ //dlclose(CcapHwhndl);
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_DRM_KEY_MNG_FEATURE
+FtModDRM::FtModDRM(void)
+ :CmdTarget(FT_DRMKEY_REQ_ID)
+{
+}
+
+FtModDRM::~FtModDRM(void)
+{
+
+}
+
+void FtModDRM::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+#ifdef FT_DRM_KEY_MNG_TRUSTONIC_FEATURE
+ //phone drmkey solution
+ META_LOG("[Meta][FT] Trustonic Ft_DRM");
+ FT_DRMKEY_INSTALL_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_DRMKEY_INSTALL_CNF));
+ //init the header
+ ft_cnf.header.id = pFrm->getCmdTarget()->getId() + 1;
+ ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+ ft_cnf.status = DRMKEY_INSTALL_FAIL;
+
+ META_LOG("[DRMKEY] pFrm->localBuf())->header.token: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->header.token);
+ META_LOG("[DRMKEY] pFrm->localBuf())->header.id: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->header.id);
+ META_LOG("[DRMKEY] pFrm->localBuf())->op: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->op);
+ META_LOG("[DRMKEY] pFrm->localBuf())->cmd.set_req.file_size: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->cmd.set_req.file_size);
+ META_LOG("[DRMKEY] pFrm->localBuf())->cmd.set_req.stage: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->cmd.set_req.stage);
+ META_LOG("[DRMKEY] pFrm->localBuf())->cmd.query_req.req: %d\n", ((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf())->cmd.query_req.req);
+ META_LOG("[DRMKEY] =========================================================\n");
+ META_LOG("[DRMKEY] ft_cnf.header.token: %d\n", ft_cnf.header.token);
+ META_LOG("[DRMKEY] ft_cnf.header.id: %d\n", ft_cnf.header.id);
+ META_LOG("[DRMKEY] ft_cnf.op: %d\n", ft_cnf.op);
+ META_LOG("[DRMKEY] ft_cnf.status: %d\n", ft_cnf.status);
+ META_LOG("[DRMKEY] ft_cnf.result.set_cnf.result: %d\n", ft_cnf.result.set_cnf.result);
+ META_LOG("[DRMKEY] ft_cnf.result.keyresult.keycount %d\n", ft_cnf.result.keyresult.keycount);
+
+ META_DRMKEY_INSTALL_OP((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf(), &ft_cnf, (char *)pFrm->peerBuf(), pFrm->peerLen());
+ WriteDataToPC(&ft_cnf, sizeof(FT_DRMKEY_INSTALL_CNF), NULL, 0);
+ META_LOG("[DRMKEY_HIDL] WriteDataToPC done");
+#else
+ //tablet drmkey solution
+ META_LOG("[Meta][FT] Inhouse Ft_DRM");
+
+ FT_DRMKEY_INSTALL_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_DRMKEY_INSTALL_CNF));
+
+ //init the header
+ ft_cnf.header.id = pFrm->getCmdTarget()->getId() + 1;
+ ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+ ft_cnf.status = DRMKEY_INSTALL_FAIL;
+
+ android::hardware::hidl_vec<uint8_t> data;
+ HIDL_FT_DRMKEY_INSTALL_REQ toServer_req;
+ HIDL_FT_DRMKEY_INSTALL_CNF toServer_cnf;
+
+ convertREQ2HIDL((FT_DRMKEY_INSTALL_REQ *)pFrm->localBuf(), &toServer_req);
+
+ memset(&toServer_cnf, 0, sizeof(HIDL_FT_DRMKEY_INSTALL_CNF));
+ convertCNF2HIDL(&ft_cnf, &toServer_cnf);
+
+ META_LOG("[KM_HIDL] start HIDL");
+ android::sp<IKeymanage> client = IKeymanage::getService();
+ META_LOG("[KM_HIDL] getService done");
+
+ data.setToExternal(pFrm->peerBuf(), pFrm->peerLen());
+ META_LOG("[KM_HIDL] data.setToExternal done");
+
+ auto callback = [&] (const HIDL_FT_DRMKEY_INSTALL_CNF& fromServer_cnf) {
+ convertCNF2nonHIDL(&fromServer_cnf, &ft_cnf);
+ };
+
+ client->meta_drmkey_install_op(toServer_req, toServer_cnf, data, pFrm->peerLen(), callback);
+
+ META_LOG("[KM_HIDL] hidl_meta_drmkey_install_op done");
+ WriteDataToPC(&ft_cnf, sizeof(FT_DRMKEY_INSTALL_CNF), NULL, 0);
+ META_LOG("[KM_HIDL] WriteDataToPC done");
+
+#endif
+
+}
+#endif
+
+#ifdef FT_GAMMA_FEATURE
+FtModGAMMA::FtModGAMMA(void)
+ :CmdTarget(FT_GAMMA_REQ_ID)
+{
+}
+FtModGAMMA::~FtModGAMMA(void)
+{
+}
+void FtModGAMMA::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+ META_LOG("[Meta][FT] FT_GAMMA_OP ");
+ META_GAMMA_OP((GAMMA_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+#endif
+///////////////////////////////////////////////////////////////////////////////////////////////+
+
+#ifdef FT_ATTESTATION_KEY_FEATURE
+FtModAttestationKey::FtModAttestationKey(void)
+ :CmdTarget(FT_ATTESTATIONKEY_REQ_ID)
+{
+
+}
+
+FtModAttestationKey::~FtModAttestationKey(void)
+{
+
+}
+
+void FtModAttestationKey::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta] FtModAttestationKey");
+
+ int finish = 0;
+ FT_ATTESTATIONKEY_INSTALL_CNF ft_cnf;
+
+ memset(&ft_cnf, 0, sizeof(FT_ATTESTATIONKEY_INSTALL_CNF));
+ ft_cnf.status = META_FAILED;
+
+
+ FT_ATTESTATIONKEY_INSTALL_REQ *req = (FT_ATTESTATIONKEY_INSTALL_REQ *)pFrm->localBuf();
+
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type= req->type;
+
+ META_LOG("[Meta] FtModAttestationKey req->type = %d", req->type);
+ switch(req->type)
+ {
+ case FT_ATTESTATIONKEY_INSTALL_SET:
+ {
+ META_LOG("[Meta] FtModAttestationKey state = %d", req->cmd.set_req.stage);
+ if((req->cmd.set_req.stage & 0x04) == 0x04) //KEY_BLK_EOF
+ finish = 1;
+ META_LOG("[Meta] call ree_import_attest_keybox to send (%d) byte.", pFrm->peerLen());
+ META_LOG("[Meta] ft_cnf.status(B): %d\n", ft_cnf.status);
+ META_LOG("[Meta] ft_cnf.result.set_cnf.result(B): %d\n", ft_cnf.result.set_cnf.result);
+ ft_cnf.result.set_cnf.result = ree_import_attest_keybox((const uint8_t *)pFrm->peerBuf(), (const uint32_t)pFrm->peerLen(), finish);
+ META_LOG("[Meta] ft_cnf.status(A): %d\n", ft_cnf.status);
+ META_LOG("[Meta] ft_cnf.result.set_cnf.result(A): %d\n", ft_cnf.result.set_cnf.result);
+ if(ft_cnf.result.set_cnf.result == 0)
+ ft_cnf.status = META_SUCCESS;
+ else
+ ft_cnf.status = META_FAILED;
+ }
+ break;
+ default:
+ break;
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_ATTESTATIONKEY_INSTALL_CNF), NULL, 0);
+}
+
+#endif
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define NVRAM_PEER_MAX_LEN 2000
+#define BLK_CREATE 0x01
+#define BLK_WRITE 0x02
+#define BLK_EOF 0x04
+
+#ifdef FT_NVRAM_FEATURE
+
+FtModNvramBackup::FtModNvramBackup(void)
+ :CmdTarget(FT_NVRAM_BACKUP_REQ_ID)
+{
+}
+
+FtModNvramBackup::~FtModNvramBackup(void)
+{
+}
+
+bool FtModNvramBackup::SendNVRAMFile(unsigned char file_ID, FT_NVRAM_BACKUP_CNF* pft_cnf)
+{
+ int backupFd;
+ int peer_buff_size = 0;
+ char* peer_buf = 0;
+ bool return_value = FALSE;
+
+ backupFd = open(makepath(file_ID), O_RDWR);
+
+ if(backupFd >= 0)
+ {
+ META_LOG("[Meta][FT] File%d opens succeed ! ",file_ID);
+ unsigned int fileLen = getFileSize(backupFd);
+
+ peer_buf = (char*)malloc(NVRAM_PEER_MAX_LEN);
+ memset(peer_buf, 0, NVRAM_PEER_MAX_LEN);
+
+ pft_cnf->block.stage = BLK_CREATE;
+ pft_cnf->block.file_ID = file_ID;
+
+ while(!(pft_cnf->block.stage & BLK_EOF))
+ {
+ peer_buff_size = read(backupFd, peer_buf, NVRAM_PEER_MAX_LEN);
+
+ if(peer_buff_size != -1)
+ {
+ pft_cnf->status = META_SUCCESS;
+ if(peer_buff_size == 0)
+ {
+ pft_cnf->block.stage |= BLK_EOF;
+ META_LOG("[Meta][FT] File%d backups succeed! ",file_ID);
+ pft_cnf->block.file_size = fileLen;
+
+ close(backupFd);
+
+ free(peer_buf);
+
+ if(remove(makepath(file_ID)) == 0)
+ {
+ META_LOG("[Meta][FT] File%d DeleteFile succeed! ",file_ID);
+ return_value = TRUE;
+ WriteDataToPC(pft_cnf, sizeof(FT_NVRAM_BACKUP_CNF),NULL, 0);
+ }
+ return return_value;
+ }
+ else
+ {
+ pft_cnf->block.stage |= BLK_WRITE;
+ if(peer_buff_size != NVRAM_PEER_MAX_LEN)
+ {
+ META_LOG("[Meta][FT] File%d backups %d data ! ",file_ID,peer_buff_size);
+ }
+ WriteDataToPC(pft_cnf, sizeof(FT_NVRAM_BACKUP_CNF),peer_buf, peer_buff_size);
+ memset(peer_buf,0,NVRAM_PEER_MAX_LEN);
+ pft_cnf->block.stage &= ~BLK_CREATE;
+ }
+
+ }
+ else
+ {
+ pft_cnf->block.stage |= BLK_EOF;
+ META_LOG("[Meta][FT] File%d backups read failed ! ", file_ID);
+ }
+
+ }
+
+ free(peer_buf);
+ close(backupFd);
+
+ }
+ else
+ {
+ META_LOG("[Meta][FT] File%d backups open failed ! ", file_ID);
+ }
+
+ return return_value;
+
+}
+
+void FtModNvramBackup::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_NvramBackup_OP ");
+
+ FT_NVRAM_BACKUP_CNF ft_cnf;
+ int bFileOpResult = 0;
+ memset(&ft_cnf, 0, sizeof(FT_NVRAM_BACKUP_CNF));
+ //init the header
+ ft_cnf.header.id = pFrm->getCmdTarget()->getId() + 1;
+ ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+ ft_cnf.status = META_FAILED;
+
+ FT_NVRAM_BACKUP_REQ *req = (FT_NVRAM_BACKUP_REQ *)pFrm->localBuf();
+
+ if (req->count > 0)
+ {
+ META_LOG("[Meta][FT] Count is %d, backup parts of NvRam!", req->count);
+ bFileOpResult = FileOp_BackupData_Special(req->buffer, req->count, req->mode);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] Count is %d, backup all NvRam!", req->count);
+ bFileOpResult = FileOp_BackupAll_NvRam();
+ }
+
+ if(bFileOpResult)
+ {
+ META_LOG("[Meta][FT] NVM_PcBackup_Get_Data Start ! ");
+ if(SendNVRAMFile(0,&ft_cnf))
+ {
+ META_LOG("[Meta][FT] Send file 0 succeed! ! ");
+ //init the header
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+ ft_cnf.block.file_size = 0;
+
+ if(SendNVRAMFile(1,&ft_cnf))
+ {
+ META_LOG("[Meta][FT] Send file 1 succeed! ! ");
+ return;
+ }
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] Failed to backup NvRam!");
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_NVRAM_BACKUP_CNF),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModNvramRestore::FtModNvramRestore(void)
+ :CmdTarget(FT_NVRAM_RESTORE_REQ_ID)
+{
+}
+
+FtModNvramRestore::~FtModNvramRestore(void)
+{
+}
+
+
+void FtModNvramRestore::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_NvramRestore_OP ");
+
+ FT_NVRAM_RESTORE_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_NVRAM_RESTORE_CNF));
+
+ FT_NVRAM_RESTORE_REQ *req = (FT_NVRAM_RESTORE_REQ *)pFrm->localBuf();
+
+ //init the header
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+
+ int backupFd;
+ unsigned int fileLen;
+ META_LOG("[Meta][FT] FT_NVRAM_Restore_OP receive block stage %x file id %d file size %d!",req->block.stage,req->block.file_ID,req->block.file_size);
+ if(req->block.stage & BLK_CREATE)
+ {
+ backupFd = open(makepath(req->block.file_ID), O_RDWR | O_TRUNC | O_CREAT, 0777);
+ }
+ else
+ {
+ backupFd = open(makepath(req->block.file_ID), O_RDWR | O_APPEND);
+ }
+
+ if(backupFd >= 0)
+ {
+ META_LOG("[Meta][FT] FT_NVRAM_Restore_OP create or open file OK!");
+ int sWriten = 0;
+ sWriten = write(backupFd,pFrm->peerBuf(),pFrm->peerLen());
+
+ if(sWriten>0)
+ {
+ ft_cnf.status = META_SUCCESS;
+ META_LOG("[Meta][FT] FT_NVRAM_Restore_OP File%d write %d data total data %d!",req->block.file_ID,sWriten,pFrm->peerLen());
+ if(req->block.stage & BLK_EOF)
+ {
+ fileLen = getFileSize(backupFd);
+ if(req->block.file_size == fileLen)
+ {
+ META_LOG("[Meta][FT] FT_NVRAM_Restore_OP write file transfer success! ");
+ close(backupFd);
+ backupFd = -1;
+
+ if(req->block.file_ID == 1)
+ {
+ if(!FileOp_RestoreAll_NvRam())
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] META_Editor_PcRestore_Set_Data failed! ");
+
+ }
+ }
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] FT_NVRAM_Restore_OP file %d size error! / %d ",req->block.file_ID,req->block.file_size);
+ }
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] FT_NVRAM_Restore_OP write file failed! sWriten =%d errno = %d",sWriten,errno);
+ }
+
+ if(backupFd != -1)
+ close(backupFd);
+
+
+ }
+ else
+ {
+ META_LOG("[Meta][FT] FT_NVRAM_Restore_OP create or open file failed!");
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_NVRAM_RESTORE_CNF),NULL, 0);
+
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModNvramReset::FtModNvramReset(void)
+ :CmdTarget(FT_NVRAM_RESET_REQ_ID)
+{
+}
+
+FtModNvramReset::~FtModNvramReset(void)
+{
+}
+
+void FtModNvramReset::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_NvramReset_OP ");
+ FT_AP_Editor_reset_cnf ft_cnf;
+
+ memset(&ft_cnf, 0, sizeof(FT_AP_Editor_reset_cnf));
+
+ FT_AP_Editor_reset_req *req = (FT_AP_Editor_reset_req *)pFrm->localBuf();
+
+ //if the reset_category and file_idx is 0xfc and 0xfccf, we reset all nvram files.
+ if ((req->reset_category == 0xfc )&& (req->file_idx ==0xfccf))
+ ft_cnf = META_Editor_ResetAllFile_OP(req); //reset all files
+ else
+ ft_cnf = META_Editor_ResetFile_OP(req); //reset one nvram file
+
+ //fill the ft module header
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_SUCCESS;
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_AP_Editor_reset_cnf),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModNvramRead::FtModNvramRead(void)
+ :CmdTarget(FT_NVRAM_READ_REQ_ID)
+{
+}
+
+FtModNvramRead::~FtModNvramRead(void)
+{
+}
+
+void FtModNvramRead::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_NvramRead_OP ");
+ // just call the inferface of ap_editor lib which will reture the data after reading sucessfully
+ if (!META_Editor_ReadFile_OP((FT_AP_Editor_read_req *)pFrm->localBuf()))
+ META_LOG("[Meta][FT] FT_APEditorR_OP META Test Fail");
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModNvramWrite::FtModNvramWrite(void)
+ :CmdTarget(FT_NVRAM_WRITE_REQ_ID)
+{
+}
+
+FtModNvramWrite::~FtModNvramWrite(void)
+{
+}
+
+void FtModNvramWrite::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_NvramWrite_OP ");
+
+ FT_AP_Editor_write_cnf ft_cnf;
+
+ memset(&ft_cnf, 0, sizeof(FT_AP_Editor_write_cnf));
+ FT_AP_Editor_write_req *req = (FT_AP_Editor_write_req *)pFrm->localBuf();
+
+ //// just call the inferface of ap_editor lib
+ ft_cnf = META_Editor_WriteFile_OP(req, (char *)pFrm->peerBuf(), pFrm->peerLen());
+
+
+
+ //fill the ft module header
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_SUCCESS;
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_AP_Editor_write_cnf),NULL, 0);
+
+}
+#endif
+
+
+FtModAPDB::FtModAPDB(void)
+ :CmdTarget(FT_APDB_REQ_ID)
+{
+}
+
+FtModAPDB::~FtModAPDB(void)
+{
+}
+
+void FtModAPDB::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_APDB_OP ");
+
+ FT_APDB_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_APDB_CNF));
+
+ FT_APDB_REQ *req = (FT_APDB_REQ *)pFrm->localBuf();
+
+
+ //fill the ft module header
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type= req->type;
+ ft_cnf.status = META_FAILED;
+
+ char szAPDBPath[64] = {MTK_APDB_PATH};
+
+ switch(req->type)
+ {
+ case FT_APDB_OP_QUERYPATH:
+ memcpy(ft_cnf.result.query_apdbpath_cnf.apdb_path, szAPDBPath, strlen(szAPDBPath));
+ META_LOG("[Meta][FT] FT_APDB_OP FT_APDB_OP_QUERYPATH apdb_path: %s",
+ ft_cnf.result.query_apdbpath_cnf.apdb_path);
+ ft_cnf.status = META_SUCCESS;
+ break;
+ default:
+ break;
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_APDB_CNF),NULL, 0);
+
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef FT_SYSENV_SUPPORT
+
+FtModSysEnv::FtModSysEnv(void)
+ :CmdTarget(FT_SYSENV_REQ_ID)
+{
+}
+
+FtModSysEnv::~FtModSysEnv(void)
+{
+}
+
+void FtModSysEnv::exec(Frame *pFrm)
+{
+
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_SYS_ENV_OP");
+
+ FT_SYS_ENV_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_SYS_ENV_CNF));
+ FT_SYS_ENV_REQ *req = (FT_SYS_ENV_REQ *)pFrm->localBuf();
+
+ //fill the ft module header
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type= req->type;
+ ft_cnf.status = META_FAILED;
+ const char *val;
+ switch(req->type)
+ {
+ case FT_SYSENV_SET:
+ META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_SET name = %s, value = %s",
+ req->cmd.sysenv_set_req.name, req->cmd.sysenv_set_req.value);
+ if(sysenv_set((char*)req->cmd.sysenv_set_req.name, (char*)req->cmd.sysenv_set_req.value) < 0)
+ {
+ META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_SET failed!");
+ }
+ else
+ {
+ META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_SET succeed!");
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_SYSENV_GET:
+ META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_GET name = %s", req->cmd.sysenv_get_req.name);
+ val = sysenv_get((char*)req->cmd.sysenv_get_req.name);
+ if(val != NULL)
+ {
+ META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_GET value = %s", val);
+ memcpy(ft_cnf.result.sysenv_get_cnf.value, val, strlen(val));
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_SYSENV_END:
+ META_LOG("[Meta][FT] FT_SYS_ENV_OP FT_SYSENV_END");
+ break;
+ }
+
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_SYS_ENV_CNF),NULL, 0);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModTargetClock::FtModTargetClock(void)
+ :CmdTarget(FT_TARGETCLOCK_REQ_ID)
+{
+}
+
+FtModTargetClock::~FtModTargetClock(void)
+{
+}
+
+void FtModTargetClock::exec(Frame *pFrm)
+{
+
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][Clock] FT_TARGET_CLOCK_OP");
+
+ FT_TARGETCLOCK_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_TARGETCLOCK_CNF));
+ FT_TARGETCLOCK_REQ *req = (FT_TARGETCLOCK_REQ *)pFrm->localBuf();
+
+ //fill the ft module header
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type= req->type;
+ ft_cnf.status = META_FAILED;
+
+ switch(req->type)
+ {
+ case FT_CLOCK_SET:
+ if(SetSysClock(&req->cmd.set_clock_req))
+ {
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_CLOCK_GET:
+ break;
+ case FT_CLOCK_END:
+ META_LOG("[Meta][Clock] FT_TARGET_CLOCK_OP FT_CLOCK_END");
+ break;
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_TARGETCLOCK_CNF), NULL, 0);
+}
+
+unsigned int FtModTargetClock::SetSysClock(SET_TARGET_CLOCK_REQ *req)
+{
+ int ret = 0;
+ struct tm tmpsec;
+ struct timespec rtime;
+ struct timespec cur_time;
+
+ memset(&tmpsec, 0, sizeof(tm));
+ memset(&rtime, 0, sizeof(timespec));
+ memset(&cur_time, 0, sizeof(timespec));
+
+ META_LOG("[Meta][Clock] set time to: %d-%02d-%02d %02d-%02d-%02d.%03d", req->year, req->mon, req->day, req->hour, req->min, req->sec, req->ms);
+ if(!IsValidDate(req))
+ return ret;
+
+ tmpsec.tm_year = req->year- 1900;
+ tmpsec.tm_mon = req->mon - 1;
+ tmpsec.tm_mday = req->day;
+ tmpsec.tm_hour = req->hour;
+ tmpsec.tm_min = req->min;
+ tmpsec.tm_sec = req->sec;
+ tmpsec.tm_isdst = -1;
+
+ rtime.tv_sec = mktime(&tmpsec);
+ clock_gettime(CLOCK_REALTIME, &cur_time);
+ rtime.tv_nsec = req->ms*1000*1000;
+
+ if(clock_settime(CLOCK_REALTIME, &rtime) != 0)
+ {
+ META_LOG("[Meta][Clock] set target clock failed! ret = %d, err = %d, err string = %s", ret, errno, strerror(errno));
+ return 0;
+ }
+
+ META_LOG("[Meta][Clock] set target clock successful!");
+ return 1;
+
+}
+
+unsigned int FtModTargetClock::IsValidDate(SET_TARGET_CLOCK_REQ *req)
+{
+ if((req->year > 2067) || (req->year < 1900))
+ {
+ META_LOG("[Meta][Clock] invalid year [1900~2067]! year = %d", req->year);
+ return 0;
+ }
+
+ if((req->mon > 12) || (req->mon < 1))
+ {
+ META_LOG("[Meta][Clock] invalid mon [1~12]! mon = %d", req->mon);
+ return 0;
+ }
+
+ if((req->day > 31) || (req->day < 1))
+ {
+ META_LOG("[Meta][Clock] invalid day [1~31]! day = %d", req->day);
+ return 0;
+ }
+
+ if(req->hour > 23)
+ {
+ META_LOG("[Meta][Clock] invalid hour [0~23]! hour = %d", req->hour);
+ return 0;
+ }
+
+ if(req->min > 59)
+ {
+ META_LOG("[Meta][Clock] invalid min [0~59]! min = %d", req->min);
+ return 0;
+ }
+
+ if(req->sec > 59)
+ {
+ META_LOG("[Meta][Clock] invalid sec [0~59]! sec = %d", req->sec);
+ return 0;
+ }
+
+ if(req->ms > 999)
+ {
+ META_LOG("[Meta][Clock] invalid ms [0~999]! ms = %d", req->ms);
+ return 0;
+ }
+
+ return 1;
+}
+
+
+FtModTestAlive::FtModTestAlive(void)
+ :CmdTarget(FT_IS_ALIVE_REQ_ID)
+{
+}
+
+FtModTestAlive::~FtModTestAlive(void)
+{
+}
+
+void FtModTestAlive::exec(Frame *pFrm)
+{
+ META_LOG("[Meta][FT] FT_TestAlive");
+ FT_IS_ALIVE_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_IS_ALIVE_CNF));
+
+ CmdTarget::exec(pFrm);
+
+
+ //just give the respone.
+ ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+ ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+
+ //write bootprof
+ writeBootprof((char *)"[META] AP Send FT_TestAlive To PC.");
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_IS_ALIVE_CNF),NULL, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//for normal version
+
+#define RELEASE_SW_TOKEN "ro.vendor.mediatek.version.release"
+#define RELEASE_PLATFORM_TOKEN "ro.board.platform"
+#define RELEASE_PRODUCT_TOKEN "ro.product.name"
+#define RELEASE_BUILD_TIME_TOKEN "ro.build.date"
+#define RELEASE_BUILD_DISP_ID_TOKEN "ro.build.display.id"
+#define RELEASE_RSC_PROJECT_TOKEN "ro.boot.rsc"
+
+FtModVersionInfo::FtModVersionInfo(void)
+ :CmdTarget(FT_VER_INFO_REQ_ID)
+{
+}
+
+FtModVersionInfo::~FtModVersionInfo(void)
+{
+}
+
+void FtModVersionInfo::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+ META_LOG("[Meta][FT] FT_VersionInfo");
+ FT_VER_INFO_CNF ft_cnf;
+
+ memset(&ft_cnf, 0, sizeof(ft_cnf));
+ //char product[256] = {0};
+
+ //initail the value of ft header
+ ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+ ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+ ft_cnf.status = META_SUCCESS;
+
+#ifdef IS_SUPPORT_SP
+ property_get(RELEASE_SW_TOKEN, (char*)ft_cnf.sw_ver, "");
+ META_LOG("[Meta][FT] ft_cnf.sw_ver = %s ", ft_cnf.sw_ver);
+
+ property_get(RELEASE_PLATFORM_TOKEN, (char*)ft_cnf.bb_chip, "");
+ META_LOG("[Meta][FT] ft_cnf.bb_chip = %s ", ft_cnf.bb_chip);
+
+ property_get(RELEASE_BUILD_TIME_TOKEN, (char*)ft_cnf.sw_time, "");
+ META_LOG("[Meta][FT] ft_cnf.sw_time = %s ", ft_cnf.sw_time);
+
+ property_get(RELEASE_PRODUCT_TOKEN, product, "");
+ META_LOG("[Meta][FT] Product Name = %s\n", product);
+
+ property_get(RELEASE_RSC_PROJECT_TOKEN, (char*)ft_cnf.rsc_ver, "");
+ META_LOG("[Meta][FT] ft_cnf.rsc_ver = %s\n", ft_cnf.rsc_ver);
+#else
+ strcpy((char*)ft_cnf.sw_ver, "Dual-IPC v1.0");
+ strcpy((char*)ft_cnf.bb_chip, "mt6870");
+ strcpy((char*)ft_cnf.sw_time, "2020-06-08-15:02:00");
+#endif
+
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModVersionInfo2::FtModVersionInfo2(void)
+ :CmdTarget(FT_VER_INFO_V2_REQ_ID)
+{
+}
+
+FtModVersionInfo2::~FtModVersionInfo2(void)
+{
+}
+
+void FtModVersionInfo2::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+ META_LOG("[Meta][FT] FT_VersionInfo2");
+ FT_VER_INFO_V2_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(ft_cnf));
+ //char product[256] = {0};
+ //char disp_id[256] = {0};
+
+ //initail the value of ft header
+ ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+ ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+ ft_cnf.status = META_SUCCESS;
+
+#ifdef IS_SUPPORT_SP
+ property_get(RELEASE_SW_TOKEN, (char*)ft_cnf.sw_ver, "");
+ META_LOG("[Meta][FT] ft_cnf.sw_ver = %s ", ft_cnf.sw_ver);
+
+ property_get(RELEASE_PLATFORM_TOKEN, (char*)ft_cnf.bb_chip, "");
+ META_LOG("[Meta][FT] ft_cnf.bb_chip = %s ", ft_cnf.bb_chip);
+
+ property_get(RELEASE_BUILD_TIME_TOKEN, (char*)ft_cnf.sw_time, "");
+ META_LOG("[Meta][FT] ft_cnf.sw_timep = %s ", ft_cnf.sw_time);
+
+ property_get(RELEASE_BUILD_DISP_ID_TOKEN, disp_id, "");
+ strncpy((char*)ft_cnf.build_disp_id, disp_id, 63);
+ META_LOG("[Meta][FT] ft_cnf.build_disp_id = %s ", ft_cnf.build_disp_id);
+
+ property_get(RELEASE_PRODUCT_TOKEN, product, "");
+ META_LOG("[Meta][FT] Product Name = %s\n", product);
+#else
+ //to do
+#endif
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//for chip version
+#define CHIPINFO_CODE_FUNC "/proc/chip/code_func"
+#define CHIPINFO_CODE_PROJ "/proc/chip/code_proj"
+#define CHIPINFO_CODE_DATE "/proc/chip/code_date"
+#define CHIPINFO_CODE_FAB "/proc/chip/code_fab"
+
+FtModChipInfo::FtModChipInfo(void)
+ :CmdTarget(FT_CHIP_INFO_REQ_ID)
+{
+}
+
+FtModChipInfo::~FtModChipInfo(void)
+{
+}
+
+void FtModChipInfo::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+ META_LOG("[Meta][FT] FT_ChipInfo");
+ FT_CHIP_INFO_CNF ft_cnf;
+ FILE *fd = 0;
+ char szInfoPath[][32] = {
+ CHIPINFO_CODE_FUNC,
+ CHIPINFO_CODE_PROJ,
+ CHIPINFO_CODE_DATE,
+ CHIPINFO_CODE_FAB};
+
+ char chip_info[4][64];
+ memset(&chip_info,0,sizeof(char)*4*64);
+
+ memset(&ft_cnf, 0, sizeof(ft_cnf));
+
+ //initail the value of ft header
+ ft_cnf.header.id = pFrm->getCmdTarget()->getId()+1;
+ ft_cnf.header.token = pFrm->getCmdTarget()->getToken();
+ ft_cnf.status = META_FAILED;
+
+ /* Get the chip info */
+ int i = 0;
+ for(i=0; i<4; i++)
+ {
+ if((fd = fopen(szInfoPath[i], "r")) != NULL)
+ {
+ if(fgets((char*)chip_info[i], 64, fd) != NULL)
+ {
+ META_LOG("[Meta][FT] %s = %s\n", szInfoPath[i], chip_info[i]);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] failed to read <%s>\n", szInfoPath[i]);
+ }
+
+ fclose(fd);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] Can't open file : %s\n", szInfoPath[i]);
+ break;
+ }
+ }
+
+ if(i == 4)
+ {
+ strncpy((char*)ft_cnf.code_func, chip_info[0], 63);
+ strncpy((char*)ft_cnf.code_proj, chip_info[1], 63);
+ strncpy((char*)ft_cnf.code_date, chip_info[2], 63);
+ strncpy((char*)ft_cnf.code_fab, chip_info[3], 63);
+ ft_cnf.status = META_SUCCESS;
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+}
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModPowerOff::FtModPowerOff(void)
+ :CmdTarget(FT_POWER_OFF_REQ_ID)
+{
+}
+
+FtModPowerOff::~FtModPowerOff(void)
+{
+}
+
+void FtModPowerOff::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_PowerOff");
+
+
+ FT_POWER_OFF_REQ *req = (FT_POWER_OFF_REQ *)pFrm->localBuf();
+
+ META_LOG("[Meta][FT] req->dummy = %d", req->dummy);
+
+ //sync();
+ usleep(200*1000);
+
+ int comPortType = getComType();
+ if(comPortType == META_USB_COM && req->dummy != 3)
+ {
+ closeUSB();
+ }
+ else if(comPortType == META_SOCKET)
+ {
+ if(NORMAL_BOOT == getBootMode())
+ {
+ /*
+ META_LOG("[Meta][FT] Send broadcast to disconnect WIFI");
+ const char *strBroadcast = "am broadcast -a Exit_Meta_Info_Activity";
+ system(strBroadcast);
+ */
+ MSocket *mSocket = getSocket(SOCKET_ATM_COMM);
+ if(mSocket != NULL)
+ {
+ mSocket->send_msg("ATM_EXIT_WIFI_APP");
+ }
+
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] com port type is uart! ");
+ }
+
+
+ switch(req->dummy)
+ {
+ case 0:
+ {
+ usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","shutdown");
+#else
+ reboot(RB_POWER_OFF);
+#endif
+ }
+ break;
+ case 2:
+ {
+ usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","reboot");
+#else
+ reboot(RB_AUTOBOOT);
+#endif
+ }
+ break;
+ case 3:
+ {
+ META_LOG("[Meta][FT] Disconnect ATM Meta ");
+ destroySerPortThread();
+ MSocket *pSocket = getSocket(SOCKET_ATCI_CLIENT);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg("calibration_stop");
+ }
+ else
+ {
+ META_LOG("[Meta][FT] pSocket is NULL");
+ }
+ }
+ break;
+ case 4:
+ {
+ checkUSBOnline();
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","shutdown");
+#else
+ reboot(RB_POWER_OFF);
+#endif
+ }
+ break;
+ case 5:
+ {
+ rebootToRecovery();
+ }
+ break;
+ }
+
+}
+
+void FtModPowerOff::checkUSBOnline()
+{
+ int status = 0;
+ while((status=readSys_int(USBONLINE_STATUS_PATH)) != 0)
+ {
+ usleep(200*1000);
+ META_LOG("[Meta][PowerOff] usb online status= %d", status);
+ }
+
+ META_LOG("[Meta][PowerOff] usb online off and to power off ");
+}
+
+#define MISC_PART_PATH "/dev/block/platform/bootdevice/by-name/para"
+void FtModPowerOff::rebootToRecovery()
+{
+ META_LOG("[Meta][PowerOff] enter rebootToRecovery");
+ const char* command = "boot-recovery";
+ int fd = -1;
+ int ret = 0;
+
+ fd = open(MISC_PART_PATH, O_RDWR);
+ if(fd < 0)
+ {
+ META_LOG("[Meta][PowerOff] open misc partition fail, errno = %d", errno);
+ return;
+ }
+
+ META_LOG("[Meta][PowerOff] command is %s", command);
+
+ ret = write(fd, command, 13);
+ if(ret > 0)
+ {
+ META_LOG("[Meta][PowerOff] write %s to misc partition success", command);
+ }
+ else
+ {
+ META_LOG("[Meta][PowerOff] write %s to misc partition failed, errno = %d",command, errno);
+ }
+ close(fd);
+ usleep(200*1000);
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","reboot");
+#else
+ reboot(RB_AUTOBOOT);
+#endif
+
+}
+
+void FtModPowerOff::closeUSB()
+{
+ FILE *PUsbFile = NULL;
+ PUsbFile = fopen("sys/devices/platform/mt_usb/cmode","w");
+ if(PUsbFile == NULL)
+ {
+ META_LOG("[Meta][FT] Could not open sys/devices/platform/mt_usb/cmode ");
+ PUsbFile = fopen("/sys/devices/platform/musb-mtu3d/musb-hdrc/cmode","w");
+ if(PUsbFile == NULL)
+ {
+ META_LOG("[Meta][FT] Could not open /sys/devices/platform/musb-mtu3d/musb-hdrc/cmode ");
+ PUsbFile = fopen("/sys/class/udc/musb-hdrc/device/cmode","w");
+ if(PUsbFile == NULL)
+ {
+ META_LOG("[Meta][FT] Could not open /sys/class/udc/musb-hdrc/device/cmode ");
+ }
+ else
+ {
+ fputc('0',PUsbFile);
+ fclose(PUsbFile);
+ }
+ }
+ else
+ {
+ fputc('0',PUsbFile);
+ fclose(PUsbFile);
+ }
+ }
+ else
+ {
+ fputc('0',PUsbFile);
+ fclose(PUsbFile);
+ }
+}
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModMetaDisconnect::FtModMetaDisconnect(void)
+ :CmdTarget(FT_DISCONNECT_REQ_ID)
+{
+}
+
+FtModMetaDisconnect::~FtModMetaDisconnect(void)
+{
+}
+
+void FtModMetaDisconnect::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FtModMetaDisconnect");
+
+ FT_DISCONNECT_REQ *req = (FT_DISCONNECT_REQ *)pFrm->localBuf();
+ FtModPowerOff ft_poweroff;
+
+ META_LOG("[Meta][FT] req->type = %d", req->type);
+
+ usleep(200*1000);
+
+ int comPortType = getComType();
+ if(comPortType == META_USB_COM && req->type != FT_CTRL_DISCONN_ATM)
+ {
+ ft_poweroff.closeUSB();
+ }
+ else if(comPortType == META_SOCKET)
+ {
+ if(NORMAL_BOOT == getBootMode())
+ {
+ META_LOG("[Meta][FT] Send broadcast to disconnect WIFI");
+ const char *strBroadcast = "am broadcast -a Exit_Meta_Info_Activity";
+ system(strBroadcast);
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] com port type is uart! ");
+ }
+
+ switch(req->type)
+ {
+ case FT_CTRL_POWEROFF:
+ {
+ usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","shutdown");
+#else
+ reboot(RB_POWER_OFF);
+#endif
+ }
+ break;
+ case FT_CTRL_REBOOT:
+ {
+ usleep(1000 * 1000);
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","reboot");
+#else
+ reboot(RB_AUTOBOOT);
+#endif
+ }
+ break;
+ case FT_CTRL_REBOOT_BYDELAY:
+ {
+ META_LOG("[Meta][FT] reboot by delay = %d", req->cmd.disconnect_req.delay);
+ sleep(req->cmd.disconnect_req.delay);
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","reboot");
+#else
+ reboot(RB_AUTOBOOT);
+#endif
+ }
+ break;
+ case FT_CTRL_DISCONN_ATM:
+ {
+ META_LOG("[Meta][FT] Disconnect ATM Meta ");
+ destroySerPortThread();
+ MSocket *pSocket = getSocket(SOCKET_ATCI_CLIENT);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg("calibration_stop");
+ }
+ else
+ {
+ META_LOG("[Meta][FT] pSocket is NULL");
+ }
+ }
+ break;
+ case FT_CTRL_CHECKUSB_POWEROFF:
+ {
+ ft_poweroff.checkUSBOnline();
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","shutdown");
+#else
+ reboot(RB_POWER_OFF);
+#endif
+ }
+ break;
+ case FT_CTRL_REBOOT_RECOVERY:
+ {
+ ft_poweroff.rebootToRecovery();
+ }
+ break;
+ case FT_CTRL_DONOTHING:
+ case FT_CTRL_TARGET_OP_END:
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModReboot::FtModReboot(void)
+ :CmdTarget(FT_REBOOT_REQ_ID)
+{
+}
+
+FtModReboot::~FtModReboot(void)
+{
+}
+
+void FtModReboot::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_Reboot");
+
+
+ FT_META_REBOOT_REQ *req = (FT_META_REBOOT_REQ *)pFrm->localBuf();
+
+ sleep(req->delay);
+
+ //Reboot target side after finishing the meta
+ //sync();
+ //reboot(RB_AUTOBOOT);
+#ifdef IS_SUPPORT_SP
+ property_set("sys.powerctl","reboot");
+#else
+ reboot(RB_AUTOBOOT);
+#endif
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+FtModBuildProp::FtModBuildProp(void)
+ :CmdTarget(FT_BUILD_PROP_REQ_ID)
+{
+}
+
+FtModBuildProp::~FtModBuildProp(void)
+{
+}
+
+void FtModBuildProp::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_BuildProp");
+
+ FT_BUILD_PROP_CNF ft_cnf;
+ FT_BUILD_PROP_REQ *req = (FT_BUILD_PROP_REQ *)pFrm->localBuf();
+ memset(&ft_cnf, 0, sizeof(FT_BUILD_PROP_CNF));
+
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+
+#ifdef IS_SUPPORT_SP
+ property_get((const char*)req->tag, (char *)ft_cnf.content, "unknown");
+#endif
+
+ META_LOG("[Meta][FT] %s = %s ",req->tag,ft_cnf.content);
+ ft_cnf.status = META_SUCCESS;
+
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_GSENSOR_FEATURE
+
+FtModGSensor::FtModGSensor(void)
+ :CmdTarget(FT_GSENSOR_REQ_ID)
+{
+}
+
+FtModGSensor::~FtModGSensor(void)
+{
+ Meta_GSensor_Close();
+}
+
+void FtModGSensor::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ //do the G-Sensor test by called the interface in meta G-Sensor lib
+ if(getInitState())
+ Meta_GSensor_OP((GS_REQ *)pFrm->localBuf());
+}
+
+int FtModGSensor::init(Frame*pFrm)
+{
+ META_LOG("[Meta][FT] FT_GSensor");
+
+ GS_CNF ft_cnf;
+ static int bInitFlag_GS = false;
+ GS_REQ *req = (GS_REQ *)pFrm->localBuf();
+
+ memset(&ft_cnf, 0, sizeof(GS_CNF));
+
+ if (bInitFlag_GS == false) {
+ // initial the G-Sensor module when it is called first time
+ if (!Meta_GSensor_Open()) {
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+ ft_cnf.op = req->op;
+
+ META_LOG("[Meta][FT] FT_GSENSOR_OP Meta_GSensor_Open Fail ");
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+ return false;
+ }
+ bInitFlag_GS = true;
+ }
+ return true;
+}
+
+#endif
+
+
+#ifdef FT_MSENSOR_FEATURE
+
+FtModMSensor::FtModMSensor(void)
+ :CmdTarget(FT_MSENSOR_REQ_ID)
+{
+ memset(&m_ft_cnf, 0, sizeof(FT_MSENSOR_CNF));
+}
+
+FtModMSensor::~FtModMSensor(void)
+{
+ Meta_MSensor_Close();
+}
+
+void FtModMSensor::exec(Frame *pFrm)
+{
+
+ META_LOG("[Meta][FT] FT_MSensor");
+
+ int res = -1;
+ memset(&m_ft_cnf, 0, sizeof(FT_MSENSOR_CNF));
+
+ FT_MSENSOR_REQ *req = (FT_MSENSOR_REQ *)pFrm->localBuf();
+
+ m_ft_cnf.header.id = req->header.id + 1;
+ m_ft_cnf.header.token = req->header.token;
+ m_ft_cnf.status = META_SUCCESS;
+
+ CmdTarget::exec(pFrm);
+
+ if(getInitState()) {
+ res = Meta_MSensor_OP();
+ if (0 == res) {
+ META_LOG("[Meta][FT] FT_MSENSOR_OP Meta_MSensor_OP success!");
+ m_ft_cnf.status = META_SUCCESS;
+ }
+ else {
+ META_LOG("[Meta][FT] FT_MSENSOR_OP Meta_MSensor_OP failed!");
+ m_ft_cnf.status = META_FAILED;
+ }
+
+ WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+ }
+
+}
+
+int FtModMSensor::init(Frame*)
+{
+ static int bInitFlag_MS = false;
+
+ if (bInitFlag_MS == false) {
+ // initial the M-Sensor module when it is called first time
+ if (!Meta_MSensor_Open()) {
+ META_LOG("[Meta][FT] FT_MSENSOR_OP Meta_MSensor_Open failed!");
+ m_ft_cnf.status = META_FAILED;
+ WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+ return false;
+ }
+ bInitFlag_MS = TRUE;
+ }
+
+ return true;
+}
+#endif
+
+#ifdef FT_ALSPS_FEATURE
+
+FtModALSPS::FtModALSPS(void)
+ :CmdTarget(FT_ALSPS_REQ_ID)
+{
+ memset(&m_ft_cnf, 0, sizeof(FT_ALSPS_CNF));
+}
+
+FtModALSPS::~FtModALSPS(void)
+{
+ Meta_ALSPS_Close();
+}
+
+void FtModALSPS::exec(Frame *pFrm)
+{
+ META_LOG("[Meta][FT] FT_ALSPS");
+
+ int res = -1;
+ memset(&m_ft_cnf, 0, sizeof(FT_ALSPS_CNF));
+
+ FT_ALSPS_REQ *req = (FT_ALSPS_REQ *)pFrm->localBuf();
+
+ m_ft_cnf.header.id = req->header.id + 1;
+ m_ft_cnf.header.token = req->header.token;
+ m_ft_cnf.status = META_SUCCESS;
+
+ CmdTarget::exec(pFrm);
+
+ if(getInitState()) {
+ res = Meta_ALSPS_OP();
+ if (0 == res) {
+ META_LOG("[Meta][FT] FT_ALSPS_OP Meta_ALSPS_OP success!");
+ m_ft_cnf.status = META_SUCCESS;
+ } else {
+ META_LOG("[Meta][FT] FT_ALSPS_OP Meta_ALSPS_OP failed!");
+ m_ft_cnf.status = META_FAILED;
+ }
+ WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+ }
+
+}
+
+int FtModALSPS::init(Frame*)
+{
+ static int bInitFlag_ALSPS = false;
+
+ if (bInitFlag_ALSPS == false) {
+ // initial the M-Sensor module when it is called first time
+ if (!Meta_ALSPS_Open()) {
+ META_LOG("[Meta][FT] FT_ALSPS_OP Meta_ALSPS_Open failed!");
+ m_ft_cnf.status = META_FAILED;
+ WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+ return false;
+ }
+ bInitFlag_ALSPS = true;
+ }
+ return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_GYROSCOPE_FEATURE
+
+FtModGyroSensor::FtModGyroSensor(void)
+ :CmdTarget(FT_GYROSCOPE_REQ_ID)
+{
+}
+
+FtModGyroSensor::~FtModGyroSensor(void)
+{
+ Meta_Gyroscope_Close();
+}
+
+void FtModGyroSensor::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ //do the Gyroscope-Sensor test by called the interface in meta Gyroscope-Sensor lib
+ if(getInitState())
+ Meta_Gyroscope_OP((GYRO_REQ *)pFrm->localBuf());
+}
+
+int FtModGyroSensor::init(Frame* pFrm)
+{
+ META_LOG("[Meta][FT] FT_GyroSensor");
+ GYRO_REQ *req = (GYRO_REQ *)pFrm->localBuf();
+ static int bInitFlag_GYRO = false;
+ GYRO_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(GYRO_CNF));
+
+ if (bInitFlag_GYRO == false) {
+ // initial the Gyroscope-Sensor module when it is called first time
+ if (!Meta_Gyroscope_Open()) {
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+ ft_cnf.op = req->op;
+
+ META_LOG("[Meta][FT] FT_GYROSENSOR_OP Meta_GYROSensor_Open Fail ");
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+ return false;
+ }
+ bInitFlag_GYRO = true;
+ }
+
+ return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#define MDDB_FILE_FOLDER "/data/vendor_de/meta/mddb/"
+#define MDDB_FILE_FOLDER_EX "/data/vendor_de/meta/mddb"
+#define MD1INFO_FILE_PATH "/data/vendor_de/meta/mddb/md1_file_map.log"
+#define MD1INFO_FILE_MAP_KEYWORD "md1_file_map"
+#define MD1DB_FILE_KEYWORD "md1_mddbmeta"
+#define MD1OPENDB_FILE_KEYWORD "md1_mddbmetaodb"
+
+#define MD3INFO_FILE_PATH "/data/vendor_de/meta/mddb/md3_file_map.log"
+#define MD3INFO_FILE_MAP_KEYWORD "md3_file_map"
+#define MD3DB_FILE_KEYWORD "md3_mddb_c2k_meta"
+
+
+
+FtModModemInfo::FtModModemInfo(void)
+ :CmdTarget(FT_MODEM_REQ_ID)
+{
+}
+
+FtModModemInfo::~FtModModemInfo(void)
+{
+}
+
+int FtModModemInfo::getModemCapability(MODEM_CAPABILITY_LIST_CNF* modem_capa)
+{
+ int modem_type = 0;
+ modem_type = getMdmType();
+
+ if((modem_type & MD1_INDEX) == MD1_INDEX)
+ {
+ if(getModemProtocol(0, (void*)modem_capa) == 0)
+ {
+ META_LOG("[Meta][FT] MD1 getModemProtocol fail");
+ return 0;
+ }
+ }
+
+ if((modem_type & MD2_INDEX) == MD2_INDEX)
+ {
+ if(getModemProtocol(1, (void*)modem_capa) == 0)
+ {
+ META_LOG("[Meta][FT] MD2 getModemProtocol fail");
+ return 0;
+ }
+ }
+
+ if((modem_type & MD3_INDEX) == MD3_INDEX)
+ {
+ if(getModemProtocol(2, (void*)modem_capa) == 0)
+ {
+ META_LOG("[Meta][FT] MD3 getModemProtocol fail");
+ return 0;
+ }
+ }
+
+ if((modem_type & MD5_INDEX) == MD5_INDEX)
+ {
+ if(getModemProtocol(4, (void*)modem_capa) == 0)
+ {
+ META_LOG("[Meta][FT] MD5 getModemProtocol fail");
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+void FtModModemInfo::rebootModem(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd)
+{
+ META_LOG("[Meta] Enter rebootModem");
+ int result = 0;
+ int modem_mode = req->cmd.reboot_modem_req.mode;
+ int modem_index = req->cmd.reboot_modem_req.modem_index;
+ META_LOG("[Meta] modem_mode = %d", modem_mode);
+ META_LOG("[Meta] modem_index = %d", modem_index);
+
+ if(getModemHwVersion(0) >= MODEM_6293) //for Gen 93 and subsequent modem
+ {
+ if(0 == ChangeModemMode(modem_mode))
+ {
+ META_LOG("[Meta] Switch modem mode to %d success", modem_mode);
+ setMDMode(modem_mode);
+ if(modem_mode == 1)
+ {
+#ifdef IS_SUPPORT_SP
+ property_set("persist.vendor.atm.mdmode", "normal");
+#endif
+ }
+ else if(modem_mode == 2)
+ {
+#ifdef IS_SUPPORT_SP
+ property_set("persist.vendor.atm.mdmode", "meta");
+#endif
+ createAllModemThread();
+ }
+ ft_cnf.status = META_SUCCESS;
+ }
+ else
+ {
+ META_LOG("[Meta] Switch modem mode from %d to %d fail", getMDMode(), modem_mode);
+ ft_cnf.status = META_FAILED;
+ }
+ }
+ else //for modem before 93
+ {
+ setActiveATModem(modem_index);
+
+ META_LOG("[Meta] Destory modem thread and close modem handle");
+ destroyAllModemThread();
+ if (fd >= 0 && 0 == (result = ioctl(fd, CCCI_IOC_SET_MD_BOOT_MODE, &modem_mode)))
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_SET_MD_BOOT_MODE success modem_mode = %d", modem_mode);
+ if (0 == (result = ioctl(fd, CCCI_IOC_MD_RESET)))
+ {
+ ft_cnf.status = META_SUCCESS;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET success " );
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET fail result = %d, errno = %d, fd = %d", result, errno, fd);
+ }
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_SET_MD_BOOT_MODE fail modem_mode = %d, result = %d, errno = %d, fd = %d", modem_mode, result, errno, fd);
+ }
+
+ }
+}
+int FtModModemInfo::getModemMode(FT_MODEM_REQ *req, FT_MODEM_CNF & ft_cnf, int fd)
+{
+ int modem_state = 0;
+ int modem_boot_mode = 0;
+ int result = 0;
+
+ META_LOG("[Meta][FT] getModemMode req->type = %d", req->type);
+ if(fd < 0)
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] invalid ioctl dev port. fd = %d", fd );
+ return -1;
+ }
+
+ while(modem_state != 2)
+ {
+ if(0 == (result=ioctl(fd, CCCI_IOC_GET_MD_STATE, &modem_state)))
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE success modem_state = %d",modem_state );
+ usleep(200*1000);
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE fail result = %d, errno = %d, fd = %d", result, errno, fd );
+ return -1;
+ }
+ }
+
+ if (0 == (result=ioctl(fd, CCCI_IOC_GET_MD_BOOT_MODE,&modem_boot_mode)))
+ {
+ ft_cnf.status = META_SUCCESS;
+ ft_cnf.result.get_modem_mode_cnf.mode = modem_boot_mode;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_BOOT_MODE success modem_boot_mode = %d",modem_boot_mode );
+ setMDMode(modem_boot_mode);//normal= 1 meta=2
+ return 0;
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_BOOT_MODE fail result = %d, errno = %d, fd = %d", result, errno, fd);
+ return -1;
+ }
+
+ return 0;
+}
+
+int FtModModemInfo::getModemState(int *modem_state, int fd)
+{
+ int result = 0;
+ int retry_count = 0;
+
+ //Get modem reboot status
+ do
+ {
+ if(0 == ioctl(fd, CCCI_IOC_GET_MD_STATE, modem_state))
+ {
+ retry_count++;
+ }
+ usleep(500*1000);
+ META_LOG("[Meta][FT][DEBUG] Query modem reboot result %d times", retry_count);
+ }while((*modem_state != 2) && (retry_count<10));
+ if(*modem_state == 2)
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE success, modem_state = %d", *modem_state);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_STATE fail, modem_state = %d", *modem_state);
+ result = -1;
+ }
+
+ return result;
+}
+
+int FtModModemInfo::getModemType(int *modem_type, int fd)
+{
+ int result = 0;
+
+ //Get modem type
+ if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_TYPE, modem_type))
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE success, modem_type = %d", *modem_type);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE fail, modem_type = %d", *modem_type);
+ result = -1;
+ }
+ return result;
+}
+
+int FtModModemInfo::setModemType(int modem_type, int fd)
+{
+ int result = 0;
+
+ //Set modem type and reboot modem
+ if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_RELOAD_MD_TYPE, &modem_type))
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_RELOAD_MD_TYPE success, modem_type = %d", modem_type);
+ if (0 == ioctl(fd, CCCI_IOC_MD_RESET))
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET success " );
+ }
+ else
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET fail " );
+ result = -1;
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_RELOAD_MD_TYPE fail, modem_type = %d", modem_type);
+ result = -1;
+ }
+ return result;
+}
+
+int FtModModemInfo::getModemIndex(FT_MODEM_REQ *req)
+{
+ int nModemIndex = 0;
+
+ if(req->type == FT_MODEM_OP_SET_MODEMTYPE)
+ {
+ nModemIndex = req->cmd.set_modem_type_req.modem_id;
+ }
+ else if(req->type == FT_MODEM_OP_GET_CURENTMODEMTYPE)
+ {
+ nModemIndex = req->cmd.get_currentmodem_type_req.modem_id;
+ }
+ else if(req->type == FT_MODEM_OP_QUERY_MDIMGTYPE)
+ {
+ nModemIndex = req->cmd.query_modem_imgtype_req.modem_id;
+ }
+
+ if(nModemIndex > 0 && nModemIndex < 6)
+ {
+ nModemIndex = nModemIndex - 1;
+ }
+ else
+ {
+ nModemIndex = 0;
+ }
+
+ return nModemIndex;
+
+}
+
+#ifdef MTK_SINGLE_BIN_MODEM_SUPPORT
+int FtModModemInfo::CopyMDDBFile(unsigned int nModemId)
+{
+ if (access(MDDB_FILE_FOLDER,F_OK) != 0 )
+ {
+ META_LOG("[Meta][FT] CopyMDDBFile %s folder doesn't exist error %s\n", MDDB_FILE_FOLDER, strerror(errno));
+ return 0;
+ }
+
+ char mddb_path[256] = {0};
+ char mdopendb_path[256] = {0};
+ char info_name[128] = {0};
+ char info_path[256] = {0};
+ memcpy(mddb_path,MDDB_FILE_FOLDER, strlen(MDDB_FILE_FOLDER));
+ memcpy(mdopendb_path,MDDB_FILE_FOLDER, strlen(MDDB_FILE_FOLDER));
+ if(nModemId == 2)
+ {
+ memcpy(info_name,MD3INFO_FILE_MAP_KEYWORD, strlen(MD3INFO_FILE_MAP_KEYWORD));
+ memcpy(info_path,MD3INFO_FILE_PATH, strlen(MD3INFO_FILE_PATH));
+ }
+ else
+ {
+ memcpy(info_name,MD1INFO_FILE_MAP_KEYWORD, strlen(MD1INFO_FILE_MAP_KEYWORD));
+ memcpy(info_path,MD1INFO_FILE_PATH, strlen(MD1INFO_FILE_PATH));
+ }
+
+ int dbRet = -1;
+ int opendbRet = -1;
+ int info_ret = restore_image_from_pt(info_name, info_path);
+ META_LOG("[Meta][FT] CopyMDDBFile copy info file retore_image_from_pt info_ret:%d", info_ret);
+ if(info_ret <= 0)
+ {
+ META_LOG("[Meta][FT] CopyMDDBFile copy info file error %s\n", strerror(errno));
+ return -1;
+ }
+ else
+ {
+ FILE* fileInfoFd = NULL;
+ fileInfoFd = fopen(info_path,"r");
+ if (fileInfoFd == NULL)
+ {
+ META_LOG("[Meta][FT] CopyMDDBFile open info file error %s\n", strerror(errno));
+ return -1;
+ }
+ else
+ {
+ char *loc = NULL;
+ char* tmp = NULL;
+ char str[256] = {0};
+ while(!feof(fileInfoFd))
+ {
+ if(fgets(str, 256, fileInfoFd)!=NULL)
+ {
+ tmp = str;
+ loc = strsep(&tmp, "=");
+ if(nModemId == 2)
+ {
+ if(!strcmp(loc, MD3DB_FILE_KEYWORD))
+ {
+ if (tmp[strlen(tmp)-1] == '\n')
+ {
+ tmp[strlen(tmp)-1] = '\0';
+ }
+ else if (tmp[strlen(tmp)-1] == '\r')
+ {
+ tmp[strlen(tmp)-1] = '\0';
+ }
+ strncat(mddb_path, tmp, strlen(tmp));
+ META_LOG("[Meta][FT] CopyMDDBFile MDDB file path =%s, len =%d\n", mddb_path,strlen(mddb_path));
+ }
+ }
+ else //default is 0
+ {
+ if(!strcmp(loc, MD1DB_FILE_KEYWORD))
+ {
+ if (tmp[strlen(tmp)-1] == '\n')
+ {
+ tmp[strlen(tmp)-1] = '\0';
+ }
+ else if (tmp[strlen(tmp)-1] == '\r')
+ {
+ tmp[strlen(tmp)-1] = '\0';
+ }
+ strncat(mddb_path, tmp, strlen(tmp));
+ META_LOG("[Meta][FT] CopyMDDBFile MDDB file path =%s, len =%d\n", mddb_path,strlen(mddb_path));
+ }
+ else if(!strcmp(loc, MD1OPENDB_FILE_KEYWORD))
+ {
+ if (tmp[strlen(tmp)-1] == '\n')
+ {
+ tmp[strlen(tmp)-1] = '\0';
+ }
+ else if (tmp[strlen(tmp)-1] == '\r')
+ {
+ tmp[strlen(tmp)-1] = '\0';
+ }
+ strncat(mdopendb_path, tmp, strlen(tmp));
+ META_LOG("[Meta][FT] CopyMDDBFile MD open DB file path =%s, len =%d\n", mdopendb_path,strlen(mdopendb_path));
+ }
+ }
+ }
+ }
+ if (fileInfoFd != NULL)
+ {
+ fclose(fileInfoFd);
+ }
+ }
+ }
+ if(nModemId == 2)
+ {
+ dbRet = restore_image_from_pt(MD3DB_FILE_KEYWORD, mddb_path);
+ return dbRet;
+ }
+ else
+ {
+ dbRet = restore_image_from_pt(MD1DB_FILE_KEYWORD, mddb_path);
+ opendbRet = restore_image_from_pt(MD1OPENDB_FILE_KEYWORD, mdopendb_path);
+ if (dbRet > 0)
+ {
+ return dbRet;
+ }
+ else
+ {
+ return opendbRet;
+ }
+ }
+}
+#endif
+
+void FtModModemInfo::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] FT_ModemInfo");
+
+ FT_MODEM_CNF ft_cnf;
+ int fd = -1;
+ static int modemCreate = 0;
+ int bDataDevice = FALSE;
+
+
+ memset(&ft_cnf, 0, sizeof(FT_MODEM_CNF));
+ ft_cnf.status = META_FAILED;
+
+
+ FT_MODEM_REQ *req = (FT_MODEM_REQ *)pFrm->localBuf();
+ META_LOG("[Meta][FT] FT_MODEM_INFO_OP, req type:%d ",req->type);
+
+ if(req->type == FT_MODEM_OP_QUERY_INFO)
+ {
+ ft_cnf.result.query_modem_info_cnf.modem_number = getMdmNumber();
+ ft_cnf.result.query_modem_info_cnf.modem_id = getActiveMdmId();
+ ft_cnf.status = META_SUCCESS;
+ }
+ else if(req->type == FT_MODEM_OP_CAPABILITY_LIST)
+ {
+ int nRet = 0;
+ MODEM_CAPABILITY_LIST_CNF modem_capa;
+ memset(&modem_capa, 0, sizeof(MODEM_CAPABILITY_LIST_CNF));
+ nRet = getModemCapability(&modem_capa);
+ memcpy(&ft_cnf.result.query_modem_cap_cnf,&modem_capa,sizeof(MODEM_CAPABILITY_LIST_CNF));
+ if (nRet == 1)
+ {
+ ft_cnf.status = META_SUCCESS;
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ }
+ }
+ else if(req->type == FT_MODEM_OP_QUERY_MDDOWNLOADSTATUS)
+ {
+ char temp[128]={0};
+ int percentage = 0;
+ int status_code = 0;
+ //property_get("persist.sys.extmddlprogress",temp,NULL);
+ META_LOG("[Meta][FT] persist.sys.extmddlprogress = %s",temp);
+ sscanf(temp,"%03d_%04d",&percentage,&status_code);
+ META_LOG("[Meta][FT] FT_MODEM_INFO_OP FT_MODEM_OP_QUERY_MDDOWNLOADSTATUS percentage = %d,status_code = %d",percentage,status_code);
+ ft_cnf.result.query_modem_download_status_cnf.percentage = percentage;
+ ft_cnf.result.query_modem_download_status_cnf.status_code = status_code;
+
+ if(percentage == 110 && status_code ==0 && modemCreate == 0)
+ {
+ unsigned int modemType = getMdmType();
+ if((modemType & MD5_INDEX) == MD5_INDEX)
+ {
+ createModemThread(4,1);
+ }
+ modemCreate = 1;
+ }
+ ft_cnf.status = META_SUCCESS;
+ }
+ else if(req->type == FT_MODEM_OP_QUERY_MDDBPATH)
+ {
+ char szMDDBPath[64] = {0};
+#ifdef MTK_SINGLE_BIN_MODEM_SUPPORT
+ if (CopyMDDBFile(req->cmd.query_mddbpath_req.modem_id) <= 0)
+ {
+ META_LOG("[Meta][FILE OPERATION] FtModModemInfo Failed to copy MD %d DB from modem image, error %s\n",req->cmd.query_mddbpath_req.modem_id,strerror(errno));
+ ft_cnf.status = META_FAILED;
+ }
+ else
+ {
+ ft_cnf.status = META_SUCCESS;
+ }
+
+ strncpy(szMDDBPath, MDDB_FILE_FOLDER_EX, strlen(MDDB_FILE_FOLDER_EX));
+#else
+
+ strncpy(szMDDBPath, MTK_MDDB_PATH, strlen(MTK_MDDB_PATH));
+ ft_cnf.status = META_SUCCESS;
+#endif
+ memcpy(ft_cnf.result.query_mddbpath_cnf.mddb_path, szMDDBPath, strlen(szMDDBPath));
+ META_LOG("[Meta][FT] FtModModemInfo mddb_path: %s",ft_cnf.result.query_mddbpath_cnf.mddb_path);
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type = req->type;
+ WriteDataToPC(&ft_cnf, sizeof(FT_MODEM_CNF),NULL, 0);
+ return;
+ }
+
+ else if(req->type == FT_MODEM_OP_SET_MODEMTYPE)
+ {
+
+ unsigned int modem_type = req->cmd.set_modem_type_req.modem_type;
+ fd = getIOCPort(getModemIndex(req),bDataDevice);
+
+ if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_RELOAD_MD_TYPE, &modem_type))
+ {
+ if (0 == ioctl(fd, CCCI_IOC_MD_RESET))
+ {
+ ft_cnf.status = META_SUCCESS;
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_MD_RESET fail " );
+ }
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_RELOAD_MD_TYPE fail modem_type = %d", modem_type);
+ }
+
+ }
+ else if(req->type == FT_MODEM_OP_GET_CURENTMODEMTYPE)
+ {
+ unsigned int modem_type=0;
+
+ fd = getIOCPort(getModemIndex(req),bDataDevice);
+
+ if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_TYPE, &modem_type))
+ {
+ ft_cnf.status = META_SUCCESS;
+ ft_cnf.result.get_currentmodem_type_cnf.current_modem_type = modem_type;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE success modem_type = %d", modem_type);
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_TYPE fail");
+ }
+
+ }
+ else if(req->type == FT_MODEM_OP_QUERY_MDIMGTYPE)
+ {
+ unsigned int mdimg_type[16]={0};
+ fd = getIOCPort(getModemIndex(req),bDataDevice);
+
+ if (fd >= 0 && 0 == ioctl(fd, CCCI_IOC_GET_MD_IMG_EXIST, &mdimg_type))
+ {
+ ft_cnf.status = META_SUCCESS;
+ memcpy(ft_cnf.result.query_modem_imgtype_cnf.mdimg_type,mdimg_type,16*sizeof(unsigned int));
+
+ for(int i = 0;i<16;i++)
+ {
+ META_LOG("[Meta][FT] mdimg_type[%d] %d",i, mdimg_type[i]);
+ }
+
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ META_LOG("[Meta][FT] ioctl CCCI_IOC_GET_MD_IMG_EXIST fail");
+ }
+
+ }
+ else if(req->type == FT_MODEM_OP_REBOOT_MODEM)
+ {
+ fd = getIOCPort(getModemIndex(req),bDataDevice);
+ rebootModem(req,ft_cnf,fd);
+ }
+ else if(req->type == FT_MODEM_OP_GET_MODEMMODE)
+ {
+ fd = getIOCPort(getModemIndex(req),bDataDevice);
+ int result = getModemMode(req,ft_cnf,fd);
+ if(bDataDevice == FALSE)
+ {
+ if(fd != -1)
+ {
+ close(fd);
+ META_LOG("[Meta][FT]Close fd");
+ fd = -1;
+ }
+ }
+
+ //create modem thread and open modem handle
+ if(result == 0)
+ createAllModemThread();
+
+ }
+ else if(req->type == FT_MODEM_OP_SUPPORT_COMPRESS)
+ {
+
+#ifdef MTK_META_COMPRESS_SUPPORT
+ META_LOG("[Meta][FT] set data compress status: %d", req->cmd.set_compress_req.action);
+ SetDataCompressStatus(req->cmd.set_compress_req.action);
+ ft_cnf.result.set_compress_cnf.result = 1;
+ ft_cnf.status = META_SUCCESS;
+#else
+ META_LOG("[Meta][FT] not support data compress");
+#endif
+
+
+ }
+ else
+ {
+ META_LOG("[Meta][FT] FT_MODEM_REQ have no this type %d",req->type );
+ }
+
+
+ if(bDataDevice == FALSE)
+ {
+ if(fd != -1)
+ {
+ close(fd);
+ META_LOG("[Meta][FT]Close fd");
+ fd = -1;
+ }
+ }
+
+ ft_cnf.header.id = req ->header.id +1;
+ ft_cnf.header.token = req ->header.token;
+ ft_cnf.type = req ->type;
+
+
+ META_LOG("[META] ft_cnf.status = %d",ft_cnf.status);
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_MODEM_CNF),NULL, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModSIMNum::FtModSIMNum(void)
+ :CmdTarget(FT_SIM_NUM_REQ_ID)
+{
+}
+
+FtModSIMNum::~FtModSIMNum(void)
+{
+}
+
+void FtModSIMNum::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_SIMNum");
+
+ FT_GET_SIM_CNF ft_cnf;
+
+ FT_GET_SIM_REQ *req = (FT_GET_SIM_REQ *)pFrm->localBuf();
+
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type = req->type;
+ ft_cnf.status = META_SUCCESS;
+ ft_cnf.number = 2;
+
+#ifdef IS_SUPPORT_SP
+ char tempstr[128]={0};
+ property_get("persist.vendor.radio.multisim.config",tempstr,"ss");
+
+ META_LOG("[Meta][FT] The sim card number default is two");
+ if((strcmp(tempstr,"dsds")==0) || (strcmp(tempstr,"dsda")==0))
+ {
+ ft_cnf.number = 2;
+ META_LOG("[Meta][FT] The sim card number is two");
+ }
+ else if(strcmp(tempstr,"tsts")==0)
+ {
+ ft_cnf.number = 3;
+ META_LOG("[Meta][FT] The sim card number is three");
+ }
+ else if(strcmp(tempstr,"qsqs")==0)
+ {
+ ft_cnf.number = 4;
+ META_LOG("[Meta][FT] The sim card number is four");
+ }
+ else if(strcmp(tempstr,"ss")==0)
+ {
+ ft_cnf.number = 1;
+ }
+#endif
+
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_SDCARD_FEATURE
+
+FtModSDcard::FtModSDcard(void)
+ :CmdTarget(FT_SDCARD_REQ_ID)
+{
+}
+
+FtModSDcard::~FtModSDcard(void)
+{
+}
+
+void FtModSDcard::exec(Frame *pFrm)
+{
+
+ CmdTarget::exec(pFrm);
+
+ if(getInitState())
+ Meta_SDcard_OP((SDCARD_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+
+}
+
+int FtModSDcard::init(Frame* pFrm)
+{
+ META_LOG("[Meta][FT] Ft_SDcard");
+
+ SDCARD_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(SDCARD_CNF));
+ static int bInitFlag_SDcard = FALSE;
+
+ SDCARD_REQ *req = (SDCARD_REQ *)pFrm->localBuf();
+
+ META_LOG("[Meta][FT] FT_SDcard_OP META Test req: %zd , %zd ",
+ sizeof(SDCARD_REQ), sizeof(SDCARD_CNF));
+
+ if (FALSE == bInitFlag_SDcard)
+ {
+ // initial the DVB module when it is called first time
+ if (!Meta_SDcard_Init(req))
+ {
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+
+ META_LOG("[Meta][FT] FT_SDcard_OP Meta_SDcard_Init Fail ");
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+ return false;
+ }
+ bInitFlag_SDcard = TRUE;
+ }
+ return true;
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_EMMC_FEATURE
+
+FtModEMMC::FtModEMMC(void)
+ :CmdTarget(FT_EMMC_REQ_ID)
+{
+}
+
+FtModEMMC::~FtModEMMC(void)
+{
+}
+
+void FtModEMMC::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_EMMC");
+
+ META_CLR_EMMC_OP((FT_EMMC_REQ *)pFrm->localBuf());
+
+}
+#endif
+
+#ifdef FT_NAND_FEATURE
+
+FtModEMMC::FtModEMMC(void)
+ :CmdTarget(FT_EMMC_REQ_ID)
+{
+}
+
+FtModEMMC::~FtModEMMC(void)
+{
+}
+
+void FtModEMMC::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_EMMC");
+
+ META_CLR_EMMC_OP((FT_EMMC_REQ *)pFrm->localBuf());
+
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_CRYPTFS_FEATURE
+
+FtModCRYPTFS::FtModCRYPTFS(void)
+ :CmdTarget(FT_CRYPTFS_REQ_ID)
+{
+}
+
+FtModCRYPTFS::~FtModCRYPTFS(void)
+{
+}
+
+void FtModCRYPTFS::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_CRYPTFS");
+
+ META_CRYPTFS_OP((FT_CRYPTFS_REQ *)pFrm->localBuf());
+
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_ADC_FEATURE
+
+FtModADC::FtModADC(void)
+ :CmdTarget(FT_ADC_REQ_ID)
+{
+}
+
+FtModADC::~FtModADC(void)
+{
+}
+
+void FtModADC::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_ADC");
+
+ Meta_ADC_OP((ADC_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModCustomer::FtModCustomer(void)
+ :CmdTarget(FT_CUSTOMER_REQ_ID)
+{
+}
+
+FtModCustomer::~FtModCustomer(void)
+{
+}
+
+void FtModCustomer::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_Customer");
+
+ FT_CUSTOMER_CNF ft_cnf;
+ memset(&ft_cnf, 0, sizeof(FT_CUSTOMER_CNF));
+ FT_CUSTOMER_REQ *req = (FT_CUSTOMER_REQ *)pFrm->localBuf();
+
+ int peer_buff_size = 1;
+ char* peer_buf = NULL;
+ int setResult = -1;
+
+ // Implement custom API logic here. The following is a sample code for testing.
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type = req->type;
+ ft_cnf.status = META_SUCCESS;
+
+ peer_buf = (char*)malloc(peer_buff_size);
+ memset(peer_buf, 0, peer_buff_size);
+
+ META_LOG("[Meta][FT] setNormalModeTestFlag");
+ setResult = setNormalModeTestFlag(req->cmd.m_u1Dummy);
+ if(0 == setResult)
+ {
+ ft_cnf.status = META_SUCCESS;
+ }
+ else
+ {
+ ft_cnf.status = META_FAILED;
+ }
+
+ META_LOG("[Meta][FT] FT_CUSTOMER_OP successful, OP type is %d!", req->type);
+
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf), peer_buf, peer_buff_size);
+ free(peer_buf);
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModSpecialTest::FtModSpecialTest(void)
+ :CmdTarget(FT_SPECIALTEST_REQ_ID)
+{
+}
+
+FtModSpecialTest::~FtModSpecialTest(void)
+{
+}
+
+void FtModSpecialTest::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_SpecialTest");
+
+ FT_SPECIALTEST_REQ *req = (FT_SPECIALTEST_REQ *)pFrm->localBuf();
+
+ FT_SPECIALTEST_CNF SpecialTestCnf;
+ memset(&SpecialTestCnf, 0, sizeof(FT_SPECIALTEST_CNF));
+ SpecialTestCnf.header.id = req->header.id +1;
+ SpecialTestCnf.header.token = req->header.token;
+ SpecialTestCnf.type = req->type;
+ SpecialTestCnf.status= META_FAILED;
+
+ switch (req->type)
+ {
+ case FT_SPECIALTEST_OP_HUGEDATA: //query the supported modules
+ META_LOG("[Meta][FT] pFTReq->type is FT_SPECIALTEST_OP_HUGEDATA ");
+ SpecialTestCnf.status= META_SUCCESS;
+ break;
+ default :
+ break;
+ }
+
+ WriteDataToPC(&SpecialTestCnf, sizeof(FT_SPECIALTEST_CNF),(char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#define CHIP_RID_PATH "/proc/rid"
+#define CHIP_RID_LEN 16
+
+
+FtModChipID::FtModChipID(void)
+ :CmdTarget(FT_GET_CHIPID_REQ_ID)
+{
+}
+
+FtModChipID::~FtModChipID(void)
+{
+}
+
+void FtModChipID::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_ChipID");
+
+ FT_GET_CHIPID_CNF ft_cnf;
+ int bytes_read = 0;
+ int res = 0;
+
+ memset(&ft_cnf, 0, sizeof(FT_GET_CHIPID_CNF));
+
+
+ FT_GET_CHIPID_REQ *req = (FT_GET_CHIPID_REQ *)pFrm->localBuf();
+
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+
+ int fd = open(CHIP_RID_PATH, O_RDONLY);
+ if (fd != -1)
+ {
+ while (bytes_read < CHIP_RID_LEN)
+ {
+ res = read(fd, ft_cnf.chipId + bytes_read, CHIP_RID_LEN);
+ if (res > 0)
+ bytes_read += res;
+ else
+ break;
+ }
+ close(fd);
+ ft_cnf.chipId[bytes_read] = '\0';
+ ft_cnf.status = META_SUCCESS;
+ META_LOG("[Meta][FT] Chip rid=%s", ft_cnf.chipId);
+ }
+ else
+ {
+ if (errno == ENOENT)
+ {
+ ft_cnf.status = META_FAILED;
+ }
+ META_LOG("[Meta][FT] Failed to open chip rid file %s, errno=%d", CHIP_RID_PATH, errno);
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf), NULL, 0);
+
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+#ifdef FT_TOUCH_FEATURE
+
+FtModCTP::FtModCTP(void)
+ :CmdTarget(FT_CTP_REQ_ID)
+{
+ memset(&m_ft_cnf, 0, sizeof(Touch_CNF));
+}
+
+FtModCTP::~FtModCTP(void)
+{
+}
+
+void FtModCTP::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+
+ memset(&m_ft_cnf, 0, sizeof(Touch_CNF));
+ Touch_REQ *req = (Touch_REQ *)pFrm->localBuf();
+
+ m_ft_cnf.header.id = req->header.id + 1;
+ m_ft_cnf.header.token = req->header.token;
+ m_ft_cnf.status = META_SUCCESS;
+ m_ft_cnf.tpd_type = req->tpd_type;
+
+ if(getInitState())
+ Meta_Touch_OP(req,(char *)pFrm->peerBuf(), pFrm->peerLen());
+
+}
+
+int FtModCTP::init(Frame*)
+{
+ META_LOG("[Meta][FT] Ft_CTP");
+
+ static int bInitFlag_CTP = false;
+ if (false == bInitFlag_CTP)
+ {
+ // initial the touch panel module when it is called first time
+ if (!Meta_Touch_Init())
+ {
+ META_LOG("[Meta][FT] FT_CTP_OP Meta_Touch_Init failed!");
+ m_ft_cnf.status = META_FAILED;
+ WriteDataToPC(&m_ft_cnf, sizeof(m_ft_cnf),NULL, 0);
+ return false;
+ }
+ bInitFlag_CTP = TRUE;
+ }
+
+ return true;
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+#ifdef FT_GPIO_FEATURE
+
+FtModGPIO::FtModGPIO(void)
+ :CmdTarget(FT_GPIO_REQ_ID)
+{
+
+}
+
+FtModGPIO::~FtModGPIO(void)
+{
+}
+
+void FtModGPIO::exec(Frame *pFrm)
+{
+ GPIO_CNF ft_cnf;
+ CmdTarget::exec(pFrm);
+
+ META_LOG("[Meta][FT] Ft_GPIO");
+ memset(&ft_cnf, 0, sizeof(GPIO_CNF));
+
+ GPIO_REQ *req = (GPIO_REQ *)pFrm->localBuf();
+
+ if(getInitState())
+ { //do the bat test by called the interface in meta bat lib
+ ft_cnf = Meta_GPIO_OP(*req,(unsigned char *)pFrm->peerBuf(), pFrm->peerLen());
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+ }
+}
+
+int FtModGPIO::init(Frame*pFrm)
+{
+ GPIO_CNF ft_cnf;
+ static int bInitFlag_GPIO = false;
+
+ META_LOG("[Meta][FT] FT_GPIO_OP META Test ");
+ memset(&ft_cnf, 0, sizeof(GPIO_CNF));
+ GPIO_REQ *req = (GPIO_REQ *)pFrm->localBuf();
+
+ if (FALSE == bInitFlag_GPIO)
+ {
+ // initial the bat module when it is called first time
+ if (!Meta_GPIO_Init())
+ {
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+
+ META_LOG("[Meta][FT] FT_GPIO_OP Meta_GPIO_Init Fail ");
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+ return false;
+ }
+ bInitFlag_GPIO = true;
+ }
+
+ return true;
+}
+
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+//for mdlogger ctrl
+//#define MDLOG_SOCKET_NAME "com.mediatek.mdlogger.socket1"
+//#define MBLOG_SOCKET_NAME "mobilelogd"
+
+FtModTargetloggerCtrl::FtModTargetloggerCtrl(void)
+ :CmdTarget(FT_TARGETLOG_CTRL_REQ_ID)
+{
+}
+
+FtModTargetloggerCtrl::~FtModTargetloggerCtrl(void)
+{
+}
+
+void FtModTargetloggerCtrl::exec(Frame *pFrm)
+{
+ META_LOG("[Meta][TARGETLOG CTRL] FtModTargetloggerCtrl");
+
+ FT_TARGETLOG_CTRL_CNF ft_cnf;
+
+ memset(&ft_cnf, 0, sizeof(FT_TARGETLOG_CTRL_CNF));
+ ft_cnf.status = META_FAILED;
+
+
+ FT_TARGETLOG_CTRL_REQ *req = (FT_TARGETLOG_CTRL_REQ *)pFrm->localBuf();
+
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type= req->type;
+
+ META_LOG("[Meta][TARGETLOG CTRL] FtModTargetloggerCtrl req->type = %d", req->type);
+ switch(req->type)
+ {
+ case FT_MDLOGGER_OP_SWITCH_TYPE:
+ {
+ if(SwitchMdloggerMode(req))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_MDLOGGER_OP_QUERY_STATUS:
+ {
+ if(QueryMdloggerStatus(ft_cnf))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_MDLOGGER_OP_QUERY_NORMALLOG_PATH:
+ {
+ if(QueryMdNormalLogPath(ft_cnf))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_MDLOGGER_OP_QUERY_EELOG_PATH:
+ {
+ if(QueryMdEELogPath(ft_cnf))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_MOBILELOG_OP_SWITCH_TYPE:
+ {
+ if(SwitchMobilelogMode(req))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_MOBILELOG_OP_QUERY_LOG_PATH:
+ {
+ if(QueryMBLogPath(ft_cnf))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_TARGETLOG_OP_PULL:
+ {
+ if(TargetLogPulling(req))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_TARGETLOG_OP_PULLING_STATUS:
+ {
+ if(GetTargetLogPullingStatus(req, ft_cnf))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_MDLOGGER_OP_SET_FILTER:
+ {
+ if(SetModemLogFilter(req))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_CONNSYSLOG_OP_SWITCH_TYPE:
+ {
+ if(SwitchConnsyslogMode(req))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_GPSLOGGER_OP_SWITCH_TYPE:
+ {
+ if(SwitchGPSlogMode(req))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+ case FT_TARGET_OP_CONNSYSLOG_LEVEL:
+ {
+ if(SetConnsysLogLevel(req))
+ ft_cnf.status = META_SUCCESS;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_TARGETLOG_CTRL_CNF),NULL, 0);
+}
+
+unsigned int FtModTargetloggerCtrl::SwitchGPSlogMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+ char msg[32] = {0};
+ //char rsp[256] = {0};
+ int mode = req->cmd.gpslog_ctrl_req.mode;
+ int action = req->cmd.gpslog_ctrl_req.action;
+ META_LOG("[Meta][TARGETLOG CTRL] GPS mode = %d, action = %d", mode, action);
+
+ if(action)
+ {
+ if(sprintf(msg, GPSLOG_START)<0)
+ {
+ META_LOG("[Meta][TARGETLOG CTRL]sprintf GPSLOG_START fail");
+ }
+ }
+ else
+ {
+ if(sprintf(msg, GPSLOG_STOP)<0)
+ {
+ META_LOG("[Meta][TARGETLOG CTRL]sprintf GPSLOG_STOP fail");
+ }
+ }
+
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_GPSLOGGER, GPSLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(msg, true);
+ return 1;
+ }
+
+ return 0;
+
+}
+
+
+unsigned int FtModTargetloggerCtrl::SetConnsysLogLevel(FT_TARGETLOG_CTRL_REQ *req)
+{
+ char msg[32] = {0};
+ //char rsp[32] = {0};
+ META_LOG("[Meta][TARGETLOG CTRL] Set connsys log level");
+
+ if(sprintf(msg, SET_FWLOG_LEVEL, req->cmd.connsyslog_set_level_req.type, req->cmd.connsyslog_set_level_req.level)<0)
+ {
+ META_LOG("[Meta][TARGETLOG CTRL]sprintf SET_FWLOG_LEVEL fail");
+ }
+
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_CONNSYSLOG, CONNSYSLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(msg, true);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+unsigned int FtModTargetloggerCtrl::SwitchMdloggerMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+ char msg[32] = {0};
+// char rsp[256] = {0};
+ int mode = req->cmd.mdlogger_ctrl_req.mode;
+ int action = req->cmd.mdlogger_ctrl_req.action;
+ META_LOG("[Meta][TARGETLOG CTRL] mode = %d, action = %d", mode, action);
+
+ if(action)
+ sprintf(msg, MDLOG_START, mode);
+ else
+ sprintf(msg, MDLOG_STOP);
+
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(msg, true);
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMdloggerStatus(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+ char rsp[256] = {0};
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(MDLOG_QUERY_STATUS, false);
+ pSocket->recv_rsp(rsp);
+
+ cnf.result.mdlogger_status_cnf.status = atoi(rsp);
+ META_LOG("[Meta][TARGETLOG CTRL] mdlogger staus = %d", cnf.result.mdlogger_status_cnf.status);
+
+ return 1;
+ }
+ else
+ {
+ META_LOG("[Meta][TARGETLOG CTRL] failed to find psocket");
+ }
+ return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMdNormalLogPath(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+ char rsp[256] = {0};
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(MDLOG_QUERY_NORMALLOG_PATH, false);
+ pSocket->recv_rsp(rsp);
+
+ if(rsp[0] != 0)
+ strncpy((char*)cnf.result.mdlogger_logpath_cnf.path, rsp, strlen(rsp));
+ else
+ cnf.result.mdlogger_logpath_cnf.path[0] = 0;
+
+ META_LOG("[Meta][TARGETLOG CTRL] modem normal log path = (%s)", cnf.result.mdlogger_logpath_cnf.path);
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMdEELogPath(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+ char rsp[256] = {0};
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(MDLOG_QUERY_EELOG_PATH, false);
+ pSocket->recv_rsp(rsp);
+
+ if(rsp[0] != 0)
+ strncpy((char*)cnf.result.mdlogger_logpath_cnf.path, rsp, strlen(rsp));
+ else
+ cnf.result.mdlogger_logpath_cnf.path[0] = 0;
+
+ META_LOG("[Meta][TARGETLOG CTRL] modem EE log path = (%s)", cnf.result.mdlogger_logpath_cnf.path);
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::QueryMBLogPath(FT_TARGETLOG_CTRL_CNF &cnf)
+{
+ char rsp[256] = {0};
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MOBILELOG, MBLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(MBLOG_QUERY_NORMALLOG_PATH, false);
+ pSocket->recv_rsp(rsp);
+
+ if(rsp[0] != 0)
+ strncpy((char*)cnf.result.mobilelog_logpath_cnf.path, rsp, strlen(rsp));
+ else
+ cnf.result.mobilelog_logpath_cnf.path[0] = 0;
+
+ META_LOG("[Meta][TARGETLOG CTRL] mobile log path = (%s)", cnf.result.mobilelog_logpath_cnf.path);
+ return 1;
+ }
+
+ return 0;
+}
+unsigned int FtModTargetloggerCtrl::SwitchMobilelogMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+ char msg[32] = {0};
+// char rsp[256] = {0};
+ int mode = req->cmd.mobilelog_ctrl_req.mode;
+ int action = req->cmd.mobilelog_ctrl_req.action;
+ META_LOG("[Meta][TARGETLOG CTRL] mode = %d, action = %d", mode, action);
+
+ if(action)
+ sprintf(msg, MBLOG_START);
+ else
+ sprintf(msg, MBLOG_STOP);
+
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MOBILELOG, MBLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(msg, true);
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned int FtModTargetloggerCtrl::TargetLogPulling(FT_TARGETLOG_CTRL_REQ *req)
+{
+ char service[32] = {0};
+ char msg[32] = {0};
+// char rsp[256] = {0};
+ int socket_type = -1;
+
+ int type = req->cmd.targetlog_pull_req.type;
+ int action = req->cmd.targetlog_pull_req.action;
+ META_LOG("[Meta][TARGETLOG CTRL] type = %d, action = %d", type, action);
+
+ switch(type)
+ {
+ case 0:
+ {
+ socket_type = SOCKET_MDLOGGER;
+ strncpy(service, MDLOG_SOCKET_NAME, strlen(MDLOG_SOCKET_NAME));
+ if(action)
+ strncpy(msg, MDLOG_PULL_START, strlen(MDLOG_PULL_START));
+ else
+ strncpy(msg, MDLOG_PULL_STOP, strlen(MDLOG_PULL_STOP));
+ }
+ break;
+ case 1:
+ {
+ socket_type = SOCKET_MOBILELOG;
+ strncpy(service, MBLOG_SOCKET_NAME, strlen(MBLOG_SOCKET_NAME));
+ if(action)
+ strncpy(msg, MBLOG_PULL_START, strlen(MBLOG_PULL_START));
+ else
+ strncpy(msg, MBLOG_PULL_STOP, strlen(MBLOG_PULL_STOP));
+ }
+ break;
+ case 2:
+ {
+ socket_type = SOCKET_CONNSYSLOG;
+ strncpy(service,CONNSYSLOG_SOCKET_NAME, strlen(CONNSYSLOG_SOCKET_NAME));
+ if(action)
+ strncpy(msg, CONNLOG_PULL_START, strlen(CONNLOG_PULL_START));
+ else
+ strncpy(msg, CONNLOG_PULL_STOP, strlen(CONNLOG_PULL_STOP));
+ }
+ break;
+ case 3:
+ {
+ socket_type = SOCKET_MDLOGGER;
+ strncpy(service, MDLOG_SOCKET_NAME, strlen(MDLOG_SOCKET_NAME));
+ if(action)
+ strncpy(msg, MDDB_PULL_START, strlen(MDDB_PULL_START));
+ }
+ break;
+ case 4:
+ {
+ socket_type = SOCKET_GPSLOGGER;
+ strncpy(service, GPSLOG_SOCKET_NAME, strlen(GPSLOG_SOCKET_NAME)+1);
+ if(action)
+ strncpy(msg, GPSLOG_PULL_START, strlen(GPSLOG_PULL_START)+1);
+ }
+ break;
+ default:
+ return 0;
+ }
+
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(socket_type, service);
+ if(pSocket != NULL)
+ {
+ pSocket->setLogPullingStatus(socket_type, 0);
+ pSocket->send_msg(msg, true);
+ return 1;
+ }
+
+ return 0;
+
+}
+
+unsigned int FtModTargetloggerCtrl::GetTargetLogPullingStatus(FT_TARGETLOG_CTRL_REQ *req, FT_TARGETLOG_CTRL_CNF &cnf)
+{
+// unsigned int status = 0;
+ unsigned int ret = 0;
+ char rsp[32] = {0};
+// unsigned int socket_type = (unsigned int)SOCKET_END;
+ unsigned int type = req->cmd.targetlog_pulling_status_req.type;
+ MLogSocket *pSocket = NULL;
+
+ META_LOG("[Meta][TARGETLOG CTRL] type = %d", type);
+
+ switch(type)
+ {
+ case 0:
+ {
+ pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+ META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+ ret = 1;
+ }
+ }
+ break;
+ case 1:
+ {
+ pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MOBILELOG, MBLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+ META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+ ret = 1;
+ }
+ }
+ break;
+ case 2:
+ {
+ pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(MDLOG_EE_DONE_STATUS, false);
+ pSocket->recv_rsp(rsp);
+ cnf.result.targetlog_pulling_status_cnf.status = atoi(rsp);
+ META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+ ret = 1;
+ }
+ }
+ break;
+ case 3:
+ {
+ pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_CONNSYSLOG, CONNSYSLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+ META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+ ret = 1;
+ }
+ }
+ break;
+ case 4:
+ {
+ pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+ META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+ ret = 1;
+ }
+ }
+ break;
+ case 5:
+ {
+ pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_GPSLOGGER, GPSLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ cnf.result.targetlog_pulling_status_cnf.status = pSocket->getLogPullingStatus(type);
+ META_LOG("[Meta][GetTargetLogPullingStatus] status = %d", cnf.result.targetlog_pulling_status_cnf.status);
+ ret = 1;
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+
+}
+
+unsigned int FtModTargetloggerCtrl::GetLogPropValue(char *key)
+{
+#ifdef IS_SUPPORT_SP
+ char val[128]={0};
+ property_get(key, val, "0");
+
+ return atoi(val);
+#else
+ return 0;
+#endif
+
+}
+
+unsigned int FtModTargetloggerCtrl::SetModemLogFilter(FT_TARGETLOG_CTRL_REQ *req)
+{
+ char msg[32] = {0};
+// char rsp[32] = {0};
+ META_LOG("[Meta][TARGETLOG CTRL] Set modem log filter");
+
+ sprintf(msg, MDLOG_SET_FILTER, req->cmd.mdlogger_setfilter_req.type);
+
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_MDLOGGER, MDLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(msg, true);
+ //pSocket->recv_rsp(rsp);
+ return 1;
+ }
+
+ return 0;
+}
+
+void* FtModTargetloggerCtrl::GetLoggerSocket(unsigned int type, const char * service)
+{
+ MSocket *pSocket = getSocket(type);
+ if(pSocket == NULL)
+ {
+ pSocket = createSocket(type);
+ if(pSocket != NULL)
+ {
+ int bInit = pSocket->initClient(service, 0);
+ if(bInit == 0)
+ {
+ delSocket(type);
+ return NULL;
+ }
+ }
+ else
+ return NULL;
+ }
+
+ return (void*)pSocket;
+}
+
+unsigned int FtModTargetloggerCtrl::SwitchConnsyslogMode(FT_TARGETLOG_CTRL_REQ *req)
+{
+ char msg[32] = {0};
+// char rsp[256] = {0};
+ int mode = req->cmd.mobilelog_ctrl_req.mode;
+ int action = req->cmd.mobilelog_ctrl_req.action;
+ META_LOG("[Meta][TARGETLOG CTRL] mode = %d, action = %d", mode, action);
+
+ if(action)
+ sprintf(msg, CONNLOG_START);
+ else
+ sprintf(msg, CONNLOG_STOP);
+
+ MLogSocket *pSocket = (MLogSocket*)GetLoggerSocket(SOCKET_CONNSYSLOG, CONNSYSLOG_SOCKET_NAME);
+ if(pSocket != NULL)
+ {
+ pSocket->send_msg(msg, true);
+ return 1;
+ }
+
+ return 0;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+FtModFileOperation::FtModFileOperation(void)
+ :CmdTarget(FT_FILE_OPERATION_REQ_ID)
+{
+ m_nFileCount = 0;
+}
+
+FtModFileOperation::~FtModFileOperation(void)
+{
+ ClearFileInfoList();
+}
+
+unsigned int FtModFileOperation::GetFileLen(char *pFilePath)
+{
+ struct stat st;
+ if(stat((const char*)pFilePath, &st) < 0)
+ {
+ META_LOG("[Meta][FT] GetFileLen pFilePath(%s) fail, errno=%d",pFilePath,errno);
+ return 0;
+ }
+ else
+ {
+ return (unsigned int)st.st_size;
+ }
+}
+
+void FtModFileOperation::ClearFileInfoList(void)
+{
+ mlist<FT_FILE_INFO*>::iterator it1 = m_fileInfoList.begin();
+ while (it1 != m_fileInfoList.end())
+ {
+ delete (*it1);
+ ++ it1;
+ }
+ m_fileInfoList.clear();
+}
+
+
+int FtModFileOperation::ListPath(unsigned char *pPath,unsigned char *pFileNameSubStr)
+{
+ if(pPath == NULL)
+ {
+ META_LOG("[Meta][FT] ListPath path is NULL");
+ return 1;
+ }
+
+ if(pFileNameSubStr == NULL || pFileNameSubStr[0] == '\0')
+ {
+ META_LOG("[Meta][FT] ListPath file name substr is NULL or 0");
+ return 1;
+ }
+
+ struct stat s;
+ if(stat((const char*)pPath, &s) < 0)
+ {
+ META_LOG("[Meta][FT] ListPath call stat fail, errno=%d",errno);
+ return 1;
+ }
+
+ if(!S_ISDIR(s.st_mode))
+ {
+ META_LOG("[Meta][FT] ListPath path(%s) is not a folder name",pPath);
+ return 1;
+ }
+
+ char currfile[1024] = {0};
+ DIR *dir = NULL;
+ struct dirent *ptr = NULL;
+ dir = opendir((const char*)pPath);
+ if(dir == NULL)
+ {
+ META_LOG("[Meta][FT] ListPath opendir(%s) fail, errno=%d",pPath,errno);
+ return 1;
+ }
+
+ m_nFileCount = 0;
+ ClearFileInfoList();
+ while((ptr = readdir(dir)) != NULL)
+ {
+ if(strcmp(ptr->d_name,".") == 0
+ || strcmp(ptr->d_name,"..") ==0)
+ continue;
+ if(strlen(ptr->d_name) > 256)
+ {
+ META_LOG("[Meta][FT] ListPath file name(%s) length is too large,just skip this file!!!!",ptr->d_name);
+ continue;
+ }
+
+ if(strcmp((const char*)pFileNameSubStr,"*") == 0
+ || strstr(ptr->d_name,(const char*)pFileNameSubStr) != NULL)
+ {
+ FT_FILE_INFO *pFileInfo = new FT_FILE_INFO;
+ if(pFileInfo==NULL)
+ {
+ META_LOG("[Meta][FT] ListPath new FT_FILE_INFO fail,errno=%d",errno);
+ closedir(dir);
+ return 1;
+ }
+ memset(pFileInfo,0,sizeof(FT_FILE_INFO));
+ memcpy(pFileInfo->file_name, ptr->d_name, strlen(ptr->d_name));
+ if(pPath[strlen((const char*)pPath)-1] != '/')
+ {
+ sprintf(currfile,"%s/%s",(char*)pPath,ptr->d_name);
+ }
+ else
+ {
+ sprintf(currfile,"%s%s",(char*)pPath,ptr->d_name);
+ }
+
+ if(ptr->d_type == DT_REG) //file
+ {
+ pFileInfo->file_type = FT_FILE_TYPE_FILE;
+ pFileInfo->file_size = GetFileLen(currfile);
+ }
+ else if(ptr->d_type == DT_DIR) //directory
+ {
+ pFileInfo->file_type = FT_FILE_TYPE_FOLDER;
+ pFileInfo->file_size = 0;
+ }
+ else
+ {
+ pFileInfo->file_type = FT_FILE_TYPE_INVALID;
+ pFileInfo->file_size = 0;
+ }
+ m_nFileCount++;
+ META_LOG("[Meta][FT] ListPath find one file or folder,file_name=%s,file_type:%d,file_size:%d,m_nFileCount:%d",pFileInfo->file_name,pFileInfo->file_type,pFileInfo->file_size,m_nFileCount);
+ m_fileInfoList.push_back(pFileInfo);
+ }
+
+ }
+
+ closedir(dir);
+ return 0;
+}
+
+FT_FILE_INFO* FtModFileOperation::GetFileInfo(unsigned int id)
+{
+ mlist<FT_FILE_INFO*>::iterator it = m_fileInfoList.begin();
+ unsigned int i = 0;
+
+ while (it != m_fileInfoList.end())
+ {
+
+ if (i == id)
+ {
+ return (*it);
+ }
+ i++;
+ ++ it;
+ }
+ return NULL;
+}
+
+
+
+int FtModFileOperation::SaveSendData(FILE_OPERATION_SENDFILE_REQ *req, char *peer_buff, unsigned short peer_len)
+{
+ int nRet = 1;
+ if(req == NULL || peer_buff == NULL)
+ {
+ return nRet;
+ }
+ if(req->dest_file_name[0] == '\0')
+ {
+ return nRet;
+ }
+
+ int SendFileFd = -1;
+ unsigned int fileLen;
+ bool bCreate = false;
+ META_LOG("[Meta][FT] SaveSendData receive block stage %x, file size %d!",req->stream_block.stage,req->stream_block.file_size);
+ if(req->stream_block.stage & BLK_CREATE)
+ {
+ SendFileFd = open((const char*)req->dest_file_name, O_RDWR | O_TRUNC | O_CREAT, 0777);
+ bCreate = true;
+ }
+ else
+ {
+ SendFileFd = open((const char*)req->dest_file_name, O_RDWR | O_APPEND);
+ }
+
+ if(SendFileFd >= 0)
+ {
+ if(bCreate)
+ {
+ if(chown((const char*)req->dest_file_name,2000,1000) == -1)
+ {
+ META_LOG("[Meta][FT] SaveSendData, failed to chown");
+ close(SendFileFd);
+ return nRet;
+
+ }
+ }
+
+ META_LOG("[Meta][FT] SaveSendData create or open file OK!");
+ unsigned short sWriten = 0;
+ sWriten = write(SendFileFd, peer_buff, peer_len);
+
+ if(sWriten)
+ {
+ META_LOG("[Meta][FT] SaveSendData write %d data total data %d!",sWriten,peer_len);
+ if(req->stream_block.stage & BLK_EOF)
+ {
+ fileLen = getFileSize(SendFileFd);
+ if(req->stream_block.file_size == fileLen)
+ {
+ META_LOG("[Meta][FT] SaveSendData write file BLK_EOF success! ");
+ close(SendFileFd);
+ SendFileFd = -1;
+ nRet = 0;
+ }
+ else
+ {
+ META_LOG("[Meta][FT] SaveSendData file size(%d) error! ",req->stream_block.file_size);
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] SaveSendData write file BLK_WRITE success! ");
+ nRet = 0;
+ }
+ }
+ else
+ {
+ META_LOG("[Meta][FT] SaveSendData write file failed!");
+ }
+
+ if(SendFileFd != -1)
+ close(SendFileFd);
+
+ }
+ else
+ {
+ META_LOG("[Meta][FT] SaveSendData create or open file failed!");
+ }
+ return nRet;
+
+}
+
+#define RECEIVE_PEER_MAX_LEN 20*1024
+
+int FtModFileOperation::SetReceiveData(FILE_OPERATION_RECEIVEFILE_REQ *req, FT_FILE_OPERATION_CNF* pft_cnf)
+{
+ int nRet = 1;
+ if(req == NULL || pft_cnf == NULL)
+ {
+ return nRet;
+ }
+ if(req->source_file_name[0] == '\0')
+ {
+ return nRet;
+ }
+
+ unsigned int nReceiveDataSize = 0;
+ int ReceiveFileFd = -1;
+ int nPeerBuffSize = 0;
+ char* pPeerBuf = NULL;
+
+ ReceiveFileFd = open((const char*)req->source_file_name, O_RDONLY);
+
+
+ if(ReceiveFileFd >= 0)
+ {
+ unsigned int nFileLen = getFileSize(ReceiveFileFd);
+ META_LOG("[Meta][FT] SetReceiveData open file %s succeed, fileSize %d ! ",req->source_file_name,nFileLen);
+
+ pPeerBuf = (char*)malloc(RECEIVE_PEER_MAX_LEN);
+ memset(pPeerBuf, 0, RECEIVE_PEER_MAX_LEN);
+
+ pft_cnf->result.receivefile_cnf.stream_block.stage = BLK_CREATE;
+
+ while(!(pft_cnf->result.receivefile_cnf.stream_block.stage & BLK_EOF))
+ {
+ nPeerBuffSize = read(ReceiveFileFd, pPeerBuf, RECEIVE_PEER_MAX_LEN);
+
+ META_LOG("[Meta][FT] SetReceiveData nPeerBuffSize:%d,nReceiveDataSize:%d,",nPeerBuffSize,nReceiveDataSize);
+ if(nPeerBuffSize != -1)
+ {
+ pft_cnf->status = META_SUCCESS;
+ pft_cnf->result.receivefile_cnf.receive_result = 0;
+ if(nPeerBuffSize == 0)
+ {
+ pft_cnf->result.receivefile_cnf.stream_block.stage |= BLK_EOF;
+ pft_cnf->result.receivefile_cnf.stream_block.file_size = nReceiveDataSize;
+ WriteDataToPC(pft_cnf, sizeof(FT_FILE_OPERATION_CNF),NULL, 0);
+ META_LOG("[Meta][FT] SetReceiveData file end, set BLK_EOF! ");
+ nRet = 0;
+ break;
+ }
+ else
+ {
+ pft_cnf->result.receivefile_cnf.stream_block.stage |= BLK_WRITE;
+ pft_cnf->result.receivefile_cnf.stream_block.file_size = nReceiveDataSize;
+ META_LOG("[Meta][FT] SetReceiveData File set %d data ! ",nPeerBuffSize);
+ WriteDataToPC(pft_cnf, sizeof(FT_FILE_OPERATION_CNF),pPeerBuf, nPeerBuffSize);
+ memset(pPeerBuf,0,RECEIVE_PEER_MAX_LEN);
+ pft_cnf->result.receivefile_cnf.stream_block.stage &= ~BLK_CREATE;
+ META_LOG("[Meta][FT] SetReceiveData set BLK_WRITE! ");
+ }
+ nReceiveDataSize = nReceiveDataSize + nPeerBuffSize;
+
+ }
+ else
+ {
+ pft_cnf->result.receivefile_cnf.stream_block.stage |= BLK_EOF;
+ META_LOG("[Meta][FT] SetReceiveData read file fail, set BLK_EOF! ");
+ }
+
+ }
+
+ free(pPeerBuf);
+ close(ReceiveFileFd);
+
+ }
+ else
+ {
+ META_LOG("[Meta][FT] SetReceiveData open File %s failed, errno=%d",req->source_file_name,errno);
+ }
+
+ return nRet;
+}
+void FtModFileOperation::exec(Frame *pFrm)
+{
+ META_LOG("[Meta][FILE OPERATION] FtModFileOperation");
+
+ FT_FILE_OPERATION_CNF ft_cnf;
+
+ memset(&ft_cnf, 0, sizeof(FT_FILE_OPERATION_CNF));
+ ft_cnf.status = META_FAILED;
+
+
+ FT_FILE_OPERATION_REQ *req = (FT_FILE_OPERATION_REQ *)pFrm->localBuf();
+
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.type= req->type;
+
+ META_LOG("[Meta][FILE OPERATION] FtModFileOperation req->type = %d", req->type);
+ switch(req->type)
+ {
+ case FT_FILE_OP_PARSE:
+ {
+ if(ListPath(req->cmd.parse_req.path_name,req->cmd.parse_req.filename_substr) == 0)
+ {
+ ft_cnf.result.parse_cnf.file_count = m_nFileCount;
+ ft_cnf.status = META_SUCCESS;
+ META_LOG("[Meta][FILE OPERATION] FtModFileOperation parse folder success!");
+ }
+ else
+ {
+ META_LOG("[Meta][FILE OPERATION] FtModFileOperation parse folder fail!");
+ }
+ }
+ break;
+ case FT_FILE_OP_GETFILEINFO:
+ {
+ if(req->cmd.getfileinfo_req.index > m_nFileCount)
+ {
+ META_LOG("[Meta][FILE OPERATION] FtModFileOperation invalid file index!");
+ }
+ else
+ {
+ FT_FILE_INFO* pFileInfo = GetFileInfo(req->cmd.getfileinfo_req.index);
+ if(pFileInfo != NULL)
+ {
+ memcpy(&(ft_cnf.result.getfileinfo_cnf.file_info),pFileInfo,sizeof(FT_FILE_INFO));
+ META_LOG("[Meta][FILE OPERATION] file_name=%s,file_type:%d,file_size:%d",pFileInfo->file_name,pFileInfo->file_type,pFileInfo->file_size);
+ ft_cnf.status = META_SUCCESS;
+ }
+ }
+ }
+ break;
+ case FT_FILE_OP_SENDFILE:
+ {
+ if(SaveSendData(&(req->cmd.sendfile_req),(char *)pFrm->peerBuf(), pFrm->peerLen()) == 0)
+ {
+ ft_cnf.result.sendfile_cnf.send_result = 0;
+ ft_cnf.status = META_SUCCESS;
+ }
+ }
+ break;
+ case FT_FILE_OP_RECEIVEFILE:
+ {
+ if(SetReceiveData(&(req->cmd.receivefile_req),&ft_cnf) == 0)
+ {
+ META_LOG("[Meta][FILE OPERATION] FtModFileOperation success to set receive data!");
+ return;
+ }
+ else
+ {
+ META_LOG("[Meta][FILE OPERATION] FtModFileOperation Failed to set receive data!");
+ }
+ }
+ break;
+ default:
+ break;
+ }
+
+ WriteDataToPC(&ft_cnf, sizeof(FT_FILE_OPERATION_CNF),NULL, 0);
+}
+
+#ifdef FT_RAT_FEATURE
+
+FtModRAT::FtModRAT(void)
+ :CmdTarget(FT_RATCONFIG_REQ_ID)
+{
+}
+
+FtModRAT::~FtModRAT(void)
+{
+}
+
+int FtModRAT::init(Frame*pFrm)
+{
+ RAT_CNF ft_cnf;
+ static int bInitFlag_RAT = false;
+
+ memset(&ft_cnf, 0, sizeof(RAT_CNF));
+ RAT_REQ *req = (RAT_REQ *)pFrm->localBuf();
+
+ if (FALSE == bInitFlag_RAT)
+ {
+ // initial the bat module when it is called first time
+ if (!META_RAT_init())
+ {
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+
+ META_LOG("[Meta][FT] FT_RAT_OP META_RAT_init Fail ");
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+ return false;
+ }
+ bInitFlag_RAT = true;
+ }
+
+ return true;
+}
+
+
+void FtModRAT::exec(Frame *pFrm)
+{
+ META_LOG("[Meta][FT] FT_RAT_OP FtModRAT ");
+
+ CmdTarget::exec(pFrm);
+ if(getInitState())
+ META_RAT_OP((RAT_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+
+#endif
+
+
+#ifdef FT_MSIM_FEATURE
+FtModMSIM::FtModMSIM(void)
+ :CmdTarget(FT_MSIM_REQ_ID)
+{
+}
+
+FtModMSIM::~FtModMSIM(void)
+{
+}
+
+int FtModMSIM::init(Frame*pFrm)
+{
+ MSIM_CNF ft_cnf;
+ static int bInitFlag_MSIM = false;
+
+ memset(&ft_cnf, 0, sizeof(MSIM_CNF));
+ MSIM_REQ *req = (MSIM_REQ *)pFrm->localBuf();
+
+ if (FALSE == bInitFlag_MSIM)
+ {
+ // initial the bat module when it is called first time
+ if (!META_MSIM_init())
+ {
+ ft_cnf.header.id = req->header.id +1;
+ ft_cnf.header.token = req->header.token;
+ ft_cnf.status = META_FAILED;
+
+ META_LOG("[Meta][FT] FT_MSIM_OP META_MSIM_init Fail ");
+ WriteDataToPC(&ft_cnf, sizeof(ft_cnf),NULL, 0);
+
+ return false;
+ }
+ bInitFlag_MSIM = true;
+ }
+
+ return true;
+}
+
+
+void FtModMSIM::exec(Frame *pFrm)
+{
+ META_LOG("[Meta][FT] FT_MSIM_OP FtModMSIM");
+
+ CmdTarget::exec(pFrm);
+ if(getInitState())
+ META_MSIM_OP((MSIM_REQ *)pFrm->localBuf(), (char *)pFrm->peerBuf(), pFrm->peerLen());
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////////////////////
+
+BOOL Meta_Mobile_Log()
+{
+ int fd = 0;
+ int len = 0;
+ BOOL ret = FALSE;
+ META_LOG("[Meta][FT] Meta_Mobile_Log ");
+
+ //support end load and user load,send stop command to mobilelog
+
+// fd = socket_local_client("mobilelogd", ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); to modify
+ if (fd < 0)
+ {
+ META_LOG("[Meta][FT] socket fd <0 ");
+ return FALSE;
+ }
+ META_LOG("[Meta][FT] socket ok\n");
+ if((len = write(fd, "stop", sizeof("stop"))) < 0)
+ {
+ META_LOG("[Meta][FT] socket write error!");
+ ret = FALSE;
+ }
+ else
+ {
+ META_LOG("[Meta][FT] write %d Bytes.", len);
+ ret = TRUE;
+ }
+ close(fd);
+ sleep(4);
+ return ret;
+
+}
+
+void FT_UtilCheckIfFuncExist(FT_UTILITY_COMMAND_REQ *req, FT_UTILITY_COMMAND_CNF *cnf)
+{
+
+ unsigned int query_ft_msg_id = req->cmd.CheckIfFuncExist.query_ft_msg_id;
+ unsigned int query_op_code = req->cmd.CheckIfFuncExist.query_op_code;
+ META_LOG("[Meta][FT] FT_UtilCheckIfFuncExist META Test ");
+ cnf->status = FT_CNF_FAIL;
+
+ META_LOG("[Meta][FT] request id = %d op = %d",query_ft_msg_id,query_op_code);
+
+
+ switch (query_ft_msg_id)
+ {
+
+#ifdef FT_FM_FEATURE
+ case FT_FM_REQ_ID:
+ if(query_op_code == 0)//FT_FM_OP_READ_CHIP_ID
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ break;
+#endif
+
+#ifdef FT_CRYPTFS_FEATURE
+ case FT_CRYPTFS_REQ_ID:
+ if(query_op_code == 0)//FT_CRYPTFS_OP_QUERYSUPPORT
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == 1)//FT_CRYPTFS_OP_VERITIFY
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ break;
+#endif
+
+ case FT_MODEM_REQ_ID:
+ if(query_op_code == FT_MODEM_OP_QUERY_INFO )
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == FT_MODEM_OP_CAPABILITY_LIST)
+ {
+ cnf->status = FT_CNF_OK;
+ }/*
+ else if(query_op_code == FT_MODEM_OP_SET_MODEMTYPE)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == FT_MODEM_OP_GET_CURENTMODEMTYPE)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == FT_MODEM_OP_QUERY_MDIMGTYPE )
+ {
+ cnf->status = FT_CNF_OK;
+ }*/
+ else if(query_op_code == FT_MODEM_OP_QUERY_MDDBPATH)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+#ifdef MTK_META_COMPRESS_SUPPORT
+ else if(query_op_code == FT_MODEM_OP_SUPPORT_COMPRESS)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+#endif
+ break;
+
+ case FT_L4AUD_REQ_ID:
+ if(query_op_code == 59)//FT_L4AUD_OP_SPEAKER_CALIBRATION_SUPPORT
+ {
+#ifdef MTK_SPEAKER_MONITOR_SUPPORT
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] MTK_SPEAKER_MONITOR_SUPPORT = yes");
+#else
+ cnf->status = FT_CNF_FAIL;
+ META_LOG("[Meta][FT] MTK_SPEAKER_MONITOR_SUPPORT = no");
+#endif
+ }
+
+ break;
+ case FT_SIM_DETECT_REQ_ID:
+ if(query_op_code == FT_SIM_DETECT_OP_EXTMOD)
+ {
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] FT_SIM_DETECT_OP_EXTMOD = yes");
+ }
+ break;
+ case FT_TARGETLOG_CTRL_REQ_ID:
+ if((query_op_code < FT_CONNSYSLOG_OP_SWITCH_TYPE) || (query_op_code == FT_GPSLOGGER_OP_SWITCH_TYPE))
+ {
+ if(getDataChannelType() == 1) //93 modem ccb channel
+ {
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] FT_MDLOGGER_OP = yes");
+ }
+ else
+ {
+ META_LOG("[Meta][FT] FT_MDLOGGER_OP = no");
+ }
+ }
+ break;
+ case FT_TARGETCLOCK_REQ_ID:
+ if(query_op_code <= FT_CLOCK_GET)
+ {
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] FT_TARGETCLOCK_OP = yes");
+ }
+ break;
+ case FT_DISCONNECT_REQ_ID:
+ if(query_op_code < FT_CTRL_DONOTHING)
+ {
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] FT_DISCONN_TARGET_OP = yes");
+ }
+ break;
+ case FT_UTILITY_COMMAND_REQ_ID:
+ if(query_op_code == FT_UTILCMD_QUERY_WCNDRIVER_READY)
+ {
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] FT_UTILCMD_QUERY_WCNDRIVER_READY = yes");
+ }
+ else if(query_op_code == FT_UTILCMD_SWITCH_WIFI_USB)
+ {
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] FT_UTILCMD_SWITCH_WIFI_USB = yes");
+ }
+ else if(query_op_code == FT_UTILCMD_PRINTF_CUSLOG)
+ {
+ cnf->status = FT_CNF_OK;
+ META_LOG("[Meta][FT] FT_UTILCMD_PRINTF_CUSLOG = yes");
+ }
+ break;
+ case FT_FILE_OPERATION_REQ_ID:
+ if(query_op_code == FT_FILE_OP_PARSE )
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == FT_FILE_OP_GETFILEINFO)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == FT_FILE_OP_SENDFILE)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == FT_FILE_OP_RECEIVEFILE)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ break;
+ case FT_RATCONFIG_REQ_ID:
+#ifdef FT_RAT_FEATURE
+ if(query_op_code == RAT_OP_READ_OPTR )
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == RAT_OP_READ_OPTRSEG)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == RAT_OP_GET_CURRENT_RAT)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == RAT_OP_SET_NEW_RAT)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+#else
+ cnf->status = FT_CNF_FAIL;
+#endif
+ break;
+ case FT_MSIM_REQ_ID:
+#ifdef FT_MSIM_FEATURE
+ if(query_op_code == MSIM_OP_GET_MSIM )
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ else if(query_op_code == MSIM_OP_SET_MSIM)
+ {
+ cnf->status = FT_CNF_OK;
+ }
+#else
+ cnf->status = FT_CNF_FAIL;
+#endif
+ break;
+ case FT_APDB_REQ_ID:
+#ifdef FT_NVRAM_FEATURE
+ if(query_op_code == FT_APDB_OP_QUERYPATH )
+ {
+ cnf->status = FT_CNF_OK;
+ }
+#else
+ cnf->status = FT_CNF_FAIL;
+#endif
+ break;
+#if ((defined FT_EMMC_FEATURE) || (defined FT_NAND_FEATURE))
+ case FT_EMMC_REQ_ID:
+ if(query_op_code == 3/*FT_EMMC_OP_UNMOUNT*/ )
+ {
+ cnf->status = FT_CNF_OK;
+ }
+ break;
+#endif
+ case FT_POWER_OFF_REQ_ID:
+ if(query_op_code == FT_SHUTDOWN_OP_WAITUSB )
+ {
+ META_LOG("[Meta][FT] FT_SHUTDOWN_OP_WAITUSB = yes");
+ cnf->status = FT_CNF_OK;
+ }
+ break;
+ default:
+ META_LOG("[Meta][FT] NOT FOUND THE PRIMITIVE_ID");
+ cnf->status = FT_CNF_FAIL;
+ break;
+ }
+
+
+ // assign return structure
+ cnf->result.CheckIfFuncExist.query_ft_msg_id = query_ft_msg_id;
+ cnf->result.CheckIfFuncExist.query_op_code = query_op_code;
+}
+
+FtModUtility::FtModUtility(void)
+ :CmdTarget(FT_UTILITY_COMMAND_REQ_ID)
+{
+}
+
+FtModUtility::~FtModUtility(void)
+{
+}
+
+#ifdef FT_NVRAM_FEATURE
+void FtModUtility::covertArray2Vector(unsigned char* in, int len, std::vector<uint8_t>& out) {
+ out.clear();
+ for(int i = 0; i < len; i++) {
+ out.push_back(in[i]);
+ }
+}
+void FtModUtility::covertVector2Array(std::vector<uint8_t> in, char* out) {
+ int size = in.size();
+ for(int i = 0; i < size; i++) {
+ out[i] = in.at(i);
+ }
+}
+#endif
+
+void FtModUtility::exec(Frame *pFrm)
+{
+ META_LOG("[Meta][FT] FT_Peripheral_OP META Test");
+
+ CmdTarget::exec(pFrm);
+
+ FT_UTILITY_COMMAND_CNF UtilityCnf;
+ //PROCESS_INFORMATION cleanBootProcInfo;
+ static META_BOOL bLCDBKInitFlag_Peri = FALSE;
+ static META_BOOL bLCDFtInitFlag_Peri = FALSE;
+ static META_BOOL bVibratorInitFlag_Peri = FALSE;
+ int nNVRAMFlag = 0;
+ unsigned int level = 0;
+ char tempstr[128]={0};
+
+ //cleanBootProcInfo.hProcess = NULL;
+ //cleanBootProcInfo.hThread = NULL;
+
+ memset(&UtilityCnf, 0, sizeof(FT_UTILITY_COMMAND_CNF));
+ FT_UTILITY_COMMAND_REQ *req = (FT_UTILITY_COMMAND_REQ *)pFrm->localBuf();
+
+ META_LOG("[Meta][FT] FT_Peripheral_OP META Test, type = %d", req->type);
+
+ UtilityCnf.header.id = req->header.id +1;
+ UtilityCnf.header.token = req->header.token;
+ UtilityCnf.type = req->type;
+ UtilityCnf.status= META_FAILED;
+
+ //do the related test.
+ switch (req->type)
+ {
+ case FT_UTILCMD_CHECK_IF_FUNC_EXIST: //query the supported modules
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_CHECK_IF_FUNC_EXIST ");
+ FT_UtilCheckIfFuncExist(req, &UtilityCnf);
+ break;
+ //delete since no use.
+ //case FT_UTILCMD_QUERY_LOCAL_TIME: //query RTC from meta cpu lib
+ // META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_QUERY_LOCAL_TIME ");
+ // UtilityCnf.result.m_WatchDogCnf= META_RTCRead_OP(req->cmd.m_WatchDogReq);
+ // UtilityCnf.status= META_SUCCESS;
+ // break;
+
+#ifdef FT_LCDBK_FEATURE
+ case FT_UTILCMD_MAIN_SUB_LCD_LIGHT_LEVEL: //test lcd backlight from meta lcd backlight lig
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_MAIN_SUB_LCD_LIGHT_LEVEL ");
+ if(bLCDBKInitFlag_Peri==FALSE)
+ {
+ if (!Meta_LCDBK_Init())
+ {
+ META_LOG("[Meta][FT] FT_Peripheral_OP Meta_LCDBK_Init Fail ");
+ goto Per_Exit;
+ }
+ bLCDBKInitFlag_Peri = TRUE;
+ }
+ UtilityCnf.result.m_LCDCnf = Meta_LCDBK_OP(req->cmd.m_LCDReq);
+ UtilityCnf.status= META_SUCCESS;
+ break;
+#endif
+
+#ifdef FT_LCD_FEATURE
+ case FT_UTILCMD_LCD_COLOR_TEST:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_LCD_COLOR_TEST ");
+ if(bLCDFtInitFlag_Peri==FALSE)
+ {
+ if (!Meta_LCDFt_Init())
+ {
+ META_LOG("[Meta][FT]] FT_Peripheral_OP Meta_LCDFt_Init Fail ");
+ goto Per_Exit;
+ }
+ bLCDFtInitFlag_Peri = TRUE;
+ }
+ UtilityCnf.result.m_LCDColorTestCNF = Meta_LCDFt_OP(req->cmd.m_LCDColorTestReq);
+ UtilityCnf.status= META_SUCCESS;
+ break;
+#endif
+
+#ifdef FT_VIBRATOR_FEATURE
+ case FT_UTILCMD_SIGNAL_INDICATOR_ONOFF:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SIGNAL_INDICATOR_ONOFF ");
+ UtilityCnf.result.m_NLEDCnf = Meta_Vibrator_OP(req->cmd.m_NLEDReq);
+ UtilityCnf.status= META_SUCCESS;
+ break;
+#endif
+
+
+#ifdef FT_VIBRATOR_FEATURE
+ case FT_UTILCMD_VIBRATOR_ONOFF: //test vibrate and indicator from meta nled lib
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_VIBRATOR_ONOFF ");
+ if(bVibratorInitFlag_Peri==FALSE)
+ {
+ if (!Meta_Vibrator_Init())
+ {
+ META_LOG("[Meta][FT] FT_Peripheral_OP Meta_Vibrator_Init Fail ");
+ goto Per_Exit;
+ }
+ bVibratorInitFlag_Peri = TRUE;
+ }
+ UtilityCnf.result.m_NLEDCnf = Meta_Vibrator_OP(req->cmd.m_NLEDReq);
+ UtilityCnf.status= META_SUCCESS;
+ break;
+#endif
+
+#ifdef FT_VIBRATOR_FEATURE
+ case FT_UTILCMD_KEYPAD_LED_ONOFF:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_KEYPAD_LED_ONOFF ");
+ UtilityCnf.result.m_NLEDCnf = Meta_Vibrator_OP(req->cmd.m_NLEDReq);
+ UtilityCnf.status= META_SUCCESS;
+ break;
+#endif
+
+#ifdef FT_NVRAM_FEATURE
+ case FT_UTILCMD_SET_CLEAN_BOOT_FLAG:
+ nNVRAMFlag = req->cmd.m_SetCleanBootFlagReq.Notused;
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_CLEAN_BOOT_FLAG, nNVRAMFlag =%d",nNVRAMFlag);
+ if ((req->cmd.m_SetCleanBootFlagReq.BackupTime)[0] != '\0')
+ {
+ META_LOG("[Meta][FT] FT_UTILCMD_SET_CLEAN_BOOT_FLAG, BackupTime =%s",req->cmd.m_SetCleanBootFlagReq.BackupTime);
+ UtilityCnf.result.m_SetCleanBootFlagCnf.drv_statsu = FileOp_BackupToBinRegion_All_Exx(req->cmd.m_SetCleanBootFlagReq.BackupTime);
+ }
+ else
+ {
+ //For NVRAM to record write barcode(1) and IMEI(2) and both barcode and IMEI(3) history
+ if ( nNVRAMFlag == 1 || nNVRAMFlag == 2 || nNVRAMFlag == 3 )
+ {
+ UtilityCnf.result.m_SetCleanBootFlagCnf.drv_statsu = FileOp_BackupToBinRegion_All_Ex(nNVRAMFlag);
+ }
+ else
+ {
+ UtilityCnf.result.m_SetCleanBootFlagCnf.drv_statsu = FileOp_BackupToBinRegion_All();
+ }
+ }
+ UtilityCnf.status=META_SUCCESS;
+ break;
+#endif
+ case FT_UTILCMD_CHECK_IF_LOW_COST_SINGLE_BANK_FLASH: //query the single flash feature, we now just return.
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_CHECK_IF_LOW_COST_SINGLE_BANK_FLASH ");
+ UtilityCnf.status=META_SUCCESS;
+ break;
+
+ case FT_UTILCMD_SAVE_MOBILE_LOG: //save mobile log
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SAVE_MOBILE_LOG ");
+ META_LOG("[Meta][FT] FT_UTILCMD_SAVE_MOBILE_LOG META Test %s,%d,%s",__FILE__,__LINE__,__FUNCTION__);
+ UtilityCnf.result.m_SaveMobileLogCnf.drv_status = Meta_Mobile_Log();
+ UtilityCnf.status = META_SUCCESS;
+ break;
+ case FT_UTILCMD_SET_LOG_LEVEL:
+ level = req->cmd.m_SetLogLevelReq.level;
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_LOG_LEVEL ");
+ META_LOG("[Meta][FT] FT_UTILCMD_SET_LOG_LEVEL META Test %s,%d,%s,level = %d",__FILE__,__LINE__,__FUNCTION__,level);
+ setLogLevel(level);
+ UtilityCnf.status = META_SUCCESS;
+ break;
+ case FT_UTILCMD_SDIO_AUTO_CALIBRATION:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SDIO_AUTO_CALIBRATION ");
+ META_LOG("[Meta][FT] FT_UTILCMD_SDIO_AUTO_CALIBRATION META Test: no more supported");
+ break;
+ case FT_UTILCMD_QUERY_WCNDRIVER_READY:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_QUERY_WCNDRIVER_READY ");
+#ifdef IS_SUPPORT_SP
+ property_get("vendor.connsys.driver.ready",tempstr,"no");
+ if(strcmp(tempstr,"yes")==0)
+ {
+ UtilityCnf.result.m_QueryWCNDriverReadyCnf.result = 1; //has ready
+ META_LOG("[Meta][FT] FT_UTILCMD_QUERY_WCNDRIVER_READY() wcn driver ready");
+ }
+ else
+ {
+ UtilityCnf.result.m_QueryWCNDriverReadyCnf.result = 0; //not ready
+ META_LOG("[Meta][FT] FT_UTILCMD_QUERY_WCNDRIVER_READY() wcn driver not ready");
+ }
+#else
+ UtilityCnf.result.m_QueryWCNDriverReadyCnf.result = 1;
+#endif
+ UtilityCnf.status = META_SUCCESS;
+ break;
+ case FT_UTILCMD_SET_ATM_FLAG:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_ATM_FLAG ");
+
+ META_LOG("[Meta][FT] setNormalModeTestFlag");
+
+ if(0 == setNormalModeTestFlag(req->cmd.m_SetATMFlagReq.flag))
+ {
+ UtilityCnf.status = META_SUCCESS;
+ }
+ else
+ {
+ UtilityCnf.status = META_FAILED;
+ }
+ break;
+ case FT_UTILCMD_SET_PRODUCT_INFO:
+ {
+ int offset = 0;
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SET_PRODUCT_INFO ");
+
+ switch(req->cmd.m_SetProductInfo.type)
+ {
+ case 0: //ATM flag
+ offset = OFFSET_ATM;
+ break;
+ case 1: //meta log flag
+ offset = OFFSET_METALOG;
+ break;
+ default:
+ break;
+ }
+
+ META_LOG("[Meta][FT] setProductInfo, type = %d, offset = %d", req->cmd.m_SetProductInfo.type, offset);
+ if(0 == setProductInfo(req->cmd.m_SetProductInfo.type, req->cmd.m_SetProductInfo.flag, offset))
+ {
+ UtilityCnf.status = META_SUCCESS;
+ }
+ else
+ {
+ UtilityCnf.status = META_FAILED;
+ }
+ }
+ break;
+ case FT_UTILCMD_SWITCH_WIFI_USB:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_SWITCH_WIFI_USB ");
+#ifdef IS_SUPPORT_SP
+ //send response to PC
+ UtilityCnf.result.m_SwitchWiFiUSBCnf.result = 1;
+ UtilityCnf.status = META_SUCCESS;
+ WriteDataToPC(&UtilityCnf, sizeof(FT_UTILITY_COMMAND_CNF),NULL, 0);
+ //destroy related resource
+ destroyVirtualRxThread();
+ //set property and then create resource
+ if(req->cmd.m_SwitchWiFiUSBReq.flag == 0) //wifi to usb
+ {
+ property_set("persist.vendor.meta.connecttype","usb");
+ META_LOG("[Meta][FT] persist.vendor.meta.connecttype = usb");
+ setComType(META_USB_COM);
+ }
+ else if(req->cmd.m_SwitchWiFiUSBReq.flag == 1) //usb to wifi
+ {
+ property_set("persist.vendor.meta.connecttype","wifi");
+ META_LOG("[Meta][FT] persist.vendor.meta.connecttype = wifi");
+ setComType(META_SOCKET);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] FT_UTILCMD_SWITCH_WIFI_USB flag = %d is valid",req->cmd.m_SwitchWiFiUSBReq.flag);
+ }
+ createVirtualRxThread();
+#endif
+ return;
+ case FT_UTILCMD_PRINTF_CUSLOG:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type is FT_UTILCMD_PRINTF_CUSLOG ");
+ if(strlen((char*)req->cmd.m_PrintCusLogReq.log) > 0)
+ {
+ META_LOG("[Meta][Customization Log] %s", req->cmd.m_PrintCusLogReq.log);
+ }
+ UtilityCnf.status = META_SUCCESS;
+ break;
+ default:
+ META_LOG("[Meta][FT] FT_Peripheral_OP pFTReq->type error ");
+ UtilityCnf.status= META_FAILED;
+ break;
+
+ }
+
+Per_Exit:
+ WriteDataToPC(&UtilityCnf, sizeof(FT_UTILITY_COMMAND_CNF),NULL, 0);
+
+}
+
+/////////////////////////////////////////////////////////////////////////////////////////
+
+
+
diff --git a/src/devtools/meta/src/common/src/MSocket.cpp b/src/devtools/meta/src/common/src/MSocket.cpp
new file mode 100644
index 0000000..cc47411
--- /dev/null
+++ b/src/devtools/meta/src/common/src/MSocket.cpp
@@ -0,0 +1,623 @@
+#ifdef IS_SUPPORT_SP
+#include <cutils/sockets.h>
+#endif
+
+#include <stdio.h>
+#include <sys/socket.h>
+#include <netinet/tcp.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include <unistd.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/un.h>
+
+#include "Context.h"
+#include "LogDefine.h"
+#include "MSocket.h"
+
+#define DATA_LEN 256
+
+MSocket::MSocket()
+{
+ m_serverID = -1;
+ m_clientID = -1;
+ m_threadID = -1;
+ m_stop = 0;
+ memset(&m_thread, 0, sizeof(pthread_t));
+ m_type = SOCKET_END;
+ m_bClientConnected = false;
+
+// signal(SIGPIPE,SIG_IGN); to modify
+
+}
+
+MSocket::~MSocket(void)
+{
+ deinit();
+}
+
+int MSocket::initServer(const char * socket_name, int namespaceId, int bListen)
+{
+ META_LOG("[META][Socket] To Create Socket Server:(%s)", socket_name);
+
+#ifdef IS_SUPPORT_SP
+ m_serverID = socket_local_server(socket_name, namespaceId, SOCK_STREAM);
+
+ META_LOG("[Meta][Socket] m_serverID = %d errno = %d", m_serverID, errno);
+
+ listen(m_serverID,4);
+#else
+
+
+#endif
+
+ if(bListen)
+ {
+ m_threadID = pthread_create(&m_thread, NULL, ThreadFunc, this);
+ if(m_threadID)
+ {
+ META_LOG("[Meta][Socket] Failed to create socket thread!");
+ return 0;
+ }
+ }
+
+ return 1;
+
+}
+
+int MSocket::initClient(const char * socket_name, int namespaceId, int bListen)
+{
+ int count = 0;
+ int val = 0;
+ signal(SIGCHLD, SIG_IGN);
+ META_LOG("[Meta][Socket] To connect server:(%s)", socket_name);
+
+#ifdef IS_SUPPORT_SP
+ while(m_clientID < 0)
+ {
+ count++;
+ m_clientID = socket_local_client(socket_name, namespaceId, SOCK_STREAM);
+ META_LOG("[Meta][Socket] init client m_clientID = %d", m_clientID);
+ META_LOG("[Meta][Socket] errno = %d, string = %s", errno, strerror(errno));
+ usleep(200*1000);
+ if(count == 5)
+ return 0;
+ }
+#else
+ int ret = -1;
+ struct sockaddr_un sun;
+ memset(&sun, 0, sizeof(struct sockaddr_un));
+ sun.sun_family = AF_UNIX;
+ strcpy(sun.sun_path, socket_name);
+ m_clientID = socket(PF_UNIX,SOCK_STREAM, 0);
+ if(m_clientID <0 )
+ {
+ META_LOG("[Meta][Socket] init client m_clientID = %d", m_clientID);
+ return 0;
+ }
+
+ while(ret == -1)
+ {
+ count++;
+ ret = ::connect(m_clientID, (struct sockaddr*)&sun, sizeof(sun));
+ META_LOG("[Meta][Socket] To connect server = %d", ret);
+ META_LOG("[Meta][Socket] errno = %d, string = %s", errno, strerror(errno));
+ usleep(200*1000);
+ if(count == 50)
+ return 0;
+ }
+
+#endif
+ META_LOG("[Meta][Socket] connect successful");
+ //if bListen is true, we will create thread to read socket data.
+ if(bListen)
+ {
+ m_threadID = pthread_create(&m_thread, NULL, ThreadFunc, this);
+ if(m_threadID)
+ {
+ META_LOG("[Meta][Socket] Failed to create socket thread!");
+ return 0;
+ }
+ }
+/*
+ if(0 == setsockopt(m_clientID, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val)))
+ {
+ META_LOG("[Meta][Socket] set socket option to TCP_NODELAY!");
+ }
+*/
+ return 1;
+}
+
+void MSocket::deinit()
+{
+ if(m_threadID == 0)
+ {
+ m_stop = 1;
+ pthread_join(m_thread, NULL);
+ }
+
+ if (m_clientID > 0)
+ {
+ close (m_clientID);
+ m_clientID = -1;
+ }
+
+ if (m_serverID > 0)
+ {
+ close (m_serverID);
+ m_serverID = -1;
+ }
+}
+
+int MSocket::connect()
+{
+ if(m_bClientConnected)
+ return 0;
+
+ while((m_clientID = accept(m_serverID, NULL, NULL)) == -1)
+ {
+ if(errno == EAGAIN)
+ {
+ usleep(100*1000);
+ continue;
+ }
+ META_LOG("[Meta][Socket] Socket accept error, errno=%d", errno);
+ return -1;
+ }
+ META_LOG("[Meta][Socket] Accept client connection, m_clientID = %d", m_clientID);
+ m_bClientConnected = true;
+
+ return 0;
+}
+
+
+void MSocket::disconnect()
+{
+ if (m_bClientConnected)
+ {
+ if (m_clientID != -1)
+ {
+ META_LOG("[Meta][Socket] Disconnect client connection, m_clientID = %d", m_clientID);
+ close(m_clientID);
+ m_clientID = -1;
+ m_bClientConnected = false;
+ }
+ }
+}
+
+
+void MSocket::send_msg(const char *msg)
+{
+ int nWritten = 0;
+
+ META_LOG("[Meta][Socket] send mssage (%s) - socket id = %d", msg, m_clientID);
+
+ if((nWritten = write(m_clientID, msg, strlen(msg))) < 0)
+ {
+ META_LOG("[Meta][Socket] socket write error: %s", strerror(errno));
+ }
+ else
+ {
+ META_LOG("[Meta][Socket] write %d Bytes, total = %zd", nWritten, strlen(msg));
+ }
+}
+
+void *MSocket::ThreadFunc(void *p)
+{
+ MSocket *pSocket = (MSocket *)p;
+ if(pSocket != NULL)
+ pSocket->wait_msg();
+
+ return NULL;
+}
+
+//////////////////////////////////////////////MATCIClientSocket////////////////////////////////////////////////////
+
+MATCIClientSocket::MATCIClientSocket()
+{
+
+}
+
+MATCIClientSocket::MATCIClientSocket(SOCKET_TYPE type)
+{
+ m_type = type;
+}
+
+MATCIClientSocket::~MATCIClientSocket()
+{
+
+}
+
+void MATCIClientSocket::wait_msg()
+{
+ const char *msg = "calibration";
+ char data[DATA_LEN] = {0};
+ int len = 0;
+
+ META_LOG("[Meta][MATCIClientSocket] wait_msg m_clientID = %d", m_clientID);
+
+ while(m_stop == 0)
+ {
+ if(!m_bClientConnected)
+ {
+ if(-1 == connect())
+ continue;
+ }
+ memset(data, 0, DATA_LEN);
+ len = read(m_clientID, data, DATA_LEN);
+
+ if(len >0)
+ {
+ if(len == DATA_LEN)
+ data[len-1] = 0;
+ else
+ data[len] = 0;
+
+ META_LOG("[Meta][MATCIClientSocket] data len = %d, rawdata = (%s)", len, data);
+ char *pos = strstr(data, msg);
+ if(pos != NULL)
+ {
+ createSerPortThread();
+ createAllModemThread();
+ continue;
+ }
+ }
+ else if(0 == len)
+ {
+ META_LOG("[Meta][MATMSocket] Socket connection lost, need to reconnect");
+ disconnect();
+ }
+ else
+ {
+ usleep(100000); // wake up every 0.1sec
+ }
+ }
+ return;
+}
+
+//////////////////////////////////////////////MATCIServerSocket////////////////////////////////////////////////////
+
+MATCIServerSocket::MATCIServerSocket()
+{
+
+}
+
+MATCIServerSocket::MATCIServerSocket(SOCKET_TYPE type)
+{
+ m_type = type;
+}
+
+MATCIServerSocket::~MATCIServerSocket()
+{
+
+}
+
+void MATCIServerSocket::wait_msg()
+{
+ const char *msg = "EMETACFG";
+ const char *msg_ok = "OK";
+ char data[DATA_LEN] = {0};
+ int len = 0;
+
+ META_LOG("[Meta][MATCIServerSocket] wait_msg m_clientID = %d", m_clientID);
+
+ while(m_stop == 0)
+ {
+ memset(data, 0, DATA_LEN);
+ len = read(m_clientID, data, DATA_LEN);
+
+ if(len > 0)
+ {
+ if(len == DATA_LEN)
+ data[len-1] = 0;
+ else
+ data[len] = 0;
+
+ META_LOG("[Meta][MATCIServerSocket] data len = %d, rawdata = %s", len, data);
+
+ char *pos = strstr(data, msg);
+ if(pos != NULL)
+ {
+ pos += 10; //reply format is +EMETACFG: X, the X is modem mode
+ int mdmode = atoi(pos); //Modem side : meta=0, normal=1
+ if(0 == mdmode)
+ setCurrentMdMode(2); //AP side: normal=1; meta = 2;
+ else if(1 == mdmode)
+ setCurrentMdMode(1);
+
+ continue;
+ }
+
+ pos = strstr(data, msg_ok);
+ if(pos != NULL)
+ {
+ META_LOG("[Meta][MATCIServerSocket] got OK from modem");
+ if(getATRespFlag()==1)
+ {
+ META_LOG("[Meta][MATCIServerSocket] setATRespFlag to 0");
+ setATRespFlag(0);
+ }
+ continue;
+ }
+ setATRespFlag(-1);
+ }
+ else
+ {
+ usleep(100*1000); // wake up every 0.1sec
+ }
+ }
+
+ return;
+}
+
+//////////////////////////////////////////////MLogSocket////////////////////////////////////////////////////
+
+MLogSocket::MLogSocket()
+{
+ m_mdlogpulling = -1;
+ m_mblogpulling = -1;
+ m_connsyslogpulling = -1;
+ m_mddbpulling = -1;
+ m_gpslogpulling = -1;
+ m_Mutex = PTHREAD_MUTEX_INITIALIZER;
+}
+
+MLogSocket::MLogSocket(SOCKET_TYPE type)
+{
+ m_type = type;
+ m_mdlogpulling = -1;
+ m_mblogpulling = -1;
+ m_connsyslogpulling = -1;
+ m_mddbpulling = -1;
+ m_gpslogpulling = -1;
+ m_Mutex = PTHREAD_MUTEX_INITIALIZER;
+}
+
+MLogSocket::~MLogSocket()
+{
+
+}
+
+void MLogSocket::wait_msg()
+{
+ char data[DATA_LEN] = {0};
+ int len = 0;
+
+ META_LOG("[Meta][MLogSocket] wait_msg m_clientID = %d", m_clientID);
+
+ while(m_stop == 0)
+ {
+ memset(data, 0, DATA_LEN);
+ len = read(m_clientID, data, DATA_LEN);
+
+ if(len > 0)
+ {
+ if(len == DATA_LEN)
+ data[len-1] = 0;
+ else
+ data[len] = 0;
+
+ META_LOG("[Meta][MLogSocket] m_clientID = %d, data len = %d, rawdata = (%s), cmd = (%s)", m_clientID, len, data, m_strCmd.c_str());
+
+ if(strstr(data, MDLOG_PULL_START) != NULL)
+ {
+ setLogPullingStatus(0, 1);
+ META_LOG("[Meta][MLogSocket] modem log pull done");
+ }
+ else if(strstr(data, MBLOG_PULL_START) != NULL)
+ {
+ setLogPullingStatus(1, 1);
+ META_LOG("[Meta][MLogSocket] mobile log pull done");
+ }
+ else if(strstr(data, CONNLOG_PULL_START) != NULL)
+ {
+ setLogPullingStatus(3, 1);
+ META_LOG("[Meta][MLogSocket] connsys log pull done");
+ }
+ else if(strstr(data, MDDB_PULL_START) != NULL)
+ {
+ setLogPullingStatus(4, 1);
+ META_LOG("[Meta][MLogSocket] mddb pull done");
+ }
+ else if(strstr(data, GPSLOG_PULL_START) != NULL)
+ {
+ setLogPullingStatus(5, 1);
+ META_LOG("[Meta][MLogSocket] gps log pull done");
+ }
+
+ if(m_strCmd.size() > 1)
+ {
+ if(strstr(data, m_strCmd.c_str()) != NULL)
+ {
+ pthread_mutex_lock(&m_Mutex);
+ m_strRsp = string(data);
+ m_strCmd = "";
+ META_LOG("[Meta][MLogSocket] wait_msg response = (%s)", m_strRsp.c_str());
+ pthread_mutex_unlock(&m_Mutex);
+ }
+ }
+ }
+ else
+ {
+ usleep(100000); // wake up every 0.1sec
+ }
+ }
+ return;
+}
+
+int MLogSocket::recv_rsp(char *buf)
+{
+ META_LOG("[Meta][MLogSocket] recv_rsp begin");
+ int count = 0;
+ while(1)
+ {
+ pthread_mutex_lock(&m_Mutex);
+ if(m_strRsp.length() > 0)
+ {
+ string strRsp = m_strRsp.erase(0, m_strRsp.find_last_of(',')+1);
+ if(strRsp.length() > 0)
+ strncpy(buf, strRsp.c_str(), strRsp.length());
+ META_LOG("[Meta][MLogSocket] recv_rsp response = (%s)", buf);
+ m_strRsp = "";
+ pthread_mutex_unlock(&m_Mutex);
+ return true;
+ }
+ pthread_mutex_unlock(&m_Mutex);
+ usleep(100000);
+ if (++count == 45)
+ {
+ pthread_mutex_lock(&m_Mutex);
+ META_LOG("[Meta][MLogSocket] recv_rsp end-false");
+ m_strCmd = "";
+ pthread_mutex_unlock(&m_Mutex);
+ return false;
+ }
+ }
+
+ META_LOG("[Meta][MLogSocket] recv_rsp end-true");
+ return true;
+}
+
+
+void MLogSocket::send_msg(const char *msg, bool ignore)
+{
+ int nWritten = 0;
+
+ if(msg==NULL)
+ return;
+
+ META_LOG("[Meta][MLogSocket] send mssage (%s) - socket id = %d", msg, m_clientID);
+
+ if(ignore == false)
+ {
+ pthread_mutex_lock(&m_Mutex);
+ m_strCmd = string(msg);
+ pthread_mutex_unlock(&m_Mutex);
+ }
+
+ if((nWritten = write(m_clientID, msg, strlen(msg))) < 0)
+ {
+ m_strCmd = "";
+ META_LOG("[Meta][MLogSocket] socket write error: %s", strerror(errno));
+ }
+ else
+ {
+ META_LOG("[Meta][MLogSocket] write %d Bytes, total = %zd", nWritten, strlen(msg));
+ }
+}
+
+int MLogSocket::getLogPullingStatus(int type)
+{
+ int status = -1;
+ switch(type)
+ {
+ case 0:
+ status = m_mdlogpulling;
+ break;
+ case 1:
+ status = m_mblogpulling;
+ break;
+ case 3:
+ status = m_connsyslogpulling;
+ break;
+ case 4:
+ status = m_mddbpulling;
+ break;
+ case 5:
+ status = m_gpslogpulling;
+ break;
+ default:
+ break;
+ }
+
+ return status;
+}
+
+void MLogSocket::setLogPullingStatus(int type, int value)
+{
+ pthread_mutex_lock(&m_Mutex);
+
+ switch(type)
+ {
+ case 0:
+ m_mdlogpulling = value;
+ break;
+ case 1:
+ m_mblogpulling = value;
+ break;
+ case 3:
+ m_connsyslogpulling = value;
+ break;
+ case 4:
+ m_mddbpulling = value;
+ break;
+ case 5:
+ m_gpslogpulling = value;
+ break;
+ default:
+ break;
+ }
+
+ pthread_mutex_unlock(&m_Mutex);
+}
+
+
+//////////////////////////////////////////////MATMSocket////////////////////////////////////////////////////
+
+MATMSocket::MATMSocket()
+{
+
+}
+
+MATMSocket::MATMSocket(SOCKET_TYPE type)
+{
+ m_type = type;
+}
+
+MATMSocket::~MATMSocket()
+{
+
+}
+
+void MATMSocket::wait_msg()
+{
+ const char *msg = "ATM";
+ char data[DATA_LEN] = {0};
+ int len = 0;
+
+ META_LOG("[Meta][MATMSocket] wait_msg m_clientID = %d", m_clientID);
+
+ while(m_stop == 0)
+ {
+ memset(data, 0, DATA_LEN);
+ len = read(m_clientID, data, DATA_LEN);
+
+ if(len > 0)
+ {
+ if(len == DATA_LEN)
+ data[len-1] = 0;
+ else
+ data[len] = 0;
+
+ META_LOG("[Meta][MATMSocket] data len = %d, rawdata = %s", len, data);
+ char *pos = strstr(data, msg);
+ if(pos != NULL)
+ {
+ HandleSocketCmd(data);
+ continue;
+ }
+ }
+ else
+ {
+ usleep(100*1000); // wake up every 0.1sec
+ }
+ }
+ return;
+}
+
+
+
+
diff --git a/src/devtools/meta/src/common/src/MdRxWatcher.cpp b/src/devtools/meta/src/common/src/MdRxWatcher.cpp
new file mode 100644
index 0000000..82767cc
--- /dev/null
+++ b/src/devtools/meta/src/common/src/MdRxWatcher.cpp
@@ -0,0 +1,336 @@
+#include <assert.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+
+
+#include <string.h>
+#include "SerPort.h"
+#include "LogDefine.h"
+#include "MdRxWatcher.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "FtModule.h"
+#include "snappy-c.h"
+
+MdRxWatcher::MdRxWatcher(int index)
+{
+ m_bufLen = 0;
+ m_frmStat = 0;
+ m_frmStat0 = 0;
+ m_chkSum = 0;
+ m_frmLen = 0;
+ m_bL1Header = 0;
+ nModemIndex = index;
+
+ m_recv_buf = (TST_MD_RECV_BUF *)malloc(sizeof(TST_MD_RECV_BUF));
+}
+
+MdRxWatcher::~MdRxWatcher(void)
+{
+ if(m_recv_buf != NULL)
+ {
+ free(m_recv_buf);
+ m_recv_buf = NULL;
+ }
+}
+
+signed int MdRxWatcher::onReceived(
+ unsigned char *buf,
+ unsigned int len)
+{
+ META_LOG("[Meta] Receive data from modem[%d], len = %d", nModemIndex, len);
+ if(getMDMode()==1)//normal mode
+ {
+ SerPort *pPort = getSerPort();
+ if(NULL == pPort || 1 == getNormalModeTestFlag()) return 0; //Discard this packet if pPort is NULL or in ATM mode
+ signed int cbWriten = 0;
+ cbWriten= pPort->write(buf, len);
+ META_LOG("[Meta] Write data by USB. data len = %d, write done = %d", len, cbWriten);
+ dumpDataInHexString(buf,len,16);
+ }
+ else
+ {
+ dumpDataInHexString(buf,len,16);
+ int mdType = getMDChType(nModemIndex);
+ if ( mdType == FT_MODEM_CH_TUNNELING ||
+ mdType == FT_MODEM_CH_TUNNELING_IGNORE_CKSM )
+ {
+ processTunnelData(buf, len);
+ }
+ else
+ {
+ process(buf, len);
+ }
+ }
+ return 0;
+}
+
+int MdRxWatcher:: fillDataToTSTBufferReverse(unsigned char data, char **buffer_ptr)
+{
+ if (data == 0x5A) {
+ *(*buffer_ptr)-- = 0x5A;
+ *(*buffer_ptr)-- = 0x5A;
+ return 2;
+ } else if (data == 0xA5) {
+ *(*buffer_ptr)-- = 0x01;
+ *(*buffer_ptr)-- = 0x5A;
+ return 2;
+ }
+
+ *(*buffer_ptr)-- = data;
+ return 1;
+}
+
+int MdRxWatcher::fillDataToTSTBuffer(unsigned char data, char **buffer_ptr)
+{
+ if (data == 0x5A) {
+ *(*buffer_ptr)++ = 0x5A;
+ *(*buffer_ptr)++ = 0x5A;
+ return 2;
+ } else if (data == 0xA5) {
+ *(*buffer_ptr)++ = 0x5A;
+ *(*buffer_ptr)++ = 0x01;
+ return 2;
+ }
+
+ *(*buffer_ptr)++ = data;
+ return 1;
+}
+
+void MdRxWatcher::processTunnelData(unsigned char *pdata, unsigned int len)
+{
+ //META_LOG("[Meta] processTunnelData, len = %d", len);
+ int md_rsp_type = RS232_RESPONSE_MD_DATA_TUNNEL_START;
+ char *buf_begin = NULL;
+ char *p = NULL;
+ if(m_recv_buf == NULL)
+ {
+ META_LOG("[Meta] failed to malloc buf in processTunnelData");
+ return;
+ }
+
+ memset(m_recv_buf, 0, sizeof(TST_MD_RECV_BUF));
+ memcpy(m_recv_buf->data, pdata, len);
+ m_recv_buf->data_len = len;
+
+ // create tunneling header
+ // TST spec: For confirm message, the length of frame content includes data and message type (1 byte).
+ // See TST spec for detail
+ unsigned int length_in_tunnel_resp = m_recv_buf->data_len + 1;
+ // Write the TST header in RESERSE ORDER, please note that buffer space must preseve enough spacing for possibile escaping translation
+ buf_begin = (char *)m_recv_buf->data-1;
+ fillDataToTSTBufferReverse((md_rsp_type + nModemIndex), &buf_begin);
+ fillDataToTSTBufferReverse((length_in_tunnel_resp & 0xff), &buf_begin);
+ fillDataToTSTBufferReverse((length_in_tunnel_resp >> 8), &buf_begin);
+ *(buf_begin) = 0x55;
+
+ // calculate checksum if needed, otherwise the checksum field is 0xff
+ char cksm_byte = 0xff;
+ char *recv_buf_end = m_recv_buf->data + m_recv_buf->data_len;
+
+ if (getMDChType(nModemIndex) == FT_MODEM_CH_TUNNELING)
+ {
+ cksm_byte = (md_rsp_type+nModemIndex);
+ cksm_byte ^=(length_in_tunnel_resp & 0xff);
+ cksm_byte ^=(length_in_tunnel_resp >> 8);
+ cksm_byte ^= 0x55;
+
+ for(p = (char *)m_recv_buf->data; p < recv_buf_end; p++) {
+ cksm_byte ^= *p;
+ }
+ }
+
+ fillDataToTSTBuffer(cksm_byte, &recv_buf_end);
+
+ processMDConfirm(buf_begin, recv_buf_end - buf_begin);
+
+}
+
+
+void MdRxWatcher::processMDConfirm(char *pdata, unsigned short len)
+{
+ //META_LOG("[Meta] processMDConfirm, len = %d", len);
+ signed int cbWriten = 0;
+
+ SerPort *pPort = getSerPort();
+ if(NULL == pPort) return; //Discard this packet because it is during port switching process, and pPort is NULL
+
+ /*
+ so we use 0x77 and 0x01 indicate 0x11,
+ use 0x77 and 0x03 indicate 0x77,
+ use 0x77 and 0x13 indicate 0x13
+ the escape is just for compatible with feature phone
+ */
+
+ META_COM_TYPE eComType = getComType();
+ if(eComType == META_USB_COM || eComType == META_PCIE_COM )
+ {
+ cbWriten = pPort->write((unsigned char *)pdata, len);
+ //META_LOG("[Meta] write data by USB. data len = %d, write done = %d", len, cbWriten);
+ dumpDataInHexString((unsigned char *)pdata,len,16);
+ return;
+ }
+}
+
+void MdRxWatcher::process(const unsigned char *buf, unsigned int len)
+{
+ unsigned char ch=0;
+ unsigned short u16Length=0;
+ const unsigned char *src=buf;
+
+ while (u16Length < len)
+ {
+ ch = *src;
+ m_frmBuf[m_bufLen] = ch;
+
+ ++ u16Length;
+ ++ m_bufLen;
+
+ if ((ch == STX_OCTET || ch == STX_L1HEADER ) &&
+ (m_frmStat != RS232_FRAME_MD_CONFIRM_DATA) &&
+ (m_frmStat != RS232_FRAME_LENHI) &&
+ (m_frmStat != RS232_FRAME_LENLO) )
+ {
+ if(ch == STX_L1HEADER)
+ m_bL1Header = true;
+ else
+ m_bL1Header = false;
+
+ if ( m_frmStat != RS232_FRAME_CHECKSUM)
+ {
+ m_frmStat = RS232_FRAME_LENHI;
+ META_LOG("[Meta] Flag change to RS232_FRAME_LENHI");
+ ++ src;
+ m_chkSum = ch;
+ ch = *src;
+ m_frmLen = 0;
+ continue;
+ }
+ }
+ else
+ {
+ if ((!m_bL1Header) &&
+ (*src == MUX_KEY_WORD ) &&
+ (m_frmStat != RS232_FRAME_KEYWORD))
+ { // enter MUX state(0x5A) and save the old
+
+ m_frmStat0 = m_frmStat;
+ m_frmStat = RS232_FRAME_KEYWORD;
+
+ ++ src;
+
+ continue;
+ }
+ else if(m_frmStat == RS232_FRAME_KEYWORD)
+ {
+ if (*src== MUX_KEY_WORD)
+ ch = MUX_KEY_WORD;
+ else if (*src == 0x01)
+ ch=STX_L1HEADER; //0xA5 escaping
+
+ //leave MUX state and restore the state
+ m_frmStat = m_frmStat0;
+ ++ m_frmLen;
+ }
+ }
+
+ switch (m_frmStat)
+ {
+ /*the state is RS232_FRAME_LENHI*/
+ case RS232_FRAME_LENHI:
+ if(m_bL1Header)
+ m_frmLen = ch;
+ else
+ m_frmLen = ch << 8;
+ m_frmStat = RS232_FRAME_LENLO;
+ break;
+
+ /*the state is RS232_FRAME_LENLO*/
+ case RS232_FRAME_LENLO:
+ if(m_bL1Header)
+ m_frmLen += (ch << 8);
+ else
+ m_frmLen += ch;
+ if ((m_frmLen +4) > FRAME_MAX_LEN)
+ {
+ m_frmStat = RS232_FRAME_STX;
+ META_LOG("[Meta] frame too long: %d+4 > %d.",
+ m_frmLen, FRAME_MAX_LEN);
+ return;
+ }
+ else
+ {
+ m_frmStat = RS232_FRAME_MD_CONFIRM_DATA;
+ }
+ break;
+
+ case RS232_FRAME_MD_CONFIRM_DATA:
+ if (m_bufLen == m_frmLen+3)
+ {
+ m_frmStat = RS232_FRAME_CHECKSUM;
+ }
+
+ break;
+
+
+ case RS232_FRAME_CHECKSUM:
+ m_frmStat = RS232_FRAME_STX;
+
+ if (m_chkSum == ch)
+ {
+ processMDConfirm((char*)m_frmBuf, m_frmLen+4);
+
+ buf = src;
+ m_bufLen = 0;
+ m_frmLen = 0;
+ m_chkSum = 0;
+ }
+ else
+ {
+ META_LOG("[Meta] CheckSum error: %d != %d",
+ (signed int)m_chkSum, (signed int)ch);
+ }
+ break;
+ case RS232_FRAME_STX:
+ m_bufLen = 0;
+ m_frmLen = 0;
+ m_chkSum = ch;
+ break;
+ default:
+ /* exception of g_cTstFrameState */
+ break;
+
+ }
+ m_chkSum ^= ch;
+ ++ src;
+ }
+
+
+}
+bool MdRxWatcher::compress(char *pdata, unsigned short len, char *compressed, size_t *compressed_len)
+{
+ META_LOG("[Meta] META Confirm. compress starts\n");
+
+ char *pTempBuf = (char*) pdata;
+ // Ask for the max size of the compressed object.
+ size_t max_compressed_len = snappy_max_compressed_length(len);
+ if (*compressed_len < max_compressed_len)
+ {
+ // to modify
+ //META_LOG("[Meta] error: snappy compression buffer is not enough. buffer size: %d, max compression len: %d\n", *compressed_len, max_compressed_len);
+ return false;
+ }
+
+ META_LOG("[Meta] snappy compress starts. len: %d\n", len);
+ snappy_status status = snappy_compress(pTempBuf, len, compressed, (size_t *)compressed_len);
+ if (status != SNAPPY_OK)
+ {
+ META_LOG("[Meta] Compression failed. status: %d\n", status);
+ return false;
+ }
+ // to modify
+ //META_LOG("[Meta] snappy compress done. comp_len: %d\n", *compressed_len);
+
+ return true;
+}
diff --git a/src/devtools/meta/src/common/src/Meta_mipc.cpp b/src/devtools/meta/src/common/src/Meta_mipc.cpp
new file mode 100644
index 0000000..1ce842f
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Meta_mipc.cpp
@@ -0,0 +1,90 @@
+#include <pthread.h>
+
+#include "Meta_mipc.h"
+#include "LogDefine.h"
+
+
+#include "mipc_msg_host.h"
+#include "mipc_msg_tlv_const.h"
+//#include "mipc_msg_tlv_api.h"
+
+MetaMIPC::MetaMIPC()
+{
+ m_bReady = false;
+}
+
+MetaMIPC::~MetaMIPC(void)
+{
+ mipc_deinit();
+}
+
+
+static void atcid_mipc_ind_cb(mipc_msg_t *msg_ptr, void *priv_ptr)
+{
+ MetaMIPC *pData = (MetaMIPC*)priv_ptr;
+
+ const char *urc = "+EIND: 128";
+ char *urc_ptr = NULL;
+ uint16_t urc_len;
+
+ urc_ptr = (char *)mipc_msg_get_val_ptr(msg_ptr, MIPC_SYS_AT_IND_T_ATCMD, &urc_len);
+
+ META_LOG("[Meta] read URC: len= %d, %s", urc_len, urc_ptr);
+
+ if( NULL != strstr(urc_ptr, urc))
+ {
+ if(pData != NULL)
+ pData->SetModemReady(true);
+ }
+}
+
+
+void MetaMIPC::Init()
+{
+ int ret =mipc_init("meta_tst");
+ META_LOG("[Meta] [MIPC] mipc_init result = %d", ret);
+
+ mipc_msg_register_ind((mipc_msg_sim_ps_id_enum)MIPC_SYS_SIM_PS_PS0, MIPC_SYS_AT_IND, (void*)atcid_mipc_ind_cb, this);
+}
+
+bool MetaMIPC::Send_at_cmd(const char* cmd, char *res)
+{
+ mipc_msg_t *msg_req_ptr = NULL;
+ mipc_msg_t *msg_cnf_ptr = NULL;
+ mipc_result_enum result;
+ char *atcmd_res_ptr = NULL;
+ uint16_t atcmd_res_len = 0;
+
+ msg_req_ptr = mipc_msg_init(MIPC_SYS_AT_REQ, (mipc_msg_sim_ps_id_enum)MIPC_SYS_SIM_PS_PS0);
+ if(msg_req_ptr != NULL)
+ {
+
+ mipc_msg_add_tlv(msg_req_ptr, MIPC_SYS_AT_REQ_T_ATCMD, strlen(cmd), cmd);
+
+ msg_cnf_ptr = mipc_msg_sync(msg_req_ptr);
+ if(msg_cnf_ptr == NULL )
+ {
+ META_LOG("[Meta] [MIPC] mipc_msg_sync failed");
+ return false;
+ }
+ META_LOG("[Meta] [MIPC] Send AT command [%s] with len:[%zd]", cmd, strlen(cmd));
+
+ mipc_msg_deinit(msg_req_ptr);
+ }
+ else
+ {
+ META_LOG("[Meta] [MIPC] mipc_msg_init failed");
+ return false;
+ }
+
+ atcmd_res_ptr = (char *)mipc_msg_get_val_ptr(msg_cnf_ptr, MIPC_SYS_AT_CNF_T_ATCMD, &atcmd_res_len);
+ atcmd_res_ptr[atcmd_res_len] = '\0';
+ META_LOG("[Meta] [MIPC] AT response:[%s] with len:[%d]", atcmd_res_ptr, atcmd_res_len);
+ strcpy(res, atcmd_res_ptr);
+ res[atcmd_res_len] = '\0';
+
+ mipc_msg_deinit(msg_cnf_ptr);
+ return true;
+
+}
+
diff --git a/src/devtools/meta/src/common/src/Modem.cpp b/src/devtools/meta/src/common/src/Modem.cpp
new file mode 100644
index 0000000..5bac286
--- /dev/null
+++ b/src/devtools/meta/src/common/src/Modem.cpp
@@ -0,0 +1,58 @@
+#include "Modem.h"
+#include "Device.h"
+#include "LogDefine.h"
+
+Modem::Modem(const char *ccci, unsigned short id)
+ : CmdTarget(id), m_pDev(new CCCI(ccci))
+{
+}
+
+Modem::Modem(unsigned short id)
+ : CmdTarget(id), m_pDev(new CCB())
+{
+
+}
+Modem::~Modem(void)
+{
+ m_pDev->close();
+ META_LOG("[Meta] Delete Modem");
+ delete m_pDev;
+}
+
+signed int Modem::pumpAsync(IDevWatcher *p)
+{
+ return m_pDev->pumpAsync(p);
+}
+
+void Modem::popUpAsync()
+{
+ m_pDev->setExitFlag(1);
+}
+
+
+void Modem::exec(Frame *pFrm)
+{
+ CmdTarget::exec(pFrm);
+ m_pDev->write(pFrm->localBuf(), pFrm->localLen());
+}
+
+void Modem::exec(const unsigned char *p, unsigned int len )
+{
+ m_pDev->write(p,len);
+}
+
+signed int Modem::getDevHandle()
+{
+ return m_pDev->getDevHandle();
+}
+
+int Modem::init(Frame*)
+{
+ return 1;
+}
+
+
+void Modem::deinit()
+{
+}
+
diff --git a/src/devtools/meta/src/common/src/PortHandle.cpp b/src/devtools/meta/src/common/src/PortHandle.cpp
new file mode 100644
index 0000000..6e51ad1
--- /dev/null
+++ b/src/devtools/meta/src/common/src/PortHandle.cpp
@@ -0,0 +1,508 @@
+#include <assert.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <string.h>
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#endif
+#include <dirent.h>
+#include <sys/poll.h>
+#include <linux/input.h>
+#include <unistd.h>
+#include "PortHandle.h"
+#include "PortInterface.h"
+#include "LogDefine.h"
+#include "SerPort.h"
+#include "Context.h"
+
+#ifdef MTK_META_DIPC
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "dipc_intf.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
+
+#if defined(MTK_META_APONLY)
+ #define DEV_USB_PATH "/dev/ttyGS0"
+#else
+ #define DEV_USB_PATH "/dev/ttyGS0"
+#endif
+
+#define DEV_PCIE_PATH "/dev/ccci_hsapif_meta"
+
+
+#define COM_PORT_TYPE_FILE "/sys/bus/platform/drivers/meta_com_type_info/meta_com_type_info"
+#define COM_PORT_TYPE_STR_LEN 1
+
+#define UART_PORT_INFO_FILE "/sys/bus/platform/drivers/meta_uart_port_info/meta_uart_port_info"
+#define UART_PORT_INFO_STR_LEN 1
+
+#define MAX_DEVICES 32
+#define MAX_LENGTH 1024
+
+
+class PortHandle
+{
+private:
+ PortHandle(void);
+public:
+ ~PortHandle(void);
+
+ static PortHandle *instance();
+ SerPort * createPort();
+ void destroyPort();
+ SerPort * getPort() const;
+ META_COM_TYPE getComType();
+ void setComType(META_COM_TYPE comType);
+ void querySerPortStatus();
+ void FTMuxPrimitiveData(META_RX_DATA *pMuxBuf);
+ int WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len);
+ int getMetaUartPort(void);
+ void destroy();
+ void usbMutexLock(bool bLock);
+
+ META_COM_TYPE getDualIPCType();
+
+private:
+ META_COM_TYPE m_comType;
+ SerPort * m_serPort;
+private:
+ static PortHandle * m_myInst;
+
+ unsigned int ev_count;
+ unsigned int ev_touch;
+ struct pollfd ev_fds[MAX_DEVICES];
+ pthread_mutex_t m_usbMutex;
+
+};
+
+PortHandle *PortHandle::m_myInst = NULL;
+
+PortHandle::PortHandle(void)
+ : m_comType(META_UNKNOWN_COM),
+ m_serPort(NULL)
+{
+ ev_count = 0;
+ ev_touch = 0;
+ memset(&ev_fds, 0, sizeof(pollfd)*MAX_DEVICES);
+ m_usbMutex = PTHREAD_MUTEX_INITIALIZER;
+}
+
+PortHandle::~PortHandle(void)
+{
+ if (m_serPort != NULL)
+ {
+ delete m_serPort;
+ m_serPort = NULL;
+ }
+}
+
+
+PortHandle *PortHandle::instance()
+{
+ return (m_myInst==NULL) ? ((m_myInst=new PortHandle)) : m_myInst;
+}
+
+void PortHandle::destroy()
+{
+ delete m_myInst;
+ m_myInst = NULL;
+}
+
+void PortHandle::destroyPort()
+{
+ if(m_serPort != NULL)
+ {
+ delete m_serPort;
+ m_serPort = NULL;
+ }
+}
+
+SerPort * PortHandle::createPort()
+{
+#if (defined(MTK_META_DIPC) && defined(MTK_META_APONLY))
+ META_COM_TYPE eComType = getDualIPCType();
+
+#else
+ META_COM_TYPE eComType = META_USB_COM;
+#endif
+
+ if(eComType == META_USB_COM)
+ {
+ m_serPort = new UsbPort(DEV_USB_PATH);
+ }
+ else if(eComType == META_PCIE_COM)
+ {
+ m_serPort = new UsbPort(DEV_PCIE_PATH);
+ }
+
+ setComType(eComType);
+
+ return m_serPort;
+}
+
+SerPort * PortHandle::getPort() const
+{
+ return m_serPort;
+}
+
+static int getBootMode_local()
+{
+ int bootMode;
+
+ bootMode = readSys_int(BOOTMODE_PATH);
+
+ if(NORMAL_BOOT== bootMode)
+ {
+ META_LOG("[Meta] Normal mode boot!");
+ }
+ else if(META_BOOT== bootMode)
+ {
+ META_LOG("[Meta] Meta mode boot!");
+ }
+ else
+ {
+ META_LOG("[Meta] Not Support boot mode! BootMode=%d",bootMode);
+ bootMode = -1;
+ }
+ return bootMode;
+}
+
+void PortHandle::setComType(META_COM_TYPE comType)
+{
+ META_LOG("[META] setComType %d",comType);
+ m_comType = comType;
+}
+
+META_COM_TYPE PortHandle::getDualIPCType()
+{
+ META_COM_TYPE type = META_USB_COM;
+#ifdef MTK_META_DIPC
+ dipc_user_init();
+
+ dipc_mode mode = query_dipc_mode();
+ META_LOG("[META] get dipc mode. PCIe_ADV:1, PCIe_ONLY:2, DUAL_IPC:3, mode = %d", mode);
+
+ port_interface interface = query_ap_port_interface(AP_PORT_META);
+ META_LOG("[META] get port interface. usb:1, PCIe:2, interface = %d", interface);
+
+ if((interface == INTF_PCIE) || (interface == INTF_USB_AND_PCIE))
+ {
+ port_status status = query_ap_pcie_port_status(AP_PORT_META);
+ META_LOG("[META] get port status. Enable:2, Disable:1, status = %d", status);
+ if(status == PORT_ENABLE)
+ type = META_PCIE_COM;
+ }
+#endif
+ return type;
+}
+
+META_COM_TYPE PortHandle::getComType()
+{
+ if (m_comType == META_UNKNOWN_COM)
+ {
+#if (defined(MTK_META_DIPC) && defined(MTK_META_APONLY))
+ m_comType = getDualIPCType();
+
+#else
+ m_comType = META_USB_COM;
+#endif
+ META_LOG("[Meta] com port type: %d", m_comType);
+ }
+
+ return m_comType;
+}
+
+
+void PortHandle::querySerPortStatus()
+{
+ usbMutexLock(true);
+ if (m_comType == META_USB_COM)
+ {
+ SerPort * pPort = getSerPort();
+ if (pPort != NULL)
+ {
+ pPort->update();
+ }
+ }
+
+ usbMutexLock(false);
+}
+
+int PortHandle::getMetaUartPort(void)
+{
+ int nPort = 1;
+ if (m_comType == META_UART_COM)
+ {
+ char buf[UART_PORT_INFO_STR_LEN + 1] = {0};
+ int fd = open(UART_PORT_INFO_FILE, O_RDONLY);
+ if (fd != -1)
+ {
+ if (read(fd, buf, sizeof(char)*COM_PORT_TYPE_STR_LEN) <= 0)
+ {
+ META_LOG("[Meta] ERROR can not read meta uart port ");
+ }
+ else
+ {
+ nPort = atoi(buf);
+ }
+ close(fd);
+
+ }
+ else
+ {
+ META_LOG("[Meta] Failed to open meta uart port file %s", UART_PORT_INFO_FILE);
+ }
+ META_LOG("[Meta] uart com port: %d", nPort);
+ }
+ else
+ {
+ META_LOG("[Meta] com port type is not uart");
+ }
+ return nPort;
+}
+
+void PortHandle::FTMuxPrimitiveData(META_RX_DATA *pMuxBuf)
+{
+ /* This primitive is logged by TST */
+ unsigned char *pTempBuf = NULL;
+ unsigned char *pTempDstBuf = NULL;
+ unsigned char *pMamptrBase = NULL;
+ unsigned char *pDestptrBase = NULL;
+ int iCheckNum = 0;
+ int dest_index=0;
+ unsigned char cCheckSum = 0;
+ int cbWriten = 0;
+ int cbTxBuffer = 0;
+ SerPort * pPort = getSerPort();
+
+ if(pMuxBuf == NULL)
+ {
+ META_LOG("[Meta] (FTMuxPrimitiveData) Err: pMuxBuf is NULL");
+ return;
+ }
+
+ cbTxBuffer = pMuxBuf->LocalLen + pMuxBuf->PeerLen + 9;
+ if (cbTxBuffer>FRAME_MAX_LEN)
+ {
+ META_LOG("[Meta] (FTMuxPrimitiveData) error frame size is too big!! ");
+ return;
+ }
+ else
+ META_LOG("[Meta] (FTMuxPrimitiveData) Type = %d Local_len = %d, Peer_len = %d", pMuxBuf->eFrameType, pMuxBuf->LocalLen, pMuxBuf->PeerLen);
+
+ //META_LOG("[Meta] (FTMuxPrimitiveData) total size = %d", cbTxBuffer);
+ pMamptrBase = (unsigned char *)malloc(cbTxBuffer);
+
+ if(pMamptrBase == NULL)
+ {
+ META_LOG("[Meta] (FTMuxPrimitiveData) Err: malloc pMamptrBase Fail");
+ return;
+ }
+ pDestptrBase = (unsigned char *)malloc(FRAME_MAX_LEN);
+ if(pDestptrBase == NULL)
+ {
+ META_LOG("[Meta] (FTMuxPrimitiveData) Err: malloc pDestptrBase Fail");
+ free(pMamptrBase);
+ return;
+ }
+
+
+ pTempDstBuf = pDestptrBase;
+ pTempBuf = pMamptrBase;
+
+ /* fill the frameheader */
+ *pTempBuf++ = 0x55;
+ *pTempBuf++=((pMuxBuf->LocalLen + pMuxBuf->PeerLen +5)&0xff00)>>8;
+ *pTempBuf++= (pMuxBuf->LocalLen + pMuxBuf->PeerLen +5)&0xff;
+ *pTempBuf++ = 0x60;
+
+ /*fill the local and peer data u16Length and its data */
+ *pTempBuf++ = ((pMuxBuf->LocalLen)&0xff); /// pMuxBuf->LocalLen ;
+ *pTempBuf++ = ((pMuxBuf->LocalLen)&0xff00)>>8;
+ *pTempBuf++ = (pMuxBuf->PeerLen )&0xff; ///pMuxBuf->PeerLen ;
+ *pTempBuf++ = ((pMuxBuf->PeerLen)&0xff00)>>8;
+
+ memcpy((pTempBuf), pMuxBuf->pData, pMuxBuf->LocalLen + pMuxBuf->PeerLen);
+
+ pTempBuf = pMamptrBase;
+
+ /* 0x5a is start data, so we use 0x5a and 0x01 inidcate 0xa5, use 0x5a and 0x5a indicate 0x5a
+ the escape is just for campatiable with feature phone */
+ while (iCheckNum != (cbTxBuffer-1))
+ {
+ cCheckSum ^= *pTempBuf;
+ *pTempDstBuf = *pTempBuf;
+ iCheckNum++;
+
+ if (*pTempBuf ==0xA5 )
+ {
+ *pTempDstBuf++ = 0x5A;
+ *pTempDstBuf++ = 0x01;
+ dest_index++; //do the escape, dest_index should add for write to uart or usb
+ }
+ else if (*pTempBuf ==0x5A )
+ {
+ *pTempDstBuf++ = 0x5A;
+ *pTempDstBuf++ = 0x5A;
+ dest_index++; //do the escape, dest_index should add for write to uart or usb
+ }
+ else
+ pTempDstBuf++;
+
+ dest_index++;
+ pTempBuf++;
+ }
+
+ /* 0x5a is start data, so we use 0x5a and 0x01 inidcate 0xa5 for check sum, use 0x5a and 0x5a indicate 0x5a
+ the escape is just for campatiable with feature phone */
+ if ( cCheckSum ==0xA5 )
+ {
+ dest_index++; //do the escape, dest_index should add for write to uart or usb
+ //Wayne replace 2048 with MAX_TST_RECEIVE_BUFFER_LENGTH
+ if ((dest_index) > FRAME_MAX_LEN)//2048)
+ {
+ META_LOG("[Meta] (FTMuxPrimitiveData) Data is too big: index = %d cbTxBuffer = %d ",dest_index, cbTxBuffer);
+ goto TSTMuxError;
+ }
+
+ *pTempDstBuf++= 0x5A;
+ *pTempDstBuf = 0x01;
+ }
+ else if ( cCheckSum ==0x5A )
+ {
+ dest_index++; //do the escape, dest_index should add for write to uart or usb
+ if ((dest_index) > FRAME_MAX_LEN)
+ {
+ META_LOG("[Meta] (FTMuxPrimitiveData) Data is too big: index = %d cbTxBuffer = %d ",dest_index, cbTxBuffer);
+ goto TSTMuxError;
+ }
+ *pTempDstBuf++= 0x5A;
+ *pTempDstBuf = 0x5A;
+ }
+ else
+ *pTempDstBuf =(char )cCheckSum;
+
+ dest_index++;
+
+ //write to PC
+ //cbWriten = write(getPort(), (void *)pDestptrBase, dest_index);
+
+ pPort->write(pDestptrBase, dest_index);
+ pTempDstBuf = pDestptrBase;
+
+ META_LOG("[Meta] FTMuxPrimitiveData: %d %d %d cChecksum: %d ",cbWriten, cbTxBuffer, dest_index,cCheckSum);
+
+ TSTMuxError:
+
+ free(pMamptrBase);
+ free(pDestptrBase);
+}
+
+
+int PortHandle::WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len)
+{
+ META_RX_DATA metaRxData;
+ memset(&metaRxData,0, sizeof(META_RX_DATA));
+ unsigned int dataLen = Local_len+Peer_len+8+1;
+ unsigned char *metaRxbuf = (unsigned char *)malloc(dataLen);
+ if(metaRxbuf==NULL)
+ {
+ return 0;
+ }
+ memset(metaRxbuf,0, dataLen);
+ unsigned char *cPeerbuf = &metaRxbuf[Local_len+8];
+
+ metaRxData.eFrameType = AP_FRAME;
+ metaRxData.pData = metaRxbuf;
+ metaRxData.LocalLen = Local_len;
+ metaRxData.PeerLen = Peer_len >0 ? Peer_len+8 : Peer_len;
+
+ if (((Local_len + Peer_len)> FT_MAX_LEN)||(Peer_len >PEER_BUF_MAX_LEN))
+ {
+ META_LOG("[Meta] (WriteDataToPC) Err: Local_len = %hu, Peer_len = %hu", Local_len,Peer_len);
+ free(metaRxbuf);
+ metaRxbuf = NULL;
+ return 0;
+ }
+
+ if ((Local_len == 0) && (Local_buf == NULL))
+ {
+ META_LOG("[Meta] (WriteDataToPC) Err: Local_len = %hu, Peer_len = %hu", Local_len,Peer_len);
+ free(metaRxbuf);
+ metaRxbuf = NULL;
+ return 0;
+ }
+
+ // copy to the temp buffer, and send it to the tst task.
+ memcpy(metaRxbuf, Local_buf, Local_len);
+ if ((Peer_len >0)&&(Peer_buf !=NULL))
+ memcpy(cPeerbuf, Peer_buf, Peer_len);
+
+ FTMuxPrimitiveData(&metaRxData);
+ free(metaRxbuf);
+ metaRxbuf = NULL;
+ return 1;
+}
+
+void PortHandle::usbMutexLock(bool bLock)
+{
+ if(bLock)
+ pthread_mutex_lock(&m_usbMutex);
+ else
+ pthread_mutex_unlock(&m_usbMutex);
+}
+/////////////////////////////////////////////////////////////////////////////////
+
+void destroyPortHandle()
+{
+ return PortHandle::instance()->destroy();
+}
+
+META_COM_TYPE getComType()
+{
+ return PortHandle::instance()->getComType();
+}
+
+SerPort * createSerPort()
+{
+ return PortHandle::instance()->createPort();
+}
+
+void destroySerPort()
+{
+ return PortHandle::instance()->destroyPort();
+}
+
+SerPort * getSerPort()
+{
+ return PortHandle::instance()->getPort();
+}
+
+void querySerPortStatus()
+{
+ return PortHandle::instance()->querySerPortStatus();
+}
+
+int WriteDataToPC(void *Local_buf,unsigned short Local_len,void *Peer_buf,unsigned short Peer_len)
+{
+ return PortHandle::instance()->WriteDataToPC(Local_buf,Local_len,Peer_buf,Peer_len);
+}
+
+void setComType(META_COM_TYPE comType)
+{
+ return PortHandle::instance()->setComType(comType);
+}
+
+void usbMutexLock(bool bLock)
+{
+ return PortHandle::instance()->usbMutexLock(bLock);
+}
+
+
diff --git a/src/devtools/meta/src/common/src/SerPort.cpp b/src/devtools/meta/src/common/src/SerPort.cpp
new file mode 100644
index 0000000..eaf952f
--- /dev/null
+++ b/src/devtools/meta/src/common/src/SerPort.cpp
@@ -0,0 +1,856 @@
+#include <stdlib.h>
+#include <unistd.h>
+#include <termios.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+extern "C" {
+#include "hardware/ccci_intf.h"
+}
+#endif
+
+#include <sys/time.h>
+
+
+#ifdef __cplusplus
+extern "C"{
+#endif
+#include "ccci_intf.h"
+#ifdef __cplusplus
+}
+#endif
+
+#include <linux/ioctl.h>
+#include <netinet/tcp.h>
+#include <sys/mman.h>
+#include <linux/netlink.h> //add for listen uevent from kernel space
+
+#include "SerPort.h"
+#include "LogDefine.h"
+#include "Context.h"
+
+static const int BACKLOG = 32;
+
+//////////////////////////////////////////////////////////////////////////
+CCCI::CCCI(const char *path)
+{
+ m_fd = open(path);
+}
+
+signed int CCCI::open(const char *path)
+{
+ int retry = 100;
+ signed int fd = NULL_FILE_DESCRIPTOR;
+
+ while(fd == NULL_FILE_DESCRIPTOR && retry != 0)
+ {
+ fd = ::open(path, O_RDWR|O_NOCTTY|O_NONBLOCK);
+ META_LOG("[Meta]Open modem. m_fd = %d", fd);
+ if (fd != NULL_FILE_DESCRIPTOR)
+ {
+ META_LOG("[Meta] Open modem port:(%s) success.", path);
+ break;
+ }
+ else
+ {
+ META_LOG("[Meta] Open modem port:(%s) fail. errno = %d", path, errno);
+ usleep(100*1000);
+ retry--;
+ }
+ }
+
+ return fd;
+}
+
+signed int CCCI::read(unsigned char *buf, unsigned int len)
+{
+ int tmpLen = 0;
+ while(1)
+ {
+ tmpLen = ::read(m_fd, buf, len);
+ if(tmpLen <= 0)
+ {
+ if(errno == EAGAIN)
+ {
+ usleep(10*1000);
+ continue;
+ }
+ //META_LOG("[META]read data error: fd = %d", m_fd);
+ return -1;
+ }
+ return tmpLen;
+ }
+ //META_LOG("[Meta] read data from device: len =%d , m_fd = %d", tmpLen, m_fd);
+}
+
+
+
+signed int CCCI::write(const unsigned char *p, unsigned int len)
+{
+ int bytes_written = -1;
+ int remain_size = len;
+ while(remain_size > 0)
+ {
+ bytes_written = ::write(m_fd, p, remain_size);
+ if (bytes_written < 0)
+ {
+ if(errno == 11) //modem is busy,AP send data too fast and modem is not able to process it, need to retry.
+ {
+ META_LOG("[Meta] Write data to CCCI device failed, modem is busy, retry to write, m_fd=%d", m_fd);
+ usleep(50*1000);
+ continue;
+ }
+ META_LOG("[Meta] Write data to CCCI device failed, return %d, errno=%d, m_fd=%d", bytes_written, errno, m_fd);
+ return bytes_written;
+ }
+ else
+ {
+ META_LOG("[Meta] Write %d bytes to CCCI device: m_fd = %d, ", bytes_written, m_fd);
+ }
+ remain_size -= bytes_written;
+ p += bytes_written;
+ }
+ return (len - remain_size);
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+CCB::CCB()
+{
+ init();
+}
+
+int CCB::init()
+{
+ while(0 == checkMdStatus())
+ {
+ META_LOG("[Meta] To check modem status");
+ usleep(100*1000);
+ }
+
+ META_LOG("[Meta] To init CCB");
+ // Initialize CCB related stuffs
+ m_fd = ccci_ccb_register(MD_SYS1, USR_SMEM_CCB_META);
+ if (m_fd <= 0) {
+ META_LOG("[Meta] ccb register failed, %d", m_fd);
+ return 0;
+ }
+
+ int ccb_ready = 0;
+ int retry = 0;
+ // check whether CCB state is ready
+ while ((ccb_ready = ccci_ccb_query_status()) != 0 && retry < META_CCB_INIT_MAX_RETRY) {
+ META_LOG("[Meta] ccb not ready, ret %d, retry %d", ccb_ready, retry);
+ usleep(100*1000);
+ retry++;
+ }
+
+ if (retry == META_CCB_INIT_MAX_RETRY) {
+ META_LOG("[Meta] ccb not retry after %d retries, ret %d", META_CCB_INIT_MAX_RETRY, ccb_ready);
+ return 0;
+ }
+ META_LOG("[Meta] CCB is ready");
+
+ return m_fd;
+
+}
+
+signed int CCB::read(unsigned char* buf, unsigned int len)
+{
+ META_LOG("[Meta] CCB to read data from device");
+
+ int bitmask = ccci_ccb_poll(META_CCB_POOL_BITMASK);
+ if (bitmask < 0) {
+ META_LOG("[Meta] CCB ccci_ccb_poll error, ret %d", bitmask);
+ return -1;
+ }
+
+ unsigned char *ccb_data_buf = NULL;
+ unsigned int ccb_data_len = 0;
+ len = 0;
+ int ret = ccci_ccb_read_get(META_CCB_BUFFER_ID, &ccb_data_buf, &ccb_data_len);
+
+ META_LOG("[Meta] CCB to read data, ret = %d, len = %d", ret, ccb_data_len);
+
+ if ((ret < 0) || (ccb_data_len == 0))
+ return 0;
+
+ //add mux header
+ buf[0] = 0xAC;
+ buf[1] = 0xCA;
+ buf[2] = 0x00;
+ buf[3] = 0xFF;
+ buf[4] = (ccb_data_len & 0x000000ff);
+ buf[5] = (ccb_data_len >> 8) & 0x000000ff;
+
+ //fill raw data- ccb buffer need 8byte align.
+ ccb_data_copy(buf+META_CCB_MUX_HEADER_LEN, ccb_data_buf, ccb_data_len, ccb_data_buf);
+
+ if ((ret = ccci_ccb_read_done(META_CCB_BUFFER_ID)) < 0) {
+ META_LOG("[Meta] CCB ccb_read_done failed, ret %d", ret);
+ }
+
+ return ccb_data_len+META_CCB_MUX_HEADER_LEN;
+}
+
+signed int CCB::write(const unsigned char* buf, unsigned int len)
+{
+ META_LOG("[Meta] CCB: to call ccci_ccb_write_alloc");
+
+ unsigned char *write_buf = NULL;
+ int retry = 0;
+ while ((write_buf = ccci_ccb_write_alloc(META_CCB_BUFFER_ID)) == NULL && retry < META_CCB_TX_MAX_RETRY)
+ {
+ META_LOG("[Meta] CCB ccb_buffer_write: cannot alloc ccb buf, retry %d", retry);
+ usleep(10000);
+ retry++;
+ }
+
+ META_LOG("[Meta] CCB: end call ccci_ccb_write_alloc");
+
+ if (retry >= META_CCB_TX_MAX_RETRY) {
+ META_LOG("[Meta] CCB ccb_buffer_write: cannot alloc ccb buf!");
+ return 0;
+ }
+
+ //ccb buffer need 8byte align.
+ ccb_data_copy(write_buf, (char*)buf, len, write_buf);
+
+ META_LOG("[Meta] CCB: to call ccci_ccb_write_done");
+
+ int ret = ccci_ccb_write_done(META_CCB_BUFFER_ID, write_buf, len);
+ if (ret < 0)
+ {
+ META_LOG("[Meta] CCB ccb_buffer_write: ccb_write_done error, ret %d", ret);
+ return 0;
+ }
+
+ META_LOG("[Meta] CCB Write %d bytes to device: m_fd = %d, ", len, m_fd);
+
+ return len;
+}
+
+void* CCB::ccb_memcpy(void *dst,void *src, size_t n)
+{
+ long *p1 = (long*)dst;
+ long *p2 = (long*)src;
+ for (unsigned int idx = 0; idx < n/sizeof(long); idx++)
+ *p1++ = *p2++;
+
+ return dst;
+}
+void CCB::ccb_data_copy(void* dst, void* src, unsigned int length, void* alignment_addr)
+{
+ unsigned int i=0,c=(0x8-(((long)(alignment_addr))&0x7));
+
+ for(; i<c && i<(unsigned int)length; i++)
+ *(((char *)(dst))+i) = *(((char *)(src))+i);
+
+ c = (length-i)&(~0x7);
+ ccb_memcpy(((char *)(dst))+i, ((char *)(src))+i, c);
+
+ for(i+=c; i<(unsigned int)length; i++)
+ *(((char *)(dst))+i) = *(((char *)(src))+i);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+
+SerPort::SerPort(const char *path)
+{
+ m_fd = open(path);
+}
+
+SerPort::SerPort()
+{
+}
+
+
+SerPort::~SerPort()
+{
+ if(m_fd > 0)
+ {
+ META_LOG("[Meta] Close serPort m_fd = %d", m_fd );
+ ::close(m_fd);
+ m_fd = NULL_FILE_DESCRIPTOR;
+ }
+}
+
+signed int SerPort::open(const char *path)
+{
+/* signed int fd = ::open(path, O_RDWR|O_NOCTTY);
+
+ META_LOG("[Meta] Open serPort. m_fd = %d", fd);
+
+ if (fd != NULL_FILE_DESCRIPTOR)
+ {
+ META_LOG("[Meta] Open serport:(%s) success.", path);
+ initTermIO(fd);
+ }
+ else
+ {
+ //META_LOG("[Meta] Open serport:(%s) fail, error code = %d", path, errno);
+ META_LOG("[Meta] Open(%s) failed, reason=[%s]%d, fd=%d.",
+ path, strerror( errno ), errno, fd );
+ }
+*/
+ signed int fd = NULL_FILE_DESCRIPTOR;
+
+ while(fd == NULL_FILE_DESCRIPTOR)
+ {
+ fd = ::open(path, O_RDWR|O_NOCTTY);
+
+ META_LOG("[Meta] Open serPort. m_fd = %d", fd);
+
+ if (fd != NULL_FILE_DESCRIPTOR)
+ {
+ META_LOG("[Meta] Open serport:(%s) success.", path);
+ initTermIO(fd);
+ }
+ else
+ {
+ //META_LOG("[Meta] Open serport:(%s) fail, error code = %d", path, errno);
+ META_LOG("[Meta] Open(%s) failed, reason=[%s]%d, fd=%d.",
+ path, strerror( errno ), errno, fd );
+ }
+ sleep(1);
+ }
+
+ return fd;
+}
+
+void SerPort::initTermIO(int portFd)
+{
+ struct termios termOptions;
+ if (fcntl(portFd, F_SETFL, 0) == -1)
+ {
+ META_LOG("[Meta] initTermIO call fcntl fail");
+ }
+ // Get the current options:
+ tcgetattr(portFd, &termOptions);
+
+ // Set 8bit data, No parity, stop 1 bit (8N1):
+ termOptions.c_cflag &= ~PARENB;
+ termOptions.c_cflag &= ~CSTOPB;
+ termOptions.c_cflag &= ~CSIZE;
+ termOptions.c_cflag |= CS8 | CLOCAL | CREAD;
+
+ // Raw mode
+ termOptions.c_iflag &= ~(INLCR | ICRNL | IXON | IXOFF | IXANY);
+ termOptions.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG); /*raw input*/
+ termOptions.c_oflag &= ~OPOST; /*raw output*/
+
+
+ tcflush(portFd,TCIFLUSH);//clear input buffer
+ termOptions.c_cc[VTIME] = (1 == getNormalModeTestFlag())? 10:100; /* inter-character timer unused */
+ termOptions.c_cc[VMIN] = 0; /* blocking read until 0 character arrives */
+
+
+ cfsetispeed(&termOptions, B921600);
+ cfsetospeed(&termOptions, B921600);
+ /*
+ * Set the new options for the port...
+ */
+ tcsetattr(portFd, TCSANOW, &termOptions);
+}
+
+void SerPort::setSerPortExitFlag()
+{
+ //Do nothing here
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+UartPort::UartPort(const char *path)
+ : SerPort(path)
+{
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+UsbPort::UsbPort(const char *path)
+ : SerPort(path)
+{
+ m_devPath = strdup(path);
+ m_ueventSocket = NULL_FILE_DESCRIPTOR;
+ m_usbMutexFlag = 1;
+ m_usbConnected = getUsbState();
+ m_getUsbUvent = false;
+}
+
+UsbPort::~UsbPort()
+{
+ // it'll never get here
+ // so it doesn't make much sense...
+ free((char*)m_devPath);
+ m_devPath = NULL;
+ deinitUeventSocket();
+}
+
+signed int UsbPort::read(unsigned char *buf, unsigned int len)
+{
+ // try to reopen USB if it was unplugged
+/* if (NULL_FILE_DESCRIPTOR == m_fd && !update())
+ {
+ return -1;
+ }
+*/
+
+ signed int ret = SerPort::read(buf, len);
+
+ // in case of error, see if USB is unplugged
+
+
+ // it doesn't make sense to do PnP check if 'read' succeeds
+
+ return ret;
+}
+
+signed int UsbPort::write(const unsigned char *buf, unsigned int len)
+{
+ // try to reopen USB if it was unplugged
+ if (NULL_FILE_DESCRIPTOR == m_fd) //&& !update())
+ {
+ return -1;
+ }
+ signed int ret = SerPort::write(buf, len);
+
+ // it doesn't make sense to do PnP check if 'write' succeeds
+
+ return ret;
+}
+
+void UsbPort::close()
+{
+ if (m_fd != NULL_FILE_DESCRIPTOR)
+ {
+ META_LOG("[Meta] Close fd : %d", m_fd);
+ ::close(m_fd);
+ m_fd = NULL_FILE_DESCRIPTOR;
+ }
+}
+void UsbPort::initUeventSocket()
+{
+ struct sockaddr_nl addr_sock;
+ int optval = 64 * 1024;
+
+ m_ueventSocket = socket(PF_NETLINK, SOCK_DGRAM, NETLINK_KOBJECT_UEVENT);
+ if (m_ueventSocket < 0)
+ {
+ META_LOG("[Meta] Unable to create uevent socket: %s", strerror(errno));
+ return;
+ }
+ META_LOG("[Meta] Create uevent socket success, m_ueventSocket: %d", m_ueventSocket);
+ if(setsockopt(m_ueventSocket, SOL_SOCKET, SO_RCVBUFFORCE, &optval, sizeof(optval)) <0)
+ {
+ META_LOG("[Meta] Unable to set uevent socket SO_RCVBUF option: %s(%d)", strerror(errno),errno);
+ }
+
+ memset(&addr_sock, 0, sizeof(addr_sock));
+ addr_sock.nl_family = AF_NETLINK;
+ addr_sock.nl_pid = getpid();
+ addr_sock.nl_groups = 0xffffffff;
+
+ if (bind(m_ueventSocket, (struct sockaddr *)&addr_sock, sizeof(addr_sock)) < 0)
+ {
+ META_LOG("[Meta] Failed to bind uevent socket: %s(%d)",strerror(errno), errno);
+ ::close(m_ueventSocket);
+ m_ueventSocket = NULL_FILE_DESCRIPTOR;
+ return;
+ }
+ META_LOG("[Meta] Bind uevent socket success");
+}
+void UsbPort::deinitUeventSocket()
+{
+ if(NULL_FILE_DESCRIPTOR != m_ueventSocket)
+ {
+ ::close(m_ueventSocket);
+ m_ueventSocket = NULL_FILE_DESCRIPTOR;
+ }
+}
+void UsbPort::handleUsbUevent(const char *buff, int len)
+{
+ const char *s = buff;
+
+ if(0 == strcmp(s, "change@/devices/virtual/android_usb/android0"))
+ {
+ m_getUsbUvent = true;
+ char state[32];
+ memset(state, 0, sizeof(state));
+ s += strlen(s) + 1;
+
+ while (*s)
+ {
+ META_LOG("[Meta] Handle uevents: %s", s);
+ if(!strncmp(s, "USB_STATE=", strlen("USB_STATE=")))
+ {
+ strncpy(state, s + strlen("USB_STATE="), sizeof(state)-1);
+ META_LOG("[Meta] uevents: USB_STATE=%s", state);
+ break;
+ }
+ s += strlen(s) + 1;
+ if (s - buff >= len)
+ break;
+ }
+
+ if (!strncmp(state, "CONFIGURED", sizeof("CONFIGURED")))
+ {
+ META_LOG("[Meta] uevents: USB connected");
+ m_usbConnected = 1;
+ }
+ else
+ {
+ META_LOG("[Meta] uevents: USB disconnected");
+ m_usbConnected = 0;
+ }
+ }
+}
+
+#define UEVENT_BUFFER_SIZE 2048
+int UsbPort::isReady()
+{
+ if(m_ueventSocket < 0)
+ initUeventSocket();
+
+ struct pollfd fds;
+ static char uevent_desc[UEVENT_BUFFER_SIZE * 2];
+
+ fds.fd = m_ueventSocket;
+ fds.events = POLLIN;
+ fds.revents = 0;
+ int ret = poll(&fds, 1, -1);
+ if (ret > 0 && (fds.revents & POLLIN))
+ {
+ /* keep last 2 zeroes to ensure double 0 termination */
+ int count = recv(m_ueventSocket, uevent_desc, sizeof(uevent_desc) - 2, 0);
+ if (count > 0)
+ {
+ //META_LOG("[Meta][DEBUG] uevent_desc: %s, count: %d ", uevent_desc, count);
+ handleUsbUevent(uevent_desc, count);
+ }
+ }
+ return m_usbConnected;
+}
+
+int UsbPort::getUsbState() const
+{
+ int type = 0;
+ char buf[21];
+ int bytes_read = 0;
+ int res = 0;
+ int fd = ::open("/sys/class/android_usb/android0/state", O_RDONLY);
+ if (fd != -1)
+ {
+ META_LOG("[Meta] Query usb state OK.");
+ memset(buf, 0, 21);
+ while (bytes_read < 10)
+ {
+ res = ::read(fd, buf + bytes_read, 10);
+ if (res > 0)
+ bytes_read += res;
+ else
+ break;
+ }
+ ::close(fd);
+ buf[bytes_read] = '\0';
+ type = strcmp(buf,"CONFIGURED");
+
+ if(0 == type)
+ {
+ META_LOG("[Meta] USB is ready.");
+ }
+ else
+ {
+ META_LOG("[Meta] USB is not ready.");
+ }
+ }
+ else
+ {
+ META_LOG("[Meta] Failed to open:/sys/class/android_usb/android0/state");
+ }
+
+ return (type == 0);
+}
+
+void UsbPort::update()
+{
+ if (!isReady())
+ {
+ if(m_usbMutexFlag && m_getUsbUvent)
+ {
+ close();
+ m_usbMutexFlag = 0;
+ }
+ }
+ else
+ {
+ if(!m_usbMutexFlag)
+ {
+ sleep(1);
+ m_fd = open(m_devPath);
+
+ if(m_fd != NULL_FILE_DESCRIPTOR)
+ {
+ m_usbMutexFlag = 1;
+ }
+ }
+ }
+
+}
+
+MetaSocket::MetaSocket(const char *path)
+{
+ m_fd = open(path);
+ m_nClientFd = NULL_FILE_DESCRIPTOR;
+ m_bConnect = false;
+ m_nSocketConnectExitFlag = 0;
+}
+
+MetaSocket::~MetaSocket()
+{
+ close();
+}
+
+signed int MetaSocket::open(const char *path)
+{
+ int sock_opt = 1;
+ int enable = 1;
+ path = NULL;
+ int fd = NULL_FILE_DESCRIPTOR;
+ char serverIP[16] = {0};
+ int nPort = 0;
+
+ if(1 == getNormalModeTestFlag())
+ {
+ WIFI_PARA wifi_para = getWifiPara();
+ strncpy(serverIP, wifi_para.ip_addr, sizeof(serverIP)-1);
+ nPort = wifi_para.port;
+ META_LOG("[Meta] Socket get server IP address:%s Port:%d", serverIP, nPort);
+ }
+
+ //Create socket
+ if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ META_LOG("[META] Socket created fail. errno=%d", errno);
+ return -1;
+ }
+
+ META_LOG("[META] Socket created success fd:%d",fd);
+
+ // SET SOCKET REUSE Address
+ if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&sock_opt, sizeof(sock_opt)) < 0)
+ {
+ META_LOG("[META] Socket setsockopt failed. errno=%d", errno);
+ ::close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return -1;
+ }
+ // SET SOCKET RECEIVE TIMEOUT
+ // Set socket to nonblock to avoid release problem
+ struct timeval timeout = {1,0};
+ if(setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeval)) < 0)
+ {
+ META_LOG("[META] Socket set receive timeout failed. errno=%d", errno);
+ ::close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return -1;
+ }
+ //SET TCP_NODELAY
+ if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&enable, sizeof(enable)) < 0)
+ {
+ META_LOG("[META] Socket setsockopt TCP_NODELAY failed. errno=%d", errno);
+ }
+ //Prepare the sockaddr_in structure
+ struct sockaddr_in* serverAddr = new struct sockaddr_in;
+ if(serverAddr == NULL)
+ {
+ META_LOG("[Meta] Socket new server addr failed. errno=%d", errno);
+ ::close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return -1;
+ }
+ else
+ {
+ memset(serverAddr,0,sizeof(sockaddr_in));
+ }
+
+ serverAddr->sin_family = AF_INET;
+ serverAddr->sin_port = htons(nPort);
+ serverAddr->sin_addr.s_addr = inet_addr(serverIP);
+
+ //Bind
+ if(bind(fd,(struct sockaddr*)serverAddr, sizeof(struct sockaddr)) < 0)
+ {
+ META_LOG("[META] Socket bind failed. errno=%d", errno);
+ goto errout;
+ }
+ META_LOG("[META] Socket bind done");
+
+ //Listen
+ if (listen(fd, BACKLOG) == -1)
+ {
+ META_LOG("[META] Socket Failed to listen Socket port, errno=%d", errno);
+ goto errout;
+ }
+ META_LOG("[META] Socket listen done");
+
+ delete serverAddr;
+ serverAddr = NULL;
+ return fd;
+
+errout:
+ delete serverAddr;
+ serverAddr = NULL;
+ ::close(fd);
+ fd = NULL_FILE_DESCRIPTOR;
+ return fd;
+}
+
+signed int MetaSocket::read(unsigned char *buf, unsigned int len)
+{
+ if(!m_bConnect)
+ {
+ if(connect() == -1)
+ {
+ META_LOG("[Meta] Socket::read connect fail");
+ return -1;
+ }
+ }
+
+ if(m_nClientFd < 0)
+ {
+ return -1;
+ }
+
+ //META_LOG("[META] Socket enter read, connect success");
+ int tmpLen = 0;
+ tmpLen = recv(m_nClientFd, buf, len, 0);
+ if(tmpLen == 0)
+ {
+ META_LOG("[META] Socket recv data len is 0, network interrupt, need to reconnect - m_nClientFd = %d, len = %d", m_nClientFd, tmpLen);
+ disconnect();
+ }
+ else
+ {
+ META_LOG("[META] Socket recv data from socket client - m_nClientFd = %d, len = %d", m_nClientFd, tmpLen);
+ }
+ return tmpLen;
+}
+
+signed int MetaSocket::write(const unsigned char *buf, unsigned int len)
+{
+ if (NULL_FILE_DESCRIPTOR == m_nClientFd)
+ {
+ return -1;
+ }
+
+ int bytes_written = -1;
+ int remain_size = len;
+ pthread_mutex_lock(&(Device::m_wMutex));
+ //META_LOG("[Meta] Socket enter write");
+ while(remain_size > 0)
+ {
+ bytes_written = send(m_nClientFd, buf, remain_size, 0);
+ if (bytes_written < 0)
+ {
+ META_LOG("[Meta] Socket write data by socket failed, return %d, errno=%d, m_nClientFd=%d", bytes_written, errno, m_nClientFd);
+ pthread_mutex_unlock(&(Device::m_wMutex));
+ return bytes_written;
+ }
+ else
+ {
+ META_LOG("[Meta] Socket write %d bytes by socket: m_nClientFd = %d, ", bytes_written, m_nClientFd);
+ }
+ remain_size -= bytes_written;
+ buf += bytes_written;
+ }
+ pthread_mutex_unlock(&(Device::m_wMutex));
+ return (len - remain_size);
+
+}
+
+void MetaSocket::close()
+{
+ disconnect();
+ if (m_fd != NULL_FILE_DESCRIPTOR)
+ {
+ ::close(m_fd);
+ m_fd = NULL_FILE_DESCRIPTOR;
+ }
+}
+
+signed int MetaSocket::connect()
+{
+ if (NULL_FILE_DESCRIPTOR == m_fd)
+ {
+ return -1;
+ }
+
+ if (m_bConnect)
+ {
+ return 0;
+ }
+
+ struct sockaddr_in* clientAddr = new struct sockaddr_in;
+ if (clientAddr == NULL)
+ {
+ META_LOG("[Meta] Socket new client addr failed. errno=%d", errno);
+ m_bConnect = false;
+ return -1;
+ }
+ memset(clientAddr,0,sizeof(struct sockaddr_in));
+ socklen_t alen = sizeof(struct sockaddr);
+
+ META_LOG("[Meta] Socket connect, accept the connection: m_nSocketConnectExitFlag = %d",m_nSocketConnectExitFlag);
+ while(m_nSocketConnectExitFlag == 0)
+ {
+ if ((m_nClientFd = accept(m_fd, (struct sockaddr*)clientAddr, &alen)) == -1)
+ {
+ if(errno == EAGAIN || errno == EINVAL)
+ {
+ usleep(200*1000);
+ continue;
+ }
+ META_LOG("Socket accept error, errno=%d", errno);
+
+ m_bConnect = false;
+
+ delete clientAddr;
+ clientAddr = NULL;
+ return -1;
+ }
+ else
+ {
+ m_bConnect = true;
+ META_LOG("[Meta] Socket connect, Received a connection from %s, m_nClientFd = %d",
+ (char*)inet_ntoa(clientAddr->sin_addr), m_nClientFd);
+ delete clientAddr;
+ clientAddr = NULL;
+ return 0;
+ }
+ }
+ delete clientAddr;
+ clientAddr = NULL;
+ return -1;
+}
+
+void MetaSocket::disconnect()
+{
+ if (m_bConnect)
+ {
+ if (m_nClientFd != NULL_FILE_DESCRIPTOR)
+ {
+ m_bConnect = false;
+ ::close(m_nClientFd);
+ m_nClientFd = NULL_FILE_DESCRIPTOR;
+ }
+ }
+}
+
+void MetaSocket::setSerPortExitFlag()
+{
+ m_nSocketConnectExitFlag = 1;
+}
+
diff --git a/src/devtools/meta/src/common/src/UsbRxWatcher.cpp b/src/devtools/meta/src/common/src/UsbRxWatcher.cpp
new file mode 100644
index 0000000..9d688c6
--- /dev/null
+++ b/src/devtools/meta/src/common/src/UsbRxWatcher.cpp
@@ -0,0 +1,1013 @@
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <unistd.h>
+#include "LogDefine.h"
+#include "UsbRxWatcher.h"
+#include "Modem.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "FtModule.h"
+#include "snappy-c.h"
+
+
+
+
+typedef struct _MetaFrame
+{
+ unsigned char start;
+ unsigned char frmLen[2];
+ unsigned char frmType;
+ unsigned char localLen[2];
+ unsigned char peerLen[2];
+ unsigned char token[2];
+ unsigned char reqId[2];
+
+}MetaFrame;
+
+
+UsbRxWatcher::UsbRxWatcher(void)
+{
+ m_checksum = STX_OCTET;
+ m_uFrameLength = 0;
+ m_frame_buf_len = 0;
+ m_flow_ctrl_flag = 0;
+ m_cTstFrameState = RS232_FRAME_STX;
+ m_cOldTstFrameState = RS232_FRAME_STX;
+
+ nRemainLen = 0;
+ m_nStartByteLen = 0;
+ m_frm_len_byte = 2;
+ m_md_index = 0;
+ memset(&m_sRs232Frame, 0, sizeof(m_sRs232Frame));
+
+}
+
+UsbRxWatcher::~UsbRxWatcher(void)
+{
+ if (m_frame_buf_len > 0)
+ {
+ free(m_sRs232Frame.buf_ptr);
+ }
+
+ //delete ti
+}
+
+signed int UsbRxWatcher::onReceived(
+ unsigned char *buf,
+ unsigned int len)
+{
+
+ META_LOG("[Meta] Receive data from USB, len = %d",len);
+ unsigned int activeATModemId = 0;
+ activeATModemId = getActiveATModem();
+
+ dumpDataInHexString(buf,len,16);
+
+
+ //modem mode = normal, boot mode = meta mode
+ if((getMDMode()==1) && (META_BOOT == getBootMode()))
+ {
+ Modem *p = getModem(activeATModemId);
+
+ char * temp =NULL;
+
+
+ if(p!=NULL)
+ {
+ dumpData(buf,len);
+ temp = strstr((char *)buf,"AT+REBOOTMD");
+ if(temp == NULL)
+ {
+ temp = strstr((char *)buf,"AT+EAMDIMG");
+ if(temp == NULL)
+ {
+ p->exec(buf,len);
+ }
+ else
+ {
+ //META_LOG("[Meta] [DEBUG] Got AT+EAMDIMG");
+ int bDataDevice = FALSE;
+ int fd = -1;
+ FtModModemInfo *pRebootMD = new FtModModemInfo;
+ SerPort *pPort = getSerPort();
+ char ack_buf[64] = {0};
+ fd = getIOCPort(0,bDataDevice);
+ int modem_type = -1;
+ temp += strlen("AT+EAMDIMG=");
+ int first_command = atoi(temp);
+ //META_LOG("[Meta] [DEBUG] first command = %d", first_command);
+ if(0 == first_command) //Get
+ {
+ temp+=2;
+ int second_command = atoi(temp);
+ //META_LOG("[Meta] [DEBUG] second command = %d", second_command);
+ if(0 == second_command) //Get modem type
+ {
+ META_LOG("[Meta] get modem type");
+ int result = pRebootMD->getModemType(&modem_type,fd);
+ if(result == 0)
+ {
+ META_LOG("[Meta][FT] Get modem type: %d success", modem_type);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] Get modem type fail");
+ }
+ sprintf(ack_buf,"\r\n%d\r\n",modem_type);
+ }
+ else if(1 == second_command)
+ {
+ int modem_state = 0;
+ META_LOG("[Meta] get modem state");
+ int result = pRebootMD->getModemState(&modem_state,fd);
+ if(result == 0)
+ {
+ META_LOG("[Meta][FT] Get modem state: %d success", modem_state);
+ }
+ else
+ {
+ META_LOG("[Meta][FT] Get modem state fail");
+ }
+ sprintf(ack_buf,"\r\n%d\r\n",modem_state);
+ }
+ pPort->write((unsigned char *)ack_buf, strlen(ack_buf));
+ }
+ else if(1 == first_command) //Set Modem Type
+ {
+ temp+=2;
+ modem_type = atoi(temp);
+ META_LOG("[Meta] set modem type= %d",modem_type);
+
+ setActiveATModem(0);
+ META_LOG("Destory modem thread and close modem handle");
+ destroyAllModemThread();
+ int result = pRebootMD->setModemType(modem_type,fd);
+ if(result == 0)
+ {
+ sleep(5);
+ META_LOG("[Meta][FT] Set modem type to %d success", modem_type);
+ sprintf(ack_buf,"%s","\r\nPASS\r\n");
+ }
+ else
+ {
+ META_LOG("[Meta][FT] Set modem type to %d fail", modem_type);
+ sprintf(ack_buf,"%s","\r\nFAIL\r\n");
+ }
+ createAllModemThread();
+ pPort->write((unsigned char *)ack_buf, strlen(ack_buf));
+ }
+
+ if(bDataDevice == FALSE)
+ {
+ if(fd != -1)
+ {
+ close(fd);
+ META_LOG("[Meta][FT]Close fd");
+ fd = -1;
+ }
+ }
+ if(pRebootMD!=NULL)
+ delete pRebootMD;
+ }
+
+ }
+ else
+ {
+ temp+=strlen("AT+REBOOTMD=");
+ int nModemIndex = atoi(temp);
+ META_LOG("[Meta] nModemIndex = %d",nModemIndex);
+ temp+=2;
+ int modem_mode = atoi(temp);
+ META_LOG("[Meta] modem_mode = %d",modem_mode);
+ FtModModemInfo *pRebootMD = new FtModModemInfo;
+ FT_MODEM_REQ req;
+ FT_MODEM_CNF ft_cnf;
+ int bDataDevice = FALSE;
+ int fd = -1;
+ memset(&req, 0, sizeof(FT_MODEM_REQ));
+ memset(&ft_cnf, 0, sizeof(FT_MODEM_CNF));
+ fd = getIOCPort(nModemIndex,bDataDevice);
+ req.cmd.reboot_modem_req.modem_index = nModemIndex;
+ req.cmd.reboot_modem_req.mode = modem_mode;
+ pRebootMD->rebootModem(&req, ft_cnf,fd);
+ sleep(5);
+ memset(&req, 0, sizeof(FT_MODEM_REQ));
+ memset(&ft_cnf, 0, sizeof(FT_MODEM_CNF));
+ int result = pRebootMD->getModemMode(&req, ft_cnf,fd);
+ if(bDataDevice == FALSE)
+ {
+ if(fd != -1)
+ {
+ close(fd);
+ META_LOG("[Meta][FT]Close fd");
+ fd = -1;
+ }
+ }
+
+ //create modem thread and open modem handle
+ if(result == 0)
+ {
+ setMDMode(modem_mode);
+ createAllModemThread();
+ }
+
+ if(pRebootMD!=NULL)
+ delete pRebootMD;
+ }
+ }
+ else
+ {
+ META_LOG("[Meta] activeATModemId = %d is invalid",activeATModemId);
+ }
+ return 0;
+ }
+ META_LOG("[Meta] nRemainLen = %d", nRemainLen);
+
+ unsigned char * data = NULL;
+ unsigned short u16Length = 0;
+
+ if(nRemainLen > 0)
+ {
+ bcopy(buf, szRemainBuf+nRemainLen, len); //Fix for memcpy do not support src/dst overlap case
+ data = szRemainBuf;
+ len = nRemainLen + len;
+ }
+ else
+ {
+ data = buf;
+ }
+
+ Frame *pFrm = decode(data, len, u16Length);
+
+ if (NULL != pFrm)
+ {
+ if(pFrm->getIsValid() == 1)
+ {
+ pFrm->exec();
+ if(len > u16Length)
+ {
+ bcopy(data+u16Length, szRemainBuf, len-u16Length); //Fix for memcpy do not support src/dst overlap case
+ nRemainLen = 0;
+ onReceived(szRemainBuf, len-u16Length);
+ }
+ else if(len == u16Length)
+ {
+ nRemainLen = 0;
+ }
+ }
+ else
+ {
+ META_LOG("[Meta] Unsupport request id");
+ if(len == u16Length)
+ {
+ nRemainLen = 0;
+ META_LOG("[Meta] discard the whole frame");
+ }
+ else if(len > u16Length)
+ {
+ bcopy(data+u16Length, szRemainBuf, len-u16Length); //Fix for memcpy do not support src/dst overlap case
+ nRemainLen = len-u16Length;
+ }
+ }
+ delete pFrm;
+ }
+ else
+ {
+ META_LOG("[Meta] pFrm is NULL");
+ if(len == u16Length)
+ {
+ nRemainLen = len;
+ bcopy(data, szRemainBuf, len); //Fix for memcpy do not support src/dst overlap case
+ META_LOG("[Meta] Data is incomplete, received = %d",len);
+ }
+ else
+ {
+ META_LOG("[Meta] Discard incomplete frame %d bytes",u16Length);
+ nRemainLen = 0;
+ onReceived(data+(u16Length-1), len-(u16Length-1));
+ }
+ }
+
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+unsigned char *UsbRxWatcher::reallocFrameBuf(unsigned int len)
+{
+ unsigned char *buf_ptr = m_sRs232Frame.buf_ptr;
+
+ META_LOG("[Meta] (reallocFrameBuf) len = %d, m_frame_buf_len=%d",len, m_frame_buf_len);
+
+ if (buf_ptr != NULL)
+ {
+ free(buf_ptr);
+ }
+
+ buf_ptr = (unsigned char *)malloc(len);
+ memset(buf_ptr,'\0',len);
+ m_frame_buf_len = len;
+
+ return buf_ptr;
+}
+
+unsigned int UsbRxWatcher::flowControl(void *pdata, unsigned int len)
+{
+ /* if the data is 0x77 and 0x01, escape to 0x11
+ if the data is 0x77 and 0x02, escape to 0x13
+ if the data is 0x77 and 0x77, escape to 0x77
+ */
+ if (getComType() == META_UART_COM)
+ {
+ unsigned int idx = 0;
+ unsigned int newLen = 0;
+ unsigned char *pTempBuf = (unsigned char*)pdata;
+ unsigned char *pDestBuf = pTempBuf;
+
+ while (idx != len)
+ {
+ ++ idx;
+
+ if (idx == len)
+ {
+ META_LOG("[Meta] root cause1:cnt:%d",idx);
+ if(*pTempBuf ==0x77)
+ {
+ m_flow_ctrl_flag = 1;
+ break;
+ }
+ }
+
+ if (*pTempBuf ==0x77 || m_flow_ctrl_flag != 0)
+ {
+ if (m_flow_ctrl_flag != 0)
+ {
+ m_flow_ctrl_flag = 0;
+ }
+ else
+ {
+ ++ idx;
+ ++ pTempBuf;
+ }
+
+ if (*pTempBuf ==0x01)
+ {
+ *pDestBuf = 0x11;
+ }
+ else if (*pTempBuf ==0x02 )
+ {
+ *pDestBuf = 0x13;
+ }
+ else if (*pTempBuf ==0x03 )
+ {
+ *pDestBuf = 0x77;
+ }
+ else
+ {
+ META_LOG("[Meta] root cause2: cnt:%d",idx);
+ break;
+ }
+ }
+ else
+ {
+ *pDestBuf = *pTempBuf;
+ }
+
+ ++ newLen;
+ ++ pTempBuf;
+ ++ pDestBuf;
+ }
+ len = newLen;
+ }
+ return len;
+}
+
+Frame *UsbRxWatcher::decodeMDFrame(void *pdata, unsigned int len,unsigned char frmType,unsigned short &u16Length)
+{
+ assert(pdata != NULL);
+
+
+ int bFrm = false;
+ unsigned char * local_ptr = (unsigned char*)pdata + u16Length;
+ unsigned char ch;
+ int newLen = m_uFrameLength;
+
+ while(u16Length != len)
+ {
+ ++u16Length;
+ ch = *local_ptr;
+
+ if(ch == MUX_KEY_WORD)
+ {
+ if(u16Length == len)
+ return NULL;
+
+ ++u16Length;
+ ++local_ptr;
+ ch = *local_ptr;
+ if((ch == MUX_KEY_WORD) || (ch == 0x01))
+ newLen ++;
+ }
+
+ if(getComType() == META_UART_COM && ch == 0x77)
+ {
+ if(u16Length == len)
+ return NULL;
+
+ ++u16Length;
+ ++local_ptr;
+ ch = *local_ptr;
+ if((ch == 0x01) || (ch == 0x02) || (ch == 0x03))
+ newLen ++;
+ }
+
+ if(ch == STX_OCTET)
+ {
+ META_LOG("[Meta] New modem frame header");
+ bFrm = true;
+ u16Length--;
+
+ }
+ else if(u16Length == newLen + 3 + m_frm_len_byte + m_nStartByteLen) // 3 + m_frm_len_byte = start byte + data type + checksum + data len(m_frm_len_byte)
+ {
+
+ META_LOG("[Meta] New modem frame tail, m_nStartByteLen:%d",m_nStartByteLen);
+ bFrm = true;
+ }
+
+ if(bFrm)
+ {
+ len = flowControl(pdata, u16Length);
+ return sendMdTask((unsigned char*)pdata + m_nStartByteLen, len - m_nStartByteLen, frmType);
+ }
+
+ ++local_ptr;
+ }
+
+ return NULL;
+}
+
+Frame * UsbRxWatcher::sendMdTask(void *pdata, unsigned int len,unsigned char frmType)
+{
+ assert(pdata != NULL);
+ Frame * pFrame = NULL;
+
+ unsigned char mdId = 0;
+ unsigned int compress = 0;
+ void *mdData = pdata;
+
+ if ((frmType == RS232_INJECT_PRIMITIVE_OCTET)|| (frmType == RS232_COMMAND_TYPE_OCTET))//0x64 0x63
+ {
+ mdId = 0;
+ //TODO
+ }
+ else if(frmType >= RS232_INJECT_PRIMITIVE_OCTETMODEM2 && frmType <= RS232_INJECT_PRIMITIVE_OCTETMODEM2_END)//0xA0 ~ A7
+ {
+ mdId = m_md_index;
+ }
+ else if(frmType >= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP && frmType<= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP_END)//0xC0 ~ 0xC7
+ {
+ mdId = m_md_index;
+ }
+ else if(frmType >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START && frmType <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_END)//0xD0 ~ 0xD7
+ {
+ mdId = m_md_index;
+ }
+
+#ifdef MTK_META_COMPRESS_SUPPORT
+ else if(frmType >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START && frmType <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_END)//0xF0 ~ 0xF7
+ {
+ mdId = m_md_index;
+ compress = 1;
+ }
+#endif
+
+ CmdTarget *md = getModem(mdId);
+
+ META_LOG("[Meta] Send data to modem[%d], data len:%d", mdId,len);
+
+ dumpDataInHexString((const unsigned char *)pdata,len,16);
+
+
+#ifdef MTK_META_COMPRESS_SUPPORT
+
+// char uncompressed[FrameMaxSize] = {0};
+ int uncompressed_len = FrameMaxSize;
+
+ if(GetDataCompressStatus() && compress)
+ {
+ memset(m_uncompressed, 0, FrameMaxSize);
+ if (true != uncompress(pdata, len, &m_uncompressed[0], &uncompressed_len))
+ {
+ META_LOG("[Meta] error: uncompress failed\n");
+ return NULL;
+ }
+
+ META_LOG("[Meta] uncompressed frame[%d]\n", uncompressed_len);
+ dumpDataInHexString((const unsigned char *)m_uncompressed, uncompressed_len, 16);
+
+// pdata = uncompressed;
+ mdData = &m_uncompressed[0];
+ len = uncompressed_len;
+ }
+
+#endif
+
+ if (NULL != md)
+ {
+ META_RX_DATA metaRxData =
+ {
+ MD_FRAME, (unsigned char*)mdData, static_cast<unsigned short>(len), 0
+ };
+
+ pFrame = new Frame(metaRxData, md);
+ }
+ else
+ {
+ META_LOG("[Meta] can not get modem object");
+ pFrame = new Frame();
+ }
+ return pFrame;
+}
+
+Frame *UsbRxWatcher::sendFtTask()
+{
+ /* send data FT task */
+ Frame * pFrame = NULL;
+
+ const unsigned short localLen = m_sRs232Frame.inject_prim.local_len;
+ const unsigned short peerLen = m_sRs232Frame.inject_prim.peer_len;
+
+ META_LOG("[Meta] Send data to FT module. localLen = %d, peerLen = %d", localLen, peerLen);
+
+ unsigned char *localBuf = m_sRs232Frame.buf_ptr;
+
+ const FT_H *hdr = (FT_H*)localBuf;
+ META_LOG("[Meta] token = %d, id = %d", hdr->token, hdr->id);
+
+ CmdTarget *mod = getModule(hdr->id);
+
+ if (mod != NULL)
+ {
+ mod->setToken( hdr->token);
+ META_RX_DATA metaRxData =
+ {
+ AP_FRAME,
+ localBuf,
+ localLen,
+ peerLen
+ };
+
+ pFrame = new Frame(metaRxData, mod);
+ }
+ else
+ {
+ pFrame = new Frame();
+ }
+
+ return pFrame;
+}
+
+Frame *UsbRxWatcher::decodeAPFrame( unsigned int input_len,unsigned char * src,unsigned short &u16Length)
+{
+ unsigned char * local_ptr = src;
+ unsigned char ch;
+
+ while(u16Length!=input_len)//request frame length don't include checksum
+ {
+ ++ u16Length;
+ ch = *local_ptr;
+
+ if ( ch == STX_OCTET )
+ {
+ META_LOG("[Meta] New APP frame header");
+ return NULL;
+ }
+
+ if (1 == checkEscape(ch))
+ {
+ if(u16Length == input_len)
+ return NULL;
+
+ ch = *(++local_ptr);
+ if(transferFrame(&ch) != 1)
+ {
+ ch = *(--local_ptr);
+ }
+ else
+ {
+ ++ u16Length;
+ }
+ }
+
+ if (m_cTstFrameState == RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER)/* fill data to tst_primitive_header_struct */
+ {
+ ++ m_sRs232Frame.received_prig_header_length;
+ *(m_sRs232Frame.header_ptr++) = ch;
+
+ if (m_sRs232Frame.received_prig_header_length == sizeof(PRIM_HEADER))
+ {
+ if (m_sRs232Frame.inject_prim.local_len != 0)
+ {
+ m_cTstFrameState = RS232_FRAME_AP_PRIM_LOCAL_PARA_DATA;
+
+ META_LOG("[Meta] RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER: LOCAL len: %d m_peer_len : %d ",
+ m_sRs232Frame.inject_prim.local_len, m_sRs232Frame.inject_prim.peer_len);
+
+ m_sRs232Frame.buf_ptr = reallocFrameBuf(m_sRs232Frame.inject_prim.local_len + m_sRs232Frame.inject_prim.peer_len+1);
+ }
+ }
+ }
+ else if(m_cTstFrameState == RS232_FRAME_AP_PRIM_LOCAL_PARA_DATA)/* fill the primitive body to local parameter buffer and peer buffer */
+ {
+ if (m_sRs232Frame.buf_ptr != NULL)
+ {
+ *(m_sRs232Frame.buf_ptr + m_sRs232Frame.received_buf_para_length) = ch;
+ }
+
+ ++ m_sRs232Frame.received_buf_para_length;
+
+ if ((m_sRs232Frame.inject_prim.local_len + m_sRs232Frame.inject_prim.peer_len) == m_sRs232Frame.received_buf_para_length)
+ {
+ m_cTstFrameState = RS232_FRAME_CHECKSUM;
+ }
+ }
+ else if(m_cTstFrameState == RS232_FRAME_CHECKSUM)
+ {
+ META_LOG("[Meta] parse state: RS232_FRAME_CHECKSUM: checksum: %d, ch: %d",m_checksum, ch);
+ m_cTstFrameState = RS232_FRAME_STX;
+ if(m_checksum != ch)
+ {
+ META_LOG("[Meta] Checksum error!");
+ return (new Frame());
+ }
+
+ m_sRs232Frame.received_buf_para_length = 0;
+ m_checksum = STX_OCTET;
+ META_LOG("[Meta] (decodeAPFrame) u16Length = %d", u16Length);
+ return sendFtTask();
+ }
+
+ ++local_ptr;
+ m_checksum ^= ch;
+ }
+ return NULL;
+}
+
+
+Frame *UsbRxWatcher::decode(
+ unsigned char *buf_ptr,
+ unsigned int input_len,
+ unsigned short &u16Length)
+{
+ unsigned char *src=buf_ptr;
+ unsigned char ch;
+ unsigned int discard_word=0;
+
+ //META_LOG("[Meta](UsbRxWatcher) To decode data");
+ dumpDataInHexString(buf_ptr,input_len,16);
+
+ while (u16Length != input_len)
+ {
+ ch = *src;
+ ++ u16Length;
+
+ if ( ch == STX_OCTET )
+ {
+ m_cTstFrameState = RS232_FRAME_LENHI;
+ ++ src;
+ m_uFrameLength = 0;
+ m_frm_len_byte = 2;
+ m_checksum = STX_OCTET;
+ m_nStartByteLen = u16Length - 1;
+
+ if (discard_word > 0)
+ {
+ META_LOG("[Meta] Discards %d chars.", discard_word);
+ discard_word = 0;
+ }
+ continue;
+ }
+ else if(m_cTstFrameState == RS232_FRAME_STX)
+ {
+ ++ discard_word;
+ ++ src;
+ continue;
+ }
+ else
+ {
+ if (1 == checkEscape(ch))
+ {
+ ch = *(++src);
+ if(transferFrame(&ch) != 1)
+ {
+ ch = *(--src);
+ }
+ else
+ {
+ if((m_cTstFrameState == RS232_FRAME_LENHI) || (m_cTstFrameState == RS232_FRAME_LENLO))
+ {
+ m_frm_len_byte += 1;
+ }
+ ++ u16Length;
+ }
+ }
+ }
+
+ switch (m_cTstFrameState)
+ {
+
+ case RS232_FRAME_LENHI:
+ m_uFrameLength = ch << 8;
+ m_cTstFrameState = RS232_FRAME_LENLO;
+ //META_LOG("[Meta] parse state: RS232_FRAME_LENHI: %x", ch);
+ break;
+
+ case RS232_FRAME_LENLO:
+ m_uFrameLength += ch;
+ m_cTstFrameState = RS232_FRAME_TYPE;
+ META_LOG("[Meta] parse state: RS232_FRAME_LENLO: %x, total: %d",ch, m_uFrameLength);
+ if ((m_uFrameLength+5) > FRAME_MAX_LEN)
+ {
+ META_LOG("[Meta] parse state: Error: Frame size is %d+5, exceeds limit of %d.",m_uFrameLength, FRAME_MAX_LEN);
+ return NULL;
+ }
+ break;
+
+ case RS232_FRAME_TYPE:
+ m_checksum ^= ch;
+ //META_LOG("[Meta] (decode) u16Length = %d",u16Length);
+ return dispatchFrame(ch, buf_ptr, input_len, src,u16Length);
+ break;
+ }
+
+ m_checksum ^= ch;
+ ++ src;
+ }
+ return NULL;
+}
+
+unsigned char UsbRxWatcher:: checkEscape(unsigned char ch)
+{
+ if ((ch == MUX_KEY_WORD ) &&
+ (m_cTstFrameState != RS232_FRAME_KEYWORD) &&
+ (m_cTstFrameState != RS232_FRAME_MD_DATA))// enter MUX state(0x5A) and save the old
+ {
+ m_cOldTstFrameState = m_cTstFrameState;
+ m_cTstFrameState = RS232_FRAME_KEYWORD;
+ return 1;
+ }
+
+ return 0;
+}
+
+unsigned char UsbRxWatcher::transferFrame(unsigned char * ch)
+{
+ unsigned char ret = 0;
+ if (m_cTstFrameState == RS232_FRAME_KEYWORD)
+ {
+ switch(*ch)
+ {
+ case MUX_KEY_WORD:
+ *ch = MUX_KEY_WORD; //5A 5A->5A
+ ret = 1;
+ break;
+ case 0x01:
+ *ch = STX_OCTET; //5A 01->55
+ ret = 1;
+ break;
+ default:
+ break;
+ }
+ m_cTstFrameState = m_cOldTstFrameState;//leave MUX state and restore the state
+ }
+
+ return ret;
+}
+
+
+
+Frame * UsbRxWatcher::dispatchFrame(unsigned char ch, unsigned char *buf_ptr, unsigned int input_len, unsigned char *src,unsigned short &u16Length)
+{
+ META_LOG("[Meta] parse state: RS232_FRAME_TYPE: %x ", ch);
+
+ if (ch == RS232_INJECT_PRIMITIVE_OCTET || ch == RS232_COMMAND_TYPE_OCTET )
+ {
+ m_cTstFrameState = RS232_FRAME_MD_DATA ;
+ /* if the frame is modem side, we just write whole data to ccci port */
+ META_LOG("[Meta] parse state: nRS232_FRAME_MD_DATA--: %d, total %d",input_len, m_uFrameLength);
+ return decodeMDFrame((void *)buf_ptr, input_len, ch,u16Length);
+ }
+ else if(ch >= RS232_INJECT_PRIMITIVE_OCTETMODEM2 && ch <= RS232_INJECT_PRIMITIVE_OCTETMODEM2_END)//0xA0 ~ A7
+ {
+ m_md_index = (ch - RS232_INJECT_PRIMITIVE_OCTETMODEM2)+1; //A0--1(MD2) A3--4(MD5)
+ m_cTstFrameState = RS232_FRAME_MD_DATA ;
+ /* if the frame is modem side, we just write whole data to ccci port */
+ META_LOG("[Meta] parse state: nRS232_FRAME_MD_DATA--: %d, total %d",input_len, m_uFrameLength);
+ return decodeMDFrame((void *)buf_ptr, input_len, ch,u16Length);
+ }
+ else if(ch >= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP && ch<= RS232_COMMAND_TYPE_MD2_MEMORY_DUMP_END)//0xC0 ~ 0xC7
+ {
+ m_md_index = (ch - RS232_COMMAND_TYPE_MD2_MEMORY_DUMP)+1;
+ m_cTstFrameState = RS232_FRAME_MD_DATA ;
+ /* if the frame is modem side, we just write whole data to ccci port */
+ META_LOG("[Meta] parse state: nRS232_FRAME_MD_DATA--: %d, total %d",input_len, m_uFrameLength);
+ return decodeMDFrame((void *)buf_ptr, input_len, ch,u16Length);
+ }
+ else if (ch ==RS232_INJECT_APPRIMITIVE_OCTET)//0x66
+ {
+ m_cTstFrameState = RS232_FRAME_AP_INJECT_PIRIMITIVE_HEADER;
+ m_sRs232Frame.received_prig_header_length = 0;
+ m_sRs232Frame.received_buf_para_length = 0;
+ m_sRs232Frame.inject_prim.local_len = 0;
+ m_sRs232Frame.inject_prim.peer_len = 0;
+ m_sRs232Frame.header_ptr = (unsigned char*)&m_sRs232Frame.inject_prim;
+ return decodeAPFrame( input_len,++src,u16Length);
+
+ }
+ else if(ch >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START &&
+ ch <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_END)//0xD0 ~ 0xD7
+ {
+ m_cTstFrameState = RS232_FRAME_MD_TUNNELING_DATA;
+ m_md_index = ch - RS232_COMMAND_TYPE_MD_DATA_TUNNEL_START;
+ return decodeLTE_C2KFrame(input_len,++src,ch,u16Length);
+ }
+#ifdef MTK_META_COMPRESS_SUPPORT
+ else if(ch >= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START &&
+ ch <= RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_END)//0xF0 ~ 0xF7
+ {
+ META_LOG("[Meta] compress meta frame");
+ m_cTstFrameState = RS232_FRAME_MD_TUNNELING_COMPRESS_DATA;
+ m_md_index = ch - RS232_COMMAND_TYPE_MD_DATA_TUNNEL_COMP_START;
+ return decodeLTE_C2KFrame(input_len,++src,ch,u16Length);
+ }
+#endif
+ else
+ {
+ m_cTstFrameState = RS232_FRAME_STX; //error reset
+ return NULL;
+ }
+
+
+}
+
+Frame *UsbRxWatcher::decodeLTE_C2KFrame(unsigned int input_len,unsigned char * src,unsigned char frmType,unsigned short &u16Length)
+{
+ unsigned char * local_ptr = src;
+ unsigned char ch;
+ int data_len = 0;
+ unsigned short newlen = m_uFrameLength;
+
+
+ META_LOG("[Meta] (decodeLTE_C2KFrame) input_len = %d, m_uFrameLength = %d",input_len,m_uFrameLength);
+
+ while(u16Length!=input_len)
+ {
+ ch = *local_ptr;
+ ++data_len;
+ ++ u16Length;
+
+ if ((getComType() == META_UART_COM) && (data_len != newlen + 1))
+ {
+ if(ch == 0x77)
+ {
+ if(u16Length == input_len)
+ return NULL;
+
+ ch = *(++local_ptr);
+ ++ data_len;
+ ++ u16Length;
+
+ if(getUARTEsc(ch) == 0)
+ {
+ META_LOG("[Meta] incorrect UART ESC (%d)\n", ch);
+ return NULL;
+ }
+
+ ++ newlen;
+ }
+ }
+
+ if (data_len == newlen + 1)
+ {
+ if(getMDChType(m_md_index) == FT_MODEM_CH_TUNNELING)
+ {
+ m_cTstFrameState = RS232_FRAME_STX;
+
+ //to check whether checksum is ESC.
+ if((int)input_len >= data_len + 3 + m_frm_len_byte) //start byte + data len + data type +checksum
+ {
+ if((getComType() == META_UART_COM) && (ch == 0x77))
+ {
+ ch = *(++local_ptr);
+ ++ u16Length;
+ if(getUARTEsc(ch) == 0)
+ {
+ META_LOG("[Meta] [case1] incorrect checksum ESC (%d)\n", ch);
+ return (new Frame());
+ }
+ }
+ else if(ch == MUX_KEY_WORD)
+ {
+ ch = *(++local_ptr);
+ ++ u16Length;
+ if(ch == 0x01)
+ ch = STX_OCTET;
+ else if(ch == MUX_KEY_WORD)
+ ch = MUX_KEY_WORD;
+ else
+ {
+ META_LOG("[Meta] [case2] incorrect checksum ESC (%d)\n", ch);
+ return (new Frame());
+ }
+ }
+ }
+ else
+ {
+ //0x77 or 0x5A is the latest byte, checksum is not completed, need to read 1 byte continue.
+ if(((getComType() == META_UART_COM) && (ch == 0x77)) || (ch == MUX_KEY_WORD))
+ {
+ META_LOG("[Meta]checksum is not completed, need to read 1 byte continue. ESC (%d)", ch);
+ return NULL;
+ }
+ }
+
+ META_LOG("[Meta] parse state: RS232_FRAME_CHECKSUM: checksum: %d, ch: %d",m_checksum, ch);
+
+ if(m_checksum != ch)
+ {
+ META_LOG("[Meta] LTE modem frame checksum error!");
+ return (new Frame());
+ }
+
+ m_checksum = STX_OCTET;
+ META_LOG("[Meta] (decodeLTE_C2KFrame) u16Length2 = %d",u16Length);
+
+ }
+ int len = flowControl(src, newlen);
+ return sendMdTask(src, len, frmType);
+ }
+ m_checksum ^= ch;
+ ++local_ptr;
+ }
+ return NULL;
+}
+
+unsigned char UsbRxWatcher::getUARTEsc(unsigned char &ch)
+{
+ int ret = 1;
+
+ switch(ch)
+ {
+ case 0x01:
+ ch = 0x11;
+ break;
+ case 0x02:
+ ch = 0x13;
+ break;
+ case 0x03:
+ ch = 0x77;
+ break;
+ default:
+ ret = 0;
+ break;
+ }
+
+ return ret;
+}
+
+bool UsbRxWatcher::uncompress(void *pdata, int len, char *uncompressed, int *uncompressed_len)
+{
+ META_LOG("[Meta] Uncompress starts\n");
+ char *pTempBuf = (char*) pdata;
+ char *pTempUncompBuf = (char*) uncompressed;
+ size_t max_uncompressed_len = 0;
+ size_t uncompressed_len_temp = *uncompressed_len;
+
+ snappy_status status = snappy_uncompressed_length(pTempBuf, len, &max_uncompressed_len);
+ if (status != SNAPPY_OK)
+ {
+ META_LOG("[Meta] error: Can not calculate uncompressed length. status: %d\n", status);
+ return false;
+ }
+
+ if (uncompressed_len_temp < max_uncompressed_len)
+ {
+ META_LOG("[Meta] error: snappy uncompression buffer is not enough. buffer size: %lu, max uncompressed len: %lu\n", uncompressed_len_temp, max_uncompressed_len);
+ return false;
+ }
+
+ META_LOG("[Meta] snappy uncompress starts. len: %d\n", len);
+ //dumpDataInHexString((const unsigned char *)pTempBuf,len,16);
+ status = snappy_uncompress((char*)pTempBuf, len, (char*)pTempUncompBuf, &uncompressed_len_temp);
+ if (status != SNAPPY_OK)
+ {
+ META_LOG("[Meta] error: Uncompression failed. status: %d\n", status);
+ return false;
+ }
+ //dumpDataInHexString((const unsigned char *)uncompressed, uncompressed_len_temp,16);
+ META_LOG("[Meta] snappy uncompress Done. uncomp_len: %lu\n", uncompressed_len_temp);
+ *uncompressed_len = (int) uncompressed_len_temp;
+ return true;
+}
+//////////////////////////////////////////////////////////////////////////
diff --git a/src/devtools/meta/src/common/src/tst_main.cpp b/src/devtools/meta/src/common/src/tst_main.cpp
new file mode 100644
index 0000000..981e5a5
--- /dev/null
+++ b/src/devtools/meta/src/common/src/tst_main.cpp
@@ -0,0 +1,73 @@
+#include <assert.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#ifdef IS_SUPPORT_SP
+#include <cutils/properties.h>
+#include <cutils/sockets.h>
+#endif
+
+#include <unistd.h>
+#include <syslog.h>
+
+#include "Modem.h"
+#include "SerPort.h"
+#include "MSocket.h"
+#include "UsbRxWatcher.h"
+#include "Context.h"
+#include "PortInterface.h"
+#include "LogDefine.h"
+
+int main(int argc, char** argv)
+{
+ openlog( "[META]", LOG_PID, LOG_DAEMON );
+
+ META_LOG("[Meta] Enter meta_tst init flow! V1.01.00");
+
+/*
+#ifndef MTK_META_APONLY
+ if(META_BOOT != getBootMode())
+ {
+ META_LOG("[Meta] not meta mode boot!");
+ return 0;
+ }
+#endif
+*/
+
+ umask(007);
+
+ UsbRxWatcher hostRx;
+ setVirtualRxWatcher(&hostRx);
+
+ SerPort *pPort = NULL;
+
+ META_LOG("[Meta] is meta mode");
+ pPort = createSerPort();
+ if (pPort != NULL)
+ {
+ pPort->pumpAsync(&hostRx);
+ }
+ else
+ {
+ META_LOG("[Meta] Enter meta_tst init fail");
+ }
+
+/*
+#ifndef MTK_META_APONLY
+ createAllModemThread();
+#endif
+*/
+ createAllModemThread();
+
+ while (1)
+ {
+ usleep(100*1000);
+ //querySerPortStatus(); //query port type change every 100ms
+ }
+
+ // infinite loop above; it'll never get here...
+ destroyContext();
+
+ return 0;
+}
diff --git a/src/devtools/meta/src/misc/snappy/snappy-c.cpp b/src/devtools/meta/src/misc/snappy/snappy-c.cpp
new file mode 100644
index 0000000..473a0b0
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-c.cpp
@@ -0,0 +1,90 @@
+// Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "snappy.h"
+#include "snappy-c.h"
+
+extern "C" {
+
+snappy_status snappy_compress(const char* input,
+ size_t input_length,
+ char* compressed,
+ size_t *compressed_length) {
+ if (*compressed_length < snappy_max_compressed_length(input_length)) {
+ return SNAPPY_BUFFER_TOO_SMALL;
+ }
+ snappy::RawCompress(input, input_length, compressed, compressed_length);
+ return SNAPPY_OK;
+}
+
+snappy_status snappy_uncompress(const char* compressed,
+ size_t compressed_length,
+ char* uncompressed,
+ size_t* uncompressed_length) {
+ size_t real_uncompressed_length;
+ if (!snappy::GetUncompressedLength(compressed,
+ compressed_length,
+ &real_uncompressed_length)) {
+ return SNAPPY_INVALID_INPUT;
+ }
+ if (*uncompressed_length < real_uncompressed_length) {
+ return SNAPPY_BUFFER_TOO_SMALL;
+ }
+ if (!snappy::RawUncompress(compressed, compressed_length, uncompressed)) {
+ return SNAPPY_INVALID_INPUT;
+ }
+ *uncompressed_length = real_uncompressed_length;
+ return SNAPPY_OK;
+}
+
+size_t snappy_max_compressed_length(size_t source_length) {
+ return snappy::MaxCompressedLength(source_length);
+}
+
+snappy_status snappy_uncompressed_length(const char *compressed,
+ size_t compressed_length,
+ size_t *result) {
+ if (snappy::GetUncompressedLength(compressed,
+ compressed_length,
+ result)) {
+ return SNAPPY_OK;
+ } else {
+ return SNAPPY_INVALID_INPUT;
+ }
+}
+
+snappy_status snappy_validate_compressed_buffer(const char *compressed,
+ size_t compressed_length) {
+ if (snappy::IsValidCompressedBuffer(compressed, compressed_length)) {
+ return SNAPPY_OK;
+ } else {
+ return SNAPPY_INVALID_INPUT;
+ }
+}
+
+} // extern "C"
diff --git a/src/devtools/meta/src/misc/snappy/snappy-c.h b/src/devtools/meta/src/misc/snappy/snappy-c.h
new file mode 100644
index 0000000..c6c2a86
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-c.h
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2011 Martin Gieseking <martin.gieseking@uos.de>.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Plain C interface (a wrapper around the C++ implementation).
+ */
+
+#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_
+#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+
+/*
+ * Return values; see the documentation for each function to know
+ * what each can return.
+ */
+typedef enum {
+ SNAPPY_OK = 0,
+ SNAPPY_INVALID_INPUT = 1,
+ SNAPPY_BUFFER_TOO_SMALL = 2
+} snappy_status;
+
+/*
+ * Takes the data stored in "input[0..input_length-1]" and stores
+ * it in the array pointed to by "compressed".
+ *
+ * <compressed_length> signals the space available in "compressed".
+ * If it is not at least equal to "snappy_max_compressed_length(input_length)",
+ * SNAPPY_BUFFER_TOO_SMALL is returned. After successful compression,
+ * <compressed_length> contains the true length of the compressed output,
+ * and SNAPPY_OK is returned.
+ *
+ * Example:
+ * size_t output_length = snappy_max_compressed_length(input_length);
+ * char* output = (char*)malloc(output_length);
+ * if (snappy_compress(input, input_length, output, &output_length)
+ * == SNAPPY_OK) {
+ * ... Process(output, output_length) ...
+ * }
+ * free(output);
+ */
+snappy_status snappy_compress(const char* input,
+ size_t input_length,
+ char* compressed,
+ size_t* compressed_length);
+
+/*
+ * Given data in "compressed[0..compressed_length-1]" generated by
+ * calling the snappy_compress routine, this routine stores
+ * the uncompressed data to
+ * uncompressed[0..uncompressed_length-1].
+ * Returns failure (a value not equal to SNAPPY_OK) if the message
+ * is corrupted and could not be decrypted.
+ *
+ * <uncompressed_length> signals the space available in "uncompressed".
+ * If it is not at least equal to the value returned by
+ * snappy_uncompressed_length for this stream, SNAPPY_BUFFER_TOO_SMALL
+ * is returned. After successful decompression, <uncompressed_length>
+ * contains the true length of the decompressed output.
+ *
+ * Example:
+ * size_t output_length;
+ * if (snappy_uncompressed_length(input, input_length, &output_length)
+ * != SNAPPY_OK) {
+ * ... fail ...
+ * }
+ * char* output = (char*)malloc(output_length);
+ * if (snappy_uncompress(input, input_length, output, &output_length)
+ * == SNAPPY_OK) {
+ * ... Process(output, output_length) ...
+ * }
+ * free(output);
+ */
+snappy_status snappy_uncompress(const char* compressed,
+ size_t compressed_length,
+ char* uncompressed,
+ size_t* uncompressed_length);
+
+/*
+ * Returns the maximal size of the compressed representation of
+ * input data that is "source_length" bytes in length.
+ */
+size_t snappy_max_compressed_length(size_t source_length);
+
+/*
+ * REQUIRES: "compressed[]" was produced by snappy_compress()
+ * Returns SNAPPY_OK and stores the length of the uncompressed data in
+ * *result normally. Returns SNAPPY_INVALID_INPUT on parsing error.
+ * This operation takes O(1) time.
+ */
+snappy_status snappy_uncompressed_length(const char* compressed,
+ size_t compressed_length,
+ size_t* result);
+
+/*
+ * Check if the contents of "compressed[]" can be uncompressed successfully.
+ * Does not return the uncompressed data; if so, returns SNAPPY_OK,
+ * or if not, returns SNAPPY_INVALID_INPUT.
+ * Takes time proportional to compressed_length, but is usually at least a
+ * factor of four faster than actual decompression.
+ */
+snappy_status snappy_validate_compressed_buffer(const char* compressed,
+ size_t compressed_length);
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+#endif /* UTIL_SNAPPY_OPENSOURCE_SNAPPY_C_H_ */
diff --git a/src/devtools/meta/src/misc/snappy/snappy-internal.h b/src/devtools/meta/src/misc/snappy/snappy-internal.h
new file mode 100644
index 0000000..c99d331
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-internal.h
@@ -0,0 +1,150 @@
+// Copyright 2008 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Internals shared between the Snappy implementation and its unittest.
+
+#ifndef UTIL_SNAPPY_SNAPPY_INTERNAL_H_
+#define UTIL_SNAPPY_SNAPPY_INTERNAL_H_
+
+#include "snappy-stubs-internal.h"
+
+namespace snappy {
+namespace internal {
+
+class WorkingMemory {
+ public:
+ WorkingMemory() : large_table_(NULL) { }
+ ~WorkingMemory() { delete[] large_table_; }
+
+ // Allocates and clears a hash table using memory in "*this",
+ // stores the number of buckets in "*table_size" and returns a pointer to
+ // the base of the hash table.
+ uint16* GetHashTable(size_t input_size, int* table_size);
+
+ private:
+ uint16 small_table_[1<<10]; // 2KB
+ uint16* large_table_; // Allocated only when needed
+
+ DISALLOW_COPY_AND_ASSIGN(WorkingMemory);
+};
+
+// Flat array compression that does not emit the "uncompressed length"
+// prefix. Compresses "input" string to the "*op" buffer.
+//
+// REQUIRES: "input_length <= kBlockSize"
+// REQUIRES: "op" points to an array of memory that is at least
+// "MaxCompressedLength(input_length)" in size.
+// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
+// REQUIRES: "table_size" is a power of two
+//
+// Returns an "end" pointer into "op" buffer.
+// "end - op" is the compressed size of "input".
+char* CompressFragment(const char* input,
+ size_t input_length,
+ char* op,
+ uint16* table,
+ const int table_size);
+
+// Return the largest n such that
+//
+// s1[0,n-1] == s2[0,n-1]
+// and n <= (s2_limit - s2).
+//
+// Does not read *s2_limit or beyond.
+// Does not read *(s1 + (s2_limit - s2)) or beyond.
+// Requires that s2_limit >= s2.
+//
+// Separate implementation for x86_64, for speed. Uses the fact that
+// x86_64 is little endian.
+#if defined(ARCH_K8)
+static inline int FindMatchLength(const char* s1,
+ const char* s2,
+ const char* s2_limit) {
+ assert(s2_limit >= s2);
+ int matched = 0;
+
+ // Find out how long the match is. We loop over the data 64 bits at a
+ // time until we find a 64-bit block that doesn't match; then we find
+ // the first non-matching bit and use that to calculate the total
+ // length of the match.
+ while (PREDICT_TRUE(s2 <= s2_limit - 8)) {
+ if (PREDICT_FALSE(UNALIGNED_LOAD64(s2) == UNALIGNED_LOAD64(s1 + matched))) {
+ s2 += 8;
+ matched += 8;
+ } else {
+ // On current (mid-2008) Opteron models there is a 3% more
+ // efficient code sequence to find the first non-matching byte.
+ // However, what follows is ~10% better on Intel Core 2 and newer,
+ // and we expect AMD's bsf instruction to improve.
+ uint64 x = UNALIGNED_LOAD64(s2) ^ UNALIGNED_LOAD64(s1 + matched);
+ int matching_bits = Bits::FindLSBSetNonZero64(x);
+ matched += matching_bits >> 3;
+ return matched;
+ }
+ }
+ while (PREDICT_TRUE(s2 < s2_limit)) {
+ if (PREDICT_TRUE(s1[matched] == *s2)) {
+ ++s2;
+ ++matched;
+ } else {
+ return matched;
+ }
+ }
+ return matched;
+}
+#else
+static inline int FindMatchLength(const char* s1,
+ const char* s2,
+ const char* s2_limit) {
+ // Implementation based on the x86-64 version, above.
+ assert(s2_limit >= s2);
+ int matched = 0;
+
+ while (s2 <= s2_limit - 4 &&
+ UNALIGNED_LOAD32(s2) == UNALIGNED_LOAD32(s1 + matched)) {
+ s2 += 4;
+ matched += 4;
+ }
+ if (LittleEndian::IsLittleEndian() && s2 <= s2_limit - 4) {
+ uint32 x = UNALIGNED_LOAD32(s2) ^ UNALIGNED_LOAD32(s1 + matched);
+ int matching_bits = Bits::FindLSBSetNonZero(x);
+ matched += matching_bits >> 3;
+ } else {
+ while ((s2 < s2_limit) && (s1[matched] == *s2)) {
+ ++s2;
+ ++matched;
+ }
+ }
+ return matched;
+}
+#endif
+
+} // end namespace internal
+} // end namespace snappy
+
+#endif // UTIL_SNAPPY_SNAPPY_INTERNAL_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy-sinksource.cpp b/src/devtools/meta/src/misc/snappy/snappy-sinksource.cpp
new file mode 100644
index 0000000..5844552
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-sinksource.cpp
@@ -0,0 +1,71 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string.h>
+
+#include "snappy-sinksource.h"
+
+namespace snappy {
+
+Source::~Source() { }
+
+Sink::~Sink() { }
+
+char* Sink::GetAppendBuffer(size_t length, char* scratch) {
+ return scratch;
+}
+
+ByteArraySource::~ByteArraySource() { }
+
+size_t ByteArraySource::Available() const { return left_; }
+
+const char* ByteArraySource::Peek(size_t* len) {
+ *len = left_;
+ return ptr_;
+}
+
+void ByteArraySource::Skip(size_t n) {
+ left_ -= n;
+ ptr_ += n;
+}
+
+UncheckedByteArraySink::~UncheckedByteArraySink() { }
+
+void UncheckedByteArraySink::Append(const char* data, size_t n) {
+ // Do no copying if the caller filled in the result of GetAppendBuffer()
+ if (data != dest_) {
+ memcpy(dest_, data, n);
+ }
+ dest_ += n;
+}
+
+char* UncheckedByteArraySink::GetAppendBuffer(size_t len, char* scratch) {
+ return dest_;
+}
+
+}
diff --git a/src/devtools/meta/src/misc/snappy/snappy-sinksource.h b/src/devtools/meta/src/misc/snappy/snappy-sinksource.h
new file mode 100644
index 0000000..faabfa1
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-sinksource.h
@@ -0,0 +1,137 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
+#define UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
+
+#include <stddef.h>
+
+
+namespace snappy {
+
+// A Sink is an interface that consumes a sequence of bytes.
+class Sink {
+ public:
+ Sink() { }
+ virtual ~Sink();
+
+ // Append "bytes[0,n-1]" to this.
+ virtual void Append(const char* bytes, size_t n) = 0;
+
+ // Returns a writable buffer of the specified length for appending.
+ // May return a pointer to the caller-owned scratch buffer which
+ // must have at least the indicated length. The returned buffer is
+ // only valid until the next operation on this Sink.
+ //
+ // After writing at most "length" bytes, call Append() with the
+ // pointer returned from this function and the number of bytes
+ // written. Many Append() implementations will avoid copying
+ // bytes if this function returned an internal buffer.
+ //
+ // If a non-scratch buffer is returned, the caller may only pass a
+ // prefix of it to Append(). That is, it is not correct to pass an
+ // interior pointer of the returned array to Append().
+ //
+ // The default implementation always returns the scratch buffer.
+ virtual char* GetAppendBuffer(size_t length, char* scratch);
+
+
+ private:
+ // No copying
+ Sink(const Sink&);
+ void operator=(const Sink&);
+};
+
+// A Source is an interface that yields a sequence of bytes
+class Source {
+ public:
+ Source() { }
+ virtual ~Source();
+
+ // Return the number of bytes left to read from the source
+ virtual size_t Available() const = 0;
+
+ // Peek at the next flat region of the source. Does not reposition
+ // the source. The returned region is empty iff Available()==0.
+ //
+ // Returns a pointer to the beginning of the region and store its
+ // length in *len.
+ //
+ // The returned region is valid until the next call to Skip() or
+ // until this object is destroyed, whichever occurs first.
+ //
+ // The returned region may be larger than Available() (for example
+ // if this ByteSource is a view on a substring of a larger source).
+ // The caller is responsible for ensuring that it only reads the
+ // Available() bytes.
+ virtual const char* Peek(size_t* len) = 0;
+
+ // Skip the next n bytes. Invalidates any buffer returned by
+ // a previous call to Peek().
+ // REQUIRES: Available() >= n
+ virtual void Skip(size_t n) = 0;
+
+ private:
+ // No copying
+ Source(const Source&);
+ void operator=(const Source&);
+};
+
+// A Source implementation that yields the contents of a flat array
+class ByteArraySource : public Source {
+ public:
+ ByteArraySource(const char* p, size_t n) : ptr_(p), left_(n) { }
+ virtual ~ByteArraySource();
+ virtual size_t Available() const;
+ virtual const char* Peek(size_t* len);
+ virtual void Skip(size_t n);
+ private:
+ const char* ptr_;
+ size_t left_;
+};
+
+// A Sink implementation that writes to a flat array without any bound checks.
+class UncheckedByteArraySink : public Sink {
+ public:
+ explicit UncheckedByteArraySink(char* dest) : dest_(dest) { }
+ virtual ~UncheckedByteArraySink();
+ virtual void Append(const char* data, size_t n);
+ virtual char* GetAppendBuffer(size_t len, char* scratch);
+
+ // Return the current output pointer so that a caller can see how
+ // many bytes were produced.
+ // Note: this is not a Sink method.
+ char* CurrentDestination() const { return dest_; }
+ private:
+ char* dest_;
+};
+
+
+}
+
+#endif // UTIL_SNAPPY_SNAPPY_SINKSOURCE_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.cpp b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.cpp
new file mode 100644
index 0000000..3822805
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.cpp
@@ -0,0 +1,42 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <string>
+#include <algorithm>
+
+#include "snappy-stubs-internal.h"
+
+namespace snappy {
+
+void Varint::Append32(string* s, uint32 value) {
+ char buf[Varint::kMax32];
+ const char* p = Varint::Encode32(buf, value);
+ s->append(buf, p - buf);
+}
+
+} // namespace snappy
diff --git a/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.h b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.h
new file mode 100644
index 0000000..12393b6
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-stubs-internal.h
@@ -0,0 +1,491 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Various stubs for the open-source version of Snappy.
+
+#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
+#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
+
+#include "snappy-stubs-public.h"
+
+#if defined(__x86_64__)
+
+// Enable 64-bit optimized versions of some routines.
+#define ARCH_K8 1
+
+#endif
+
+// Needed by OS X, among others.
+#ifndef MAP_ANONYMOUS
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
+// Pull in std::min, std::ostream, and the likes. This is safe because this
+// header file is never used from any public header files.
+using namespace std;
+
+// The size of an array, if known at compile-time.
+// Will give unexpected results if used on a pointer.
+// We undefine it first, since some compilers already have a definition.
+#ifdef ARRAYSIZE
+#undef ARRAYSIZE
+#endif
+#define ARRAYSIZE(a) (sizeof(a) / sizeof(*(a)))
+
+// Static prediction hints.
+#ifdef HAVE_BUILTIN_EXPECT
+#define PREDICT_FALSE(x) (__builtin_expect(x, 0))
+#define PREDICT_TRUE(x) (__builtin_expect(!!(x), 1))
+#else
+#define PREDICT_FALSE(x) x
+#define PREDICT_TRUE(x) x
+#endif
+
+// This is only used for recomputing the tag byte table used during
+// decompression; for simplicity we just remove it from the open-source
+// version (anyone who wants to regenerate it can just do the call
+// themselves within main()).
+#define DEFINE_bool(flag_name, default_value, description) \
+ bool FLAGS_ ## flag_name = default_value
+#define DECLARE_bool(flag_name) \
+ extern bool FLAGS_ ## flag_name
+
+namespace snappy {
+
+static const uint32 kuint32max = static_cast<uint32>(0xFFFFFFFF);
+static const int64 kint64max = static_cast<int64>(0x7FFFFFFFFFFFFFFFLL);
+
+// Potentially unaligned loads and stores.
+
+// x86 and PowerPC can simply do these loads and stores native.
+
+#if defined(__i386__) || defined(__x86_64__) || defined(__powerpc__)
+
+#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
+#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+#define UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64 *>(_p))
+
+#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+#define UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64 *>(_p) = (_val))
+
+// ARMv7 and newer support native unaligned accesses, but only of 16-bit
+// and 32-bit values (not 64-bit); older versions either raise a fatal signal,
+// do an unaligned read and rotate the words around a bit, or do the reads very
+// slowly (trip through kernel mode). There's no simple #define that says just
+// “ARMv7 or higher”, so we have to filter away all ARMv5 and ARMv6
+// sub-architectures.
+//
+// This is a mess, but there's not much we can do about it.
+
+#elif defined(__arm__) && \
+ !defined(__ARM_ARCH_4__) && \
+ !defined(__ARM_ARCH_4T__) && \
+ !defined(__ARM_ARCH_5__) && \
+ !defined(__ARM_ARCH_5T__) && \
+ !defined(__ARM_ARCH_5TE__) && \
+ !defined(__ARM_ARCH_5TEJ__) && \
+ !defined(__ARM_ARCH_6__) && \
+ !defined(__ARM_ARCH_6J__) && \
+ !defined(__ARM_ARCH_6K__) && \
+ !defined(__ARM_ARCH_6Z__) && \
+ !defined(__ARM_ARCH_6ZK__) && \
+ !defined(__ARM_ARCH_6T2__)
+
+#define UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16 *>(_p))
+#define UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32 *>(_p))
+
+#define UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16 *>(_p) = (_val))
+#define UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32 *>(_p) = (_val))
+
+// TODO(user): NEON supports unaligned 64-bit loads and stores.
+// See if that would be more efficient on platforms supporting it,
+// at least for copies.
+
+inline uint64 UNALIGNED_LOAD64(const void *p) {
+ uint64 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline void UNALIGNED_STORE64(void *p, uint64 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+#else
+
+// These functions are provided for architectures that don't support
+// unaligned loads and stores.
+
+inline uint16 UNALIGNED_LOAD16(const void *p) {
+ uint16 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline uint32 UNALIGNED_LOAD32(const void *p) {
+ uint32 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline uint64 UNALIGNED_LOAD64(const void *p) {
+ uint64 t;
+ memcpy(&t, p, sizeof t);
+ return t;
+}
+
+inline void UNALIGNED_STORE16(void *p, uint16 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+inline void UNALIGNED_STORE32(void *p, uint32 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+inline void UNALIGNED_STORE64(void *p, uint64 v) {
+ memcpy(p, &v, sizeof v);
+}
+
+#endif
+
+// This can be more efficient than UNALIGNED_LOAD64 + UNALIGNED_STORE64
+// on some platforms, in particular ARM.
+inline void UnalignedCopy64(const void *src, void *dst) {
+ if (sizeof(void *) == 8) {
+ UNALIGNED_STORE64(dst, UNALIGNED_LOAD64(src));
+ } else {
+ const char *src_char = reinterpret_cast<const char *>(src);
+ char *dst_char = reinterpret_cast<char *>(dst);
+
+ UNALIGNED_STORE32(dst_char, UNALIGNED_LOAD32(src_char));
+ UNALIGNED_STORE32(dst_char + 4, UNALIGNED_LOAD32(src_char + 4));
+ }
+}
+
+// The following guarantees declaration of the byte swap functions.
+#ifdef WORDS_BIGENDIAN
+
+#ifdef HAVE_SYS_BYTEORDER_H
+#include <sys/byteorder.h>
+#endif
+
+#ifdef HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+
+#ifdef _MSC_VER
+#include <stdlib.h>
+#define bswap_16(x) _byteswap_ushort(x)
+#define bswap_32(x) _byteswap_ulong(x)
+#define bswap_64(x) _byteswap_uint64(x)
+
+#elif defined(__APPLE__)
+// Mac OS X / Darwin features
+#include <libkern/OSByteOrder.h>
+#define bswap_16(x) OSSwapInt16(x)
+#define bswap_32(x) OSSwapInt32(x)
+#define bswap_64(x) OSSwapInt64(x)
+
+#elif defined(HAVE_BYTESWAP_H)
+#include <byteswap.h>
+
+#elif defined(bswap32)
+// FreeBSD defines bswap{16,32,64} in <sys/endian.h> (already #included).
+#define bswap_16(x) bswap16(x)
+#define bswap_32(x) bswap32(x)
+#define bswap_64(x) bswap64(x)
+
+#elif defined(BSWAP_64)
+// Solaris 10 defines BSWAP_{16,32,64} in <sys/byteorder.h> (already #included).
+#define bswap_16(x) BSWAP_16(x)
+#define bswap_32(x) BSWAP_32(x)
+#define bswap_64(x) BSWAP_64(x)
+
+#else
+
+inline uint16 bswap_16(uint16 x) {
+ return (x << 8) | (x >> 8);
+}
+
+inline uint32 bswap_32(uint32 x) {
+ x = ((x & 0xff00ff00UL) >> 8) | ((x & 0x00ff00ffUL) << 8);
+ return (x >> 16) | (x << 16);
+}
+
+inline uint64 bswap_64(uint64 x) {
+ x = ((x & 0xff00ff00ff00ff00ULL) >> 8) | ((x & 0x00ff00ff00ff00ffULL) << 8);
+ x = ((x & 0xffff0000ffff0000ULL) >> 16) | ((x & 0x0000ffff0000ffffULL) << 16);
+ return (x >> 32) | (x << 32);
+}
+
+#endif
+
+#endif // WORDS_BIGENDIAN
+
+// Convert to little-endian storage, opposite of network format.
+// Convert x from host to little endian: x = LittleEndian.FromHost(x);
+// convert x from little endian to host: x = LittleEndian.ToHost(x);
+//
+// Store values into unaligned memory converting to little endian order:
+// LittleEndian.Store16(p, x);
+//
+// Load unaligned values stored in little endian converting to host order:
+// x = LittleEndian.Load16(p);
+class LittleEndian {
+ public:
+ // Conversion functions.
+#ifdef WORDS_BIGENDIAN
+
+ static uint16 FromHost16(uint16 x) { return bswap_16(x); }
+ static uint16 ToHost16(uint16 x) { return bswap_16(x); }
+
+ static uint32 FromHost32(uint32 x) { return bswap_32(x); }
+ static uint32 ToHost32(uint32 x) { return bswap_32(x); }
+
+ static bool IsLittleEndian() { return false; }
+
+#else // !defined(WORDS_BIGENDIAN)
+
+ static uint16 FromHost16(uint16 x) { return x; }
+ static uint16 ToHost16(uint16 x) { return x; }
+
+ static uint32 FromHost32(uint32 x) { return x; }
+ static uint32 ToHost32(uint32 x) { return x; }
+
+ static bool IsLittleEndian() { return true; }
+
+#endif // !defined(WORDS_BIGENDIAN)
+
+ // Functions to do unaligned loads and stores in little-endian order.
+ static uint16 Load16(const void *p) {
+ return ToHost16(UNALIGNED_LOAD16(p));
+ }
+
+ static void Store16(void *p, uint16 v) {
+ UNALIGNED_STORE16(p, FromHost16(v));
+ }
+
+ static uint32 Load32(const void *p) {
+ return ToHost32(UNALIGNED_LOAD32(p));
+ }
+
+ static void Store32(void *p, uint32 v) {
+ UNALIGNED_STORE32(p, FromHost32(v));
+ }
+};
+
+// Some bit-manipulation functions.
+class Bits {
+ public:
+ // Return floor(log2(n)) for positive integer n. Returns -1 iff n == 0.
+ static int Log2Floor(uint32 n);
+
+ // Return the first set least / most significant bit, 0-indexed. Returns an
+ // undefined value if n == 0. FindLSBSetNonZero() is similar to ffs() except
+ // that it's 0-indexed.
+ static int FindLSBSetNonZero(uint32 n);
+ static int FindLSBSetNonZero64(uint64 n);
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(Bits);
+};
+
+#ifdef HAVE_BUILTIN_CTZ
+
+inline int Bits::Log2Floor(uint32 n) {
+ return n == 0 ? -1 : 31 ^ __builtin_clz(n);
+}
+
+inline int Bits::FindLSBSetNonZero(uint32 n) {
+ return __builtin_ctz(n);
+}
+
+inline int Bits::FindLSBSetNonZero64(uint64 n) {
+ return __builtin_ctzll(n);
+}
+
+#else // Portable versions.
+
+inline int Bits::Log2Floor(uint32 n) {
+ if (n == 0)
+ return -1;
+ int log = 0;
+ uint32 value = n;
+ for (int i = 4; i >= 0; --i) {
+ int shift = (1 << i);
+ uint32 x = value >> shift;
+ if (x != 0) {
+ value = x;
+ log += shift;
+ }
+ }
+ assert(value == 1);
+ return log;
+}
+
+inline int Bits::FindLSBSetNonZero(uint32 n) {
+ int rc = 31;
+ for (int i = 4, shift = 1 << 4; i >= 0; --i) {
+ const uint32 x = n << shift;
+ if (x != 0) {
+ n = x;
+ rc -= shift;
+ }
+ shift >>= 1;
+ }
+ return rc;
+}
+
+// FindLSBSetNonZero64() is defined in terms of FindLSBSetNonZero().
+inline int Bits::FindLSBSetNonZero64(uint64 n) {
+ const uint32 bottombits = static_cast<uint32>(n);
+ if (bottombits == 0) {
+ // Bottom bits are zero, so scan in top bits
+ return 32 + FindLSBSetNonZero(static_cast<uint32>(n >> 32));
+ } else {
+ return FindLSBSetNonZero(bottombits);
+ }
+}
+
+#endif // End portable versions.
+
+// Variable-length integer encoding.
+class Varint {
+ public:
+ // Maximum lengths of varint encoding of uint32.
+ static const int kMax32 = 5;
+
+ // Attempts to parse a varint32 from a prefix of the bytes in [ptr,limit-1].
+ // Never reads a character at or beyond limit. If a valid/terminated varint32
+ // was found in the range, stores it in *OUTPUT and returns a pointer just
+ // past the last byte of the varint32. Else returns NULL. On success,
+ // "result <= limit".
+ static const char* Parse32WithLimit(const char* ptr, const char* limit,
+ uint32* OUTPUT);
+
+ // REQUIRES "ptr" points to a buffer of length sufficient to hold "v".
+ // EFFECTS Encodes "v" into "ptr" and returns a pointer to the
+ // byte just past the last encoded byte.
+ static char* Encode32(char* ptr, uint32 v);
+
+ // EFFECTS Appends the varint representation of "value" to "*s".
+ static void Append32(string* s, uint32 value);
+};
+
+inline const char* Varint::Parse32WithLimit(const char* p,
+ const char* l,
+ uint32* OUTPUT) {
+ const unsigned char* ptr = reinterpret_cast<const unsigned char*>(p);
+ const unsigned char* limit = reinterpret_cast<const unsigned char*>(l);
+ uint32 b, result;
+ if (ptr >= limit) return NULL;
+ b = *(ptr++); result = b & 127; if (b < 128) goto done;
+ if (ptr >= limit) return NULL;
+ b = *(ptr++); result |= (b & 127) << 7; if (b < 128) goto done;
+ if (ptr >= limit) return NULL;
+ b = *(ptr++); result |= (b & 127) << 14; if (b < 128) goto done;
+ if (ptr >= limit) return NULL;
+ b = *(ptr++); result |= (b & 127) << 21; if (b < 128) goto done;
+ if (ptr >= limit) return NULL;
+ b = *(ptr++); result |= (b & 127) << 28; if (b < 16) goto done;
+ return NULL; // Value is too long to be a varint32
+ done:
+ *OUTPUT = result;
+ return reinterpret_cast<const char*>(ptr);
+}
+
+inline char* Varint::Encode32(char* sptr, uint32 v) {
+ // Operate on characters as unsigneds
+ unsigned char* ptr = reinterpret_cast<unsigned char*>(sptr);
+ static const int B = 128;
+ if (v < (1<<7)) {
+ *(ptr++) = v;
+ } else if (v < (1<<14)) {
+ *(ptr++) = v | B;
+ *(ptr++) = v>>7;
+ } else if (v < (1<<21)) {
+ *(ptr++) = v | B;
+ *(ptr++) = (v>>7) | B;
+ *(ptr++) = v>>14;
+ } else if (v < (1<<28)) {
+ *(ptr++) = v | B;
+ *(ptr++) = (v>>7) | B;
+ *(ptr++) = (v>>14) | B;
+ *(ptr++) = v>>21;
+ } else {
+ *(ptr++) = v | B;
+ *(ptr++) = (v>>7) | B;
+ *(ptr++) = (v>>14) | B;
+ *(ptr++) = (v>>21) | B;
+ *(ptr++) = v>>28;
+ }
+ return reinterpret_cast<char*>(ptr);
+}
+
+// If you know the internal layout of the std::string in use, you can
+// replace this function with one that resizes the string without
+// filling the new space with zeros (if applicable) --
+// it will be non-portable but faster.
+inline void STLStringResizeUninitialized(string* s, size_t new_size) {
+ s->resize(new_size);
+}
+
+// Return a mutable char* pointing to a string's internal buffer,
+// which may not be null-terminated. Writing through this pointer will
+// modify the string.
+//
+// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
+// next call to a string method that invalidates iterators.
+//
+// As of 2006-04, there is no standard-blessed way of getting a
+// mutable reference to a string's internal buffer. However, issue 530
+// (http://www.open-std.org/JTC1/SC22/WG21/docs/lwg-defects.html#530)
+// proposes this as the method. It will officially be part of the standard
+// for C++0x. This should already work on all current implementations.
+inline char* string_as_array(string* str) {
+ return str->empty() ? NULL : &*str->begin();
+}
+
+} // namespace snappy
+
+#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_INTERNAL_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy-stubs-public.h b/src/devtools/meta/src/misc/snappy/snappy-stubs-public.h
new file mode 100644
index 0000000..2db0373
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy-stubs-public.h
@@ -0,0 +1,98 @@
+// Copyright 2011 Google Inc. All Rights Reserved.
+// Author: sesse@google.com (Steinar H. Gunderson)
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Various type stubs for the open-source version of Snappy.
+//
+// This file cannot include config.h, as it is included from snappy.h,
+// which is a public header. Instead, snappy-stubs-public.h is generated by
+// from snappy-stubs-public.h.in at configure time.
+
+#ifndef UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
+#define UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
+
+#if 1
+#include <stdint.h>
+#endif
+
+#if 1
+#include <stddef.h>
+#endif
+
+#if 0
+#include <sys/uio.h>
+#endif
+
+#define SNAPPY_MAJOR 1
+#define SNAPPY_MINOR 1
+#define SNAPPY_PATCHLEVEL 2
+#define SNAPPY_VERSION \
+ ((SNAPPY_MAJOR << 16) | (SNAPPY_MINOR << 8) | SNAPPY_PATCHLEVEL)
+
+#include <string>
+
+namespace snappy {
+
+#if 1
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
+#else
+typedef signed char int8;
+typedef unsigned char uint8;
+typedef short int16;
+typedef unsigned short uint16;
+typedef int int32;
+typedef unsigned int uint32;
+typedef long long int64;
+typedef unsigned long long uint64;
+#endif
+
+typedef std::string string;
+
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&); \
+ void operator=(const TypeName&)
+
+#if !0
+// Windows does not have an iovec type, yet the concept is universally useful.
+// It is simple to define it ourselves, so we put it inside our own namespace.
+struct iovec {
+ void* iov_base;
+ size_t iov_len;
+};
+#endif
+
+} // namespace snappy
+
+#endif // UTIL_SNAPPY_OPENSOURCE_SNAPPY_STUBS_PUBLIC_H_
diff --git a/src/devtools/meta/src/misc/snappy/snappy.cpp b/src/devtools/meta/src/misc/snappy/snappy.cpp
new file mode 100644
index 0000000..02982f5
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy.cpp
@@ -0,0 +1,1305 @@
+// Copyright 2005 Google Inc. All Rights Reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "snappy.h"
+#include "snappy-internal.h"
+#include "snappy-sinksource.h"
+
+#include <stdio.h>
+
+#include <algorithm>
+#include <string>
+#include <vector>
+
+namespace snappy {
+
+// Any hash function will produce a valid compressed bitstream, but a good
+// hash function reduces the number of collisions and thus yields better
+// compression for compressible input, and more speed for incompressible
+// input. Of course, it doesn't hurt if the hash function is reasonably fast
+// either, as it gets called a lot.
+static inline uint32 HashBytes(uint32 bytes, int shift) {
+ uint32 kMul = 0x1e35a7bd;
+ return (bytes * kMul) >> shift;
+}
+static inline uint32 Hash(const char* p, int shift) {
+ return HashBytes(UNALIGNED_LOAD32(p), shift);
+}
+
+size_t MaxCompressedLength(size_t source_len) {
+ // Compressed data can be defined as:
+ // compressed := item* literal*
+ // item := literal* copy
+ //
+ // The trailing literal sequence has a space blowup of at most 62/60
+ // since a literal of length 60 needs one tag byte + one extra byte
+ // for length information.
+ //
+ // Item blowup is trickier to measure. Suppose the "copy" op copies
+ // 4 bytes of data. Because of a special check in the encoding code,
+ // we produce a 4-byte copy only if the offset is < 65536. Therefore
+ // the copy op takes 3 bytes to encode, and this type of item leads
+ // to at most the 62/60 blowup for representing literals.
+ //
+ // Suppose the "copy" op copies 5 bytes of data. If the offset is big
+ // enough, it will take 5 bytes to encode the copy op. Therefore the
+ // worst case here is a one-byte literal followed by a five-byte copy.
+ // I.e., 6 bytes of input turn into 7 bytes of "compressed" data.
+ //
+ // This last factor dominates the blowup, so the final estimate is:
+ return 32 + source_len + source_len/6;
+}
+
+enum {
+ LITERAL = 0,
+ COPY_1_BYTE_OFFSET = 1, // 3 bit length + 3 bits of offset in opcode
+ COPY_2_BYTE_OFFSET = 2,
+ COPY_4_BYTE_OFFSET = 3
+};
+static const int kMaximumTagLength = 5; // COPY_4_BYTE_OFFSET plus the actual offset.
+
+// Copy "len" bytes from "src" to "op", one byte at a time. Used for
+// handling COPY operations where the input and output regions may
+// overlap. For example, suppose:
+// src == "ab"
+// op == src + 2
+// len == 20
+// After IncrementalCopy(src, op, len), the result will have
+// eleven copies of "ab"
+// ababababababababababab
+// Note that this does not match the semantics of either memcpy()
+// or memmove().
+static inline void IncrementalCopy(const char* src, char* op, ssize_t len) {
+ assert(len > 0);
+ do {
+ *op++ = *src++;
+ } while (--len > 0);
+}
+
+// Equivalent to IncrementalCopy except that it can write up to ten extra
+// bytes after the end of the copy, and that it is faster.
+//
+// The main part of this loop is a simple copy of eight bytes at a time until
+// we've copied (at least) the requested amount of bytes. However, if op and
+// src are less than eight bytes apart (indicating a repeating pattern of
+// length < 8), we first need to expand the pattern in order to get the correct
+// results. For instance, if the buffer looks like this, with the eight-byte
+// <src> and <op> patterns marked as intervals:
+//
+// abxxxxxxxxxxxx
+// [------] src
+// [------] op
+//
+// a single eight-byte copy from <src> to <op> will repeat the pattern once,
+// after which we can move <op> two bytes without moving <src>:
+//
+// ababxxxxxxxxxx
+// [------] src
+// [------] op
+//
+// and repeat the exercise until the two no longer overlap.
+//
+// This allows us to do very well in the special case of one single byte
+// repeated many times, without taking a big hit for more general cases.
+//
+// The worst case of extra writing past the end of the match occurs when
+// op - src == 1 and len == 1; the last copy will read from byte positions
+// [0..7] and write to [4..11], whereas it was only supposed to write to
+// position 1. Thus, ten excess bytes.
+
+namespace {
+
+const int kMaxIncrementCopyOverflow = 10;
+
+inline void IncrementalCopyFastPath(const char* src, char* op, ssize_t len) {
+ while (op - src < 8) {
+ UnalignedCopy64(src, op);
+ len -= op - src;
+ op += op - src;
+ }
+ while (len > 0) {
+ UnalignedCopy64(src, op);
+ src += 8;
+ op += 8;
+ len -= 8;
+ }
+}
+
+} // namespace
+
+static inline char* EmitLiteral(char* op,
+ const char* literal,
+ int len,
+ bool allow_fast_path) {
+ int n = len - 1; // Zero-length literals are disallowed
+ if (n < 60) {
+ // Fits in tag byte
+ *op++ = LITERAL | (n << 2);
+
+ // The vast majority of copies are below 16 bytes, for which a
+ // call to memcpy is overkill. This fast path can sometimes
+ // copy up to 15 bytes too much, but that is okay in the
+ // main loop, since we have a bit to go on for both sides:
+ //
+ // - The input will always have kInputMarginBytes = 15 extra
+ // available bytes, as long as we're in the main loop, and
+ // if not, allow_fast_path = false.
+ // - The output will always have 32 spare bytes (see
+ // MaxCompressedLength).
+ if (allow_fast_path && len <= 16) {
+ UnalignedCopy64(literal, op);
+ UnalignedCopy64(literal + 8, op + 8);
+ return op + len;
+ }
+ } else {
+ // Encode in upcoming bytes
+ char* base = op;
+ int count = 0;
+ op++;
+ while (n > 0) {
+ *op++ = n & 0xff;
+ n >>= 8;
+ count++;
+ }
+ assert(count >= 1);
+ assert(count <= 4);
+ *base = LITERAL | ((59+count) << 2);
+ }
+ memcpy(op, literal, len);
+ return op + len;
+}
+
+static inline char* EmitCopyLessThan64(char* op, size_t offset, int len) {
+ assert(len <= 64);
+ assert(len >= 4);
+ assert(offset < 65536);
+
+ if ((len < 12) && (offset < 2048)) {
+ size_t len_minus_4 = len - 4;
+ assert(len_minus_4 < 8); // Must fit in 3 bits
+ *op++ = COPY_1_BYTE_OFFSET + ((len_minus_4) << 2) + ((offset >> 8) << 5);
+ *op++ = offset & 0xff;
+ } else {
+ *op++ = COPY_2_BYTE_OFFSET + ((len-1) << 2);
+ LittleEndian::Store16(op, offset);
+ op += 2;
+ }
+ return op;
+}
+
+static inline char* EmitCopy(char* op, size_t offset, int len) {
+ // Emit 64 byte copies but make sure to keep at least four bytes reserved
+ while (len >= 68) {
+ op = EmitCopyLessThan64(op, offset, 64);
+ len -= 64;
+ }
+
+ // Emit an extra 60 byte copy if have too much data to fit in one copy
+ if (len > 64) {
+ op = EmitCopyLessThan64(op, offset, 60);
+ len -= 60;
+ }
+
+ // Emit remainder
+ op = EmitCopyLessThan64(op, offset, len);
+ return op;
+}
+
+
+bool GetUncompressedLength(const char* start, size_t n, size_t* result) {
+ uint32 v = 0;
+ const char* limit = start + n;
+ if (Varint::Parse32WithLimit(start, limit, &v) != NULL) {
+ *result = v;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+namespace internal {
+uint16* WorkingMemory::GetHashTable(size_t input_size, int* table_size) {
+ // Use smaller hash table when input.size() is smaller, since we
+ // fill the table, incurring O(hash table size) overhead for
+ // compression, and if the input is short, we won't need that
+ // many hash table entries anyway.
+ assert(kMaxHashTableSize >= 256);
+ size_t htsize = 256;
+ while (htsize < kMaxHashTableSize && htsize < input_size) {
+ htsize <<= 1;
+ }
+
+ uint16* table;
+ if (htsize <= ARRAYSIZE(small_table_)) {
+ table = small_table_;
+ } else {
+ if (large_table_ == NULL) {
+ large_table_ = new uint16[kMaxHashTableSize];
+ }
+ table = large_table_;
+ }
+
+ *table_size = htsize;
+ memset(table, 0, htsize * sizeof(*table));
+ return table;
+}
+} // end namespace internal
+
+// For 0 <= offset <= 4, GetUint32AtOffset(GetEightBytesAt(p), offset) will
+// equal UNALIGNED_LOAD32(p + offset). Motivation: On x86-64 hardware we have
+// empirically found that overlapping loads such as
+// UNALIGNED_LOAD32(p) ... UNALIGNED_LOAD32(p+1) ... UNALIGNED_LOAD32(p+2)
+// are slower than UNALIGNED_LOAD64(p) followed by shifts and casts to uint32.
+//
+// We have different versions for 64- and 32-bit; ideally we would avoid the
+// two functions and just inline the UNALIGNED_LOAD64 call into
+// GetUint32AtOffset, but GCC (at least not as of 4.6) is seemingly not clever
+// enough to avoid loading the value multiple times then. For 64-bit, the load
+// is done when GetEightBytesAt() is called, whereas for 32-bit, the load is
+// done at GetUint32AtOffset() time.
+
+#ifdef ARCH_K8
+
+typedef uint64 EightBytesReference;
+
+static inline EightBytesReference GetEightBytesAt(const char* ptr) {
+ return UNALIGNED_LOAD64(ptr);
+}
+
+static inline uint32 GetUint32AtOffset(uint64 v, int offset) {
+ assert(offset >= 0);
+ assert(offset <= 4);
+ return v >> (LittleEndian::IsLittleEndian() ? 8 * offset : 32 - 8 * offset);
+}
+
+#else
+
+typedef const char* EightBytesReference;
+
+static inline EightBytesReference GetEightBytesAt(const char* ptr) {
+ return ptr;
+}
+
+static inline uint32 GetUint32AtOffset(const char* v, int offset) {
+ assert(offset >= 0);
+ assert(offset <= 4);
+ return UNALIGNED_LOAD32(v + offset);
+}
+
+#endif
+
+// Flat array compression that does not emit the "uncompressed length"
+// prefix. Compresses "input" string to the "*op" buffer.
+//
+// REQUIRES: "input" is at most "kBlockSize" bytes long.
+// REQUIRES: "op" points to an array of memory that is at least
+// "MaxCompressedLength(input.size())" in size.
+// REQUIRES: All elements in "table[0..table_size-1]" are initialized to zero.
+// REQUIRES: "table_size" is a power of two
+//
+// Returns an "end" pointer into "op" buffer.
+// "end - op" is the compressed size of "input".
+namespace internal {
+char* CompressFragment(const char* input,
+ size_t input_size,
+ char* op,
+ uint16* table,
+ const int table_size) {
+ // "ip" is the input pointer, and "op" is the output pointer.
+ const char* ip = input;
+ assert(input_size <= kBlockSize);
+ assert((table_size & (table_size - 1)) == 0); // table must be power of two
+ const int shift = 32 - Bits::Log2Floor(table_size);
+ assert(static_cast<int>(kuint32max >> shift) == table_size - 1);
+ const char* ip_end = input + input_size;
+ const char* base_ip = ip;
+ // Bytes in [next_emit, ip) will be emitted as literal bytes. Or
+ // [next_emit, ip_end) after the main loop.
+ const char* next_emit = ip;
+
+ const size_t kInputMarginBytes = 15;
+ if (PREDICT_TRUE(input_size >= kInputMarginBytes)) {
+ const char* ip_limit = input + input_size - kInputMarginBytes;
+
+ for (uint32 next_hash = Hash(++ip, shift); ; ) {
+ assert(next_emit < ip);
+ // The body of this loop calls EmitLiteral once and then EmitCopy one or
+ // more times. (The exception is that when we're close to exhausting
+ // the input we goto emit_remainder.)
+ //
+ // In the first iteration of this loop we're just starting, so
+ // there's nothing to copy, so calling EmitLiteral once is
+ // necessary. And we only start a new iteration when the
+ // current iteration has determined that a call to EmitLiteral will
+ // precede the next call to EmitCopy (if any).
+ //
+ // Step 1: Scan forward in the input looking for a 4-byte-long match.
+ // If we get close to exhausting the input then goto emit_remainder.
+ //
+ // Heuristic match skipping: If 32 bytes are scanned with no matches
+ // found, start looking only at every other byte. If 32 more bytes are
+ // scanned, look at every third byte, etc.. When a match is found,
+ // immediately go back to looking at every byte. This is a small loss
+ // (~5% performance, ~0.1% density) for compressible data due to more
+ // bookkeeping, but for non-compressible data (such as JPEG) it's a huge
+ // win since the compressor quickly "realizes" the data is incompressible
+ // and doesn't bother looking for matches everywhere.
+ //
+ // The "skip" variable keeps track of how many bytes there are since the
+ // last match; dividing it by 32 (ie. right-shifting by five) gives the
+ // number of bytes to move ahead for each iteration.
+ uint32 skip = 32;
+
+ const char* next_ip = ip;
+ const char* candidate;
+ do {
+ ip = next_ip;
+ uint32 hash = next_hash;
+ assert(hash == Hash(ip, shift));
+ uint32 bytes_between_hash_lookups = skip++ >> 5;
+ next_ip = ip + bytes_between_hash_lookups;
+ if (PREDICT_FALSE(next_ip > ip_limit)) {
+ goto emit_remainder;
+ }
+ next_hash = Hash(next_ip, shift);
+ candidate = base_ip + table[hash];
+ assert(candidate >= base_ip);
+ assert(candidate < ip);
+
+ table[hash] = ip - base_ip;
+ } while (PREDICT_TRUE(UNALIGNED_LOAD32(ip) !=
+ UNALIGNED_LOAD32(candidate)));
+
+ // Step 2: A 4-byte match has been found. We'll later see if more
+ // than 4 bytes match. But, prior to the match, input
+ // bytes [next_emit, ip) are unmatched. Emit them as "literal bytes."
+ assert(next_emit + 16 <= ip_end);
+ op = EmitLiteral(op, next_emit, ip - next_emit, true);
+
+ // Step 3: Call EmitCopy, and then see if another EmitCopy could
+ // be our next move. Repeat until we find no match for the
+ // input immediately after what was consumed by the last EmitCopy call.
+ //
+ // If we exit this loop normally then we need to call EmitLiteral next,
+ // though we don't yet know how big the literal will be. We handle that
+ // by proceeding to the next iteration of the main loop. We also can exit
+ // this loop via goto if we get close to exhausting the input.
+ EightBytesReference input_bytes;
+ uint32 candidate_bytes = 0;
+
+ do {
+ // We have a 4-byte match at ip, and no need to emit any
+ // "literal bytes" prior to ip.
+ const char* base = ip;
+ int matched = 4 + FindMatchLength(candidate + 4, ip + 4, ip_end);
+ ip += matched;
+ size_t offset = base - candidate;
+ assert(0 == memcmp(base, candidate, matched));
+ op = EmitCopy(op, offset, matched);
+ // We could immediately start working at ip now, but to improve
+ // compression we first update table[Hash(ip - 1, ...)].
+ const char* insert_tail = ip - 1;
+ next_emit = ip;
+ if (PREDICT_FALSE(ip >= ip_limit)) {
+ goto emit_remainder;
+ }
+ input_bytes = GetEightBytesAt(insert_tail);
+ uint32 prev_hash = HashBytes(GetUint32AtOffset(input_bytes, 0), shift);
+ table[prev_hash] = ip - base_ip - 1;
+ uint32 cur_hash = HashBytes(GetUint32AtOffset(input_bytes, 1), shift);
+ candidate = base_ip + table[cur_hash];
+ candidate_bytes = UNALIGNED_LOAD32(candidate);
+ table[cur_hash] = ip - base_ip;
+ } while (GetUint32AtOffset(input_bytes, 1) == candidate_bytes);
+
+ next_hash = HashBytes(GetUint32AtOffset(input_bytes, 2), shift);
+ ++ip;
+ }
+ }
+
+ emit_remainder:
+ // Emit the remaining bytes as a literal
+ if (next_emit < ip_end) {
+ op = EmitLiteral(op, next_emit, ip_end - next_emit, false);
+ }
+
+ return op;
+}
+} // end namespace internal
+
+// Signature of output types needed by decompression code.
+// The decompression code is templatized on a type that obeys this
+// signature so that we do not pay virtual function call overhead in
+// the middle of a tight decompression loop.
+//
+// class DecompressionWriter {
+// public:
+// // Called before decompression
+// void SetExpectedLength(size_t length);
+//
+// // Called after decompression
+// bool CheckLength() const;
+//
+// // Called repeatedly during decompression
+// bool Append(const char* ip, size_t length);
+// bool AppendFromSelf(uint32 offset, size_t length);
+//
+// // The rules for how TryFastAppend differs from Append are somewhat
+// // convoluted:
+// //
+// // - TryFastAppend is allowed to decline (return false) at any
+// // time, for any reason -- just "return false" would be
+// // a perfectly legal implementation of TryFastAppend.
+// // The intention is for TryFastAppend to allow a fast path
+// // in the common case of a small append.
+// // - TryFastAppend is allowed to read up to <available> bytes
+// // from the input buffer, whereas Append is allowed to read
+// // <length>. However, if it returns true, it must leave
+// // at least five (kMaximumTagLength) bytes in the input buffer
+// // afterwards, so that there is always enough space to read the
+// // next tag without checking for a refill.
+// // - TryFastAppend must always return decline (return false)
+// // if <length> is 61 or more, as in this case the literal length is not
+// // decoded fully. In practice, this should not be a big problem,
+// // as it is unlikely that one would implement a fast path accepting
+// // this much data.
+// //
+// bool TryFastAppend(const char* ip, size_t available, size_t length);
+// };
+
+// -----------------------------------------------------------------------
+// Lookup table for decompression code. Generated by ComputeTable() below.
+// -----------------------------------------------------------------------
+
+// Mapping from i in range [0,4] to a mask to extract the bottom 8*i bits
+static const uint32 wordmask[] = {
+ 0u, 0xffu, 0xffffu, 0xffffffu, 0xffffffffu
+};
+
+// Data stored per entry in lookup table:
+// Range Bits-used Description
+// ------------------------------------
+// 1..64 0..7 Literal/copy length encoded in opcode byte
+// 0..7 8..10 Copy offset encoded in opcode byte / 256
+// 0..4 11..13 Extra bytes after opcode
+//
+// We use eight bits for the length even though 7 would have sufficed
+// because of efficiency reasons:
+// (1) Extracting a byte is faster than a bit-field
+// (2) It properly aligns copy offset so we do not need a <<8
+static const uint16 char_table[256] = {
+ 0x0001, 0x0804, 0x1001, 0x2001, 0x0002, 0x0805, 0x1002, 0x2002,
+ 0x0003, 0x0806, 0x1003, 0x2003, 0x0004, 0x0807, 0x1004, 0x2004,
+ 0x0005, 0x0808, 0x1005, 0x2005, 0x0006, 0x0809, 0x1006, 0x2006,
+ 0x0007, 0x080a, 0x1007, 0x2007, 0x0008, 0x080b, 0x1008, 0x2008,
+ 0x0009, 0x0904, 0x1009, 0x2009, 0x000a, 0x0905, 0x100a, 0x200a,
+ 0x000b, 0x0906, 0x100b, 0x200b, 0x000c, 0x0907, 0x100c, 0x200c,
+ 0x000d, 0x0908, 0x100d, 0x200d, 0x000e, 0x0909, 0x100e, 0x200e,
+ 0x000f, 0x090a, 0x100f, 0x200f, 0x0010, 0x090b, 0x1010, 0x2010,
+ 0x0011, 0x0a04, 0x1011, 0x2011, 0x0012, 0x0a05, 0x1012, 0x2012,
+ 0x0013, 0x0a06, 0x1013, 0x2013, 0x0014, 0x0a07, 0x1014, 0x2014,
+ 0x0015, 0x0a08, 0x1015, 0x2015, 0x0016, 0x0a09, 0x1016, 0x2016,
+ 0x0017, 0x0a0a, 0x1017, 0x2017, 0x0018, 0x0a0b, 0x1018, 0x2018,
+ 0x0019, 0x0b04, 0x1019, 0x2019, 0x001a, 0x0b05, 0x101a, 0x201a,
+ 0x001b, 0x0b06, 0x101b, 0x201b, 0x001c, 0x0b07, 0x101c, 0x201c,
+ 0x001d, 0x0b08, 0x101d, 0x201d, 0x001e, 0x0b09, 0x101e, 0x201e,
+ 0x001f, 0x0b0a, 0x101f, 0x201f, 0x0020, 0x0b0b, 0x1020, 0x2020,
+ 0x0021, 0x0c04, 0x1021, 0x2021, 0x0022, 0x0c05, 0x1022, 0x2022,
+ 0x0023, 0x0c06, 0x1023, 0x2023, 0x0024, 0x0c07, 0x1024, 0x2024,
+ 0x0025, 0x0c08, 0x1025, 0x2025, 0x0026, 0x0c09, 0x1026, 0x2026,
+ 0x0027, 0x0c0a, 0x1027, 0x2027, 0x0028, 0x0c0b, 0x1028, 0x2028,
+ 0x0029, 0x0d04, 0x1029, 0x2029, 0x002a, 0x0d05, 0x102a, 0x202a,
+ 0x002b, 0x0d06, 0x102b, 0x202b, 0x002c, 0x0d07, 0x102c, 0x202c,
+ 0x002d, 0x0d08, 0x102d, 0x202d, 0x002e, 0x0d09, 0x102e, 0x202e,
+ 0x002f, 0x0d0a, 0x102f, 0x202f, 0x0030, 0x0d0b, 0x1030, 0x2030,
+ 0x0031, 0x0e04, 0x1031, 0x2031, 0x0032, 0x0e05, 0x1032, 0x2032,
+ 0x0033, 0x0e06, 0x1033, 0x2033, 0x0034, 0x0e07, 0x1034, 0x2034,
+ 0x0035, 0x0e08, 0x1035, 0x2035, 0x0036, 0x0e09, 0x1036, 0x2036,
+ 0x0037, 0x0e0a, 0x1037, 0x2037, 0x0038, 0x0e0b, 0x1038, 0x2038,
+ 0x0039, 0x0f04, 0x1039, 0x2039, 0x003a, 0x0f05, 0x103a, 0x203a,
+ 0x003b, 0x0f06, 0x103b, 0x203b, 0x003c, 0x0f07, 0x103c, 0x203c,
+ 0x0801, 0x0f08, 0x103d, 0x203d, 0x1001, 0x0f09, 0x103e, 0x203e,
+ 0x1801, 0x0f0a, 0x103f, 0x203f, 0x2001, 0x0f0b, 0x1040, 0x2040
+};
+
+// In debug mode, allow optional computation of the table at startup.
+// Also, check that the decompression table is correct.
+#ifndef NDEBUG
+DEFINE_bool(snappy_dump_decompression_table, false,
+ "If true, we print the decompression table at startup.");
+
+static uint16 MakeEntry(unsigned int extra,
+ unsigned int len,
+ unsigned int copy_offset) {
+ // Check that all of the fields fit within the allocated space
+ assert(extra == (extra & 0x7)); // At most 3 bits
+ assert(copy_offset == (copy_offset & 0x7)); // At most 3 bits
+ assert(len == (len & 0x7f)); // At most 7 bits
+ return len | (copy_offset << 8) | (extra << 11);
+}
+
+static void ComputeTable() {
+ uint16 dst[256];
+
+ // Place invalid entries in all places to detect missing initialization
+ int assigned = 0;
+ for (int i = 0; i < 256; i++) {
+ dst[i] = 0xffff;
+ }
+
+ // Small LITERAL entries. We store (len-1) in the top 6 bits.
+ for (unsigned int len = 1; len <= 60; len++) {
+ dst[LITERAL | ((len-1) << 2)] = MakeEntry(0, len, 0);
+ assigned++;
+ }
+
+ // Large LITERAL entries. We use 60..63 in the high 6 bits to
+ // encode the number of bytes of length info that follow the opcode.
+ for (unsigned int extra_bytes = 1; extra_bytes <= 4; extra_bytes++) {
+ // We set the length field in the lookup table to 1 because extra
+ // bytes encode len-1.
+ dst[LITERAL | ((extra_bytes+59) << 2)] = MakeEntry(extra_bytes, 1, 0);
+ assigned++;
+ }
+
+ // COPY_1_BYTE_OFFSET.
+ //
+ // The tag byte in the compressed data stores len-4 in 3 bits, and
+ // offset/256 in 5 bits. offset%256 is stored in the next byte.
+ //
+ // This format is used for length in range [4..11] and offset in
+ // range [0..2047]
+ for (unsigned int len = 4; len < 12; len++) {
+ for (unsigned int offset = 0; offset < 2048; offset += 256) {
+ dst[COPY_1_BYTE_OFFSET | ((len-4)<<2) | ((offset>>8)<<5)] =
+ MakeEntry(1, len, offset>>8);
+ assigned++;
+ }
+ }
+
+ // COPY_2_BYTE_OFFSET.
+ // Tag contains len-1 in top 6 bits, and offset in next two bytes.
+ for (unsigned int len = 1; len <= 64; len++) {
+ dst[COPY_2_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(2, len, 0);
+ assigned++;
+ }
+
+ // COPY_4_BYTE_OFFSET.
+ // Tag contents len-1 in top 6 bits, and offset in next four bytes.
+ for (unsigned int len = 1; len <= 64; len++) {
+ dst[COPY_4_BYTE_OFFSET | ((len-1)<<2)] = MakeEntry(4, len, 0);
+ assigned++;
+ }
+
+ // Check that each entry was initialized exactly once.
+ if (assigned != 256) {
+ fprintf(stderr, "ComputeTable: assigned only %d of 256\n", assigned);
+ abort();
+ }
+ for (int i = 0; i < 256; i++) {
+ if (dst[i] == 0xffff) {
+ fprintf(stderr, "ComputeTable: did not assign byte %d\n", i);
+ abort();
+ }
+ }
+
+ if (FLAGS_snappy_dump_decompression_table) {
+ printf("static const uint16 char_table[256] = {\n ");
+ for (int i = 0; i < 256; i++) {
+ printf("0x%04x%s",
+ dst[i],
+ ((i == 255) ? "\n" : (((i%8) == 7) ? ",\n " : ", ")));
+ }
+ printf("};\n");
+ }
+
+ // Check that computed table matched recorded table
+ for (int i = 0; i < 256; i++) {
+ if (dst[i] != char_table[i]) {
+ fprintf(stderr, "ComputeTable: byte %d: computed (%x), expect (%x)\n",
+ i, static_cast<int>(dst[i]), static_cast<int>(char_table[i]));
+ abort();
+ }
+ }
+}
+#endif /* !NDEBUG */
+
+// Helper class for decompression
+class SnappyDecompressor {
+ private:
+ Source* reader_; // Underlying source of bytes to decompress
+ const char* ip_; // Points to next buffered byte
+ const char* ip_limit_; // Points just past buffered bytes
+ uint32 peeked_; // Bytes peeked from reader (need to skip)
+ bool eof_; // Hit end of input without an error?
+ char scratch_[kMaximumTagLength]; // See RefillTag().
+
+ // Ensure that all of the tag metadata for the next tag is available
+ // in [ip_..ip_limit_-1]. Also ensures that [ip,ip+4] is readable even
+ // if (ip_limit_ - ip_ < 5).
+ //
+ // Returns true on success, false on error or end of input.
+ bool RefillTag();
+
+ public:
+ explicit SnappyDecompressor(Source* reader)
+ : reader_(reader),
+ ip_(NULL),
+ ip_limit_(NULL),
+ peeked_(0),
+ eof_(false) {
+ }
+
+ ~SnappyDecompressor() {
+ // Advance past any bytes we peeked at from the reader
+ reader_->Skip(peeked_);
+ }
+
+ // Returns true iff we have hit the end of the input without an error.
+ bool eof() const {
+ return eof_;
+ }
+
+ // Read the uncompressed length stored at the start of the compressed data.
+ // On succcess, stores the length in *result and returns true.
+ // On failure, returns false.
+ bool ReadUncompressedLength(uint32* result) {
+ assert(ip_ == NULL); // Must not have read anything yet
+ // Length is encoded in 1..5 bytes
+ *result = 0;
+ uint32 shift = 0;
+ while (true) {
+ if (shift >= 32) return false;
+ size_t n;
+ const char* ip = reader_->Peek(&n);
+ if (n == 0) return false;
+ const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
+ reader_->Skip(1);
+ *result |= static_cast<uint32>(c & 0x7f) << shift;
+ if (c < 128) {
+ break;
+ }
+ shift += 7;
+ }
+ return true;
+ }
+
+ // Process the next item found in the input.
+ // Returns true if successful, false on error or end of input.
+ template <class Writer>
+ void DecompressAllTags(Writer* writer) {
+ const char* ip = ip_;
+
+ // We could have put this refill fragment only at the beginning of the loop.
+ // However, duplicating it at the end of each branch gives the compiler more
+ // scope to optimize the <ip_limit_ - ip> expression based on the local
+ // context, which overall increases speed.
+ #define MAYBE_REFILL() \
+ if (ip_limit_ - ip < kMaximumTagLength) { \
+ ip_ = ip; \
+ if (!RefillTag()) return; \
+ ip = ip_; \
+ }
+
+ MAYBE_REFILL();
+ for ( ;; ) {
+ const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip++));
+
+ if ((c & 0x3) == LITERAL) {
+ size_t literal_length = (c >> 2) + 1u;
+ if (writer->TryFastAppend(ip, ip_limit_ - ip, literal_length)) {
+ assert(literal_length < 61);
+ ip += literal_length;
+ // NOTE(user): There is no MAYBE_REFILL() here, as TryFastAppend()
+ // will not return true unless there's already at least five spare
+ // bytes in addition to the literal.
+ continue;
+ }
+ if (PREDICT_FALSE(literal_length >= 61)) {
+ // Long literal.
+ const size_t literal_length_length = literal_length - 60;
+ literal_length =
+ (LittleEndian::Load32(ip) & wordmask[literal_length_length]) + 1;
+ ip += literal_length_length;
+ }
+
+ size_t avail = ip_limit_ - ip;
+ while (avail < literal_length) {
+ if (!writer->Append(ip, avail)) return;
+ literal_length -= avail;
+ reader_->Skip(peeked_);
+ size_t n;
+ ip = reader_->Peek(&n);
+ avail = n;
+ peeked_ = avail;
+ if (avail == 0) return; // Premature end of input
+ ip_limit_ = ip + avail;
+ }
+ if (!writer->Append(ip, literal_length)) {
+ return;
+ }
+ ip += literal_length;
+ MAYBE_REFILL();
+ } else {
+ const uint32 entry = char_table[c];
+ const uint32 trailer = LittleEndian::Load32(ip) & wordmask[entry >> 11];
+ const uint32 length = entry & 0xff;
+ ip += entry >> 11;
+
+ // copy_offset/256 is encoded in bits 8..10. By just fetching
+ // those bits, we get copy_offset (since the bit-field starts at
+ // bit 8).
+ const uint32 copy_offset = entry & 0x700;
+ if (!writer->AppendFromSelf(copy_offset + trailer, length)) {
+ return;
+ }
+ MAYBE_REFILL();
+ }
+ }
+
+#undef MAYBE_REFILL
+ }
+};
+
+bool SnappyDecompressor::RefillTag() {
+ const char* ip = ip_;
+ if (ip == ip_limit_) {
+ // Fetch a new fragment from the reader
+ reader_->Skip(peeked_); // All peeked bytes are used up
+ size_t n;
+ ip = reader_->Peek(&n);
+ peeked_ = n;
+ if (n == 0) {
+ eof_ = true;
+ return false;
+ }
+ ip_limit_ = ip + n;
+ }
+
+ // Read the tag character
+ assert(ip < ip_limit_);
+ const unsigned char c = *(reinterpret_cast<const unsigned char*>(ip));
+ const uint32 entry = char_table[c];
+ const uint32 needed = (entry >> 11) + 1; // +1 byte for 'c'
+ assert(needed <= sizeof(scratch_));
+
+ // Read more bytes from reader if needed
+ uint32 nbuf = ip_limit_ - ip;
+ if (nbuf < needed) {
+ // Stitch together bytes from ip and reader to form the word
+ // contents. We store the needed bytes in "scratch_". They
+ // will be consumed immediately by the caller since we do not
+ // read more than we need.
+ memmove(scratch_, ip, nbuf);
+ reader_->Skip(peeked_); // All peeked bytes are used up
+ peeked_ = 0;
+ while (nbuf < needed) {
+ size_t length;
+ const char* src = reader_->Peek(&length);
+ if (length == 0) return false;
+ uint32 to_add = min<uint32>(needed - nbuf, length);
+ memcpy(scratch_ + nbuf, src, to_add);
+ nbuf += to_add;
+ reader_->Skip(to_add);
+ }
+ assert(nbuf == needed);
+ ip_ = scratch_;
+ ip_limit_ = scratch_ + needed;
+ } else if (nbuf < kMaximumTagLength) {
+ // Have enough bytes, but move into scratch_ so that we do not
+ // read past end of input
+ memmove(scratch_, ip, nbuf);
+ reader_->Skip(peeked_); // All peeked bytes are used up
+ peeked_ = 0;
+ ip_ = scratch_;
+ ip_limit_ = scratch_ + nbuf;
+ } else {
+ // Pass pointer to buffer returned by reader_.
+ ip_ = ip;
+ }
+ return true;
+}
+
+template <typename Writer>
+static bool InternalUncompress(Source* r, Writer* writer) {
+ // Read the uncompressed length from the front of the compressed input
+ SnappyDecompressor decompressor(r);
+ uint32 uncompressed_len = 0;
+ if (!decompressor.ReadUncompressedLength(&uncompressed_len)) return false;
+ return InternalUncompressAllTags(&decompressor, writer, uncompressed_len);
+}
+
+template <typename Writer>
+static bool InternalUncompressAllTags(SnappyDecompressor* decompressor,
+ Writer* writer,
+ uint32 uncompressed_len) {
+ writer->SetExpectedLength(uncompressed_len);
+
+ // Process the entire input
+ decompressor->DecompressAllTags(writer);
+ return (decompressor->eof() && writer->CheckLength());
+}
+
+bool GetUncompressedLength(Source* source, uint32* result) {
+ SnappyDecompressor decompressor(source);
+ return decompressor.ReadUncompressedLength(result);
+}
+
+size_t Compress(Source* reader, Sink* writer) {
+ size_t written = 0;
+ size_t N = reader->Available();
+ char ulength[Varint::kMax32];
+ char* p = Varint::Encode32(ulength, N);
+ writer->Append(ulength, p-ulength);
+ written += (p - ulength);
+
+ internal::WorkingMemory wmem;
+ char* scratch = NULL;
+ char* scratch_output = NULL;
+
+ while (N > 0) {
+ // Get next block to compress (without copying if possible)
+ size_t fragment_size;
+ const char* fragment = reader->Peek(&fragment_size);
+ assert(fragment_size != 0); // premature end of input
+ const size_t num_to_read = min(N, kBlockSize);
+ size_t bytes_read = fragment_size;
+
+ size_t pending_advance = 0;
+ if (bytes_read >= num_to_read) {
+ // Buffer returned by reader is large enough
+ pending_advance = num_to_read;
+ fragment_size = num_to_read;
+ } else {
+ // Read into scratch buffer
+ if (scratch == NULL) {
+ // If this is the last iteration, we want to allocate N bytes
+ // of space, otherwise the max possible kBlockSize space.
+ // num_to_read contains exactly the correct value
+ scratch = new char[num_to_read];
+ }
+ memcpy(scratch, fragment, bytes_read);
+ reader->Skip(bytes_read);
+
+ while (bytes_read < num_to_read) {
+ fragment = reader->Peek(&fragment_size);
+ size_t n = min<size_t>(fragment_size, num_to_read - bytes_read);
+ memcpy(scratch + bytes_read, fragment, n);
+ bytes_read += n;
+ reader->Skip(n);
+ }
+ assert(bytes_read == num_to_read);
+ fragment = scratch;
+ fragment_size = num_to_read;
+ }
+ assert(fragment_size == num_to_read);
+
+ // Get encoding table for compression
+ int table_size;
+ uint16* table = wmem.GetHashTable(num_to_read, &table_size);
+
+ // Compress input_fragment and append to dest
+ const int max_output = MaxCompressedLength(num_to_read);
+
+ // Need a scratch buffer for the output, in case the byte sink doesn't
+ // have room for us directly.
+ if (scratch_output == NULL) {
+ scratch_output = new char[max_output];
+ } else {
+ // Since we encode kBlockSize regions followed by a region
+ // which is <= kBlockSize in length, a previously allocated
+ // scratch_output[] region is big enough for this iteration.
+ }
+ char* dest = writer->GetAppendBuffer(max_output, scratch_output);
+ char* end = internal::CompressFragment(fragment, fragment_size,
+ dest, table, table_size);
+ writer->Append(dest, end - dest);
+ written += (end - dest);
+
+ N -= num_to_read;
+ reader->Skip(pending_advance);
+ }
+
+ delete[] scratch;
+ delete[] scratch_output;
+
+ return written;
+}
+
+// -----------------------------------------------------------------------
+// IOVec interfaces
+// -----------------------------------------------------------------------
+
+// A type that writes to an iovec.
+// Note that this is not a "ByteSink", but a type that matches the
+// Writer template argument to SnappyDecompressor::DecompressAllTags().
+class SnappyIOVecWriter {
+ private:
+ const struct iovec* output_iov_;
+ const size_t output_iov_count_;
+
+ // We are currently writing into output_iov_[curr_iov_index_].
+ int curr_iov_index_;
+
+ // Bytes written to output_iov_[curr_iov_index_] so far.
+ size_t curr_iov_written_;
+
+ // Total bytes decompressed into output_iov_ so far.
+ size_t total_written_;
+
+ // Maximum number of bytes that will be decompressed into output_iov_.
+ size_t output_limit_;
+
+ inline char* GetIOVecPointer(int index, size_t offset) {
+ return reinterpret_cast<char*>(output_iov_[index].iov_base) +
+ offset;
+ }
+
+ public:
+ // Does not take ownership of iov. iov must be valid during the
+ // entire lifetime of the SnappyIOVecWriter.
+ inline SnappyIOVecWriter(const struct iovec* iov, size_t iov_count)
+ : output_iov_(iov),
+ output_iov_count_(iov_count),
+ curr_iov_index_(0),
+ curr_iov_written_(0),
+ total_written_(0),
+ output_limit_(-1) {
+ }
+
+ inline void SetExpectedLength(size_t len) {
+ output_limit_ = len;
+ }
+
+ inline bool CheckLength() const {
+ return total_written_ == output_limit_;
+ }
+
+ inline bool Append(const char* ip, size_t len) {
+ if (total_written_ + len > output_limit_) {
+ return false;
+ }
+
+ while (len > 0) {
+ assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
+ if (curr_iov_written_ >= output_iov_[curr_iov_index_].iov_len) {
+ // This iovec is full. Go to the next one.
+ if (curr_iov_index_ + 1 >= output_iov_count_) {
+ return false;
+ }
+ curr_iov_written_ = 0;
+ ++curr_iov_index_;
+ }
+
+ const size_t to_write = std::min(
+ len, output_iov_[curr_iov_index_].iov_len - curr_iov_written_);
+ memcpy(GetIOVecPointer(curr_iov_index_, curr_iov_written_),
+ ip,
+ to_write);
+ curr_iov_written_ += to_write;
+ total_written_ += to_write;
+ ip += to_write;
+ len -= to_write;
+ }
+
+ return true;
+ }
+
+ inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
+ const size_t space_left = output_limit_ - total_written_;
+ if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16 &&
+ output_iov_[curr_iov_index_].iov_len - curr_iov_written_ >= 16) {
+ // Fast path, used for the majority (about 95%) of invocations.
+ char* ptr = GetIOVecPointer(curr_iov_index_, curr_iov_written_);
+ UnalignedCopy64(ip, ptr);
+ UnalignedCopy64(ip + 8, ptr + 8);
+ curr_iov_written_ += len;
+ total_written_ += len;
+ return true;
+ }
+
+ return false;
+ }
+
+ inline bool AppendFromSelf(size_t offset, size_t len) {
+ if (offset > total_written_ || offset == 0) {
+ return false;
+ }
+ const size_t space_left = output_limit_ - total_written_;
+ if (len > space_left) {
+ return false;
+ }
+
+ // Locate the iovec from which we need to start the copy.
+ int from_iov_index = curr_iov_index_;
+ size_t from_iov_offset = curr_iov_written_;
+ while (offset > 0) {
+ if (from_iov_offset >= offset) {
+ from_iov_offset -= offset;
+ break;
+ }
+
+ offset -= from_iov_offset;
+ --from_iov_index;
+ assert(from_iov_index >= 0);
+ from_iov_offset = output_iov_[from_iov_index].iov_len;
+ }
+
+ // Copy <len> bytes starting from the iovec pointed to by from_iov_index to
+ // the current iovec.
+ while (len > 0) {
+ assert(from_iov_index <= curr_iov_index_);
+ if (from_iov_index != curr_iov_index_) {
+ const size_t to_copy = std::min(
+ output_iov_[from_iov_index].iov_len - from_iov_offset,
+ len);
+ Append(GetIOVecPointer(from_iov_index, from_iov_offset), to_copy);
+ len -= to_copy;
+ if (len > 0) {
+ ++from_iov_index;
+ from_iov_offset = 0;
+ }
+ } else {
+ assert(curr_iov_written_ <= output_iov_[curr_iov_index_].iov_len);
+ size_t to_copy = std::min(output_iov_[curr_iov_index_].iov_len -
+ curr_iov_written_,
+ len);
+ if (to_copy == 0) {
+ // This iovec is full. Go to the next one.
+ if (curr_iov_index_ + 1 >= output_iov_count_) {
+ return false;
+ }
+ ++curr_iov_index_;
+ curr_iov_written_ = 0;
+ continue;
+ }
+ if (to_copy > len) {
+ to_copy = len;
+ }
+ IncrementalCopy(GetIOVecPointer(from_iov_index, from_iov_offset),
+ GetIOVecPointer(curr_iov_index_, curr_iov_written_),
+ to_copy);
+ curr_iov_written_ += to_copy;
+ from_iov_offset += to_copy;
+ total_written_ += to_copy;
+ len -= to_copy;
+ }
+ }
+
+ return true;
+ }
+
+};
+
+bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,
+ const struct iovec* iov, size_t iov_cnt) {
+ ByteArraySource reader(compressed, compressed_length);
+ return RawUncompressToIOVec(&reader, iov, iov_cnt);
+}
+
+bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,
+ size_t iov_cnt) {
+ SnappyIOVecWriter output(iov, iov_cnt);
+ return InternalUncompress(compressed, &output);
+}
+
+// -----------------------------------------------------------------------
+// Flat array interfaces
+// -----------------------------------------------------------------------
+
+// A type that writes to a flat array.
+// Note that this is not a "ByteSink", but a type that matches the
+// Writer template argument to SnappyDecompressor::DecompressAllTags().
+class SnappyArrayWriter {
+ private:
+ char* base_;
+ char* op_;
+ char* op_limit_;
+
+ public:
+ inline explicit SnappyArrayWriter(char* dst)
+ : base_(dst),
+ op_(dst) {
+ }
+
+ inline void SetExpectedLength(size_t len) {
+ op_limit_ = op_ + len;
+ }
+
+ inline bool CheckLength() const {
+ return op_ == op_limit_;
+ }
+
+ inline bool Append(const char* ip, size_t len) {
+ char* op = op_;
+ const size_t space_left = op_limit_ - op;
+ if (space_left < len) {
+ return false;
+ }
+ memcpy(op, ip, len);
+ op_ = op + len;
+ return true;
+ }
+
+ inline bool TryFastAppend(const char* ip, size_t available, size_t len) {
+ char* op = op_;
+ const size_t space_left = op_limit_ - op;
+ if (len <= 16 && available >= 16 + kMaximumTagLength && space_left >= 16) {
+ // Fast path, used for the majority (about 95%) of invocations.
+ UnalignedCopy64(ip, op);
+ UnalignedCopy64(ip + 8, op + 8);
+ op_ = op + len;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ inline bool AppendFromSelf(size_t offset, size_t len) {
+ char* op = op_;
+ const size_t space_left = op_limit_ - op;
+
+ // Check if we try to append from before the start of the buffer.
+ // Normally this would just be a check for "produced < offset",
+ // but "produced <= offset - 1u" is equivalent for every case
+ // except the one where offset==0, where the right side will wrap around
+ // to a very big number. This is convenient, as offset==0 is another
+ // invalid case that we also want to catch, so that we do not go
+ // into an infinite loop.
+ assert(op >= base_);
+ size_t produced = op - base_;
+ if (produced <= offset - 1u) {
+ return false;
+ }
+ if (len <= 16 && offset >= 8 && space_left >= 16) {
+ // Fast path, used for the majority (70-80%) of dynamic invocations.
+ UnalignedCopy64(op - offset, op);
+ UnalignedCopy64(op - offset + 8, op + 8);
+ } else {
+ if (space_left >= len + kMaxIncrementCopyOverflow) {
+ IncrementalCopyFastPath(op - offset, op, len);
+ } else {
+ if (space_left < len) {
+ return false;
+ }
+ IncrementalCopy(op - offset, op, len);
+ }
+ }
+
+ op_ = op + len;
+ return true;
+ }
+};
+
+bool RawUncompress(const char* compressed, size_t n, char* uncompressed) {
+ ByteArraySource reader(compressed, n);
+ return RawUncompress(&reader, uncompressed);
+}
+
+bool RawUncompress(Source* compressed, char* uncompressed) {
+ SnappyArrayWriter output(uncompressed);
+ return InternalUncompress(compressed, &output);
+}
+
+bool Uncompress(const char* compressed, size_t n, string* uncompressed) {
+ size_t ulength;
+ if (!GetUncompressedLength(compressed, n, &ulength)) {
+ return false;
+ }
+ // On 32-bit builds: max_size() < kuint32max. Check for that instead
+ // of crashing (e.g., consider externally specified compressed data).
+ if (ulength > uncompressed->max_size()) {
+ return false;
+ }
+ STLStringResizeUninitialized(uncompressed, ulength);
+ return RawUncompress(compressed, n, string_as_array(uncompressed));
+}
+
+
+// A Writer that drops everything on the floor and just does validation
+class SnappyDecompressionValidator {
+ private:
+ size_t expected_;
+ size_t produced_;
+
+ public:
+ inline SnappyDecompressionValidator() : produced_(0) { }
+ inline void SetExpectedLength(size_t len) {
+ expected_ = len;
+ }
+ inline bool CheckLength() const {
+ return expected_ == produced_;
+ }
+ inline bool Append(const char* ip, size_t len) {
+ produced_ += len;
+ return produced_ <= expected_;
+ }
+ inline bool TryFastAppend(const char* ip, size_t available, size_t length) {
+ return false;
+ }
+ inline bool AppendFromSelf(size_t offset, size_t len) {
+ // See SnappyArrayWriter::AppendFromSelf for an explanation of
+ // the "offset - 1u" trick.
+ if (produced_ <= offset - 1u) return false;
+ produced_ += len;
+ return produced_ <= expected_;
+ }
+};
+
+bool IsValidCompressedBuffer(const char* compressed, size_t n) {
+ ByteArraySource reader(compressed, n);
+ SnappyDecompressionValidator writer;
+ return InternalUncompress(&reader, &writer);
+}
+
+void RawCompress(const char* input,
+ size_t input_length,
+ char* compressed,
+ size_t* compressed_length) {
+ ByteArraySource reader(input, input_length);
+ UncheckedByteArraySink writer(compressed);
+ Compress(&reader, &writer);
+
+ // Compute how many bytes were added
+ *compressed_length = (writer.CurrentDestination() - compressed);
+}
+
+size_t Compress(const char* input, size_t input_length, string* compressed) {
+ // Pre-grow the buffer to the max length of the compressed output
+ compressed->resize(MaxCompressedLength(input_length));
+
+ size_t compressed_length;
+ RawCompress(input, input_length, string_as_array(compressed),
+ &compressed_length);
+ compressed->resize(compressed_length);
+ return compressed_length;
+}
+
+
+} // end namespace snappy
+
diff --git a/src/devtools/meta/src/misc/snappy/snappy.h b/src/devtools/meta/src/misc/snappy/snappy.h
new file mode 100644
index 0000000..e879e79
--- /dev/null
+++ b/src/devtools/meta/src/misc/snappy/snappy.h
@@ -0,0 +1,184 @@
+// Copyright 2005 and onwards Google Inc.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// A light-weight compression algorithm. It is designed for speed of
+// compression and decompression, rather than for the utmost in space
+// savings.
+//
+// For getting better compression ratios when you are compressing data
+// with long repeated sequences or compressing data that is similar to
+// other data, while still compressing fast, you might look at first
+// using BMDiff and then compressing the output of BMDiff with
+// Snappy.
+
+#ifndef UTIL_SNAPPY_SNAPPY_H__
+#define UTIL_SNAPPY_SNAPPY_H__
+
+#include <stddef.h>
+#include <string>
+
+#include "snappy-stubs-public.h"
+
+namespace snappy {
+ class Source;
+ class Sink;
+
+ // ------------------------------------------------------------------------
+ // Generic compression/decompression routines.
+ // ------------------------------------------------------------------------
+
+ // Compress the bytes read from "*source" and append to "*sink". Return the
+ // number of bytes written.
+ size_t Compress(Source* source, Sink* sink);
+
+ // Find the uncompressed length of the given stream, as given by the header.
+ // Note that the true length could deviate from this; the stream could e.g.
+ // be truncated.
+ //
+ // Also note that this leaves "*source" in a state that is unsuitable for
+ // further operations, such as RawUncompress(). You will need to rewind
+ // or recreate the source yourself before attempting any further calls.
+ bool GetUncompressedLength(Source* source, uint32* result);
+
+ // ------------------------------------------------------------------------
+ // Higher-level string based routines (should be sufficient for most users)
+ // ------------------------------------------------------------------------
+
+ // Sets "*output" to the compressed version of "input[0,input_length-1]".
+ // Original contents of *output are lost.
+ //
+ // REQUIRES: "input[]" is not an alias of "*output".
+ size_t Compress(const char* input, size_t input_length, string* output);
+
+ // Decompresses "compressed[0,compressed_length-1]" to "*uncompressed".
+ // Original contents of "*uncompressed" are lost.
+ //
+ // REQUIRES: "compressed[]" is not an alias of "*uncompressed".
+ //
+ // returns false if the message is corrupted and could not be decompressed
+ bool Uncompress(const char* compressed, size_t compressed_length,
+ string* uncompressed);
+
+
+ // ------------------------------------------------------------------------
+ // Lower-level character array based routines. May be useful for
+ // efficiency reasons in certain circumstances.
+ // ------------------------------------------------------------------------
+
+ // REQUIRES: "compressed" must point to an area of memory that is at
+ // least "MaxCompressedLength(input_length)" bytes in length.
+ //
+ // Takes the data stored in "input[0..input_length]" and stores
+ // it in the array pointed to by "compressed".
+ //
+ // "*compressed_length" is set to the length of the compressed output.
+ //
+ // Example:
+ // char* output = new char[snappy::MaxCompressedLength(input_length)];
+ // size_t output_length;
+ // RawCompress(input, input_length, output, &output_length);
+ // ... Process(output, output_length) ...
+ // delete [] output;
+ void RawCompress(const char* input,
+ size_t input_length,
+ char* compressed,
+ size_t* compressed_length);
+
+ // Given data in "compressed[0..compressed_length-1]" generated by
+ // calling the Snappy::Compress routine, this routine
+ // stores the uncompressed data to
+ // uncompressed[0..GetUncompressedLength(compressed)-1]
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompress(const char* compressed, size_t compressed_length,
+ char* uncompressed);
+
+ // Given data from the byte source 'compressed' generated by calling
+ // the Snappy::Compress routine, this routine stores the uncompressed
+ // data to
+ // uncompressed[0..GetUncompressedLength(compressed,compressed_length)-1]
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompress(Source* compressed, char* uncompressed);
+
+ // Given data in "compressed[0..compressed_length-1]" generated by
+ // calling the Snappy::Compress routine, this routine
+ // stores the uncompressed data to the iovec "iov". The number of physical
+ // buffers in "iov" is given by iov_cnt and their cumulative size
+ // must be at least GetUncompressedLength(compressed). The individual buffers
+ // in "iov" must not overlap with each other.
+ //
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompressToIOVec(const char* compressed, size_t compressed_length,
+ const struct iovec* iov, size_t iov_cnt);
+
+ // Given data from the byte source 'compressed' generated by calling
+ // the Snappy::Compress routine, this routine stores the uncompressed
+ // data to the iovec "iov". The number of physical
+ // buffers in "iov" is given by iov_cnt and their cumulative size
+ // must be at least GetUncompressedLength(compressed). The individual buffers
+ // in "iov" must not overlap with each other.
+ //
+ // returns false if the message is corrupted and could not be decrypted
+ bool RawUncompressToIOVec(Source* compressed, const struct iovec* iov,
+ size_t iov_cnt);
+
+ // Returns the maximal size of the compressed representation of
+ // input data that is "source_bytes" bytes in length;
+ size_t MaxCompressedLength(size_t source_bytes);
+
+ // REQUIRES: "compressed[]" was produced by RawCompress() or Compress()
+ // Returns true and stores the length of the uncompressed data in
+ // *result normally. Returns false on parsing error.
+ // This operation takes O(1) time.
+ bool GetUncompressedLength(const char* compressed, size_t compressed_length,
+ size_t* result);
+
+ // Returns true iff the contents of "compressed[]" can be uncompressed
+ // successfully. Does not return the uncompressed data. Takes
+ // time proportional to compressed_length, but is usually at least
+ // a factor of four faster than actual decompression.
+ bool IsValidCompressedBuffer(const char* compressed,
+ size_t compressed_length);
+
+ // The size of a compression block. Note that many parts of the compression
+ // code assumes that kBlockSize <= 65536; in particular, the hash table
+ // can only store 16-bit offsets, and EmitCopy() also assumes the offset
+ // is 65535 bytes or less. Note also that if you change this, it will
+ // affect the framing format (see framing_format.txt).
+ //
+ // Note that there might be older data around that is compressed with larger
+ // block sizes, so the decompression code should not rely on the
+ // non-existence of long backreferences.
+ static const int kBlockLog = 16;
+ static const size_t kBlockSize = 1 << kBlockLog;
+
+ static const int kMaxHashTableBits = 14;
+ static const size_t kMaxHashTableSize = 1 << kMaxHashTableBits;
+} // end namespace snappy
+
+
+#endif // UTIL_SNAPPY_SNAPPY_H__
diff --git a/src/devtools/packer/LICENSE b/src/devtools/packer/LICENSE
new file mode 100644
index 0000000..88a087d
--- /dev/null
+++ b/src/devtools/packer/LICENSE
@@ -0,0 +1,36 @@
+/* Copyright Statement:
+ *
+ * This software/firmware and related documentation ("MediaTek Software") are
+ * protected under relevant copyright laws. The information contained herein is
+ * confidential and proprietary to MediaTek Inc. and/or its licensors. Without
+ * the prior written permission of MediaTek inc. and/or its licensors, any
+ * reproduction, modification, use or disclosure of MediaTek Software, and
+ * information contained herein, in whole or in part, shall be strictly
+ * prohibited.
+ *
+ * Copyright (C) [2020] MediaTek Inc. All rights reserved.
+ *
+ * BY OPENING THIS FILE, RECEIVER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
+ * THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
+ * RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO RECEIVER
+ * ON AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL
+ * WARRANTIES, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR
+ * NONINFRINGEMENT. NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH
+ * RESPECT TO THE SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY,
+ * INCORPORATED IN, OR SUPPLIED WITH THE MEDIATEK SOFTWARE, AND RECEIVER AGREES
+ * TO LOOK ONLY TO SUCH THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO.
+ * RECEIVER EXPRESSLY ACKNOWLEDGES THAT IT IS RECEIVER'S SOLE RESPONSIBILITY TO
+ * OBTAIN FROM ANY THIRD PARTY ALL PROPER LICENSES CONTAINED IN MEDIATEK
+ * SOFTWARE. MEDIATEK SHALL ALSO NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE
+ * RELEASES MADE TO RECEIVER'S SPECIFICATION OR TO CONFORM TO A PARTICULAR
+ * STANDARD OR OPEN FORUM. RECEIVER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S
+ * ENTIRE AND CUMULATIVE LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE
+ * RELEASED HEREUNDER WILL BE, AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE
+ * MEDIATEK SOFTWARE AT ISSUE, OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE
+ * CHARGE PAID BY RECEIVER TO MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.
+ *
+ * The following software/firmware and/or related documentation ("MediaTek
+ * Software") have been modified by MediaTek Inc. All revisions are subject to
+ * any receiver's applicable license agreements with MediaTek Inc.
+ */
diff --git a/src/devtools/packer/mt2731/cryptoSB.py b/src/devtools/packer/mt2731/cryptoSB.py
new file mode 100644
index 0000000..a481b17
--- /dev/null
+++ b/src/devtools/packer/mt2731/cryptoSB.py
@@ -0,0 +1,490 @@
+import binascii
+import Crypto.Random.OSRNG.posix as RNG
+from Crypto.Cipher import AES
+from Crypto.Hash import MD5
+from Crypto.Hash import SHA
+from Crypto.Hash import SHA224
+from Crypto.Hash import SHA256
+from Crypto.Hash import SHA384
+from Crypto.Hash import SHA512
+from Crypto.Hash import HMAC
+from Crypto.Util import Counter
+import CryptoPlus
+from CryptoPlus.Cipher import python_AES as CP_python_AES
+import ecdsa
+from ecdsa import SigningKey, VerifyingKey
+from ecdsa.curves import NIST192p, NIST224p, NIST256p, NIST384p
+from ecdsa.util import sigencode_string
+from hashlib import sha1, sha224, sha256, sha384
+
+''' Select ECDSA Curve '''
+__CURVE = 'prime256v1'
+
+AUTH_ECDSA_NISTP256 = 0
+AUTH_ECDSA_NISTP384 = 1
+AUTH_AES_CMAC = 2
+AUTH_HMAC_SHA256 = 3
+
+AUTH_ECDSA_NISTP192 = 10
+AUTH_ECDSA_NISTP224 = 11
+
+''' Select ECDSA module '''
+
+''' Select Key Mode '''
+__K_STRING = 0
+__K_PEM = 1
+__K_DER = 2
+
+
+def crypto_pad_to_align(x, align):
+ if(align == 0):
+ return x
+ else:
+ size = len(x)
+ #print("size 0x%x" %size)
+ pad_size = (align - size % align) % align
+ for i in range(0, pad_size, 1):
+ x += b'\x00'
+ #cryptoSB.dump(x)
+ return x
+
+
+# This module is python-ecdsa (warner/python-ecdsa)
+class pythonECDSA:
+ def __init__(self, priv=None, pub=None, curve=None):
+ #print("pure-python ECDSA init")
+ None
+ def sign_string(self, privk, msg, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.from_string(privk, curve=NIST256p, hashfunc=sha256)
+ signature_str = sk.sign(msg, hashfunc=sha256, sigencode=sigencode_string)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.from_string(privk, curve=NIST384p, hashfunc=sha384)
+ signature_str = sk.sign(msg, hashfunc=sha384, sigencode=sigencode_string)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.from_string(privk, curve=NIST192p, hashfunc=sha1)
+ signature_str = sk.sign(msg, hashfunc=sha1, sigencode=sigencode_string)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.from_string(privk, curve=NIST224p, hashfunc=sha224)
+ signature_str = sk.sign(msg, hashfunc=sha224, sigencode=sigencode_string)
+ return signature_str
+ def sign_pem(self, privk, msg, sbc_auth_alg):
+ #print(" run sign pem")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.from_pem(privk, hashfunc=sha256)
+ signature_pem = sk.sign(msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.from_pem(privk, hashfunc=sha384)
+ signature_pem = sk.sign(msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.from_pem(privk, hashfunc=sha1)
+ signature_pem = sk.sign(msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.from_pem(privk, hashfunc=sha224)
+ signature_pem = sk.sign(msg, hashfunc=sha224)
+
+ return signature_pem
+ def sign_der(self, privk, msg, sbc_auth_alg):
+ #print(" run sign der")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.from_der(privk, hashfunc=sha256)
+ signature_der = sk.sign(msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.from_der(privk, hashfunc=sha384)
+ signature_der = sk.sign(msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.from_der(privk, hashfunc=sha1)
+ signature_der = sk.sign(msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.from_der(privk, hashfunc=sha224)
+ signature_der = sk.sign(msg, hashfunc=sha224)
+
+
+ return signature_der
+ def verify_string(self, pubk, signature_str, msg, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ vk = VerifyingKey.from_string(pubk, curve=NIST256p, hashfunc=sha256)
+ ret = vk.verify(signature_str, msg)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ vk = VerifyingKey.from_string(pubk, curve=NIST384p, hashfunc=sha384)
+ ret = vk.verify(signature_str, msg)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ vk = VerifyingKey.from_string(pubk, curve=NIST192p, hashfunc=sha1)
+ ret = vk.verify(signature_str, msg)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ vk = VerifyingKey.from_string(pubk, curve=NIST224p, hashfunc=sha224)
+ ret = vk.verify(signature_str, msg)
+ return ret
+ def verify_pem(self, pubk, signature_pem, msg, sbc_auth_alg):
+ #print(" run verify pem")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha224)
+ return ret
+ def verify_der(self, pubk, signature_der, msg, sbc_auth_alg):
+ #print(" run verify der")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha224)
+ return ret
+ def gen_key_string(self, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST384p, hashfunc=sha384)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.generate(curve=NIST192p, hashfunc=sha1)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.generate(curve=NIST224p, hashfunc=sha224)
+ vk = sk.get_verifying_key()
+ privk_str = sk.to_string()
+ pubk_str = vk.to_string()
+ return privk_str, pubk_str
+ def gen_key_pem(self, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST384p, hashfunc=sha384)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.generate(curve=NIST192p, hashfunc=sha1)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.generate(curve=NIST224p, hashfunc=sha224)
+ vk = sk.get_verifying_key()
+ privk_pem = sk.to_pem()
+ pubk_pem = vk.to_pem()
+ return privk_pem, pubk_pem
+ def gen_key_der(self, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST384p, hashfunc=sha384)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST192p, hashfunc=sha1)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.generate(curve=NIST224p, hashfunc=sha224)
+ vk = sk.get_verifying_key()
+ privk_der = sk.to_der()
+ pubk_der = vk.to_der()
+ return privk_der, pubk_der
+
+class AESCipher:
+ def __init__(self, key, blk_sz):
+ #self.key = md5(key.encode('utf8')).hexdigest()
+ self.key = key
+ self.blk_sz = blk_sz
+ keylen = len(key)
+ if(keylen != blk_sz):
+ print("ERROR: key length fail:")
+ return 0
+
+ def aes_encrypt(self, data):
+ #data = pad(data)
+ #print(":".join("{:02x}".format(ord(e)) for e in data))
+ cryptor = AES.new(self.key, AES.MODE_ECB)
+ return cryptor.encrypt(data)
+
+ def aes_decrypt(self, data):
+ #data = pad(data)
+ #print(":".join("{:02x}".format(ord(e)) for e in data))
+ cryptor = AES.new(self.key, AES.MODE_ECB)
+ return cryptor.decrypt(data)
+
+ def aes_cbc_encrypt(self, data, iv):
+ cryptor = AES.new(self.key, AES.MODE_CBC, iv)
+ return cryptor.encrypt(data)
+
+ def aes_cbc_decrypt(self, data, iv):
+ cryptor = AES.new(self.key, AES.MODE_CBC, iv)
+ return cryptor.decrypt(data)
+
+ def aes_ctr_encrypt_only_counter(self, data, prefix_const, init_counter):
+ #ctr_e = Counter.new(64, prefix = prefix_const)
+ #cryptor = AES.new(self.key, AES.MODE_CTR, counter=lambda: init_counter)
+
+ ctr_e = Counter.new(128, initial_value=long(init_counter.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_e)
+
+ return cryptor.encrypt(data)
+
+ def aes_ctr_decrypt_only_counter(self, data, prefix_const, init_counter):
+ #ctr_d = Counter.new(128, prefix = prefix_const)
+ #cryptor = AES.new(self.key, AES.MODE_CTR, counter=lambda: init_counter)
+
+ ctr_d = Counter.new(128, initial_value=long(init_counter.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_d)
+ return cryptor.decrypt(data)
+
+ def aes_ctr_encrypt(self, data, prefix_str, initvalue):
+ #print("0x%x" %long(initvalue.encode('hex'), 16))
+ #print(len(prefix_str))
+ nbits = (128 - (len(prefix_str)*8))
+ ctr_e = Counter.new(nbits, prefix = prefix_str, initial_value=long(initvalue.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_e)
+
+ return cryptor.encrypt(data)
+
+ def aes_ctr_decrypt(self, data, prefix_str, initvalue):
+ nbits = (128 - (len(prefix_str)*8))
+ ctr_d = Counter.new(nbits, prefix = prefix_str, initial_value=long(initvalue.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_d)
+
+ return cryptor.decrypt(data)
+
+
+def strip_key(key):
+ #src_key = key.lstrip("x").rstrip("L")
+ src_key = key[2:].rstrip("L")
+ key_byte = binascii.a2b_hex(src_key)
+ return key_byte
+
+def my_img_enc(data, key, iv, img_enc_alg, align=None):
+ #dump(data)
+
+ #align
+ bin = crypto_pad_to_align(data, align)
+
+ if(img_enc_alg == 0):
+ # AES 128 ECB
+ aes = AESCipher(key, 16)
+ encmsg = aes.aes_encrypt(bin)
+ #print("AES 128 ECB image result:")
+ #dump(encmsg)
+ elif(img_enc_alg == 1):
+ # AES 128 CBC
+ aes = AESCipher(key, 16)
+ encmsg = aes.aes_cbc_encrypt(bin, iv)
+ #print("AES 128 CBC image result:")
+ #dump(encmsg)
+ elif(img_enc_alg == 2):
+ # AES 256 ECB
+ aes = AESCipher(key, 32)
+ encmsg = aes.aes_encrypt(bin)
+ #print("AES 256 ECB image result:")
+ #dump(encmsg)
+ elif(img_enc_alg == 3):
+ # AES 256 CBC
+ aes = AESCipher(key, 32)
+ encmsg = aes.aes_cbc_encrypt(bin, iv)
+ #print("AES 256 CBC image result:")
+ #dump(encmsg)
+
+ return encmsg
+
+# dump str to bytes
+def dump(data):
+ for i in range(0, len(data)):
+ print ("0x%02x,"%ord(data[i])),
+ if(((i+1)%16) == 0):
+ print("")
+
+class HASH:
+ def __init__(self):
+ #print("//class HASH init")
+ None
+
+ def hash_sha1(self, data):
+ #print("SHA1:")
+ hash = SHA.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_sha224(self, data):
+ #print("SHA224:")
+ hash = SHA224.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_sha256(self, data):
+ #print("SHA256:")
+ hash = SHA256.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_sha384(self, data):
+ #print("SHA384:")
+ hash = SHA384.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+
+ def hash_sha512(self, data):
+ #print("SHA512:")
+ hash = SHA512.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_md5(self, data):
+ #print("MD5:")
+ hash = MD5.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+
+def sb_hash(data, sbc_auth_alg):
+ #print("run my_hash:")
+
+ #myhash = HASH()
+
+ if((sbc_auth_alg == 1) or (sbc_auth_alg == 5) ):
+ sbhash = HASH()
+ digest = sbhash.hash_sha384(data)
+ return digest
+ elif(sbc_auth_alg == 0) or (sbc_auth_alg == 2) or (sbc_auth_alg == 3) or (sbc_auth_alg == 4):
+ sbhash = HASH()
+ digest = sbhash.hash_sha256(data)
+ return digest
+ elif((sbc_auth_alg == 6)):
+ sbhash = HASH()
+ digest = sbhash.hash_sha512(data)
+ return digest
+ else:
+ print("ERROR: run sb_hash fail")
+
+
+
+def hmac_sha256(key, bdata):
+
+ b = HMAC.new(key, digestmod=SHA256)
+ b.update(bdata)
+ digest = b.digest()
+ #digest = b.hexdigest()
+ #dump(digest)
+
+ return digest
+
+def aescmac(key, msg):
+ #print("AES CMAC: ")
+ cipher = CP_python_AES.new(key, CP_python_AES.MODE_CMAC)
+ out = cipher.encrypt(msg)
+
+ #outhex = cipher.encrypt(msg).encode('hex')
+ #out = outhex.decode('hex')
+ return out
+
+def ecdsa_sign_nistp256_string(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_string(privk, msg, AUTH_ECDSA_NISTP256)
+
+ return signature
+
+def ecdsa_sign_nistp256_pem(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_pem(privk, msg, AUTH_ECDSA_NISTP256)
+ return signature
+
+def ecdsa_sign_nistp256_der(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_der(privk, msg, AUTH_ECDSA_NISTP256)
+
+ return signature
+
+def ecdsa_sign_nistp384_string(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_string(privk, msg, AUTH_ECDSA_NISTP384)
+ return signature
+
+def ecdsa_sign_nistp384_pem(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_pem(privk, msg, AUTH_ECDSA_NISTP384)
+
+ return signature
+
+def ecdsa_sign_nistp384_der(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_der(privk, msg, AUTH_ECDSA_NISTP384)
+
+ return signature
+
+
+def pubkey_string(pubk, sbc_auth_alg):
+ sk = VerifyingKey.from_pem(pubk)
+ return sk.to_string()
+def privkey_string(privk, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.from_pem(privk, hashfunc=sha256)
+ return sk.to_string()
+ else:
+ sk = SigningKey.from_pem(privk, hashfunc=sha384)
+ return sk.to_string()
+
+def sb_sign(privk, pubk, msg, sbc_auth_alg, key_mode=__K_STRING):
+ #print("Start sb_sign:")
+
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ #pyelliptic ECDSA NIST p256
+ if(key_mode == __K_STRING):
+ signature = ecdsa_sign_nistp256_string(privk, msg)
+ #another use
+ #ecdsa = pythonECDSA()
+ #signature = ecdsa.sign_string(privk, msg, AUTH_ECDSA_NISTP256)
+
+ elif(key_mode == __K_PEM):
+ signature = ecdsa_sign_nistp256_pem(privk, msg)
+
+ elif(key_mode == __K_DER):
+ signature = ecdsa_sign_nistp256_der(privk, msg)
+ return signature
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ #pyelliptic ECDSA_NIST_p384
+ if(key_mode == __K_STRING):
+ signature = ecdsa_sign_nistp384_string(privk, msg)
+
+ elif(key_mode == __K_PEM):
+ signature = ecdsa_sign_nistp384_pem(privk, msg)
+
+ elif(key_mode == __K_DER):
+ signature = ecdsa_sign_nistp384_der(privk, msg)
+
+ return signature
+
+ elif(sbc_auth_alg == AUTH_AES_CMAC):
+ #AES128_CMAC
+ signature = aescmac(privk, msg)
+ return signature
+ elif(sbc_auth_alg == AUTH_HMAC_SHA256):
+ #HMAC-SHA256
+ signature = hmac_sha256(privk, msg)
+ return signature
+ else:
+ print("ERROR: wrong authentication algorithm!!")
+
diff --git a/src/devtools/packer/mt2731/mipack.py b/src/devtools/packer/mt2731/mipack.py
new file mode 100644
index 0000000..c38d979
--- /dev/null
+++ b/src/devtools/packer/mt2731/mipack.py
@@ -0,0 +1,693 @@
+#!/usr/bin/python
+# -*- coding: utf8 -*-
+
+import json
+import struct
+import sys
+import binascii
+import cryptoSB
+import copy
+
+from jsoncomment import JsonComment
+
+__Align = 16
+__Align_16_en = 0
+
+__TEST = 0
+
+g_magic_size = 8
+g_total_len_size = 4
+g_bl_version_size = 4
+g_img_number_size = 4
+g_ls_cmd_number_size = 4
+g_mi_header_info_size = (g_magic_size + g_total_len_size + g_bl_version_size + g_img_number_size + g_ls_cmd_number_size)
+
+g_img_header_size = 96
+g_ls_cmd_size = 8
+
+g_img_oneoffset_table_size = 4
+g_img_onehash_table_size = 64
+
+g_public_key_size = 96
+g_sbc_auth_alg_size = 4
+g_sbc_auth_inf_size = 4
+g_sbc_size = (g_public_key_size + g_sbc_auth_alg_size + g_sbc_auth_inf_size)
+
+g_boot_hash_size = 64
+g_signature_size = 96
+g_auth_size = (g_boot_hash_size + g_signature_size)
+
+def to_int(s):
+ if isinstance(s, (str, unicode)):
+ return int(s, 0)
+ else:
+ return s
+
+def byte_to_int(bytes):
+ result = 0
+
+ for b in bytes:
+ result = result*256 + ord(b)
+
+ return result
+
+def read_desc(mi_desc_fn):
+ #desc = json.load(open(mi_desc_fn))
+
+ parser = JsonComment(json)
+ desc = parser.loads(open(mi_desc_fn).read())
+
+ for img in desc['images']:
+ img['img_enc_alg'] = to_int(img['img_enc_alg'])
+ img['img_enc_inf'] = to_int(img['img_enc_inf'])
+
+ '''0627 remove int assign avoid key start is (0x00..)'''
+ #img['img_iv'] = to_int(img['img_iv'])
+
+ return desc
+
+
+def gen_ver_magic(major, minor, revision):
+ major = to_int(major)
+ minor = to_int(minor)
+ revision = to_int(revision)
+
+ x = major ^ 0xaa
+ y = minor ^ 0x55
+ z = revision ^ 0x99
+ checksum = (x + y + z) & 0xff
+
+ return (major << 0) | (minor << 8) | (revision << 16) | (checksum << 24)
+
+def my_gen_ver_magic(major, minor, revision):
+ major = to_int(major)
+ minor = to_int(minor)
+ revision = to_int(revision)
+
+ x = major ^ 0xaa
+ y = minor ^ 0x55
+ z = revision ^ 0x99
+ checksum = (x + y + z) & 0xff
+
+ highmagic = byte_to_int(b'\x27\x21\xca\xfe')
+ #print(hex(highmagic))
+
+ return (major << 0) | (minor << 8) | (revision << 16) | (checksum << 24), highmagic
+
+def my_gen_mtk_magic(magic):
+ magic_str = my_to_bytes(magic, g_magic_size, endianess='little')
+
+ lowmagic = byte_to_int(magic_str[4:8])
+ highmagic = byte_to_int(magic_str[0:4])
+
+ return lowmagic, highmagic
+
+def pad_to_align(align, current_size):
+ if not align:
+ return ''
+
+ pad_size = (align - current_size % align) % align
+ pad = '\0' * pad_size
+
+ return pad
+
+
+def dump(data):
+ for i in range(0, len(data)):
+ if(i%16 == 0):
+ print("[%04X]" % i),
+
+ print("%02x" % ord(data[i])),
+ if(((i+1)%16) == 0):
+ print
+
+def pack_load_script(mi_desc):
+ ls_script = []
+ reserved = 0
+ images = mi_desc['images']
+ img_num = len(images)
+
+ ls_cmds = mi_desc['load_srcipt_cmd']
+ ls_cmds_num = len(ls_cmds)
+ #print("ls_cmds_num: %d" %ls_cmds_num)
+
+ for i in range(ls_cmds_num):
+ ls_cmd = ls_cmds[i]
+ cmd = ls_cmd['cmd']
+
+ if cmd == "LOAD":
+ cmd_id = 0
+ img_file = ls_cmd['img_file']
+ addr = to_int(ls_cmd['addr'])
+
+ img_id = -1
+ for j in range(img_num):
+ img = images[j]
+ img_binary_name = img['img_file']
+ if img_file == img_binary_name:
+ img_id = j
+ break
+
+ if img_id == -1:
+ print("Please check img file name")
+ return
+
+ packed_cmd = struct.pack('<BBHI', cmd_id, img_id, reserved, addr)
+ #dump(packed_cmd)
+ #print
+ elif cmd == "MCU-ENTRY":
+ cmd_id = 2
+ mcu_id = ls_cmd['mcu_id']
+ addr = to_int(ls_cmd['addr'])
+ packed_cmd = struct.pack('<BBHI', cmd_id, mcu_id, reserved, addr)
+ #dump(packed_cmd)
+ #print
+ elif cmd == "MCU_RESET-ENTRY":
+ cmd_id = 1
+ mcu_id = ls_cmd['mcu_id']
+ addr = to_int(ls_cmd['addr'])
+ packed_cmd = struct.pack('<BBHI', cmd_id, mcu_id, reserved, addr)
+ #dump(packed_cmd)
+ #print
+ else:
+ print("unknown command: %s" %cmd)
+ return
+
+ ls_script += packed_cmd
+
+ #print("load script:")
+ #dump(ls_script)
+
+ return ls_script
+
+
+def my_pack_images(mi_desc, privk, enckey, align=None, img_dir=''):
+ '''
+ mipack_file
+ mi_header_info
+ u32 magic
+ u32 total_len
+ u32 bl_version
+ u32 img_number (N)
+ u32 load_script_cmd_number (M)
+
+ img_info[1]~img_info[N]
+ u32 img_length
+ u32 img_offset
+ 64Byes img_hash
+ u32 img_enc_inf
+ u32 img_enc_alg
+ 16Bytes img_iv
+
+ load_script_cmd[1]~load_script_cmd[M]
+ u64 cmd
+
+ sbc data
+ 96Bytes public_key
+ u32 sbc_auth_inf
+ u32 sbc_auth_alg
+
+ auth data
+ 64Bytes boothash
+ 96Bytes signature
+
+ [img binary 1]
+ ...
+ [img binary 1]
+ '''
+
+ key_mode = 0
+
+ mi_header_struct = struct.Struct('<IIIIII')
+ sbc_struct = struct.Struct('<II')
+
+ #run hash
+ hash = cryptoSB.HASH()
+
+ # ver_magic
+ #version = mi_desc['version']
+ #major, minor, revision = version.split('.')
+ #ver_magic_l, ver_magic_h = my_gen_ver_magic(major, minor, revision)
+
+ ver_magic_l, ver_magic_h = my_gen_mtk_magic(to_int(mi_desc['magic_num']))
+
+ # bl region
+ bl_version = mi_desc['bl_version']
+ images = mi_desc['images']
+ img_num = len(images)
+ ls_cmds = mi_desc['load_srcipt_cmd']
+ ls_cmds_num = len(ls_cmds)
+
+ '''size of bl + imgl + sbc + auth'''
+ # Fixed size section: mi_header, sbc data, auth data
+ # Non-fixed size section: img_info, load script
+ bl_total_len = g_mi_header_info_size + g_sbc_size + g_auth_size
+ bl_total_len += img_num * g_img_header_size
+ bl_total_len += ls_cmds_num * g_ls_cmd_size
+
+
+ #print("==== multi-image header size ====")
+ #print("g_mi_header_info_size=%d, g_sbc_size=%d, g_auth_size=%d, bl_total_len = %d" %(g_mi_header_info_size, g_sbc_size, g_auth_size, bl_total_len))
+
+ #img_header_table = []
+ img_headers = []
+ bins = []
+ sbc_region = []
+ hashtable = []
+ imagetmp = [[], [], [], [], [], [], [], [], [], []]
+ packtmp = []
+ blh_hash = []
+ signaturelist = []
+
+ imagesize = []
+
+
+ # sbc region
+ ##pub_key = to_int(mi_desc['public_key'])
+ ##public_key = my_binify(pub_key)
+ '''20180627 remove int assign avoid key start is (0x00..)'''
+ pub_key = (mi_desc['public_key'])
+ public_key = cryptoSB.strip_key(pub_key)
+ public_key_append = my_pad_to_align(public_key, 96)
+ sbc_region.append(public_key_append)
+ pubk = b'\x04' + public_key
+
+ #print("======= sbc region =========")
+ sbc_auth_alg = mi_desc['sbc_auth_alg']
+ #print("sbc_auth_alg = 0x%x" %sbc_auth_alg)
+ sbc_auth_inf = mi_desc['sbc_auth_inf']
+ #print("sbc_auth_inf = 0x%x" %sbc_auth_inf)
+ sbc = sbc_struct.pack(sbc_auth_inf, sbc_auth_alg)
+ sbc_region.append(sbc)
+
+
+ # pad before 1st image
+
+ #pad = pad_to_align(64, expected_size)
+ #bins.append(pad)
+ #expected_size += len(pad)
+
+
+ # images
+ # 16 bytes aligned
+ img_offset = (bl_total_len + 15) & (~15)
+ img_offset_table = []
+
+ for i in range(img_num):
+ #print("\n\n======== Start image step: =========")
+
+
+ img = images[i]
+ img_file = img['img_file']
+ img_enc_inf = img['img_enc_inf']
+ img_enc_alg = img['img_enc_alg']
+ #print("img_enc_inf=0x%x" %img_enc_inf)
+
+ bin = open(img_dir + '/' + img_file, 'rb').read()
+
+ iv_int = img['img_iv']
+ #iv = my_binify(iv_int)
+ '''0627 remove int assign avoid key start is (0x00..)'''
+ iv = cryptoSB.strip_key(iv_int)
+ iv0= int(iv[0:4].encode('hex'), 16)
+ iv1= int(iv[4:8].encode('hex'), 16)
+ iv2= int(iv[8:12].encode('hex'), 16)
+ iv3= int(iv[12:16].encode('hex'), 16)
+ #print type(iv)
+ #print("IV:")
+ #cryptoSB.dump(iv)
+
+
+ if(img_enc_inf == 1):
+ '''image encrypt'''
+ out = cryptoSB.my_img_enc(bin, enckey, iv, img_enc_alg, __Align)
+ bins.append(out)
+ #bins = out
+ elif(img_enc_inf == 2):
+ '''image encrypt'''
+ out = cryptoSB.my_img_enc(bin, enckey, iv, img_enc_alg, __Align)
+ bins.append(out)
+ #bins = out
+ else:
+ '''plaintext image'''
+ out = my_pad_to_align(bin, __Align)
+ bins.append(out)
+ #bins = out
+
+ # binary length should be 16 bytes aligned
+ length = len(out)
+
+ imagesize.append(length)
+ #print("")
+ #print("image[%d] offset : 0x%x" %(i, img_offset))
+ #print("image[%d] size : 0x%x" %(i, imagesize[i]))
+
+ imagetmp[i] = copy.copy(bins)
+
+ img_str = ''.join(bins)
+ #print type(img_str)
+ #print("========= image[%d] binary ==========" %i)
+ #cryptoSB.dump(img_str)
+
+
+ # hash each (image header + image binary)
+ #print('')
+ #print("========= image[%d] binary hash ==========" %i)
+ hashvalue = cryptoSB.sb_hash(img_str, sbc_auth_alg)
+ imghash = my_pad_to_align(hashvalue, 64)
+ #cryptoSB.dump(imghash)
+
+ # img_header
+ img_hdr = struct.pack('<II',
+ length,
+ img_offset)
+ img_hdr += "".join(imghash)
+ '''20180719 fix IV order fail'''
+ img_hdr += struct.pack('<II16s',
+ img_enc_inf,
+ img_enc_alg,
+ iv)
+
+
+ img_offset_table.append(str(img_offset))
+ img_offset += length
+ #img_offset_table.append(my_to_bytes(img_offset, 4, endianess='little'))
+
+ #print("\n=====>")
+ #print("image[%d] header info :" %i)
+ #cryptoSB.dump(img_hdr)
+ img_headers.append(img_hdr)
+
+ #img_headers.remove(img_hdr)
+ while len(bins) > 0:
+ bins.pop()
+
+
+ #print("\n\nSTART to pack all sections ...")
+ pack = []
+
+ #print("======== append mi_header info ==========")
+ total_len = int(img_offset_table[img_num-1]) + int(imagesize[img_num-1])
+
+ mi_header = mi_header_struct.pack(
+ ver_magic_l,
+ ver_magic_h,
+ total_len,
+ bl_version,
+ img_num,
+ ls_cmds_num)
+
+
+ pack.append(mi_header)
+
+ # append image info
+ for i in range(img_num):
+ pack += img_headers[i]
+
+
+ ls_script = pack_load_script(mi_desc)
+ if ls_script == None:
+ print("pack_load_script fail")
+ return
+
+ # append load script
+ pack += ls_script
+
+ # append sbc data
+ pack += sbc_region
+
+ # for easy view. please remove it while release final
+ '''align for (bl + imgl + sbc)'''
+ if(__Align_16_en == 1):
+ padnum = pad_to_align(16, len(''.join(pack)))
+ pack.append(padnum)
+
+ #print("======== append mi_header hash: ==========")
+ bl_header = ''.join(pack)
+ #cryptoSB.dump(bl_header)
+ blh = copy.copy(bl_header)
+ boothash = cryptoSB.sb_hash(blh, sbc_auth_alg)
+ boothash_append = my_pad_to_align(boothash, g_boot_hash_size)
+ #cryptoSB.dump(boothash_append)
+ blh_hash.append(boothash_append)
+
+ # append hash
+ pack += blh_hash
+
+ #print("======== append mi_header signature: =========")
+ #privk = "\xc1\xbe\xe4\xfa\x86\xaf\x86\x84\x67\x7c\xae\xee\xa8\x8a\xb0\x72\x3e\x55\x4a\xef\x01\x60\xb8\xfc\x65\x3c\x0e\x00\x08\x0f\x4f\x78"
+ #pubk = "\x04\x14\xc1\xcf\x10\x99\x9d\x3a\x98\xf3\x71\xb8\xd8\x9b\x3b\x26\xb2\x9e\xe1\xbd\x99\xf3\xe0\x39\x3d\x34\x21\x6a\x6f\x49\x58\x7a\xb1\xdd\x8a\xba\x7a\x9d\x02\x99\x5f\xda\xa0\xb8\x62\x82\xae\xc2\xd0\xc6\x88\xc2\x26\x03\x97\x86\x65\x46\xbb\x20\xc9\xd1\x44\xb9\x84"
+
+ if sbc_auth_inf == 0:
+ padbytes = '\0' * g_signature_size
+ signaturelist.append(padbytes)
+ else:
+ pem_key_format = mi_desc['pem_key_format']
+ if(pem_key_format == 1):
+ '''PEM format'''
+ key_mode = 1
+ elif(pem_key_format == 2):
+ '''DER format'''
+ key_mode = 2
+ else:
+ '''String format'''
+ key_mode = 0
+
+ #ecdsa = cryptoSB.ECDSA()
+ #signature = ecdsa.sign(privk, pubk, boothash, sbc_auth_alg)
+ ''' 20180616 fix the sb_sign msg error : not boothash -> blh is right'''
+ signature = cryptoSB.sb_sign(privk, pubk, blh, sbc_auth_alg, key_mode)
+ #print("signature size = %d" %len(signature))
+ signature_append = my_pad_to_align(signature, g_signature_size)
+ #cryptoSB.dump(signature_append)
+ signaturelist.append(signature_append)
+
+ #check verify
+ #ret = ecdsa.verify(pubk, boothash, signature, sbc_auth_alg)
+ #print("ecdsa verify: %s" %ret)
+
+
+ #dump("".join(signaturelist))
+ # append signature
+ pack += signaturelist
+
+ # for easy view, please remove it while release final
+ '''align for (bl + imgl + sbc + auth)'''
+ if(__Align_16_en == 1):
+ padnum = pad_to_align(16, len(''.join(pack)))
+ pack.append(padnum)
+
+ # append image binary
+ for i in range(img_num):
+ offset = int(img_offset_table[i])
+ pad_num = offset - len(''.join(pack))
+ #print("offset = %d" %offset)
+ #print("pad_num = %d" %pad_num)
+
+ padbytes = '\0' * pad_num
+ pack.append(padbytes)
+ pack += imagetmp[i]
+
+ #print(len(''.join(pack)))
+
+ # clear list
+ while len(signaturelist) > 0:
+ signaturelist.pop()
+
+
+ return ''.join(pack)
+
+'''support to_bytes to python 2.7'''
+def my_to_bytes(n, length, endianess='big'):
+ h = '%x' % n
+ s = ('0'*(len(h) % 2) + h).zfill(length*2).decode('hex')
+ return s if endianess == 'big' else s[::-1]
+
+'''long to byte string'''
+def my_binify(x):
+ h = hex(x)[2:].rstrip('L')
+ return binascii.unhexlify(h)
+
+def my_binify2(x):
+ if(hex(x)[0:2] == '0x'):
+ h = hex(x)[2:].rstrip('L')
+ else:
+ h = hex(x).rstrip('L')
+
+ return binascii.unhexlify(h)
+
+def my_pad_to_align(x, align):
+ if(align == 0):
+ return x
+ else:
+ size = len(x)
+ #print("size 0x%x" %size)
+ pad_size = (align - size % align) % align
+ for i in range(0, pad_size, 1):
+ x += b'\x00'
+
+ #cryptoSB.dump(x)
+ return x
+
+
+def img_enc(mi_desc, key, align=None):
+
+ images = mi_desc['images']
+ img_num = len(images)
+
+ img = images[0]
+ #load_addr = img['load_addr']
+ #entrypoint = img['entrypoint']
+ img_file = img['img_file']
+ img_enc_alg = img['img_enc_alg']
+ #print(img_enc_alg)
+ img_enc_inf = img['img_enc_inf']
+ #print(img_enc_inf)
+ iv = img['img_iv']
+ iv = my_binify(iv)
+ #print type(iv)
+ #print("img_enc dump:")
+ #cryptoSB.dump(iv)
+
+ bin = open(img_file, 'rb').read()
+ #cryptoSB.dump(bin)
+
+ #align
+ bin = my_pad_to_align(bin, 64)
+
+ aes = cryptoSB.AESCipher(key, 16)
+ encmsg = aes.aes_encrypt(bin)
+ #print("result image enc:")
+ #cryptoSB.dump(encmsg)
+
+ return encmsg
+
+
+
+
+if __name__ == '__main__':
+ import os, sys, getopt
+
+
+ def print_usage():
+ print ('usage:', os.path.basename(sys.argv[0]), "[options] <image config>.json\n", \
+ 'options:\n', \
+ '\t[-o | --output out.img]\n', \
+ '\t[-h | --help]\n', \
+ '\t[-i | --input]\n', \
+ '\t[-k | --prikey hexkey e.g. 0x0102..]\n', \
+ '\t[-s | --enckey hexkey e.g. 0x0102..]\n', \
+ '\t[-p | --pemdir <pem path>\n', \
+ '\t[-d | --imgdir <image path>\n')
+
+
+ def main():
+ opts, args = getopt.getopt(sys.argv[1:],
+ 'ho:a:i:k:s:p:d:',
+ ['help', 'output=', 'align=', 'input=',
+ 'prikey=', 'enckey=', 'pemdir=', 'imgdir=']
+ )
+
+ out_name = None
+ align = 0
+ infile_name = None
+ aeskey = None
+ pubkey = None
+ privk = None
+ pem_dir = "binfile"
+ img_dir = ''
+
+ for o, a in opts:
+ if o in ('-h', '--help'):
+ print_usage()
+ sys.exit()
+ elif o in ('-o', '--output'):
+ out_name = a
+ elif o in ('-a', '--align'):
+ align = int(a)
+ elif o in ('-i', '--input'):
+ ## doesn't need currently
+ infile_name = a
+ elif o in ('-k', '--prikey'):
+ privkey = a
+ elif o in ('-s', '--enckey'):
+ aeskey = a
+ elif o in ('-p', '--pemdir'):
+ pem_dir = a
+ elif o in ('-d', '--imgdir'):
+ img_dir = a
+ else:
+ print_usage()
+ sys.exit(1)
+
+ if len(args) >= 1:
+ mi_desc_fn = args[0]
+ else:
+ print_usage()
+ sys.exit(1)
+
+ if not out_name:
+ fn, ext = os.path.splitext(mi_desc_fn)
+ out_name = fn + '.img'
+
+ """ read json script """
+ mi_desc = read_desc(mi_desc_fn)
+
+ #mipack = pack_images(mi_desc, align)
+
+ #print 'output: %s (%d bytes)' % (out_name, len(mipack))
+ #open(out_name, 'wb').write(mipack)
+
+ cmd_line_key = mi_desc['cmd_line_key']
+ sign_priv_key = mi_desc['sign_priv_key']
+ aes_enc_sym_key = mi_desc['aes_enc_sym_key']
+
+ """ Where is the key input from """
+
+ pem_key_format = mi_desc['pem_key_format']
+ if(pem_key_format == 1):
+ sbc_auth_alg = mi_desc['sbc_auth_alg']
+ if(sbc_auth_alg == 0):
+ key_path = pem_dir + "/ecdsa_p256_private.pem"
+ #print(key_path)
+ privk = open(key_path,"rb").read()
+ #privk = open("binfile/ecdsa_p256_private.pem","rb").read()
+ #pubk_pem = open("binfile/ecdsa_p256_public.pem","rb").read()
+ elif(sbc_auth_alg == 1):
+ privk = open("binfile/ecdsa_p384_private.pem","rb").read()
+
+ key = cryptoSB.strip_key(aes_enc_sym_key)
+
+ else:
+ if(cmd_line_key == 1):
+ key = cryptoSB.strip_key(aeskey)
+ privk = cryptoSB.strip_key(privkey)
+ #print("dump privkey:")
+ #cryptoSB.dump(privk)
+ elif(cmd_line_key == 0):
+ key = cryptoSB.strip_key(aes_enc_sym_key)
+ privk = cryptoSB.strip_key(sign_priv_key)
+ #print("dump privkey:")
+ #cryptoSB.dump(privk)
+ else:
+ prnit("ERROR: please check cmd_line_key json")
+
+
+
+ #run hash
+ #hash = cryptoSB.HASH()
+ #imghash = hash.hash_sha256(enc_data)
+ #cryptoSB.dump(imghash)
+
+ mipack = my_pack_images(mi_desc, privk, key, align, img_dir)
+ if mipack == None:
+ print("my_pack_images fail")
+ return
+
+ #out_name = 'my_' + fn + '.img'
+ #out_name = fn + '.img'
+ print('output: %s (%d bytes)' % (out_name, len(mipack)))
+ open(out_name, 'wb').write(mipack)
+
+ main()
+
diff --git a/src/devtools/packer/mt2735/cryptoSB.py b/src/devtools/packer/mt2735/cryptoSB.py
new file mode 100644
index 0000000..1c44a61
--- /dev/null
+++ b/src/devtools/packer/mt2735/cryptoSB.py
@@ -0,0 +1,615 @@
+import binascii
+import Crypto.Random.OSRNG.posix as RNG
+from Crypto.Cipher import AES
+from Crypto.Hash import MD5
+from Crypto.Hash import SHA
+from Crypto.Hash import SHA224
+from Crypto.Hash import SHA256
+from Crypto.Hash import SHA384
+from Crypto.Hash import SHA512
+from Crypto.Hash import HMAC
+from Crypto.Util import Counter
+import CryptoPlus
+from CryptoPlus.Cipher import python_AES as CP_python_AES
+import ecdsa
+from ecdsa import SigningKey, VerifyingKey
+from ecdsa.curves import NIST192p, NIST224p, NIST256p, NIST384p, NIST521p
+from ecdsa.util import sigencode_string
+from hashlib import sha1, sha224, sha256, sha384, sha512
+
+#from pycrypto_lib.SelfTest.Signature import test_pkcs1_15_mytest as rsa_mytest
+#from pycrypto_lib.SelfTest.Signature import test_pkcs1_pss_mytest as rsa_pss_mytest
+import test_pkcs1_15_mytest as rsa_mytest
+import test_pkcs1_pss_mytest as rsa_pss_mytest
+
+''' Select ECDSA Curve '''
+__CURVE = 'prime256v1'
+
+AUTH_ECDSA_NISTP256 = 0
+AUTH_ECDSA_NISTP384 = 1
+AUTH_ECDSA_NISTP521 = 2
+AUTH_RSA2048 = 3
+AUTH_RSA3072 = 4
+AUTH_RSA4096 = 5
+
+AUTH_AES_CMAC = 12
+AUTH_HMAC_SHA256 = 13
+
+AUTH_ECDSA_NISTP192 = 10
+AUTH_ECDSA_NISTP224 = 11
+
+
+''' Select ECDSA module '''
+
+''' Select Key Mode '''
+__K_STRING = 0
+__K_PEM = 1
+__K_DER = 2
+
+
+def crypto_pad_to_align(x, align):
+ if(align == 0):
+ return x
+ else:
+ size = len(x)
+ #print("size 0x%x" %size)
+ pad_size = (align - size % align) % align
+ for i in range(0, pad_size, 1):
+ x += b'\x00'
+ #cryptoSB.dump(x)
+ return x
+
+
+# This module is python-ecdsa (warner/python-ecdsa)
+class pythonECDSA:
+ def __init__(self, priv=None, pub=None, curve=None):
+ #print("pure-python ECDSA init")
+ None
+ def sign_string(self, privk, msg, sbc_auth_alg, sbc_auth_alg_hash):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ if(sbc_auth_alg_hash == 0):
+ sk = SigningKey.from_string(privk, curve=NIST256p, hashfunc=sha256)
+ signature_str = sk.sign(msg, hashfunc=sha256, sigencode=sigencode_string)
+ elif(sbc_auth_alg_hash == 1):
+ sk = SigningKey.from_string(privk, curve=NIST256p, hashfunc=sha384)
+ signature_str = sk.sign(msg, hashfunc=sha384, sigencode=sigencode_string)
+ elif(sbc_auth_alg_hash == 2):
+ sk = SigningKey.from_string(privk, curve=NIST256p, hashfunc=sha512)
+ signature_str = sk.sign(msg, hashfunc=sha512, sigencode=sigencode_string)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ if(sbc_auth_alg_hash == 0):
+ sk = SigningKey.from_string(privk, curve=NIST384p, hashfunc=sha256)
+ signature_str = sk.sign(msg, hashfunc=sha256, sigencode=sigencode_string)
+ elif(sbc_auth_alg_hash == 1):
+ sk = SigningKey.from_string(privk, curve=NIST384p, hashfunc=sha384)
+ signature_str = sk.sign(msg, hashfunc=sha384, sigencode=sigencode_string)
+ elif(sbc_auth_alg_hash == 2):
+ sk = SigningKey.from_string(privk, curve=NIST384p, hashfunc=sha512)
+ signature_str = sk.sign(msg, hashfunc=sha512, sigencode=sigencode_string)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP521):
+ if(sbc_auth_alg_hash == 0):
+ sk = SigningKey.from_string(privk, curve=NIST521p, hashfunc=sha256)
+ signature_str = sk.sign(msg, hashfunc=sha256, sigencode=sigencode_string)
+ elif(sbc_auth_alg_hash == 1):
+ sk = SigningKey.from_string(privk, curve=NIST521p, hashfunc=sha384)
+ signature_str = sk.sign(msg, hashfunc=sha384, sigencode=sigencode_string)
+ elif(sbc_auth_alg_hash == 2):
+ sk = SigningKey.from_string(privk, curve=NIST521p, hashfunc=sha512)
+ signature_str = sk.sign(msg, hashfunc=sha512, sigencode=sigencode_string)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.from_string(privk, curve=NIST192p, hashfunc=sha256)
+ signature_str = sk.sign(msg, hashfunc=sha256, sigencode=sigencode_string)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.from_string(privk, curve=NIST224p, hashfunc=sha256)
+ signature_str = sk.sign(msg, hashfunc=sha256, sigencode=sigencode_string)
+ return signature_str
+ def sign_pem(self, privk, msg, sbc_auth_alg):
+ #print(" run sign pem")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.from_pem(privk, hashfunc=sha256)
+ signature_pem = sk.sign(msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.from_pem(privk, hashfunc=sha384)
+ signature_pem = sk.sign(msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.from_pem(privk, hashfunc=sha1)
+ signature_pem = sk.sign(msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.from_pem(privk, hashfunc=sha224)
+ signature_pem = sk.sign(msg, hashfunc=sha224)
+
+ return signature_pem
+ def sign_der(self, privk, msg, sbc_auth_alg):
+ #print(" run sign der")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.from_der(privk, hashfunc=sha256)
+ signature_der = sk.sign(msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.from_der(privk, hashfunc=sha384)
+ signature_der = sk.sign(msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.from_der(privk, hashfunc=sha1)
+ signature_der = sk.sign(msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.from_der(privk, hashfunc=sha224)
+ signature_der = sk.sign(msg, hashfunc=sha224)
+
+
+ return signature_der
+ def verify_string(self, pubk, signature_str, msg, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ vk = VerifyingKey.from_string(pubk, curve=NIST256p, hashfunc=sha256)
+ ret = vk.verify(signature_str, msg)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ vk = VerifyingKey.from_string(pubk, curve=NIST384p, hashfunc=sha384)
+ ret = vk.verify(signature_str, msg)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ vk = VerifyingKey.from_string(pubk, curve=NIST192p, hashfunc=sha1)
+ ret = vk.verify(signature_str, msg)
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ vk = VerifyingKey.from_string(pubk, curve=NIST224p, hashfunc=sha224)
+ ret = vk.verify(signature_str, msg)
+ return ret
+ def verify_pem(self, pubk, signature_pem, msg, sbc_auth_alg):
+ #print(" run verify pem")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ vk = VerifyingKey.from_pem(pubk)
+ ret = vk.verify(signature_pem, msg, hashfunc=sha224)
+ return ret
+ def verify_der(self, pubk, signature_der, msg, sbc_auth_alg):
+ #print(" run verify der")
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha256)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha384)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha1)
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ vk = VerifyingKey.from_der(pubk)
+ ret = vk.verify(signature_der, msg, hashfunc=sha224)
+ return ret
+ def gen_key_string(self, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST384p, hashfunc=sha384)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.generate(curve=NIST192p, hashfunc=sha1)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.generate(curve=NIST224p, hashfunc=sha224)
+ vk = sk.get_verifying_key()
+ privk_str = sk.to_string()
+ pubk_str = vk.to_string()
+ return privk_str, pubk_str
+ def gen_key_pem(self, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST384p, hashfunc=sha384)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP192):
+ sk = SigningKey.generate(curve=NIST192p, hashfunc=sha1)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.generate(curve=NIST224p, hashfunc=sha224)
+ vk = sk.get_verifying_key()
+ privk_pem = sk.to_pem()
+ pubk_pem = vk.to_pem()
+ return privk_pem, pubk_pem
+ def gen_key_der(self, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.generate(curve=NIST256p, hashfunc=sha256)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST384p, hashfunc=sha384)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ sk = SigningKey.generate(curve=NIST192p, hashfunc=sha1)
+ vk = sk.get_verifying_key()
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP224):
+ sk = SigningKey.generate(curve=NIST224p, hashfunc=sha224)
+ vk = sk.get_verifying_key()
+ privk_der = sk.to_der()
+ pubk_der = vk.to_der()
+ return privk_der, pubk_der
+
+class AESCipher:
+ def __init__(self, key, blk_sz):
+ #self.key = md5(key.encode('utf8')).hexdigest()
+ self.key = key
+ self.blk_sz = blk_sz
+ keylen = len(key)
+ if(keylen != blk_sz):
+ print("ERROR: key length fail:")
+ return 0
+
+ def aes_encrypt(self, data):
+ #data = pad(data)
+ #print(":".join("{:02x}".format(ord(e)) for e in data))
+ cryptor = AES.new(self.key, AES.MODE_ECB)
+ return cryptor.encrypt(data)
+
+ def aes_decrypt(self, data):
+ #data = pad(data)
+ #print(":".join("{:02x}".format(ord(e)) for e in data))
+ cryptor = AES.new(self.key, AES.MODE_ECB)
+ return cryptor.decrypt(data)
+
+ def aes_cbc_encrypt(self, data, iv):
+ cryptor = AES.new(self.key, AES.MODE_CBC, iv)
+ return cryptor.encrypt(data)
+
+ def aes_cbc_decrypt(self, data, iv):
+ cryptor = AES.new(self.key, AES.MODE_CBC, iv)
+ return cryptor.decrypt(data)
+
+ def aes_ctr_encrypt_only_counter(self, data, prefix_const, init_counter):
+ #ctr_e = Counter.new(64, prefix = prefix_const)
+ #cryptor = AES.new(self.key, AES.MODE_CTR, counter=lambda: init_counter)
+
+ ctr_e = Counter.new(128, initial_value=long(init_counter.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_e)
+
+ return cryptor.encrypt(data)
+
+ def aes_ctr_decrypt_only_counter(self, data, prefix_const, init_counter):
+ #ctr_d = Counter.new(128, prefix = prefix_const)
+ #cryptor = AES.new(self.key, AES.MODE_CTR, counter=lambda: init_counter)
+
+ ctr_d = Counter.new(128, initial_value=long(init_counter.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_d)
+ return cryptor.decrypt(data)
+
+ def aes_ctr_encrypt(self, data, prefix_str, initvalue):
+ #print("0x%x" %long(initvalue.encode('hex'), 16))
+ #print(len(prefix_str))
+ nbits = (128 - (len(prefix_str)*8))
+ ctr_e = Counter.new(nbits, prefix = prefix_str, initial_value=long(initvalue.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_e)
+
+ return cryptor.encrypt(data)
+
+ def aes_ctr_decrypt(self, data, prefix_str, initvalue):
+ nbits = (128 - (len(prefix_str)*8))
+ ctr_d = Counter.new(nbits, prefix = prefix_str, initial_value=long(initvalue.encode('hex'), 16), allow_wraparound=True)
+ cryptor = AES.new(self.key, AES.MODE_CTR, counter=ctr_d)
+
+ return cryptor.decrypt(data)
+
+
+def strip_key(key):
+ #src_key = key.lstrip("x").rstrip("L")
+ src_key = key[2:].rstrip("L")
+ key_byte = binascii.a2b_hex(src_key)
+ return key_byte
+
+def my_a2b_hex(key):
+ key_byte = binascii.a2b_hex(key)
+ return key_byte
+
+def my_img_enc(data, key, iv, img_enc_alg, align=None):
+ #dump(data)
+
+ #align
+ bin = crypto_pad_to_align(data, align)
+
+ if(img_enc_alg == 0):
+ # AES 128 ECB
+ aes = AESCipher(key, 16)
+ encmsg = aes.aes_encrypt(bin)
+ #print("AES 128 ECB image result:")
+ #dump(encmsg)
+ elif(img_enc_alg == 1):
+ # AES 128 CBC
+ aes = AESCipher(key, 16)
+ encmsg = aes.aes_cbc_encrypt(bin, iv)
+ #print("AES 128 CBC image result:")
+ #dump(encmsg)
+ elif(img_enc_alg == 2):
+ # AES 256 ECB
+ aes = AESCipher(key, 32)
+ encmsg = aes.aes_encrypt(bin)
+ #print("AES 256 ECB image result:")
+ #dump(encmsg)
+ elif(img_enc_alg == 3):
+ # AES 256 CBC
+ aes = AESCipher(key, 32)
+ encmsg = aes.aes_cbc_encrypt(bin, iv)
+ #print("AES 256 CBC image result:")
+ #dump(encmsg)
+
+ return encmsg
+
+# dump str to bytes
+def dump(data):
+ for i in range(0, len(data)):
+ print ("0x%02x,"%ord(data[i])),
+ if(((i+1)%16) == 0):
+ print("")
+
+class HASH:
+ def __init__(self):
+ #print("//class HASH init")
+ None
+
+ def hash_sha1(self, data):
+ #print("SHA1:")
+ hash = SHA.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_sha224(self, data):
+ #print("SHA224:")
+ hash = SHA224.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_sha256(self, data):
+ #print("SHA256:")
+ hash = SHA256.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_sha384(self, data):
+ #print("SHA384:")
+ hash = SHA384.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+
+ def hash_sha512(self, data):
+ #print("SHA512:")
+ hash = SHA512.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+ def hash_md5(self, data):
+ #print("MD5:")
+ hash = MD5.new()
+ hash.update(data)
+ digest = hash.digest()
+ return digest
+
+'''
+def sb_hash(data, sbc_auth_alg):
+ #print("run my_hash:")
+
+ #myhash = HASH()
+
+ if((sbc_auth_alg == 1) or (sbc_auth_alg == 5) ):
+ sbhash = HASH()
+ digest = sbhash.hash_sha384(data)
+ return digest
+ elif(sbc_auth_alg == 0) or (sbc_auth_alg == 2) or (sbc_auth_alg == 3) or (sbc_auth_alg == 4):
+ sbhash = HASH()
+ digest = sbhash.hash_sha256(data)
+ return digest
+ elif((sbc_auth_alg == 6)):
+ sbhash = HASH()
+ digest = sbhash.hash_sha512(data)
+ return digest
+ else:
+ print("ERROR: run sb_hash fail")
+'''
+def sb_hash(data, sbc_auth_alg_hash):
+ #print("run my_hash:")
+
+ #myhash = HASH()
+
+ if(sbc_auth_alg_hash == 0):
+ sbhash = HASH()
+ digest = sbhash.hash_sha256(data)
+ return digest
+ elif(sbc_auth_alg_hash == 1):
+ sbhash = HASH()
+ digest = sbhash.hash_sha384(data)
+ return digest
+ elif(sbc_auth_alg_hash == 2):
+ sbhash = HASH()
+ digest = sbhash.hash_sha512(data)
+ return digest
+ else:
+ print("ERROR: run sb_hash fail")
+
+
+def hmac_sha256(key, bdata):
+
+ b = HMAC.new(key, digestmod=SHA256)
+ b.update(bdata)
+ digest = b.digest()
+ #digest = b.hexdigest()
+ #dump(digest)
+
+ return digest
+
+def aescmac(key, msg):
+ #print("AES CMAC: ")
+ cipher = CP_python_AES.new(key, CP_python_AES.MODE_CMAC)
+ out = cipher.encrypt(msg)
+
+ #outhex = cipher.encrypt(msg).encode('hex')
+ #out = outhex.decode('hex')
+ return out
+
+def ecdsa_sign_nistp256_string(privk, msg, sbc_auth_alg_hash):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_string(privk, msg, AUTH_ECDSA_NISTP256, sbc_auth_alg_hash)
+
+ return signature
+
+def ecdsa_sign_nistp256_pem(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_pem(privk, msg, AUTH_ECDSA_NISTP256)
+ return signature
+
+def ecdsa_sign_nistp256_der(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_der(privk, msg, AUTH_ECDSA_NISTP256)
+
+ return signature
+
+def ecdsa_sign_nistp384_string(privk, msg, sbc_auth_alg_hash):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_string(privk, msg, AUTH_ECDSA_NISTP384, sbc_auth_alg_hash)
+ return signature
+
+def ecdsa_sign_nistp384_pem(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_pem(privk, msg, AUTH_ECDSA_NISTP384)
+
+ return signature
+
+def ecdsa_sign_nistp384_der(privk, msg):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_der(privk, msg, AUTH_ECDSA_NISTP384)
+
+ return signature
+
+def ecdsa_sign_nistp521_string(privk, msg, sbc_auth_alg_hash):
+ ecdsa = pythonECDSA()
+ signature = ecdsa.sign_string(privk, msg, AUTH_ECDSA_NISTP521, sbc_auth_alg_hash)
+ return signature
+
+def pubkey_string(pubk, sbc_auth_alg):
+ sk = VerifyingKey.from_pem(pubk)
+ return sk.to_string()
+def privkey_string(privk, sbc_auth_alg):
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ sk = SigningKey.from_pem(privk, hashfunc=sha256)
+ return sk.to_string()
+ else:
+ sk = SigningKey.from_pem(privk, hashfunc=sha384)
+ return sk.to_string()
+
+def sb_sign(privk, pubk, msg, sbc_auth_alg, sbc_auth_alg_hash, rsa_parse, sbc_rsa_pad_sel, key_mode=__K_STRING):
+ print("Start sb_sign:")
+
+ if(sbc_auth_alg == AUTH_ECDSA_NISTP256):
+ #pyelliptic ECDSA NIST p256
+ if(key_mode == __K_STRING):
+ signature = ecdsa_sign_nistp256_string(privk, msg, sbc_auth_alg_hash)
+ #another use
+ #ecdsa = pythonECDSA()
+ #signature = ecdsa.sign_string(privk, msg, AUTH_ECDSA_NISTP256)
+
+ elif(key_mode == __K_PEM):
+ signature = ecdsa_sign_nistp256_pem(privk, msg)
+
+ elif(key_mode == __K_DER):
+ signature = ecdsa_sign_nistp256_der(privk, msg)
+ return signature
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP384):
+ #pyelliptic ECDSA_NIST_p384
+ if(key_mode == __K_STRING):
+ signature = ecdsa_sign_nistp384_string(privk, msg, sbc_auth_alg_hash)
+
+ elif(key_mode == __K_PEM):
+ signature = ecdsa_sign_nistp384_pem(privk, msg)
+
+ elif(key_mode == __K_DER):
+ signature = ecdsa_sign_nistp384_der(privk, msg)
+
+ return signature
+
+ elif(sbc_auth_alg == AUTH_ECDSA_NISTP521):
+ #pyelliptic ECDSA_NIST_p521
+ if(key_mode == __K_STRING):
+ signature = ecdsa_sign_nistp521_string(privk, msg, sbc_auth_alg_hash)
+ return signature
+ elif(sbc_auth_alg == AUTH_RSA2048):
+ if(sbc_rsa_pad_sel == 0):
+ print("auth rsa2048 pkcs1_v15 padding")
+ myrsa = rsa_mytest.sbc_rsa_sign1_mytest(rsa_parse, msg)
+ print("mytest rsa pkcs1_15 sign:")
+ signature = myrsa.sbc_rsa_sign1_json()
+ print("mytest rsa pkcs1_15 verify:")
+ myrsa.sbc_rsa_verify1()
+ elif(sbc_rsa_pad_sel == 1):
+ print("auth rsa2048 pkcs1_pss padding")
+ myrsa = rsa_pss_mytest.testSign1_mytest(rsa_parse, msg)
+ print("mytest rsa pkcs1_pss sign:")
+ signature = myrsa.sbc_rsa_sign1_json()
+ print("mytest rsa pkcs1_pss verify:")
+ myrsa.verify1_mytest()
+ else:
+ print("ERROR: padding selection fail")
+ return signature
+
+ elif(sbc_auth_alg == AUTH_RSA3072):
+ if(sbc_rsa_pad_sel == 0):
+ print("auth rsa3072 pkcs1_v15 padding")
+ myrsa = rsa_mytest.sbc_rsa_sign1_mytest(rsa_parse, msg)
+ print("mytest rsa pkcs1_15 sign:")
+ signature = myrsa.sbc_rsa_sign1_json()
+ print("mytest rsa pkcs1_15 verify:")
+ myrsa.sbc_rsa_verify1()
+ elif(sbc_rsa_pad_sel == 1):
+ print("auth rsa3072 pkcs1_pss padding")
+ myrsa = rsa_pss_mytest.testSign1_mytest(rsa_parse, msg)
+ print("mytest rsa pkcs1_pss sign:")
+ signature = myrsa.sbc_rsa_sign1_json()
+ print("mytest rsa pkcs1_pss verify:")
+ myrsa.verify1_mytest()
+ else:
+ print("ERROR: padding selection fail")
+ return signature
+
+ elif(sbc_auth_alg == AUTH_RSA4096):
+ if(sbc_rsa_pad_sel == 0):
+ print("auth rsa4096 pkcs1_v15 padding")
+ myrsa = rsa_mytest.sbc_rsa_sign1_mytest(rsa_parse, msg)
+ print("mytest rsa pkcs1_15 sign:")
+ signature = myrsa.sbc_rsa_sign1_json()
+ print("mytest rsa pkcs1_15 verify:")
+ myrsa.sbc_rsa_verify1()
+ elif(sbc_rsa_pad_sel == 1):
+ print("auth rsa4096 pkcs1_pss padding")
+ myrsa = rsa_pss_mytest.testSign1_mytest(rsa_parse, msg)
+ print("mytest rsa pkcs1_pss sign:")
+ signature = myrsa.sbc_rsa_sign1_json()
+ print("mytest rsa pkcs1_pss verify:")
+ myrsa.verify1_mytest()
+ else:
+ print("ERROR: padding selection fail")
+ return signature
+
+ elif(sbc_auth_alg == AUTH_AES_CMAC):
+ #AES128_CMAC
+ signature = aescmac(privk, msg)
+ return signature
+ elif(sbc_auth_alg == AUTH_HMAC_SHA256):
+ #HMAC-SHA256
+ signature = hmac_sha256(privk, msg)
+ return signature
+ else:
+ print("ERROR: wrong authentication algorithm!!")
+
diff --git a/src/devtools/packer/mt2735/mipack.py b/src/devtools/packer/mt2735/mipack.py
new file mode 100644
index 0000000..42723fa
--- /dev/null
+++ b/src/devtools/packer/mt2735/mipack.py
@@ -0,0 +1,888 @@
+#!/usr/bin/python
+# -*- coding: utf8 -*-
+
+import json
+import struct
+import sys
+import binascii
+import cryptoSB
+import copy
+
+from jsoncomment import JsonComment
+
+__Align = 16
+__Align_16_en = 0
+__Align_LK_entry_en = 1
+
+__TEST = 0
+
+__Align_pub_key_apend = 512
+__Align_sign_size = 512
+__Align_LK_entry_size = 4096
+
+g_magic_size = 8
+g_total_len_size = 4
+g_bl_version_size = 4
+g_img_number_size = 4
+g_ls_cmd_number_size = 4
+g_mi_header_info_size = (g_magic_size + g_total_len_size + g_bl_version_size + g_img_number_size + g_ls_cmd_number_size)
+
+g_img_header_size = 96
+g_ls_cmd_size = 8
+
+g_img_oneoffset_table_size = 4
+g_img_onehash_table_size = 64
+
+g_public_key_size = __Align_pub_key_apend
+g_rsa_n_size = __Align_pub_key_apend
+g_sbc_auth_inf_size = 4
+g_sbc_auth_key_hash_size = 4
+g_sbc_auth_alg_size = 4
+g_sbc_auth_alg_hash_size = 4
+g_sbc_rsa_pad_sel_size = 4
+g_sbc_pub_key_len_size = 4
+g_sbc_size = (g_public_key_size + g_rsa_n_size + g_sbc_auth_inf_size + g_sbc_auth_key_hash_size + g_sbc_auth_alg_size + g_sbc_auth_alg_hash_size + g_sbc_rsa_pad_sel_size + g_sbc_pub_key_len_size)
+
+g_boot_hash_size = 64
+g_signature_size = __Align_sign_size
+g_auth_size = (g_boot_hash_size + g_signature_size)
+
+g_ck_magic_size = 16
+g_ck_soc_id_size = 32
+g_ck_pub_key_size = __Align_pub_key_apend
+g_ck_auth_algo_size = 4
+g_ck_put_key_len_size = 4
+g_ck_signature_size = __Align_sign_size
+g_ck_size = (g_ck_magic_size + g_ck_soc_id_size + g_ck_pub_key_size + g_ck_auth_algo_size + g_ck_put_key_len_size + g_ck_signature_size)
+
+def to_int(s):
+ if isinstance(s, (str, unicode)):
+ return int(s, 0)
+ else:
+ return s
+
+def byte_to_int(bytes):
+ result = 0
+
+ for b in bytes:
+ result = result*256 + ord(b)
+
+ return result
+
+def read_desc(mi_desc_fn):
+ #desc = json.load(open(mi_desc_fn))
+
+ parser = JsonComment(json)
+ desc = parser.loads(open(mi_desc_fn).read())
+
+ for img in desc['images']:
+ img['img_enc_alg'] = to_int(img['img_enc_alg'])
+ img['img_enc_inf'] = to_int(img['img_enc_inf'])
+
+ '''0627 remove int assign avoid key start is (0x00..)'''
+ #img['img_iv'] = to_int(img['img_iv'])
+
+ return desc
+
+
+def gen_ver_magic(major, minor, revision):
+ major = to_int(major)
+ minor = to_int(minor)
+ revision = to_int(revision)
+
+ x = major ^ 0xaa
+ y = minor ^ 0x55
+ z = revision ^ 0x99
+ checksum = (x + y + z) & 0xff
+
+ return (major << 0) | (minor << 8) | (revision << 16) | (checksum << 24)
+
+def my_gen_ver_magic(major, minor, revision):
+ major = to_int(major)
+ minor = to_int(minor)
+ revision = to_int(revision)
+
+ x = major ^ 0xaa
+ y = minor ^ 0x55
+ z = revision ^ 0x99
+ checksum = (x + y + z) & 0xff
+
+ highmagic = byte_to_int(b'\x27\x21\xca\xfe')
+ #print(hex(highmagic))
+
+ return (major << 0) | (minor << 8) | (revision << 16) | (checksum << 24), highmagic
+
+def my_gen_mtk_magic(magic):
+ magic_str = my_to_bytes(magic, g_magic_size, endianess='little')
+
+ lowmagic = byte_to_int(magic_str[4:8])
+ highmagic = byte_to_int(magic_str[0:4])
+
+ return lowmagic, highmagic
+
+def pad_to_align(align, current_size):
+ if not align:
+ return ''
+
+ pad_size = (align - current_size % align) % align
+ pad = '\0' * pad_size
+
+ return pad
+
+
+def dump(data):
+ for i in range(0, len(data)):
+ if(i%16 == 0):
+ print("[%04X]" % i),
+
+ print("%02x" % ord(data[i])),
+ if(((i+1)%16) == 0):
+ print
+
+def pack_load_script(mi_desc):
+ ls_script = []
+ reserved = 0
+ images = mi_desc['images']
+ img_num = len(images)
+
+ ls_cmds = mi_desc['load_srcipt_cmd']
+ ls_cmds_num = len(ls_cmds)
+ #print("ls_cmds_num: %d" %ls_cmds_num)
+
+ for i in range(ls_cmds_num):
+ ls_cmd = ls_cmds[i]
+ cmd = ls_cmd['cmd']
+
+ if cmd == "LOAD":
+ cmd_id = 0
+ img_file = ls_cmd['img_file']
+ addr = to_int(ls_cmd['addr'])
+
+ img_id = -1
+ for j in range(img_num):
+ img = images[j]
+ img_binary_name = img['img_file']
+ if img_file == img_binary_name:
+ img_id = j
+ break
+
+ if img_id == -1:
+ print("Please check img file name")
+ return
+
+ packed_cmd = struct.pack('<BBHI', cmd_id, img_id, reserved, addr)
+ #dump(packed_cmd)
+ #print
+ elif cmd == "MCU-ENTRY":
+ cmd_id = 2
+ mcu_id = ls_cmd['mcu_id']
+ addr = to_int(ls_cmd['addr'])
+ packed_cmd = struct.pack('<BBHI', cmd_id, mcu_id, reserved, addr)
+ #dump(packed_cmd)
+ #print
+ elif cmd == "MCU_RESET-ENTRY":
+ cmd_id = 1
+ mcu_id = ls_cmd['mcu_id']
+ addr = to_int(ls_cmd['addr'])
+ packed_cmd = struct.pack('<BBHI', cmd_id, mcu_id, reserved, addr)
+ #dump(packed_cmd)
+ #print
+ else:
+ print("unknown command: %s" %cmd)
+ return
+
+ ls_script += packed_cmd
+
+ #print("load script:")
+ #dump(ls_script)
+
+ return ls_script
+
+def rsa_data_parser(mi_desc, sbc_rsa_pad_sel):
+ rsa_dict = {"n":'', "e":'', "d":''}
+ rsa_parse = []
+
+ if(sbc_rsa_pad_sel == 0):
+ rsa_d = mi_desc['rsa_data']
+ rsa_data = rsa_d[0]
+
+ rsa_dict['n'] = rsa_data['n']
+ rsa_dict['e'] = rsa_data['e']
+ rsa_dict['d'] = rsa_data['d']
+ rsa_parse.append(rsa_dict)
+ #print(rsa_parse)
+
+ #rsa_parse.append(rsa_data['n'])
+ #rsa_parse.append(rsa_data['e'])
+ #rsa_parse.append(rsa_data['d'])
+ rsa_parse.append(rsa_data['msg2hash'])
+ rsa_parse.append(rsa_data['signvalue'])
+ rsa_parse.append(rsa_data['shafunc'])
+ rsa_parse.append(rsa_data['msgtest'])
+ print("dump rsa_data_parser")
+ #print(rsa_parse)
+ #print(rsa_parse[0])
+ else:
+ rsa_d = mi_desc['rsa_data_pss']
+ rsa_data = rsa_d[0]
+
+ rsa_dict['n'] = rsa_data['n']
+ rsa_dict['e'] = rsa_data['e']
+ rsa_dict['d'] = rsa_data['d']
+ rsa_parse.append(rsa_dict)
+
+ rsa_parse.append(rsa_data['msg2hash'])
+ rsa_parse.append(rsa_data['signvalue'])
+ rsa_parse.append(rsa_data['salt'])
+ rsa_parse.append(rsa_data['shafunc'])
+ rsa_parse.append(rsa_data['msgtest'])
+ print("dump rsa_data_parser")
+ print(rsa_parse)
+
+ return rsa_parse
+
+def ck_rsa_data_parser(mi_desc, sbc_rsa_pad_sel):
+ rsa_dict = {"n":'', "e":'', "d":''}
+ rsa_parse = []
+
+ if(sbc_rsa_pad_sel == 0):
+ rsa_d = mi_desc['ck_rsa_data']
+ rsa_data = rsa_d[0]
+
+ rsa_dict['n'] = rsa_data['n']
+ rsa_dict['e'] = rsa_data['e']
+ rsa_dict['d'] = rsa_data['d']
+ rsa_parse.append(rsa_dict)
+ #print(rsa_parse)
+
+ #rsa_parse.append(rsa_data['n'])
+ #rsa_parse.append(rsa_data['e'])
+ #rsa_parse.append(rsa_data['d'])
+ rsa_parse.append(rsa_data['msg2hash'])
+ rsa_parse.append(rsa_data['signvalue'])
+ rsa_parse.append(rsa_data['shafunc'])
+ rsa_parse.append(rsa_data['msgtest'])
+ print("dump rsa_data_parser")
+ #print(rsa_parse)
+ #print(rsa_parse[0])
+ else:
+ rsa_d = mi_desc['ck_rsa_data_pss']
+ rsa_data = rsa_d[0]
+
+ rsa_dict['n'] = rsa_data['n']
+ rsa_dict['e'] = rsa_data['e']
+ rsa_dict['d'] = rsa_data['d']
+ rsa_parse.append(rsa_dict)
+
+ rsa_parse.append(rsa_data['msg2hash'])
+ rsa_parse.append(rsa_data['signvalue'])
+ rsa_parse.append(rsa_data['salt'])
+ rsa_parse.append(rsa_data['shafunc'])
+ rsa_parse.append(rsa_data['msgtest'])
+ print("dump rsa_data_parser")
+ print(rsa_parse)
+
+ return rsa_parse
+
+def my_pack_images(mi_desc, privk, enckey, align=None, img_dir=''):
+ '''
+ mipack_file
+ mi_header_info
+ u32 magic
+ u32 total_len
+ u32 bl_version
+ u32 img_number (N)
+ u32 load_script_cmd_number (M)
+
+ img_info[1]~img_info[N]
+ u32 img_length
+ u32 img_offset
+ 64Byes img_hash
+ u32 img_enc_inf
+ u32 img_enc_alg
+ 16Bytes img_iv
+
+ load_script_cmd[1]~load_script_cmd[M]
+ u64 cmd
+
+ sbc data
+ 512Bytes sbc_pub_key
+ 512Bytes sbc_rsa_n
+ u32 sbc_auth_info
+ u32 sbc_key_hash
+ u32 sbc_auth_algo_dsa
+ u32 sbc_auth_algo_hash
+ u32 sbc_rsa_pad_sel
+ u32 sbc_pub_key_len
+
+ auth data
+ 64Bytes boothash
+ 512Bytes signature
+
+ [img binary 1]
+ ...
+ [img binary 1]
+ '''
+
+ key_mode = 0
+
+ mi_header_struct = struct.Struct('<IIIIII')
+ sbc_struct = struct.Struct('<IIIIII')
+ ck_struct = struct.Struct('<II')
+
+
+ #run hash
+ hash = cryptoSB.HASH()
+
+ # ver_magic
+ #version = mi_desc['version']
+ #major, minor, revision = version.split('.')
+ #ver_magic_l, ver_magic_h = my_gen_ver_magic(major, minor, revision)
+
+ ver_magic_l, ver_magic_h = my_gen_mtk_magic(to_int(mi_desc['magic_num']))
+
+ # bl region
+ bl_version = mi_desc['bl_version']
+ images = mi_desc['images']
+ img_num = len(images)
+ ls_cmds = mi_desc['load_srcipt_cmd']
+ ls_cmds_num = len(ls_cmds)
+
+ '''size of bl + imgl + sbc + auth'''
+ # Fixed size section: mi_header, sbc data, auth data
+ # Non-fixed size section: img_info, load script
+ bl_total_len = g_mi_header_info_size + g_sbc_size + g_auth_size
+ #bl_total_len = g_mi_header_info_size + g_sbc_size + g_auth_size + g_ck_size
+ bl_total_len += img_num * g_img_header_size
+ bl_total_len += ls_cmds_num * g_ls_cmd_size
+
+
+ #print("==== multi-image header size ====")
+ #print("g_mi_header_info_size=%d, g_sbc_size=%d, g_auth_size=%d, bl_total_len = %d" %(g_mi_header_info_size, g_sbc_size, g_auth_size, bl_total_len))
+
+ #img_header_table = []
+ img_headers = []
+ bins = []
+ sbc_region = []
+ hashtable = []
+ imagetmp = [[], [], [], [], [], [], [], [], [], []]
+ packtmp = []
+ blh_hash = []
+ signaturelist = []
+ ck_region = []
+ cksignaturelist = []
+
+ imagesize = []
+
+
+ sbc_auth_alg = mi_desc['sbc_auth_alg']
+ sbc_rsa_pad_sel = mi_desc['sbc_rsa_pad_sel']
+ ''' parer rsa test pattern '''
+ rsa_parse = rsa_data_parser(mi_desc, sbc_rsa_pad_sel)
+
+ # sbc region
+ ##pub_key = to_int(mi_desc['public_key'])
+ ##public_key = my_binify(pub_key)
+ '''20180627 remove int assign avoid key start is (0x00..)'''
+ pub_key = (mi_desc['public_key'])
+ public_key = cryptoSB.strip_key(pub_key)
+ pubk = b'\x04' + public_key
+
+ rsa_e = cryptoSB.my_a2b_hex(rsa_parse[0]['e'])
+ rsa_n = cryptoSB.my_a2b_hex(rsa_parse[0]['n'])
+ if((sbc_auth_alg == 0) or (sbc_auth_alg == 1) or (sbc_auth_alg == 2)):
+ public_key_append = my_pad_to_align(public_key, __Align_pub_key_apend)
+ sbc_region.append(public_key_append)
+
+ #sbc_rsa_n = (mi_desc['sbc_rsa_n'])
+ #rsa_modulus = cryptoSB.strip_key(sbc_rsa_n)
+ rsa_modulus_append = my_pad_to_align(rsa_n, __Align_pub_key_apend)
+ sbc_region.append(rsa_modulus_append)
+ elif((sbc_auth_alg == 3) or (sbc_auth_alg == 4) or (sbc_auth_alg == 5)):
+ rsa_e_append = my_pad_to_align(rsa_e, __Align_pub_key_apend)
+ sbc_region.append(rsa_e_append)
+ rsa_n_append = my_pad_to_align(rsa_n, __Align_pub_key_apend)
+ sbc_region.append(rsa_n_append)
+
+
+ #print("======= sbc region =========")
+ sbc_auth_inf = mi_desc['sbc_auth_inf']
+ #print("sbc_auth_inf = 0x%x" %sbc_auth_inf)
+ sbc_key_hash = mi_desc['sbc_key_hash']
+ sbc_auth_alg = mi_desc['sbc_auth_alg']
+ #print("sbc_auth_alg = 0x%x" %sbc_auth_alg)
+ sbc_auth_alg_hash = mi_desc['sbc_auth_alg_hash']
+ sbc_rsa_pad_sel = mi_desc['sbc_rsa_pad_sel']
+ sbc_pub_key_len = mi_desc['sbc_pub_key_len']
+ sbc = sbc_struct.pack(sbc_auth_inf, sbc_key_hash, sbc_auth_alg, sbc_auth_alg_hash, sbc_rsa_pad_sel, sbc_pub_key_len)
+ sbc_region.append(sbc)
+
+ #print("======= ck region =========")
+ ck_mg = (mi_desc['ck_magic_num'])
+ ck_magic = cryptoSB.strip_key(ck_mg)
+ ck_region.append(ck_magic)
+ ck_sid = (mi_desc['ck_soc_id'])
+ ck_soc_id = cryptoSB.strip_key(ck_sid)
+ ck_region.append(ck_soc_id)
+ ck_pkey = (mi_desc['ck_pub_key'])
+
+ ck_pub_key = cryptoSB.strip_key(ck_pkey)
+ ck_pub_key_append = my_pad_to_align(ck_pub_key, __Align_pub_key_apend)
+ ck_region.append(ck_pub_key_append)
+ ck_pubk = b'\x04' + ck_pub_key
+
+ ck_rsa_n = (mi_desc['ck_rsa_n'])
+ ck_rsa_modulus = cryptoSB.strip_key(ck_rsa_n)
+ ck_rsa_modulus_append = my_pad_to_align(ck_rsa_modulus, __Align_pub_key_apend)
+ ck_region.append(ck_rsa_modulus_append)
+
+ ck_auth_algo = mi_desc['ck_auth_algo']
+ ck_pub_key_len = mi_desc['ck_pub_key_len']
+ ck = ck_struct.pack(ck_auth_algo, ck_pub_key_len)
+ ck_region.append(ck)
+
+ ck_en = mi_desc['change_key_en']
+ sign_ck_priv_key = mi_desc['sign_ck_priv_key']
+ signckprivk = cryptoSB.strip_key(sign_ck_priv_key)
+
+ # pad before 1st image
+
+ #pad = pad_to_align(64, expected_size)
+ #bins.append(pad)
+ #expected_size += len(pad)
+
+
+ # images
+ if(__Align_LK_entry_en == 1):
+ ''' workaround: L3 half share cache size is not enough for BL2 image.
+ 1. the offset of first image align to 0x1000
+ '''
+ img_offset = (bl_total_len + 4095) & (~4095)
+ else:
+ ''' 512 bytes aligned (20200310) '''
+ img_offset = (bl_total_len + 511) & (~511)
+
+ img_offset_table = []
+
+ for i in range(img_num):
+ #print("\n\n======== Start image step: =========")
+
+
+ img = images[i]
+ img_file = img['img_file']
+ img_enc_inf = img['img_enc_inf']
+ img_enc_alg = img['img_enc_alg']
+ #print("img_enc_inf=0x%x" %img_enc_inf)
+
+ bin = open(img_dir + '/' + img_file, 'rb').read()
+
+ iv_int = img['img_iv']
+ #iv = my_binify(iv_int)
+ '''0627 remove int assign avoid key start is (0x00..)'''
+ iv = cryptoSB.strip_key(iv_int)
+ iv0= int(iv[0:4].encode('hex'), 16)
+ iv1= int(iv[4:8].encode('hex'), 16)
+ iv2= int(iv[8:12].encode('hex'), 16)
+ iv3= int(iv[12:16].encode('hex'), 16)
+ #print type(iv)
+ #print("IV:")
+ #cryptoSB.dump(iv)
+
+
+ if(img_enc_inf == 1):
+ '''image encrypt'''
+ out = cryptoSB.my_img_enc(bin, enckey, iv, img_enc_alg, __Align)
+ bins.append(out)
+ #bins = out
+ elif(img_enc_inf == 2):
+ '''image encrypt'''
+ out = cryptoSB.my_img_enc(bin, enckey, iv, img_enc_alg, __Align)
+ bins.append(out)
+ #bins = out
+ else:
+ '''plaintext image'''
+ out = my_pad_to_align(bin, __Align)
+ bins.append(out)
+ #bins = out
+
+ # binary length should be 16 bytes aligned
+ length = len(out)
+
+ imagesize.append(length)
+ #print("")
+ #print("image[%d] offset : 0x%x" %(i, img_offset))
+ #print("image[%d] size : 0x%x" %(i, imagesize[i]))
+
+ imagetmp[i] = copy.copy(bins)
+
+ img_str = ''.join(bins)
+ #print type(img_str)
+ #print("========= image[%d] binary ==========" %i)
+ #cryptoSB.dump(img_str)
+
+
+ # hash each (image header + image binary)
+ #print('')
+ #print("========= image[%d] binary hash ==========" %i)
+ hashvalue = cryptoSB.sb_hash(img_str, sbc_auth_alg_hash)
+ imghash = my_pad_to_align(hashvalue, g_boot_hash_size)
+ #cryptoSB.dump(imghash)
+
+ # img_header
+ img_hdr = struct.pack('<II',
+ length,
+ img_offset)
+ img_hdr += "".join(imghash)
+ '''20180719 fix IV order fail'''
+ img_hdr += struct.pack('<II16s',
+ img_enc_inf,
+ img_enc_alg,
+ iv)
+
+
+ img_offset_table.append(str(img_offset))
+ length = (length + 511) & (~511)
+ img_offset += length
+ #img_offset_table.append(my_to_bytes(img_offset, 4, endianess='little'))
+
+ #print("\n=====>")
+ #print("image[%d] header info :" %i)
+ #cryptoSB.dump(img_hdr)
+ img_headers.append(img_hdr)
+
+ #img_headers.remove(img_hdr)
+ while len(bins) > 0:
+ bins.pop()
+
+
+ #print("\n\nSTART to pack all sections ...")
+ pack = []
+
+ #print("======== append mi_header info ==========")
+ total_len = int(img_offset_table[img_num-1]) + int(imagesize[img_num-1])
+
+ mi_header = mi_header_struct.pack(
+ ver_magic_l,
+ ver_magic_h,
+ total_len,
+ bl_version,
+ img_num,
+ ls_cmds_num)
+
+
+ pack.append(mi_header)
+
+ # append image info
+ for i in range(img_num):
+ pack += img_headers[i]
+
+
+ ls_script = pack_load_script(mi_desc)
+ if ls_script == None:
+ print("pack_load_script fail")
+ return
+
+ # append load script
+ pack += ls_script
+
+ # append sbc data
+ pack += sbc_region
+
+ # for easy view. please remove it while release final
+ '''align for (bl + imgl + sbc)'''
+ if(__Align_16_en == 1):
+ padnum = pad_to_align(16, len(''.join(pack)))
+ pack.append(padnum)
+
+ #print("======== append mi_header hash: ==========")
+ bl_header = ''.join(pack)
+ #cryptoSB.dump(bl_header)
+ blh = copy.copy(bl_header)
+ boothash = cryptoSB.sb_hash(blh, sbc_auth_alg_hash)
+ boothash_append = my_pad_to_align(boothash, g_boot_hash_size)
+ #cryptoSB.dump(boothash_append)
+ blh_hash.append(boothash_append)
+
+ # append hash
+ pack += blh_hash
+
+ #print("======== append mi_header signature: =========")
+ #privk = "\xc1\xbe\xe4\xfa\x86\xaf\x86\x84\x67\x7c\xae\xee\xa8\x8a\xb0\x72\x3e\x55\x4a\xef\x01\x60\xb8\xfc\x65\x3c\x0e\x00\x08\x0f\x4f\x78"
+ #pubk = "\x04\x14\xc1\xcf\x10\x99\x9d\x3a\x98\xf3\x71\xb8\xd8\x9b\x3b\x26\xb2\x9e\xe1\xbd\x99\xf3\xe0\x39\x3d\x34\x21\x6a\x6f\x49\x58\x7a\xb1\xdd\x8a\xba\x7a\x9d\x02\x99\x5f\xda\xa0\xb8\x62\x82\xae\xc2\xd0\xc6\x88\xc2\x26\x03\x97\x86\x65\x46\xbb\x20\xc9\xd1\x44\xb9\x84"
+
+ if sbc_auth_inf == 0:
+ padbytes = '\0' * g_signature_size
+ signaturelist.append(padbytes)
+ else:
+ pem_key_format = mi_desc['pem_key_format']
+ if(pem_key_format == 1):
+ '''PEM format'''
+ key_mode = 1
+ elif(pem_key_format == 2):
+ '''DER format'''
+ key_mode = 2
+ else:
+ '''String format'''
+ key_mode = 0
+
+ #ecdsa = cryptoSB.ECDSA()
+ #signature = ecdsa.sign(privk, pubk, boothash, sbc_auth_alg)
+ ''' 20180616 fix the sb_sign msg error : not boothash -> blh is right'''
+ if(ck_en == 0):
+ print("original format: no change key:")
+ signature = cryptoSB.sb_sign(privk, pubk, blh, sbc_auth_alg, sbc_auth_alg_hash, rsa_parse, sbc_rsa_pad_sel, key_mode)
+ else:
+ signature = cryptoSB.sb_sign(signckprivk, pubk, blh, sbc_auth_alg, sbc_auth_alg_hash, ck_rsa_parse, sbc_rsa_pad_sel, key_mode)
+
+ #print("signature size = %d" %len(signature))
+ signature_append = my_pad_to_align(signature, g_signature_size)
+ #cryptoSB.dump(signature_append)
+ signaturelist.append(signature_append)
+
+ #check verify
+ #ret = ecdsa.verify(pubk, boothash, signature, sbc_auth_alg)
+ #print("ecdsa verify: %s" %ret)
+
+
+ #dump("".join(signaturelist))
+ # append signature
+ pack += signaturelist
+
+ # for easy view, please remove it while release final
+ '''align for (bl + imgl + sbc + auth + ck)'''
+ if(__Align_16_en == 1):
+ padnum = pad_to_align(16, len(''.join(pack)))
+ pack.append(padnum)
+
+ # append ck field
+ ''' Skipped: no use on 2735
+ pack += ck_region
+
+ ck_field = ''.join(ck_region)
+ cryptoSB.dump(ck_field)
+ ckf = copy.copy(ck_field)
+
+ ck_signature = cryptoSB.sb_sign(privk, pubk, ckf, sbc_auth_alg, sbc_auth_alg_hash, rsa_parse, sbc_rsa_pad_sel, key_mode)
+ #print("ck_signature size = %d" %len(ck_signature))
+ ck_signature_append = my_pad_to_align(ck_signature, g_signature_size)
+ #cryptoSB.dump(ck_signature_append)
+ cksignaturelist.append(ck_signature_append)
+
+ pack += cksignaturelist
+ '''
+ # end append ck field
+
+ # append image binary
+ for i in range(img_num):
+ offset = int(img_offset_table[i])
+ pad_num = offset - len(''.join(pack))
+ #print("offset = %d" %offset)
+ #print("pad_num = %d" %pad_num)
+
+ padbytes = '\0' * pad_num
+ pack.append(padbytes)
+ pack += imagetmp[i]
+
+ #print(len(''.join(pack)))
+
+ # clear list
+ while len(signaturelist) > 0:
+ signaturelist.pop()
+
+
+ return ''.join(pack)
+
+'''support to_bytes to python 2.7'''
+def my_to_bytes(n, length, endianess='big'):
+ h = '%x' % n
+ s = ('0'*(len(h) % 2) + h).zfill(length*2).decode('hex')
+ return s if endianess == 'big' else s[::-1]
+
+'''long to byte string'''
+def my_binify(x):
+ h = hex(x)[2:].rstrip('L')
+ return binascii.unhexlify(h)
+
+def my_binify2(x):
+ if(hex(x)[0:2] == '0x'):
+ h = hex(x)[2:].rstrip('L')
+ else:
+ h = hex(x).rstrip('L')
+
+ return binascii.unhexlify(h)
+
+def my_pad_to_align(x, align):
+ if(align == 0):
+ return x
+ else:
+ size = len(x)
+ #print("size 0x%x" %size)
+ pad_size = (align - size % align) % align
+ for i in range(0, pad_size, 1):
+ x += b'\x00'
+
+ #cryptoSB.dump(x)
+ return x
+
+
+def img_enc(mi_desc, key, align=None):
+
+ images = mi_desc['images']
+ img_num = len(images)
+
+ img = images[0]
+ #load_addr = img['load_addr']
+ #entrypoint = img['entrypoint']
+ img_file = img['img_file']
+ img_enc_alg = img['img_enc_alg']
+ #print(img_enc_alg)
+ img_enc_inf = img['img_enc_inf']
+ #print(img_enc_inf)
+ iv = img['img_iv']
+ iv = my_binify(iv)
+ #print type(iv)
+ #print("img_enc dump:")
+ #cryptoSB.dump(iv)
+
+ bin = open(img_file, 'rb').read()
+ #cryptoSB.dump(bin)
+
+ #align
+ bin = my_pad_to_align(bin, 64)
+
+ aes = cryptoSB.AESCipher(key, 16)
+ encmsg = aes.aes_encrypt(bin)
+ #print("result image enc:")
+ #cryptoSB.dump(encmsg)
+
+ return encmsg
+
+
+
+
+if __name__ == '__main__':
+ import os, sys, getopt
+
+
+ def print_usage():
+ print ('usage:', os.path.basename(sys.argv[0]), "[options] <image config>.json\n", \
+ 'options:\n', \
+ '\t[-o | --output out.img]\n', \
+ '\t[-h | --help]\n', \
+ '\t[-i | --input]\n', \
+ '\t[-k | --prikey hexkey e.g. 0x0102..]\n', \
+ '\t[-s | --enckey hexkey e.g. 0x0102..]\n', \
+ '\t[-p | --pemdir <pem path>\n', \
+ '\t[-d | --imgdir <image path>\n')
+
+
+ def main():
+ opts, args = getopt.getopt(sys.argv[1:],
+ 'ho:a:i:k:s:p:d:',
+ ['help', 'output=', 'align=', 'input=',
+ 'prikey=', 'enckey=', 'pemdir=', 'imgdir=']
+ )
+
+ out_name = None
+ align = 0
+ infile_name = None
+ aeskey = None
+ pubkey = None
+ privk = None
+ pem_dir = "binfile"
+ img_dir = ''
+
+ for o, a in opts:
+ if o in ('-h', '--help'):
+ print_usage()
+ sys.exit()
+ elif o in ('-o', '--output'):
+ out_name = a
+ elif o in ('-a', '--align'):
+ align = int(a)
+ elif o in ('-i', '--input'):
+ ## doesn't need currently
+ infile_name = a
+ elif o in ('-k', '--prikey'):
+ privkey = a
+ elif o in ('-s', '--enckey'):
+ aeskey = a
+ elif o in ('-p', '--pemdir'):
+ pem_dir = a
+ elif o in ('-d', '--imgdir'):
+ img_dir = a
+ else:
+ print_usage()
+ sys.exit(1)
+
+ if len(args) >= 1:
+ mi_desc_fn = args[0]
+ else:
+ print_usage()
+ sys.exit(1)
+
+ if not out_name:
+ fn, ext = os.path.splitext(mi_desc_fn)
+ out_name = fn + '.img'
+
+ """ read json script """
+ mi_desc = read_desc(mi_desc_fn)
+
+ #mipack = pack_images(mi_desc, align)
+
+ #print 'output: %s (%d bytes)' % (out_name, len(mipack))
+ #open(out_name, 'wb').write(mipack)
+
+ cmd_line_key = mi_desc['cmd_line_key']
+ sign_priv_key = mi_desc['sign_priv_key']
+ aes_enc_sym_key = mi_desc['aes_enc_sym_key']
+
+ """ Where is the key input from """
+
+ pem_key_format = mi_desc['pem_key_format']
+ if(pem_key_format == 1):
+ sbc_auth_alg = mi_desc['sbc_auth_alg']
+ if(sbc_auth_alg == 0):
+ key_path = pem_dir + "/ecdsa_p256_private.pem"
+ #print(key_path)
+ privk = open(key_path,"rb").read()
+ #privk = open("binfile/ecdsa_p256_private.pem","rb").read()
+ #pubk_pem = open("binfile/ecdsa_p256_public.pem","rb").read()
+ elif(sbc_auth_alg == 1):
+ privk = open("binfile/ecdsa_p384_private.pem","rb").read()
+
+ key = cryptoSB.strip_key(aes_enc_sym_key)
+
+ else:
+ if(cmd_line_key == 1):
+ key = cryptoSB.strip_key(aeskey)
+ privk = cryptoSB.strip_key(privkey)
+ #print("dump privkey:")
+ #cryptoSB.dump(privk)
+ elif(cmd_line_key == 0):
+ key = cryptoSB.strip_key(aes_enc_sym_key)
+ privk = cryptoSB.strip_key(sign_priv_key)
+ #print("dump privkey:")
+ #cryptoSB.dump(privk)
+ else:
+ prnit("ERROR: please check cmd_line_key json")
+
+
+
+ #run hash
+ #hash = cryptoSB.HASH()
+ #imghash = hash.hash_sha256(enc_data)
+ #cryptoSB.dump(imghash)
+
+ mipack = my_pack_images(mi_desc, privk, key, align, img_dir)
+ if mipack == None:
+ print("my_pack_images fail")
+ return
+
+ #out_name = 'my_' + fn + '.img'
+ #out_name = fn + '.img'
+ print('output: %s (%d bytes)' % (out_name, len(mipack)))
+ open(out_name, 'wb').write(mipack)
+
+ main()
+
diff --git a/src/devtools/packer/mt2735/test_pkcs1_15_mytest.py b/src/devtools/packer/mt2735/test_pkcs1_15_mytest.py
new file mode 100644
index 0000000..d15b1e0
--- /dev/null
+++ b/src/devtools/packer/mt2735/test_pkcs1_15_mytest.py
@@ -0,0 +1,620 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Signature/test_pkcs1_15.py: Self-test for PKCS#1 v1.5 signatures
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+__revision__ = "$Id$"
+
+import unittest
+
+from Crypto.PublicKey import RSA
+from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
+from Crypto.Hash import *
+from Crypto import Random
+from Crypto.Signature import PKCS1_v1_5 as PKCS
+from Crypto.Util.py3compat import *
+
+def isStr(s):
+ t = ''
+ try:
+ t += s
+ except TypeError:
+ return 0
+ return 1
+
+def rws(t):
+ """Remove white spaces, tabs, and new lines from a string"""
+ for c in ['\n', '\t', ' ']:
+ t = t.replace(c,'')
+ return t
+
+def t2b(t):
+ """Convert a text string with bytes in hex form to a byte string"""
+ clean = b(rws(t))
+ if len(clean)%2 == 1:
+ raise ValueError("Even number of characters expected")
+ return a2b_hex(clean)
+
+# dump str to bytes
+def rsa_dump(data):
+ print("-----------pkcs1v15_mytest dump:----------")
+ for i in range(0, len(data)):
+ print ("0x%02x,"%ord(data[i])),
+ if(((i+1)%16) == 0):
+ print("")
+ print("-----------pkcs1v15_mytest dump end----------")
+
+
+class PKCS1_15_Tests(unittest.TestCase):
+
+ # List of tuples with test data for PKCS#1 v1.5.
+ # Each tuple is made up by:
+ # Item #0: dictionary with RSA key component, or key to import
+ # Item #1: data to hash and sign
+ # Item #2: signature of the data #1, done with the key #0, after
+ # hashing it with #3
+ # Item #3: hash object generator
+
+ _testData = (
+
+ #
+ # Taken from ftp://ftp.rsa.com/pub/pkcs/ascii/examples.asc
+ # "Some Examples of the PKCS Standards", 1999
+ #
+ (
+
+ # Private key, from 2.1
+ {
+ 'n':'''0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0 c0 01 c6
+ 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51 d0 53 b3 e3 78 2a 1d
+ e5 dc 5a f4 eb e9 94 68 17 01 14 a1 df e6 7c dc 9a 9a f5 5d
+ 65 56 20 bb ab''',
+ 'e':'''01 00
+ 01''',
+ 'd':'''01 23 c5 b6 1b a3 6e db 1d 36 79 90 41 99 a8 9e a8 0c 09
+ b9 12 2e 14 00 c0 9a dc f7 78 46 76 d0 1d 23 35 6a 7d 44 d6
+ bd 8b d5 0e 94 bf c7 23 fa 87 d8 86 2b 75 17 76 91 c1 1d 75
+ 76 92 df 88 81'''
+ },
+ # Data to sign, from 3.1
+ '''30 81 a4 02 01 00 30 42 31 0b 30 09 06
+ 03 55 04 06 13 02 55 53 31 1d 30 1b 06 03 55 04 0a 13 14
+ 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 74 69 6f
+ 6e 31 14 30 12 06 03 55 04 03 13 0b 54 65 73 74 20 55 73
+ 65 72 20 31 30 5b 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01
+ 05 00 03 4a 00 30 47 02 40
+ 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0
+ c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51
+ d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17
+ 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab
+ 02 03 01 00 01''',
+ # Signature, from 3.2 (at the very end)
+ '''06 db 36 cb 18 d3 47 5b 9c 01 db 3c 78 95 28 08
+ 02 79 bb ae ff 2b 7d 55 8e d6 61 59 87 c8 51 86
+ 3f 8a 6c 2c ff bc 89 c3 f7 5a 18 d9 6b 12 7c 71
+ 7d 54 d0 d8 04 8d a8 a0 54 46 26 d1 7a 2a 8f be''',
+ MD2
+ ),
+
+ #
+ # RSA keypair generated with openssl
+ #
+ (
+ """-----BEGIN RSA PRIVATE KEY-----
+ MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII
+ q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8
+ Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI
+ OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr
+ +rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK
+ JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9
+ n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ==
+ -----END RSA PRIVATE KEY-----""",
+ "This is a test\x0a",
+ #
+ # PKCS#1 signature computed with openssl
+ #
+ '''4a700a16432a291a3194646952687d5316458b8b86fb0a25aa30e0dcecdb
+ 442676759ac63d56ec1499c3ae4c0013c2053cabd5b5804848994541ac16
+ fa243a4d''',
+ SHA
+ ),
+
+ #
+ # Test vector from http://www.di-mgt.com.au/rsa_alg.html#signpkcs1
+ #
+ (
+ {
+ 'n':'''E08973398DD8F5F5E88776397F4EB005BB5383DE0FB7ABDC7DC775290D052E6D
+ 12DFA68626D4D26FAA5829FC97ECFA82510F3080BEB1509E4644F12CBBD832CF
+ C6686F07D9B060ACBEEE34096A13F5F7050593DF5EBA3556D961FF197FC981E6
+ F86CEA874070EFAC6D2C749F2DFA553AB9997702A648528C4EF357385774575F''',
+ 'e':'''010001''',
+ 'd':'''00A403C327477634346CA686B57949014B2E8AD2C862B2C7D748096A8B91F736
+ F275D6E8CD15906027314735644D95CD6763CEB49F56AC2F376E1CEE0EBF282D
+ F439906F34D86E085BD5656AD841F313D72D395EFE33CBFF29E4030B3D05A28F
+ B7F18EA27637B07957D32F2BDE8706227D04665EC91BAF8B1AC3EC9144AB7F21'''
+ },
+ "abc",
+ '''60AD5A78FB4A4030EC542C8974CD15F55384E836554CEDD9A322D5F4135C6267
+ A9D20970C54E6651070B0144D43844C899320DD8FA7819F7EBC6A7715287332E
+ C8675C136183B3F8A1F81EF969418267130A756FDBB2C71D9A667446E34E0EAD
+ 9CF31BFB66F816F319D0B7E430A5F2891553986E003720261C7E9022C0D9F11F''',
+ SHA
+ )
+
+ )
+
+ def testSign1(self):
+ print("ttest")
+ for i in range(len(self._testData)):
+ row = self._testData[i]
+ # Build the key
+ if isStr(row[0]):
+ key = RSA.importKey(row[0])
+ else:
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e','d') ]
+ key = RSA.construct(comps)
+ h = row[3].new()
+ # Data to sign can either be in hex form or not
+ try:
+ h.update(t2b(row[1]))
+ except:
+ h.update(b(row[1]))
+ # The real test
+ signer = PKCS.new(key)
+ self.failUnless(signer.can_sign())
+ s = signer.sign(h)
+ self.assertEqual(s, t2b(row[2]))
+
+ def testVerify1(self):
+ for i in range(len(self._testData)):
+ row = self._testData[i]
+ # Build the key
+ if isStr(row[0]):
+ key = RSA.importKey(row[0]).publickey()
+ else:
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e') ]
+ key = RSA.construct(comps)
+ h = row[3].new()
+ # Data to sign can either be in hex form or not
+ try:
+ h.update(t2b(row[1]))
+ except:
+ h.update(b(row[1]))
+ # The real test
+ verifier = PKCS.new(key)
+ self.failIf(verifier.can_sign())
+ result = verifier.verify(h, t2b(row[2]))
+ self.failUnless(result)
+
+ def testSignVerify(self):
+ rng = Random.new().read
+ key = RSA.generate(1024, rng)
+
+ for hashmod in (MD2,MD5,SHA,SHA224,SHA256,SHA384,SHA512,RIPEMD):
+ h = hashmod.new()
+ h.update(b('blah blah blah'))
+
+ signer = PKCS.new(key)
+ s = signer.sign(h)
+ result = signer.verify(h, s)
+ self.failUnless(result)
+
+
+
+class testSign1_mytest():
+ # List of tuples with test data for PKCS#1 v1.5.
+ # Each tuple is made up by:
+ # Item #0: dictionary with RSA key component, or key to import
+ # Item #1: data to hash and sign
+ # Item #2: signature of the data #1, done with the key #0, after
+ # hashing it with #3
+ # Item #3: hash object generator
+
+ def __init__(self):
+ _testData = (
+
+ #
+ # Taken from ftp://ftp.rsa.com/pub/pkcs/ascii/examples.asc
+ # "Some Examples of the PKCS Standards", 1999
+ #
+ (
+
+ # Private key, from 2.1
+ {
+ 'n':'''0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0 c0 01 c6
+ 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51 d0 53 b3 e3 78 2a 1d
+ e5 dc 5a f4 eb e9 94 68 17 01 14 a1 df e6 7c dc 9a 9a f5 5d
+ 65 56 20 bb ab''',
+ 'e':'''01 00
+ 01''',
+ 'd':'''01 23 c5 b6 1b a3 6e db 1d 36 79 90 41 99 a8 9e a8 0c 09
+ b9 12 2e 14 00 c0 9a dc f7 78 46 76 d0 1d 23 35 6a 7d 44 d6
+ bd 8b d5 0e 94 bf c7 23 fa 87 d8 86 2b 75 17 76 91 c1 1d 75
+ 76 92 df 88 81'''
+ },
+ # Data to sign, from 3.1
+ '''30 81 a4 02 01 00 30 42 31 0b 30 09 06
+ 03 55 04 06 13 02 55 53 31 1d 30 1b 06 03 55 04 0a 13 14
+ 45 78 61 6d 70 6c 65 20 4f 72 67 61 6e 69 7a 61 74 69 6f
+ 6e 31 14 30 12 06 03 55 04 03 13 0b 54 65 73 74 20 55 73
+ 65 72 20 31 30 5b 30 0d 06 09 2a 86 48 86 f7 0d 01 01 01
+ 05 00 03 4a 00 30 47 02 40
+ 0a 66 79 1d c6 98 81 68 de 7a b7 74 19 bb 7f b0
+ c0 01 c6 27 10 27 00 75 14 29 42 e1 9a 8d 8c 51
+ d0 53 b3 e3 78 2a 1d e5 dc 5a f4 eb e9 94 68 17
+ 01 14 a1 df e6 7c dc 9a 9a f5 5d 65 56 20 bb ab
+ 02 03 01 00 01''',
+ # Signature, from 3.2 (at the very end)
+ '''06 db 36 cb 18 d3 47 5b 9c 01 db 3c 78 95 28 08
+ 02 79 bb ae ff 2b 7d 55 8e d6 61 59 87 c8 51 86
+ 3f 8a 6c 2c ff bc 89 c3 f7 5a 18 d9 6b 12 7c 71
+ 7d 54 d0 d8 04 8d a8 a0 54 46 26 d1 7a 2a 8f be''',
+ MD2
+ ),
+
+ #
+ # RSA keypair generated with openssl
+ #
+ (
+ """-----BEGIN RSA PRIVATE KEY-----
+ MIIBOwIBAAJBAL8eJ5AKoIsjURpcEoGubZMxLD7+kT+TLr7UkvEtFrRhDDKMtuII
+ q19FrL4pUIMymPMSLBn3hJLe30Dw48GQM4UCAwEAAQJACUSDEp8RTe32ftq8IwG8
+ Wojl5mAd1wFiIOrZ/Uv8b963WJOJiuQcVN29vxU5+My9GPZ7RA3hrDBEAoHUDPrI
+ OQIhAPIPLz4dphiD9imAkivY31Rc5AfHJiQRA7XixTcjEkojAiEAyh/pJHks/Mlr
+ +rdPNEpotBjfV4M4BkgGAA/ipcmaAjcCIQCHvhwwKVBLzzTscT2HeUdEeBMoiXXK
+ JACAr3sJQJGxIQIgarRp+m1WSKV1MciwMaTOnbU7wxFs9DP1pva76lYBzgUCIQC9
+ n0CnZCJ6IZYqSt0H5N7+Q+2Ro64nuwV/OSQfM6sBwQ==
+ -----END RSA PRIVATE KEY-----""",
+ "This is a test\x0a",
+ #
+ # PKCS#1 signature computed with openssl
+ #
+ '''4a700a16432a291a3194646952687d5316458b8b86fb0a25aa30e0dcecdb
+ 442676759ac63d56ec1499c3ae4c0013c2053cabd5b5804848994541ac16
+ fa243a4d''',
+ SHA
+ ),
+
+ #
+ # Test vector from http://www.di-mgt.com.au/rsa_alg.html#signpkcs1
+ #
+ (
+ {
+ 'n':'''E08973398DD8F5F5E88776397F4EB005BB5383DE0FB7ABDC7DC775290D052E6D
+ 12DFA68626D4D26FAA5829FC97ECFA82510F3080BEB1509E4644F12CBBD832CF
+ C6686F07D9B060ACBEEE34096A13F5F7050593DF5EBA3556D961FF197FC981E6
+ F86CEA874070EFAC6D2C749F2DFA553AB9997702A648528C4EF357385774575F''',
+ 'e':'''010001''',
+ 'd':'''00A403C327477634346CA686B57949014B2E8AD2C862B2C7D748096A8B91F736
+ F275D6E8CD15906027314735644D95CD6763CEB49F56AC2F376E1CEE0EBF282D
+ F439906F34D86E085BD5656AD841F313D72D395EFE33CBFF29E4030B3D05A28F
+ B7F18EA27637B07957D32F2BDE8706227D04665EC91BAF8B1AC3EC9144AB7F21'''
+ },
+ "abc",
+ '''60AD5A78FB4A4030EC542C8974CD15F55384E836554CEDD9A322D5F4135C6267
+ A9D20970C54E6651070B0144D43844C899320DD8FA7819F7EBC6A7715287332E
+ C8675C136183B3F8A1F81EF969418267130A756FDBB2C71D9A667446E34E0EAD
+ 9CF31BFB66F816F319D0B7E430A5F2891553986E003720261C7E9022C0D9F11F''',
+ SHA
+ ),
+
+ #RSA 2048 + SHA1 + py_rsakey_golden1.pem (generate by pycrypto_rsa_sign_pkca1v15_sha1)
+ (
+ {
+ 'n':'''b9bd2e2ed0f531dc00a0f44bf36caa1c2358d3c48645cb51bec95a3a38fb7f99
+ fc646814da5f6b410ea9897fa0d8bfa8a1bd21065a66e105918175248a6b089c
+ 39dc9805f03ab4f9a3f43684c8f9b8cd7fbe2ab120eeda08200c370cb51fe725
+ 8f72130a962e551581157aec40bc99435d4cc50e74a878a428b0dc739cd518b9
+ 8089b162ca609ce84bce7cf303a0174d1520505775e57f685b63b8e16646486d
+ 131582b08be3b7b379a7e076791fe32537bc464e847dcb4aed95286a3b70af32
+ 0f30e9ac44c26ce8cf093e3f851a9d96ebd6876f93f330df94c4cf07b1dddab1
+ 60d287aebe0fa4cf050fe9fb5cb04f8f85c5d3454ef6bc17581a41793359c61b''',
+ 'e':'''010001''',
+ 'd':'''3a44ef4820a5cb8e8963f5401e8de8900b46c2a8d4b6f0a224886695fd6a690d
+ 95f0a9f660cbae8a2a5f659374928b0e0c2f993cb4ffb1785dbd8f52775a3cc9
+ 461dbe539e99cc4cc4f2c867bfe517e4e03e7886391eb5a7f6e5de1f4e7343c0
+ b4cfc4c97d73eb9d6371a9ae946096745bc0c9d14f27cb3134d2c7563dcd5c83
+ cc2c817446175812cb4040275e6b4c91d3bad61de64a3cc14973e11108170f18
+ 6ce1b124457e7bcc28768d69ae60bd4e2e275d72b6eedb157cdc1bbd2e802c86
+ b478c0c76cd2fa2e4ed54f274a84f57a50716c0ff8df37a2ad409b1a3335332c
+ d4225868dd4cfd4304b3eb4884630e1977fad20c7ce9ed9467632658296a0601'''
+ },
+ "abc",
+ '''7b80ab542c939b7f8b042b2ac653f2792d139caf83bd612a8a29685ac52fd8ff
+ faa2ddb09547f4719ec60c8f9942c3356d36d087d869ffa84384246076017dcc
+ abe38d4cf6f00155216a29aad02673f61dfbac98869be64e40ffd888975e6203
+ ef5dca5f82f28deb02ff1406cc079173309becb97b00c867007aaf2be0e9d355
+ 64c03df71c50ec5132ac61ceade753c9ecce164ae0d4315f0fa308fbe900e75d
+ 51130992df550f7732fbc4c849e1f3c1a13927fe2c73f450cb33496ef1213567
+ 6cbfa1d0c39dd9137582807aae36c88e556a6255b7499f22bf4ef03371514ca6
+ 23d2ccf1d6b0896ac0572d175e92c9e47699f0962ef2c4a924a7f300aff847ac''',
+ SHA
+ )
+ )
+
+ self._testData = _testData
+
+ def testsign1_mytest(self):
+ print("mytest rsa sign")
+ for i in range(len(self._testData)):
+ row = self._testData[i]
+ # Build the key
+ if isStr(row[0]):
+ print("testData[%d]" %i)
+ key = RSA.importKey(row[0])
+ else:
+ print("e testData[%d]" %i)
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e','d') ]
+ key = RSA.construct(comps)
+ h = row[3].new()
+ # Data to sign can either be in hex form or not
+ try:
+ print("try")
+ h.update(t2b(row[1]))
+ except:
+ print("except")
+ h.update(b(row[1]))
+ # The real test
+ signer = PKCS.new(key)
+ t_flag = signer.can_sign()
+ if t_flag:
+ print("mytest: can sign")
+ else:
+ print("mytest: can't sign")
+ s = signer.sign(h)
+ rsa_dump(s)
+ if s == t2b(row[2]):
+ print("signature compare pass")
+ else:
+ print("signature compare fail")
+
+ def testverify1_mytest(self):
+ print("mytest rsa verify")
+ for i in range(len(self._testData)):
+ row = self._testData[i]
+ # Build the key
+ if isStr(row[0]):
+ key = RSA.importKey(row[0]).publickey()
+ else:
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e') ]
+ key = RSA.construct(comps)
+ h = row[3].new()
+ # Data to sign can either be in hex form or not
+ try:
+ h.update(t2b(row[1]))
+ except:
+ h.update(b(row[1]))
+ # The real test
+ verifier = PKCS.new(key)
+ t_flag = verifier.can_sign()
+ if t_flag:
+ print("mytest: can't verify")
+ else:
+ print("mytest: can verify")
+ result = verifier.verify(h, t2b(row[2]))
+ if result:
+ print("verify pass")
+ else:
+ print("verify fail")
+
+
+class sbc_rsa_sign1_mytest():
+ # List of tuples with test data for PKCS#1 v1.5.
+ # Each tuple is made up by:
+ # Item #0: dictionary with RSA key component, or key to import
+ # Item #1: data to hash and sign
+ # Item #2: signature of the data #1, done with the key #0, after
+ # hashing it with #3
+ # Item #3: hash object generator
+
+ def __init__(self, rsa_parse, msg):
+ _testData = (
+
+ #
+ # RSA keypair generated with openssl
+ #
+
+
+ #
+ # Test vector from http://www.di-mgt.com.au/rsa_alg.html#signpkcs1
+ #
+ (
+ {
+ 'n':'''E08973398DD8F5F5E88776397F4EB005BB5383DE0FB7ABDC7DC775290D052E6D
+ 12DFA68626D4D26FAA5829FC97ECFA82510F3080BEB1509E4644F12CBBD832CF
+ C6686F07D9B060ACBEEE34096A13F5F7050593DF5EBA3556D961FF197FC981E6
+ F86CEA874070EFAC6D2C749F2DFA553AB9997702A648528C4EF357385774575F''',
+ 'e':'''010001''',
+ 'd':'''00A403C327477634346CA686B57949014B2E8AD2C862B2C7D748096A8B91F736
+ F275D6E8CD15906027314735644D95CD6763CEB49F56AC2F376E1CEE0EBF282D
+ F439906F34D86E085BD5656AD841F313D72D395EFE33CBFF29E4030B3D05A28F
+ B7F18EA27637B07957D32F2BDE8706227D04665EC91BAF8B1AC3EC9144AB7F21'''
+ },
+ "abc",
+ '''60AD5A78FB4A4030EC542C8974CD15F55384E836554CEDD9A322D5F4135C6267
+ A9D20970C54E6651070B0144D43844C899320DD8FA7819F7EBC6A7715287332E
+ C8675C136183B3F8A1F81EF969418267130A756FDBB2C71D9A667446E34E0EAD
+ 9CF31BFB66F816F319D0B7E430A5F2891553986E003720261C7E9022C0D9F11F''',
+ SHA
+ ),
+
+ #RSA 2048 + SHA1 + py_rsakey_golden1.pem (generate by pycrypto_rsa_sign_pkca1v15_sha1)
+ (
+ {
+ 'n':'''b9bd2e2ed0f531dc00a0f44bf36caa1c2358d3c48645cb51bec95a3a38fb7f99
+ fc646814da5f6b410ea9897fa0d8bfa8a1bd21065a66e105918175248a6b089c
+ 39dc9805f03ab4f9a3f43684c8f9b8cd7fbe2ab120eeda08200c370cb51fe725
+ 8f72130a962e551581157aec40bc99435d4cc50e74a878a428b0dc739cd518b9
+ 8089b162ca609ce84bce7cf303a0174d1520505775e57f685b63b8e16646486d
+ 131582b08be3b7b379a7e076791fe32537bc464e847dcb4aed95286a3b70af32
+ 0f30e9ac44c26ce8cf093e3f851a9d96ebd6876f93f330df94c4cf07b1dddab1
+ 60d287aebe0fa4cf050fe9fb5cb04f8f85c5d3454ef6bc17581a41793359c61b''',
+ 'e':'''010001''',
+ 'd':'''3a44ef4820a5cb8e8963f5401e8de8900b46c2a8d4b6f0a224886695fd6a690d
+ 95f0a9f660cbae8a2a5f659374928b0e0c2f993cb4ffb1785dbd8f52775a3cc9
+ 461dbe539e99cc4cc4f2c867bfe517e4e03e7886391eb5a7f6e5de1f4e7343c0
+ b4cfc4c97d73eb9d6371a9ae946096745bc0c9d14f27cb3134d2c7563dcd5c83
+ cc2c817446175812cb4040275e6b4c91d3bad61de64a3cc14973e11108170f18
+ 6ce1b124457e7bcc28768d69ae60bd4e2e275d72b6eedb157cdc1bbd2e802c86
+ b478c0c76cd2fa2e4ed54f274a84f57a50716c0ff8df37a2ad409b1a3335332c
+ d4225868dd4cfd4304b3eb4884630e1977fad20c7ce9ed9467632658296a0601'''
+ },
+ "abc",
+ '''7b80ab542c939b7f8b042b2ac653f2792d139caf83bd612a8a29685ac52fd8ff
+ faa2ddb09547f4719ec60c8f9942c3356d36d087d869ffa84384246076017dcc
+ abe38d4cf6f00155216a29aad02673f61dfbac98869be64e40ffd888975e6203
+ ef5dca5f82f28deb02ff1406cc079173309becb97b00c867007aaf2be0e9d355
+ 64c03df71c50ec5132ac61ceade753c9ecce164ae0d4315f0fa308fbe900e75d
+ 51130992df550f7732fbc4c849e1f3c1a13927fe2c73f450cb33496ef1213567
+ 6cbfa1d0c39dd9137582807aae36c88e556a6255b7499f22bf4ef03371514ca6
+ 23d2ccf1d6b0896ac0572d175e92c9e47699f0962ef2c4a924a7f300aff847ac''',
+ SHA
+ )
+ )
+
+ self._testData = _testData
+ self.rsa_parse = rsa_parse
+ self.msg = msg
+
+ def sbc_rsa_sign1(self):
+ print("mytest rsa sign")
+ for i in range(len(self._testData)):
+ row = self._testData[i]
+ # Build the key
+ if isStr(row[0]):
+ print("testData[%d]" %i)
+ key = RSA.importKey(row[0])
+ else:
+ print("e testData[%d]" %i)
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e','d') ]
+ key = RSA.construct(comps)
+ h = row[3].new()
+ # Data to sign can either be in hex form or not
+ try:
+ print("try")
+ h.update(t2b(row[1]))
+ except:
+ print("except")
+ h.update(b(row[1]))
+ # The real test
+ signer = PKCS.new(key)
+ t_flag = signer.can_sign()
+ if t_flag:
+ print("mytest: can sign")
+ else:
+ print("mytest: can't sign")
+ s = signer.sign(h)
+ rsa_dump(s)
+ if s == t2b(row[2]):
+ print("signature compare pass")
+ else:
+ print("signature compare fail")
+ return s
+
+ def sbc_rsa_sign1_json(self):
+ print("mytest rsa sign json")
+ row = self.rsa_parse
+ #print(self.rsa_parse)
+ # Build the key
+ if isStr(row[0]):
+ #print("testData[%d]" %i)
+ key = RSA.importKey(row[0])
+ else:
+ #print("e testData[%d]" %i)
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e','d') ]
+ key = RSA.construct(comps)
+
+ if(row[3] == "SHA"):
+ h = SHA.new()
+ elif(row[3] == "SHA256"):
+ h = SHA256.new()
+ elif(row[3] == "SHA384"):
+ h = SHA384.new()
+ elif(row[3] == "SHA512"):
+ h = SHA512.new()
+ else:
+ h = SHA256.new()
+ # Data to sign can either be in hex form or not
+ if(row[4] == 1):
+ try:
+ print("try")
+ h.update(t2b(row[1]))
+ except:
+ print("except")
+ h.update(b(row[1]))
+ else:
+ h.update(self.msg)
+ rsa_dump(h.digest())
+
+ # The real test
+ signer = PKCS.new(key)
+ t_flag = signer.can_sign()
+ if t_flag:
+ print("mytest: can sign")
+ else:
+ print("mytest: can't sign")
+ s = signer.sign(h)
+ rsa_dump(s)
+ if s == t2b(row[2]):
+ print("signature compare pass")
+ else:
+ print("signature compare fail")
+ return s
+
+ def sbc_rsa_verify1(self):
+ print("mytest rsa verify")
+ for i in range(len(self._testData)):
+ row = self._testData[i]
+ # Build the key
+ if isStr(row[0]):
+ key = RSA.importKey(row[0]).publickey()
+ else:
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e') ]
+ key = RSA.construct(comps)
+ h = row[3].new()
+ # Data to sign can either be in hex form or not
+ try:
+ h.update(t2b(row[1]))
+ except:
+ h.update(b(row[1]))
+ # The real test
+ verifier = PKCS.new(key)
+ t_flag = verifier.can_sign()
+ if t_flag:
+ print("mytest: can't verify")
+ else:
+ print("mytest: can verify")
+ result = verifier.verify(h, t2b(row[2]))
+ if result:
+ print("verify pass")
+ else:
+ print("verify fail")
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(PKCS1_15_Tests)
+ return tests
+
+if __name__ == '__main__':
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4 expandtab:
diff --git a/src/devtools/packer/mt2735/test_pkcs1_pss_mytest.py b/src/devtools/packer/mt2735/test_pkcs1_pss_mytest.py
new file mode 100644
index 0000000..555e1fb
--- /dev/null
+++ b/src/devtools/packer/mt2735/test_pkcs1_pss_mytest.py
@@ -0,0 +1,845 @@
+# -*- coding: utf-8 -*-
+#
+# SelfTest/Signature/test_pkcs1_pss.py: Self-test for PKCS#1 PSS signatures
+#
+# ===================================================================
+# The contents of this file are dedicated to the public domain. To
+# the extent that dedication to the public domain is not available,
+# everyone is granted a worldwide, perpetual, royalty-free,
+# non-exclusive license to exercise all rights associated with the
+# contents of this file for any purpose whatsoever.
+# No rights are reserved.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+# ===================================================================
+
+from __future__ import nested_scopes
+
+__revision__ = "$Id$"
+
+import unittest
+
+from Crypto.PublicKey import RSA
+from Crypto import Random
+from Crypto.SelfTest.st_common import list_test_cases, a2b_hex, b2a_hex
+from Crypto.Hash import *
+from Crypto.Signature import PKCS1_PSS as PKCS
+from Crypto.Util.py3compat import *
+
+def isStr(s):
+ t = ''
+ try:
+ t += s
+ except TypeError:
+ return 0
+ return 1
+
+def rws(t):
+ """Remove white spaces, tabs, and new lines from a string"""
+ for c in ['\t', '\n', ' ']:
+ t = t.replace(c,'')
+ return t
+
+def t2b(t):
+ """Convert a text string with bytes in hex form to a byte string"""
+ clean = b(rws(t))
+ if len(clean)%2 == 1:
+ raise ValueError("Even number of characters expected")
+ return a2b_hex(clean)
+
+# dump str to bytes
+def rsa_dump(data):
+ print("-----------pss_mytest dump:----------")
+ for i in range(0, len(data)):
+ print ("0x%02x,"%ord(data[i])),
+ if(((i+1)%16) == 0):
+ print("")
+ print("-----------pss_mytest dump end-----------")
+
+# Helper class to count how many bytes have been requested
+# from the key's private RNG, w/o counting those used for blinding
+class MyKey:
+ def __init__(self, key):
+ self._key = key
+ self.n = key.n
+ self.asked = 0
+ def _randfunc(self, N):
+ self.asked += N
+ return self._key._randfunc(N)
+ def sign(self, m):
+ return self._key.sign(m)
+ def has_private(self):
+ return self._key.has_private()
+ def decrypt(self, m):
+ return self._key.decrypt(m)
+ def verify(self, m, p):
+ return self._key.verify(m, p)
+ def encrypt(self, m, p):
+ return self._key.encrypt(m, p)
+
+class PKCS1_PSS_Tests(unittest.TestCase):
+
+ # List of tuples with test data for PKCS#1 PSS
+ # Each tuple is made up by:
+ # Item #0: dictionary with RSA key component, or key to import
+ # Item #1: data to hash and sign
+ # Item #2: signature of the data #1, done with the key #0,
+ # and salt #3 after hashing it with #4
+ # Item #3: salt
+ # Item #4: hash object generator
+
+ _testData = (
+
+ #
+ # From in pss-vect.txt to be found in
+ # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ #
+ (
+ # Private key
+ {
+ 'n':'''a2 ba 40 ee 07 e3 b2 bd 2f 02 ce 22 7f 36 a1 95
+ 02 44 86 e4 9c 19 cb 41 bb bd fb ba 98 b2 2b 0e
+ 57 7c 2e ea ff a2 0d 88 3a 76 e6 5e 39 4c 69 d4
+ b3 c0 5a 1e 8f ad da 27 ed b2 a4 2b c0 00 fe 88
+ 8b 9b 32 c2 2d 15 ad d0 cd 76 b3 e7 93 6e 19 95
+ 5b 22 0d d1 7d 4e a9 04 b1 ec 10 2b 2e 4d e7 75
+ 12 22 aa 99 15 10 24 c7 cb 41 cc 5e a2 1d 00 ee
+ b4 1f 7c 80 08 34 d2 c6 e0 6b ce 3b ce 7e a9 a5''',
+ 'e':'''01 00 01''',
+ # In the test vector, only p and q were given...
+ # d is computed offline as e^{-1} mod (p-1)(q-1)
+ 'd':'''50e2c3e38d886110288dfc68a9533e7e12e27d2aa56
+ d2cdb3fb6efa990bcff29e1d2987fb711962860e7391b1ce01
+ ebadb9e812d2fbdfaf25df4ae26110a6d7a26f0b810f54875e
+ 17dd5c9fb6d641761245b81e79f8c88f0e55a6dcd5f133abd3
+ 5f8f4ec80adf1bf86277a582894cb6ebcd2162f1c7534f1f49
+ 47b129151b71'''
+ },
+
+ # Data to sign
+ '''85 9e ef 2f d7 8a ca 00 30 8b dc 47 11 93 bf 55
+ bf 9d 78 db 8f 8a 67 2b 48 46 34 f3 c9 c2 6e 64
+ 78 ae 10 26 0f e0 dd 8c 08 2e 53 a5 29 3a f2 17
+ 3c d5 0c 6d 5d 35 4f eb f7 8b 26 02 1c 25 c0 27
+ 12 e7 8c d4 69 4c 9f 46 97 77 e4 51 e7 f8 e9 e0
+ 4c d3 73 9c 6b bf ed ae 48 7f b5 56 44 e9 ca 74
+ ff 77 a5 3c b7 29 80 2f 6e d4 a5 ff a8 ba 15 98
+ 90 fc''',
+ # Signature
+ '''8d aa 62 7d 3d e7 59 5d 63 05 6c 7e c6 59 e5 44
+ 06 f1 06 10 12 8b aa e8 21 c8 b2 a0 f3 93 6d 54
+ dc 3b dc e4 66 89 f6 b7 95 1b b1 8e 84 05 42 76
+ 97 18 d5 71 5d 21 0d 85 ef bb 59 61 92 03 2c 42
+ be 4c 29 97 2c 85 62 75 eb 6d 5a 45 f0 5f 51 87
+ 6f c6 74 3d ed dd 28 ca ec 9b b3 0e a9 9e 02 c3
+ 48 82 69 60 4f e4 97 f7 4c cd 7c 7f ca 16 71 89
+ 71 23 cb d3 0d ef 5d 54 a2 b5 53 6a d9 0a 74 7e''',
+ # Salt
+ '''e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8
+ 3b ce 7e 61''',
+ # Hash algorithm
+ SHA
+ ),
+
+ #
+ # Example 1.1 to be found in
+ # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ #
+ (
+ # Private key
+ {
+ 'n':'''a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1
+ 56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91
+ d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3
+ 94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df
+ d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77
+ c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1
+ 05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4
+ ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37''',
+ 'e':'''01 00 01''',
+ 'd':'''33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47
+ 71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8
+ 94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8
+ c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a
+ e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27
+ a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c
+ 31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b
+ d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25'''
+ },
+ # Message
+ '''cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26
+ d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6
+ 23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15
+ 6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76
+ 97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3
+ d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0
+ 61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29
+ cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61
+ 93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08
+ a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c
+ 29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca
+ b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16
+ be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed
+ 1b 73 31 8b 75 0a 01 67 d0''',
+ # Signature
+ '''90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71
+ fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87
+ e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2
+ 26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15
+ df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9
+ c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65
+ 98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4
+ c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c''',
+ # Salt
+ '''de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f
+ 3e 67 76 af''',
+ # Hash
+ SHA
+ ),
+
+ #
+ # Example 1.2 to be found in
+ # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ #
+ (
+ # Private key
+ {
+ 'n':'''a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1
+ 56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91
+ d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3
+ 94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df
+ d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77
+ c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1
+ 05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4
+ ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37''',
+ 'e':'''01 00 01''',
+ 'd':'''33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47
+ 71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8
+ 94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8
+ c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a
+ e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27
+ a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c
+ 31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b
+ d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25'''
+ },
+ # Message
+ '''85 13 84 cd fe 81 9c 22 ed 6c 4c cb 30 da eb 5c
+ f0 59 bc 8e 11 66 b7 e3 53 0c 4c 23 3e 2b 5f 8f
+ 71 a1 cc a5 82 d4 3e cc 72 b1 bc a1 6d fc 70 13
+ 22 6b 9e''',
+ # Signature
+ '''3e f7 f4 6e 83 1b f9 2b 32 27 41 42 a5 85 ff ce
+ fb dc a7 b3 2a e9 0d 10 fb 0f 0c 72 99 84 f0 4e
+ f2 9a 9d f0 78 07 75 ce 43 73 9b 97 83 83 90 db
+ 0a 55 05 e6 3d e9 27 02 8d 9d 29 b2 19 ca 2c 45
+ 17 83 25 58 a5 5d 69 4a 6d 25 b9 da b6 60 03 c4
+ cc cd 90 78 02 19 3b e5 17 0d 26 14 7d 37 b9 35
+ 90 24 1b e5 1c 25 05 5f 47 ef 62 75 2c fb e2 14
+ 18 fa fe 98 c2 2c 4d 4d 47 72 4f db 56 69 e8 43''',
+ # Salt
+ '''ef 28 69 fa 40 c3 46 cb 18 3d ab 3d 7b ff c9 8f
+ d5 6d f4 2d''',
+ # Hash
+ SHA
+ ),
+
+ #
+ # Example 2.1 to be found in
+ # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ #
+ (
+ # Private key
+ {
+ 'n':'''01 d4 0c 1b cf 97 a6 8a e7 cd bd 8a 7b f3 e3 4f
+ a1 9d cc a4 ef 75 a4 74 54 37 5f 94 51 4d 88 fe
+ d0 06 fb 82 9f 84 19 ff 87 d6 31 5d a6 8a 1f f3
+ a0 93 8e 9a bb 34 64 01 1c 30 3a d9 91 99 cf 0c
+ 7c 7a 8b 47 7d ce 82 9e 88 44 f6 25 b1 15 e5 e9
+ c4 a5 9c f8 f8 11 3b 68 34 33 6a 2f d2 68 9b 47
+ 2c bb 5e 5c ab e6 74 35 0c 59 b6 c1 7e 17 68 74
+ fb 42 f8 fc 3d 17 6a 01 7e dc 61 fd 32 6c 4b 33
+ c9''',
+ 'e':'''01 00 01''',
+ 'd':'''02 7d 14 7e 46 73 05 73 77 fd 1e a2 01 56 57 72
+ 17 6a 7d c3 83 58 d3 76 04 56 85 a2 e7 87 c2 3c
+ 15 57 6b c1 6b 9f 44 44 02 d6 bf c5 d9 8a 3e 88
+ ea 13 ef 67 c3 53 ec a0 c0 dd ba 92 55 bd 7b 8b
+ b5 0a 64 4a fd fd 1d d5 16 95 b2 52 d2 2e 73 18
+ d1 b6 68 7a 1c 10 ff 75 54 5f 3d b0 fe 60 2d 5f
+ 2b 7f 29 4e 36 01 ea b7 b9 d1 ce cd 76 7f 64 69
+ 2e 3e 53 6c a2 84 6c b0 c2 dd 48 6a 39 fa 75 b1'''
+ },
+ # Message
+ '''da ba 03 20 66 26 3f ae db 65 98 48 11 52 78 a5
+ 2c 44 fa a3 a7 6f 37 51 5e d3 36 32 10 72 c4 0a
+ 9d 9b 53 bc 05 01 40 78 ad f5 20 87 51 46 aa e7
+ 0f f0 60 22 6d cb 7b 1f 1f c2 7e 93 60''',
+ # Signature
+ '''01 4c 5b a5 33 83 28 cc c6 e7 a9 0b f1 c0 ab 3f
+ d6 06 ff 47 96 d3 c1 2e 4b 63 9e d9 13 6a 5f ec
+ 6c 16 d8 88 4b dd 99 cf dc 52 14 56 b0 74 2b 73
+ 68 68 cf 90 de 09 9a db 8d 5f fd 1d ef f3 9b a4
+ 00 7a b7 46 ce fd b2 2d 7d f0 e2 25 f5 46 27 dc
+ 65 46 61 31 72 1b 90 af 44 53 63 a8 35 8b 9f 60
+ 76 42 f7 8f ab 0a b0 f4 3b 71 68 d6 4b ae 70 d8
+ 82 78 48 d8 ef 1e 42 1c 57 54 dd f4 2c 25 89 b5
+ b3''',
+ # Salt
+ '''57 bf 16 0b cb 02 bb 1d c7 28 0c f0 45 85 30 b7
+ d2 83 2f f7''',
+ SHA
+ ),
+
+ #
+ # Example 8.1 to be found in
+ # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ #
+ (
+ # Private key
+ {
+ 'n':'''49 53 70 a1 fb 18 54 3c 16 d3 63 1e 31 63 25 5d
+ f6 2b e6 ee e8 90 d5 f2 55 09 e4 f7 78 a8 ea 6f
+ bb bc df 85 df f6 4e 0d 97 20 03 ab 36 81 fb ba
+ 6d d4 1f d5 41 82 9b 2e 58 2d e9 f2 a4 a4 e0 a2
+ d0 90 0b ef 47 53 db 3c ee 0e e0 6c 7d fa e8 b1
+ d5 3b 59 53 21 8f 9c ce ea 69 5b 08 66 8e de aa
+ dc ed 94 63 b1 d7 90 d5 eb f2 7e 91 15 b4 6c ad
+ 4d 9a 2b 8e fa b0 56 1b 08 10 34 47 39 ad a0 73
+ 3f''',
+ 'e':'''01 00 01''',
+ 'd':'''6c 66 ff e9 89 80 c3 8f cd ea b5 15 98 98 83 61
+ 65 f4 b4 b8 17 c4 f6 a8 d4 86 ee 4e a9 13 0f e9
+ b9 09 2b d1 36 d1 84 f9 5f 50 4a 60 7e ac 56 58
+ 46 d2 fd d6 59 7a 89 67 c7 39 6e f9 5a 6e ee bb
+ 45 78 a6 43 96 6d ca 4d 8e e3 de 84 2d e6 32 79
+ c6 18 15 9c 1a b5 4a 89 43 7b 6a 61 20 e4 93 0a
+ fb 52 a4 ba 6c ed 8a 49 47 ac 64 b3 0a 34 97 cb
+ e7 01 c2 d6 26 6d 51 72 19 ad 0e c6 d3 47 db e9'''
+ },
+ # Message
+ '''81 33 2f 4b e6 29 48 41 5e a1 d8 99 79 2e ea cf
+ 6c 6e 1d b1 da 8b e1 3b 5c ea 41 db 2f ed 46 70
+ 92 e1 ff 39 89 14 c7 14 25 97 75 f5 95 f8 54 7f
+ 73 56 92 a5 75 e6 92 3a f7 8f 22 c6 99 7d db 90
+ fb 6f 72 d7 bb 0d d5 74 4a 31 de cd 3d c3 68 58
+ 49 83 6e d3 4a ec 59 63 04 ad 11 84 3c 4f 88 48
+ 9f 20 97 35 f5 fb 7f da f7 ce c8 ad dc 58 18 16
+ 8f 88 0a cb f4 90 d5 10 05 b7 a8 e8 4e 43 e5 42
+ 87 97 75 71 dd 99 ee a4 b1 61 eb 2d f1 f5 10 8f
+ 12 a4 14 2a 83 32 2e db 05 a7 54 87 a3 43 5c 9a
+ 78 ce 53 ed 93 bc 55 08 57 d7 a9 fb''',
+ # Signature
+ '''02 62 ac 25 4b fa 77 f3 c1 ac a2 2c 51 79 f8 f0
+ 40 42 2b 3c 5b af d4 0a 8f 21 cf 0f a5 a6 67 cc
+ d5 99 3d 42 db af b4 09 c5 20 e2 5f ce 2b 1e e1
+ e7 16 57 7f 1e fa 17 f3 da 28 05 2f 40 f0 41 9b
+ 23 10 6d 78 45 aa f0 11 25 b6 98 e7 a4 df e9 2d
+ 39 67 bb 00 c4 d0 d3 5b a3 55 2a b9 a8 b3 ee f0
+ 7c 7f ec db c5 42 4a c4 db 1e 20 cb 37 d0 b2 74
+ 47 69 94 0e a9 07 e1 7f bb ca 67 3b 20 52 23 80
+ c5''',
+ # Salt
+ '''1d 65 49 1d 79 c8 64 b3 73 00 9b e6 f6 f2 46 7b
+ ac 4c 78 fa''',
+ SHA
+ )
+ )
+
+ def testSign1(self):
+ for i in range(len(self._testData)):
+ # Build the key
+ comps = [ long(rws(self._testData[i][0][x]),16) for x in ('n','e','d') ]
+ key = MyKey(RSA.construct(comps))
+ # Hash function
+ h = self._testData[i][4].new()
+ # Data to sign
+ h.update(t2b(self._testData[i][1]))
+ # Salt
+ test_salt = t2b(self._testData[i][3])
+ key._randfunc = lambda N: test_salt
+ # The real test
+ signer = PKCS.new(key)
+ self.failUnless(signer.can_sign())
+ s = signer.sign(h)
+ self.assertEqual(s, t2b(self._testData[i][2]))
+
+ def testVerify1(self):
+ for i in range(len(self._testData)):
+ # Build the key
+ comps = [ long(rws(self._testData[i][0][x]),16) for x in ('n','e') ]
+ key = MyKey(RSA.construct(comps))
+ # Hash function
+ h = self._testData[i][4].new()
+ # Data to sign
+ h.update(t2b(self._testData[i][1]))
+ # Salt
+ test_salt = t2b(self._testData[i][3])
+ # The real test
+ key._randfunc = lambda N: test_salt
+ verifier = PKCS.new(key)
+ self.failIf(verifier.can_sign())
+ result = verifier.verify(h, t2b(self._testData[i][2]))
+ self.failUnless(result)
+
+ def testSignVerify(self):
+ h = SHA.new()
+ h.update(b('blah blah blah'))
+
+ rng = Random.new().read
+ key = MyKey(RSA.generate(1024,rng))
+
+ # Helper function to monitor what's request from MGF
+ global mgfcalls
+ def newMGF(seed,maskLen):
+ global mgfcalls
+ mgfcalls += 1
+ return bchr(0x00)*maskLen
+
+ # Verify that PSS is friendly to all ciphers
+ for hashmod in (MD2,MD5,SHA,SHA224,SHA256,SHA384,RIPEMD):
+ h = hashmod.new()
+ h.update(b('blah blah blah'))
+
+ # Verify that sign() asks for as many random bytes
+ # as the hash output size
+ key.asked = 0
+ signer = PKCS.new(key)
+ s = signer.sign(h)
+ self.failUnless(signer.verify(h, s))
+ self.assertEqual(key.asked, h.digest_size)
+
+ h = SHA.new()
+ h.update(b('blah blah blah'))
+
+ # Verify that sign() uses a different salt length
+ for sLen in (0,3,21):
+ key.asked = 0
+ signer = PKCS.new(key, saltLen=sLen)
+ s = signer.sign(h)
+ self.assertEqual(key.asked, sLen)
+ self.failUnless(signer.verify(h, s))
+
+ # Verify that sign() uses the custom MGF
+ mgfcalls = 0
+ signer = PKCS.new(key, newMGF)
+ s = signer.sign(h)
+ self.assertEqual(mgfcalls, 1)
+ self.failUnless(signer.verify(h, s))
+
+ # Verify that sign() does not call the RNG
+ # when salt length is 0, even when a new MGF is provided
+ key.asked = 0
+ mgfcalls = 0
+ signer = PKCS.new(key, newMGF, 0)
+ s = signer.sign(h)
+ self.assertEqual(key.asked,0)
+ self.assertEqual(mgfcalls, 1)
+ self.failUnless(signer.verify(h, s))
+
+
+class testSign1_mytest():
+
+ # List of tuples with test data for PKCS#1 PSS
+ # Each tuple is made up by:
+ # Item #0: dictionary with RSA key component, or key to import
+ # Item #1: data to hash and sign
+ # Item #2: signature of the data #1, done with the key #0,
+ # and salt #3 after hashing it with #4
+ # Item #3: salt
+ # Item #4: hash object generator
+
+ def __init__(self, rsa_parse, msg):
+ _testData = (
+
+ #
+ # From in pss-vect.txt to be found in
+ # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ #
+ (
+ # Private key
+ {
+ 'n':'''a2 ba 40 ee 07 e3 b2 bd 2f 02 ce 22 7f 36 a1 95
+ 02 44 86 e4 9c 19 cb 41 bb bd fb ba 98 b2 2b 0e
+ 57 7c 2e ea ff a2 0d 88 3a 76 e6 5e 39 4c 69 d4
+ b3 c0 5a 1e 8f ad da 27 ed b2 a4 2b c0 00 fe 88
+ 8b 9b 32 c2 2d 15 ad d0 cd 76 b3 e7 93 6e 19 95
+ 5b 22 0d d1 7d 4e a9 04 b1 ec 10 2b 2e 4d e7 75
+ 12 22 aa 99 15 10 24 c7 cb 41 cc 5e a2 1d 00 ee
+ b4 1f 7c 80 08 34 d2 c6 e0 6b ce 3b ce 7e a9 a5''',
+ 'e':'''01 00 01''',
+ # In the test vector, only p and q were given...
+ # d is computed offline as e^{-1} mod (p-1)(q-1)
+ 'd':'''50e2c3e38d886110288dfc68a9533e7e12e27d2aa56
+ d2cdb3fb6efa990bcff29e1d2987fb711962860e7391b1ce01
+ ebadb9e812d2fbdfaf25df4ae26110a6d7a26f0b810f54875e
+ 17dd5c9fb6d641761245b81e79f8c88f0e55a6dcd5f133abd3
+ 5f8f4ec80adf1bf86277a582894cb6ebcd2162f1c7534f1f49
+ 47b129151b71'''
+ },
+
+ # Data to sign
+ '''85 9e ef 2f d7 8a ca 00 30 8b dc 47 11 93 bf 55
+ bf 9d 78 db 8f 8a 67 2b 48 46 34 f3 c9 c2 6e 64
+ 78 ae 10 26 0f e0 dd 8c 08 2e 53 a5 29 3a f2 17
+ 3c d5 0c 6d 5d 35 4f eb f7 8b 26 02 1c 25 c0 27
+ 12 e7 8c d4 69 4c 9f 46 97 77 e4 51 e7 f8 e9 e0
+ 4c d3 73 9c 6b bf ed ae 48 7f b5 56 44 e9 ca 74
+ ff 77 a5 3c b7 29 80 2f 6e d4 a5 ff a8 ba 15 98
+ 90 fc''',
+ # Signature
+ '''8d aa 62 7d 3d e7 59 5d 63 05 6c 7e c6 59 e5 44
+ 06 f1 06 10 12 8b aa e8 21 c8 b2 a0 f3 93 6d 54
+ dc 3b dc e4 66 89 f6 b7 95 1b b1 8e 84 05 42 76
+ 97 18 d5 71 5d 21 0d 85 ef bb 59 61 92 03 2c 42
+ be 4c 29 97 2c 85 62 75 eb 6d 5a 45 f0 5f 51 87
+ 6f c6 74 3d ed dd 28 ca ec 9b b3 0e a9 9e 02 c3
+ 48 82 69 60 4f e4 97 f7 4c cd 7c 7f ca 16 71 89
+ 71 23 cb d3 0d ef 5d 54 a2 b5 53 6a d9 0a 74 7e''',
+ # Salt
+ '''e3 b5 d5 d0 02 c1 bc e5 0c 2b 65 ef 88 a1 88 d8
+ 3b ce 7e 61''',
+ # Hash algorithm
+ SHA
+ ),
+
+ #
+ # Example 1.1 to be found in
+ # ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1-vec.zip
+ #
+ (
+ # Private key
+ {
+ 'n':'''a5 6e 4a 0e 70 10 17 58 9a 51 87 dc 7e a8 41 d1
+ 56 f2 ec 0e 36 ad 52 a4 4d fe b1 e6 1f 7a d9 91
+ d8 c5 10 56 ff ed b1 62 b4 c0 f2 83 a1 2a 88 a3
+ 94 df f5 26 ab 72 91 cb b3 07 ce ab fc e0 b1 df
+ d5 cd 95 08 09 6d 5b 2b 8b 6d f5 d6 71 ef 63 77
+ c0 92 1c b2 3c 27 0a 70 e2 59 8e 6f f8 9d 19 f1
+ 05 ac c2 d3 f0 cb 35 f2 92 80 e1 38 6b 6f 64 c4
+ ef 22 e1 e1 f2 0d 0c e8 cf fb 22 49 bd 9a 21 37''',
+ 'e':'''01 00 01''',
+ 'd':'''33 a5 04 2a 90 b2 7d 4f 54 51 ca 9b bb d0 b4 47
+ 71 a1 01 af 88 43 40 ae f9 88 5f 2a 4b be 92 e8
+ 94 a7 24 ac 3c 56 8c 8f 97 85 3a d0 7c 02 66 c8
+ c6 a3 ca 09 29 f1 e8 f1 12 31 88 44 29 fc 4d 9a
+ e5 5f ee 89 6a 10 ce 70 7c 3e d7 e7 34 e4 47 27
+ a3 95 74 50 1a 53 26 83 10 9c 2a ba ca ba 28 3c
+ 31 b4 bd 2f 53 c3 ee 37 e3 52 ce e3 4f 9e 50 3b
+ d8 0c 06 22 ad 79 c6 dc ee 88 35 47 c6 a3 b3 25'''
+ },
+ # Message
+ '''cd c8 7d a2 23 d7 86 df 3b 45 e0 bb bc 72 13 26
+ d1 ee 2a f8 06 cc 31 54 75 cc 6f 0d 9c 66 e1 b6
+ 23 71 d4 5c e2 39 2e 1a c9 28 44 c3 10 10 2f 15
+ 6a 0d 8d 52 c1 f4 c4 0b a3 aa 65 09 57 86 cb 76
+ 97 57 a6 56 3b a9 58 fe d0 bc c9 84 e8 b5 17 a3
+ d5 f5 15 b2 3b 8a 41 e7 4a a8 67 69 3f 90 df b0
+ 61 a6 e8 6d fa ae e6 44 72 c0 0e 5f 20 94 57 29
+ cb eb e7 7f 06 ce 78 e0 8f 40 98 fb a4 1f 9d 61
+ 93 c0 31 7e 8b 60 d4 b6 08 4a cb 42 d2 9e 38 08
+ a3 bc 37 2d 85 e3 31 17 0f cb f7 cc 72 d0 b7 1c
+ 29 66 48 b3 a4 d1 0f 41 62 95 d0 80 7a a6 25 ca
+ b2 74 4f d9 ea 8f d2 23 c4 25 37 02 98 28 bd 16
+ be 02 54 6f 13 0f d2 e3 3b 93 6d 26 76 e0 8a ed
+ 1b 73 31 8b 75 0a 01 67 d0''',
+ # Signature
+ '''90 74 30 8f b5 98 e9 70 1b 22 94 38 8e 52 f9 71
+ fa ac 2b 60 a5 14 5a f1 85 df 52 87 b5 ed 28 87
+ e5 7c e7 fd 44 dc 86 34 e4 07 c8 e0 e4 36 0b c2
+ 26 f3 ec 22 7f 9d 9e 54 63 8e 8d 31 f5 05 12 15
+ df 6e bb 9c 2f 95 79 aa 77 59 8a 38 f9 14 b5 b9
+ c1 bd 83 c4 e2 f9 f3 82 a0 d0 aa 35 42 ff ee 65
+ 98 4a 60 1b c6 9e b2 8d eb 27 dc a1 2c 82 c2 d4
+ c3 f6 6c d5 00 f1 ff 2b 99 4d 8a 4e 30 cb b3 3c''',
+ # Salt
+ '''de e9 59 c7 e0 64 11 36 14 20 ff 80 18 5e d5 7f
+ 3e 67 76 af''',
+ # Hash
+ SHA
+ ),
+
+ (
+ # Private key
+ """-----BEGIN RSA PRIVATE KEY-----
+ MIICXQIBAAKBgQC1OZn2ExXQ5z/1XhBomiy7j6YGQU7EuBXcvnvizU6fGkdcLWKA
+ MBQJxHOnCJwUSvCecea58P4WSDaAGk/Rbd3y1b1Akr7ilcpW+l0ymfF95pBIMBt1
+ gXDaHtaM1GgR4H0FisR68fHm2LDMNdGdVdGz3vqpUBboVx7fmLyEAxswuQIDAQAB
+ AoGBAKkGWW/mqxFVrhSnL/yv14r0VvA8lz/pRhLF4vxNasgAFZCGj/lpXjch8JBY
+ +mH+51+Qcpb4i7OylIp0f/+gTkGuSAYPYwzwqG3ALwAF4Z5i8qKmklQtEJ+9p7lu
+ POivMzla4Qx7bvBp+Bq4/8lyg5o+D279MN68455wub516+7RAkEAz+InzJO8H8lN
+ OKpysNCPx9WQNkpMLODRlOYxDg6/QiHNBshT+Kd8tU9xT8fqPWCybfrYNKDWEahz
+ C/QVPWR5JQJBAN8r1qZo0KWvOay81ogC6aLoLauJX6UHuhxN1U1cS/AjdSJezWZp
+ L3zmS9iSJbTyojzwGTly6e+2kGHYafLwlwUCQGD+Ujd/jrz9/Yu863pYNV215W2P
+ SO9/jgn9RVIby10dzD2n5pYT/3nRMTtaOY6duWLbMVmM2ZSvlc4z+l0ErgkCQA8F
+ SVY7+ccdCxm4QAw5ffYsAF7qSRi3c2xSRMgHLUlFaa3diZ+Z9stGSNaTx5vtNMQ7
+ OMdoF5y9wewD/+WNEe0CQQCPXCxOab5++0AB25wqwP2Zk/nFiNznd7+Rk/TIS4c+
+ +C8/NPfkYJD7aNcpflFvyeLAWJgtSs+ebVHYpEZpUnY5
+ -----END RSA PRIVATE KEY-----""",
+ # Data to sign
+ "abc",
+ # Signature
+ '''7e a9 02 59 20 eb a1 b1 67 99 56 44 72 88 00 3d
+ 11 4a 3d 16 40 d2 77 6b 60 62 06 b6 19 f0 7e de
+ 52 93 0d d9 74 25 44 fd b3 4f 5c cf fb b7 98 34
+ ae ad e3 9e 79 93 fc 5f 4b 48 d0 08 95 c4 66 5e
+ d5 17 7a 5b 05 a2 7e fb 21 72 68 12 f7 6d 3b fe
+ 97 30 81 c5 75 de e4 26 6c d6 d8 28 0b ae 33 a0
+ f6 9d f0 23 2f f7 12 0b 40 a3 37 7d 25 bf 60 c9
+ 84 d4 19 27 61 27 f6 a0 62 8b 52 32 26 9a 0c 77''',
+ # Salt
+ '''25 5a 3c e4 34 ae e1 41 09 a5 96 f6 a6 7e 34 b6
+ 8e 56 3f 2d 92 07 41 55 f3 e4 a5 9e 47 98 d2 e4''',
+ # Hash algorithm
+ SHA256
+ ),
+
+ (
+ # Private key
+ """-----BEGIN RSA PRIVATE KEY-----
+ MIIJKwIBAAKCAgEA3zT2hUJNVJPMixm5F6GJl1oNIVPyV3AlcSmSdHkpPZH9LuRd
+ NEQ1Yv5PuHSFw8PSKmySg+5uMeZudconbCOAoF2pnHgMAw2unm4wc7GJf//E/k7f
+ UwCG6VD/8aO2U0Fkiwo5XpbSe91fmtqXAsyoqBvAsJAdGGGtede7httEa/PhHf2R
+ qzzDdyx5VUnZm4IolN7Q25J730L5mOlkwOzH0uuE7zlnwDnMV6sbsFopwiyI012l
+ Tmj0gIVC2nTCRiJxctRT7Hxiqtq+/PR1rLTzN/80uhN0nHGkHJKHtyJRojjkkwPR
+ 1QugU3A5P569i6ZvncOYq7o5gpaPzmaR7el1h7z057oIiHPo+bSfhhnN8Lc1qo0D
+ BNkKhxLuC3W8yd0nndGzNYAKK1VCxL06zYIyyokrx/Q1+RSkKcvmcJcHVQRkSlh9
+ QSyoUTCGdVRcOugP1wXoPkAFFfjep8+xLNnS61Rb58O+P7Jr/0970eMz0ZlM16aq
+ P3jpyBy16vv/EVPsBcQR29W4Xl7ngJzXIXpWG8YKZ2n9zTOVhXQgdEevUhREIE8o
+ fsKA8NnAsKbaKixplR86HXCE3fLiJxICDHHfXDRxsAyDCAav7u1I6P0Z8MVaQWGx
+ XApyljlViaV1xDKgqhfMqKA488Butza5RV9/rJjDtcl/ANK5yza7tlSKYr0CAwEA
+ AQKCAgEAnrz71Smh9VRnU0Wn7LZlM85HKDybTLPk7OWz0kGYosEAXijqYBFiJlTW
+ PUghGWhaPvGYAVu/4p0OUZbDEpTtFR+HUE/Puxwv41xZ+O157B3p6zIMgOsPBz8j
+ xqW3NN58sqVCx5Jbftug8nAilUsXZvbVwru69WwCA3T5WJ73ug5nOvzqa+161XY7
+ k/xBVebrFXSg9IbosY7gE29oyAuc0NPOZpNcxchVGsQFnRWCPSWO6ULgHTNnLz+W
+ m+YNg/Na219FkBml0fxfd2Yjif/mORy2Ut8jP19SZz+OZR9zDvuHE0bUI79w9eYJ
+ 0MUD6B0lo/1GxlpaLBUHkLJBdgFiIyJ6kbt0ol0TAL6oHxvK/m/6K8hKmlnsyf2J
+ OJV4ijzWotP9Ogwb2ZoXncRvD8m28MAYXbLOVVJEEWqxaGFti62CR7dDAZ3dNg8t
+ IotGC1OlYJlCuGIUvBQC9SHeaFCrRofEPKBJjpuYSpj1RmwR9LQIJLDg2xeiEMj8
+ 3uiSZu81ygClaFaMwHiedV/gASSXYqhcVF9dvzvQ+M7oG8b7TLJ8MhWB+cUjA5we
+ Yq47uOSmW9wS1rid3YuHtsZEZ9wzXaaM8yX2ELlaJ3GiaMGB/ww/T0St8VEwdG9J
+ DKWWlcIFy2p1TlpA69G8nv7oI4Im3kLJlQa10/f44hQ7UaFOh8ECggEBAOb8rD+9
+ P1IGWPwbe1AG7U8PtbJs0g+jldJ/WIxG9T9hIhO5QTVBgQoSmBE6weedbO0EydVf
+ QIE1yJ8aRCukL5j5X1drXKJbbdC4z569aRPZwcRRdgQ3DbZImgK/JUwNaVwB6lMe
+ QLU84CXDPZAufakKKeBQvxXSJ+WqxlFh7adcRePwS70KtJuoLkP0/8AVIhZE79bj
+ pZxYBa7zD4UV9Dvyu0QWYnOVo29cCxgWiA61o8hZn0d5QFpe1fnuayNrzDNEttnb
+ 8Mw7WhsbO7dAri7/SkCY16HyhWXXypEM6VcvdHSV5McqO+bo1Bnv1VPyPTLr38W/
+ 8PlYB41DcJ8/HeMCggEBAPdgnOfZDRmByz8aKB6HJ6RM0tR837ak4KxVcXJ2RYPY
+ acF9ybS8rpE5LuP/lS2/qtHMT4aPqvNvPPl1gUw+mmrmzYLmhKgCyD0SiYqC1kH4
+ zlfODQTOe1ZdaGFbyIwrf8GhPPQmdiDqAzWsdIDv4WU/pJXlboAb4sTPVxSuGnAH
+ ZOHkWQRDBhjZp0ASMpNc+EgqBZ2MaKijxKuZQP9JX7Pi0Gzy6p2t0y03ZOUpL4QW
+ 5RxET7Idr3jYua9Ckb9+Z+A/5xQE6XHv4BIwshW33Kdp147Jp3pUnwU/BWSKRo2a
+ cLFb5APcJxf17rzH17BzJ/wT/f/R5dqKqX0xDkXyXt8CggEBAKW+lRK/hxoid+Of
+ DKLl9Y6PpT88mpaiOTVsL2uo1v39guhIPCQstp01rmxejxjVe32vu+whhzWwFB8m
+ R9hQ3d6UwfcGkNfnZysoEcLEAww9aq6mDVsE7g/olKp34hlqXjmpHi06PhBOeEBg
+ kmJNGdob8uSEzDiqLfq8ycVH0bIPog7nNFGXxvUSfvBAcuuvvl/gY4D8pK9E8f8R
+ ZgeHM1N43ysCLO7nZvjXQRatxD9Z0wZGWOZ+eNDf0AahL7ug9EuteM9m5KiHxiZB
+ Kl5aSSJsCSnFAqWwUkw7xZzDeQQYhyXJEPpgsc8FLnzV/WtZHNTXMCDDk/Q3WGPj
+ CoMaVSUCggEBAO2hnjhNVXsaJo7QZpekx1zZ+3DpH9IIolaJoXgNywszGawoVFnN
+ IngYkUWtn7UZuFLey8n8OoCsa8tKqFEAlj94xRQosmfefFHGe99VfdJT2ouYQQNM
+ AkjdY8aab5TOuGPdqnryc2l8wmaN6kBtrnwfXdAsXDCuGPFsJz+TW4wgXjVssGIa
+ rEG02yf+Ex1iIpLX4xsL5QGSh/s7NafF6SwZBpSR6PRdJU37N223WZCumZnEuTXl
+ tEkHD6Ae93kXSVuupyCg80ti3UE8C+Y2/7zGPK5KYhpuLW/RsTF6bvnZ0MVe+zMG
+ CXvH4HTyF+zFQjSxU76p9/4uU1ASjp58i8sCggEBANdzShhwJnaxKW7e7hiLA5k1
+ G579ubQfDZy/UJOMeDzmrhpcVN5+cH5afFHMHQczzY0GkBkHz4zgN2euOY/Vh/RR
+ F+rwzwBisLKq2Oiwu5oPKLD5aIFxbOahzSI8N8Upk7J/pBGlFYeg/13bJtb1DrMV
+ tslxK8cJa2RFUesi2Jy9kz2bFaKIub8rSBCoXhLbccjZwV2W93oDOU44KnXauFvt
+ UJlFTRbTsf1YII46Zl4dFstWAb+R6DYHNU+xFpJpSVAeOW7R4i4pq7FKl1Xrr0nu
+ X7iTAH08FfZMzQxQ/jazDvc22rgMGbGuGkjHqFntiBsEkFDW9s3lMjrMy8xPcLk=
+ -----END RSA PRIVATE KEY-----""",
+ # Data to sign
+ "abc",
+ # Signature
+ '''70 1b 61 7e 96 cf b5 9e 59 af ed eb c2 b3 55 fd
+ 64 c2 6c b4 c7 ad 62 19 af ed f3 b0 82 fa 1d e7
+ 8f 6f 01 a1 74 67 48 9b a6 c0 ba 7f dc ce 91 49
+ 7c da d3 d0 aa c8 e9 4d be 9f ea 1f 62 0e 11 55
+ 4e 82 03 c3 fb 4a f4 ba d9 ab 08 e4 8f 07 ba f0
+ ed 5d 6e f7 8b 27 9d 08 dd b4 36 b5 3b 89 b2 e0
+ f3 43 b2 9b 4a e6 b1 03 b4 87 5d a9 58 3c 2b 6f
+ fa 22 0c 28 d9 28 7a b6 c4 7f 03 f0 21 55 d0 be
+ 12 0a 8a e9 c5 3c e5 d2 6b e3 9a ce 92 87 e4 10
+ 5f e0 66 db 46 66 e5 72 be b4 3c d1 8e cf 1a ea
+ ba 69 65 09 e9 a1 04 55 3c b5 92 87 57 97 00 cf
+ 47 20 e8 8a df 93 18 6a cf 2b d3 af 55 8f 55 d5
+ 78 a0 fa 27 e8 f5 f5 a6 3b b5 ec f1 c2 8d b5 f9
+ 68 de ca b4 e2 4a 00 cd f5 19 47 8e 36 f4 0e 4f
+ 5d 34 a3 ec 63 39 08 15 69 b2 83 6d f7 b0 99 3b
+ b0 bf 2b e6 ae 9a 60 5b 43 e4 18 18 ec be 09 ba
+ 85 8a dc 77 75 cd c6 eb 98 d6 b0 9c de a4 d7 1a
+ df 2c 3f aa 7c 52 ff 3e 0f 87 20 2b dd 93 92 49
+ 43 f8 b9 d4 8e de c5 3b 37 a5 ee 8c 68 cc 6d ff
+ c6 98 c6 af 00 b8 f4 bf b7 7f 51 b0 53 a5 68 fb
+ bf b2 62 57 2e cd 7c c0 0e cc 3e 69 3b a5 a2 bf
+ 3f ad c6 1b 66 39 57 71 e3 b7 c8 20 b6 51 46 58
+ 70 be 64 96 38 c4 e1 51 3b 63 68 3c 38 fb d4 b2
+ 60 ed 0f 2e b5 cf 1e 2c 9c ec 7f b9 19 51 3b 4c
+ 30 0d 74 a0 e6 f6 14 ea ff cd c5 2e 6a cd c2 f5
+ 53 3b f4 64 1a 44 9e 16 64 d6 82 f5 7d 1a 47 00
+ 51 04 90 1b 8e b7 91 d6 73 91 46 74 bd ea 08 86
+ 41 e4 f5 e5 04 61 f8 bd a4 b7 56 6a 0b a2 b3 ee
+ 00 f8 cc 04 28 36 de 99 05 2b e2 eb 92 ff 26 1d
+ db 29 5a 72 51 a4 b7 f7 ea 5c 27 53 68 0d 89 8c
+ 1f 17 87 85 9c 1d 8d 42 b4 cb 42 49 c7 0c 1e df
+ e0 8e ee e3 1e 77 5d 16 5f 75 31 1c 5c af 3e 02
+ ''',
+ # Salt
+ '''c8 e6 96 a2 a5 5b ab 2f eb b8 42 89 f8 de 0c 8d
+ 8d 82 99 b8 25 b8 f2 35 73 2c 49 d4 d1 f3 04 4d''',
+ # Hash algorithm
+ SHA256
+ ),
+ )
+
+ self._testData = _testData
+ self.rsa_parse = rsa_parse
+ self.msg = msg
+
+ def sign1_mytest(self):
+ for i in range(len(self._testData)):
+ print("Test vector[%d]" %i)
+ # Build the key
+ if isStr(self._testData[i][0]):
+ print("pem")
+ key = RSA.importKey(self._testData[i][0])
+ else:
+ comps = [ long(rws(self._testData[i][0][x]),16) for x in ('n','e','d') ]
+ key = MyKey(RSA.construct(comps))
+ # Hash function
+ h = self._testData[i][4].new()
+ # Data to sign
+ try:
+ print("try")
+ h.update(t2b(self._testData[i][1]))
+ except:
+ print("except")
+ h.update(b(self._testData[i][1]))
+ # Salt
+ test_salt = t2b(self._testData[i][3])
+ key._randfunc = lambda N: test_salt
+ # The real test
+ signer = PKCS.new(key)
+ t_flag = signer.can_sign()
+ if t_flag:
+ print("mytest: can sign")
+ else:
+ print("mytest: can't sign")
+ s = signer.sign(h)
+ print("salt:")
+ #rsa_dump(test_salt)
+ rsa_dump(key._randfunc(test_salt))
+ print("signature:")
+ rsa_dump(s)
+
+ if s == t2b(self._testData[i][2]):
+ print("[Pass] RSA PSS signature compare pass")
+ else:
+ print("[Fail] PSA PSS signature compare fail")
+
+ def sbc_rsa_sign1_json(self):
+ row = self.rsa_parse
+ # Build the key
+ if isStr(row[0]):
+ print("pem")
+ key = RSA.importKey(row[0])
+ else:
+ comps = [ long(rws(row[0][x]),16) for x in ('n','e','d') ]
+ key = MyKey(RSA.construct(comps))
+ # Hash function
+ if(row[4] == "SHA"):
+ h = SHA.new()
+ elif(row[4] == "SHA256"):
+ h = SHA256.new()
+ elif(row[4] == "SHA384"):
+ h = SHA384.new()
+ elif(row[4] == "SHA512"):
+ h = SHA512.new()
+ else:
+ h = SHA256.new()
+ # Data to sign
+ if(row[5] == 1):
+ try:
+ print("try")
+ h.update(t2b(row[1]))
+ except:
+ print("except")
+ h.update(b(row[1]))
+ else:
+ h.update(self.msg)
+ rsa_dump(h.digest())
+
+ # Salt
+ test_salt = t2b(row[3])
+ key._randfunc = lambda N: test_salt
+ # The real test
+ signer = PKCS.new(key)
+ t_flag = signer.can_sign()
+ if t_flag:
+ print("mytest: can sign")
+ else:
+ print("mytest: can't sign")
+ s = signer.sign(h)
+ print("salt:")
+ #rsa_dump(test_salt)
+ rsa_dump(key._randfunc(test_salt))
+ print("signature:")
+ rsa_dump(s)
+
+ if s == t2b(row[2]):
+ print("[Pass] RSA PSS signature compare pass")
+ else:
+ print("[Fail] PSA PSS signature compare fail")
+ return s
+
+ def verify1_mytest(self):
+ for i in range(len(self._testData)):
+ print("Test vector[%d]" %i)
+ row = self._testData[i]
+ # Build the key
+ if isStr(row[0]):
+ key = RSA.importKey(row[0]).publickey()
+ else:
+ comps = [ long(rws(self._testData[i][0][x]),16) for x in ('n','e') ]
+ key = MyKey(RSA.construct(comps))
+ # Hash function
+ h = self._testData[i][4].new()
+ # Data to sign
+ try:
+ h.update(t2b(self._testData[i][1]))
+ # Salt
+ test_salt = t2b(self._testData[i][3])
+ except:
+ h.update(b(self._testData[i][1]))
+ # Salt
+ test_salt = b(self._testData[i][3])
+ # The real test
+ key._randfunc = lambda N: test_salt
+ verifier = PKCS.new(key)
+ t_flag = verifier.can_sign()
+ if t_flag:
+ print("mytest: can't verify")
+ else:
+ print("mytest: can verify")
+ result = verifier.verify(h, t2b(self._testData[i][2]))
+ if result:
+ print("[Pass] RSA PSS verify pass")
+ else:
+ print("[Fail] RSA PSS verify fail")
+
+
+def get_tests(config={}):
+ tests = []
+ tests += list_test_cases(PKCS1_PSS_Tests)
+ return tests
+
+if __name__ == '__main__':
+ suite = lambda: unittest.TestSuite(get_tests())
+ unittest.main(defaultTest='suite')
+
+# vim:set ts=4 sw=4 sts=4