1#!/usr/bin/env python3 2# Copyright(c) 2022 Intel Corporation. All rights reserved. 3# SPDX-License-Identifier: Apache-2.0 4import os 5import sys 6import logging 7import time 8import argparse 9import socket 10import struct 11import hashlib 12from urllib.parse import urlparse 13 14RET = 0 15HOST = None 16PORT = 0 17PORT_LOG = 9999 18PORT_REQ = PORT_LOG + 1 19BUF_SIZE = 4096 20 21# Define the command and its 22# possible max size 23CMD_LOG_START = "start_log" 24CMD_DOWNLOAD = "download" 25MAX_CMD_SZ = 16 26 27# Define the header format and size for 28# transmiting the firmware 29PACKET_HEADER_FORMAT_FW = 'I 42s 32s' 30 31logging.basicConfig() 32log = logging.getLogger("cavs-client") 33log.setLevel(logging.INFO) 34 35class cavstool_client(): 36 def __init__(self, host, port, args): 37 self.host = host 38 self.port = port 39 self.args = args 40 self.sock = None 41 self.cmd = None 42 43 def send_cmd(self, cmd): 44 with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock: 45 self.sock = sock 46 self.cmd = cmd 47 self.sock.connect((self.host, self.port)) 48 self.sock.sendall(cmd.encode("utf-8")) 49 log.info(f"Sent: {cmd}") 50 ack = str(self.sock.recv(MAX_CMD_SZ), "utf-8") 51 log.info(f"Receive: {ack}") 52 53 if ack == CMD_LOG_START: 54 self.monitor_log() 55 elif ack == CMD_DOWNLOAD: 56 self.run() 57 else: 58 log.error(f"Receive incorrect msg:{ack} expect:{cmd}") 59 60 def uploading(self, filename): 61 # Send the FW to server 62 fname = os.path.basename(filename) 63 fsize = os.path.getsize(filename) 64 65 md5_tx = hashlib.md5(open(filename,'rb').read(), 66 usedforsecurity=False).hexdigest() 67 68 # Pack the header and the expecting packed size is 78 bytes. 69 # The header by convention includes: 70 # size(4), filename(42), MD5(32) 71 values = (fsize, fname.encode('utf-8'), md5_tx.encode('utf-8')) 72 log.info(f'filename:{fname}, size:{fsize}, md5:{md5_tx}') 73 74 s = struct.Struct(PACKET_HEADER_FORMAT_FW) 75 header_data = s.pack(*values) 76 header_size = s.size 77 log.info(f'header size: {header_size}') 78 79 with open(filename,'rb') as f: 80 log.info(f'Sending...') 81 82 total = self.sock.send(header_data) 83 total += self.sock.sendfile(f) 84 85 log.info(f"Done Sending ({total}).") 86 87 rck = self.sock.recv(MAX_CMD_SZ).decode("utf-8") 88 log.info(f"RCK ({rck}).") 89 if not rck == "success": 90 global RET 91 RET = -1 92 log.error(f"Firmware uploading failed") 93 94 def run(self): 95 filename = str(self.args.fw_file) 96 self.uploading(filename) 97 98 def monitor_log(self): 99 log.info(f"Start to monitor log output...") 100 while True: 101 # Receive data from the server and print out 102 receive_log = str(self.sock.recv(BUF_SIZE), "utf-8").replace('\x00','') 103 if receive_log: 104 sys.stdout.write(f"{receive_log}") 105 sys.stdout.flush() 106 time.sleep(0.1) 107 108 def __del__(self): 109 self.sock.close() 110 111 112def main(): 113 if args.log_only: 114 log.info("Monitor process") 115 116 try: 117 client = cavstool_client(HOST, PORT, args) 118 client.send_cmd(CMD_LOG_START) 119 except KeyboardInterrupt: 120 pass 121 122 else: 123 log.info("Uploading process") 124 client = cavstool_client(HOST, PORT, args) 125 client.send_cmd(CMD_DOWNLOAD) 126 127ap = argparse.ArgumentParser(description="DSP loader/logger client tool", allow_abbrev=False) 128ap.add_argument("-q", "--quiet", action="store_true", 129 help="No loader output, just DSP logging") 130ap.add_argument("-l", "--log-only", action="store_true", 131 help="Don't load firmware, just show log output") 132ap.add_argument("-s", "--server-addr", default="localhost", 133 help="Specify the adsp server address") 134ap.add_argument("-p", "--log-port", type=int, 135 help="Specify the PORT that connected to log server") 136ap.add_argument("-r", "--req-port", type=int, 137 help="Specify the PORT that connected to request server") 138ap.add_argument("fw_file", nargs="?", help="Firmware file") 139args = ap.parse_args() 140 141if args.quiet: 142 log.setLevel(logging.WARN) 143 144if args.log_port: 145 PORT_LOG = args.log_port 146 147if args.req_port: 148 PORT_REQ = args.req_port 149 150if args.server_addr: 151 url = urlparse("//" + args.server_addr) 152 153 if url.hostname: 154 HOST = url.hostname 155 156 if url.port: 157 PORT = int(url.port) 158 else: 159 if args.log_only: 160 PORT = PORT_LOG 161 else: 162 PORT = PORT_REQ 163 164log.info(f"REMOTE HOST: {HOST} PORT: {PORT}") 165 166if __name__ == "__main__": 167 main() 168 169 sys.exit(RET) 170