[Debugger] Implementation of transport over serial connection (#2800)
JerryScript-DCO-1.0-Signed-off-by: Robert Sipka rsipka.uszeged@partner.samsung.com
This commit is contained in:
@@ -24,6 +24,11 @@ import logging
|
||||
import time
|
||||
import jerry_client_main
|
||||
|
||||
from jerry_client_websocket import WebSocket
|
||||
from jerry_client_rawpacket import RawPacket
|
||||
from jerry_client_tcp import Socket
|
||||
from jerry_client_serial import Serial
|
||||
|
||||
def write(string):
|
||||
print(string, end='')
|
||||
|
||||
@@ -246,14 +251,40 @@ def src_check_args(args):
|
||||
print("Error: Non-negative integer number expected: %s" % (val_errno))
|
||||
return -1
|
||||
|
||||
# pylint: disable=too-many-branches,too-many-locals,too-many-statements
|
||||
# pylint: disable=too-many-branches,too-many-locals,too-many-statements,redefined-variable-type
|
||||
def main():
|
||||
args = jerry_client_main.arguments_parse()
|
||||
|
||||
debugger = jerry_client_main.JerryDebugger(args.address, args.channel)
|
||||
channel = None
|
||||
protocol = None
|
||||
|
||||
if args.protocol == "tcp":
|
||||
address = None
|
||||
if ":" not in args.address:
|
||||
address = (args.address, 5001) # use default port
|
||||
else:
|
||||
host, port = args.address.split(":")
|
||||
address = (host, int(port))
|
||||
|
||||
protocol = Socket(address)
|
||||
elif args.protocol == "serial":
|
||||
protocol = Serial(args.serial_config)
|
||||
else:
|
||||
print("Unsupported transmission protocol")
|
||||
return -1
|
||||
|
||||
if args.channel == "websocket":
|
||||
channel = WebSocket(protocol=protocol)
|
||||
elif args.channel == "rawpacket":
|
||||
channel = RawPacket(protocol=protocol)
|
||||
else:
|
||||
print("Unsupported communication channel")
|
||||
return -1
|
||||
|
||||
debugger = jerry_client_main.JerryDebugger(channel)
|
||||
debugger.non_interactive = args.non_interactive
|
||||
|
||||
logging.debug("Connected to JerryScript on %d port", debugger.port)
|
||||
logging.debug("Connected to JerryScript")
|
||||
|
||||
prompt = DebuggerPrompt(debugger)
|
||||
prompt.prompt = "(jerry-debugger) "
|
||||
|
||||
@@ -21,12 +21,9 @@ import re
|
||||
import select
|
||||
import struct
|
||||
import sys
|
||||
from jerry_client_websocket import WebSocket
|
||||
from jerry_client_rawpacket import RawPacket
|
||||
from jerry_client_tcp import Socket
|
||||
|
||||
# Expected debugger protocol version.
|
||||
JERRY_DEBUGGER_VERSION = 8
|
||||
JERRY_DEBUGGER_VERSION = 9
|
||||
|
||||
# Messages sent by the server to client.
|
||||
JERRY_DEBUGGER_CONFIGURATION = 1
|
||||
@@ -60,6 +57,7 @@ JERRY_DEBUGGER_SCOPE_CHAIN = 28
|
||||
JERRY_DEBUGGER_SCOPE_CHAIN_END = 29
|
||||
JERRY_DEBUGGER_SCOPE_VARIABLES = 30
|
||||
JERRY_DEBUGGER_SCOPE_VARIABLES_END = 31
|
||||
JERRY_DEBUGGER_CLOSE_CONNECTION = 32
|
||||
|
||||
# Debugger option flags
|
||||
JERRY_DEBUGGER_LITTLE_ENDIAN = 0x1
|
||||
@@ -123,7 +121,7 @@ def arguments_parse():
|
||||
parser = argparse.ArgumentParser(description="JerryScript debugger client")
|
||||
|
||||
parser.add_argument("address", action="store", nargs="?", default="localhost:5001",
|
||||
help="specify a unique network address for connection (default: %(default)s)")
|
||||
help="specify a unique network address for tcp connection (default: %(default)s)")
|
||||
parser.add_argument("-v", "--verbose", action="store_true", default=False,
|
||||
help="increase verbosity (default: %(default)s)")
|
||||
parser.add_argument("--non-interactive", action="store_true", default=False,
|
||||
@@ -138,6 +136,10 @@ def arguments_parse():
|
||||
help="specify a javascript source file to execute")
|
||||
parser.add_argument("--channel", choices=["websocket", "rawpacket"], default="websocket",
|
||||
help="specify the communication channel (default: %(default)s)")
|
||||
parser.add_argument("--protocol", choices=["tcp", "serial"], default="tcp",
|
||||
help="specify the transmission protocol over the communication channel (default: %(default)s)")
|
||||
parser.add_argument("--serial-config", metavar="CONFIG_STRING", default="/dev/ttyUSB0,115200,8,N,1",
|
||||
help="Configure parameters for serial port (default: %(default)s)")
|
||||
args = parser.parse_args()
|
||||
|
||||
if args.verbose:
|
||||
@@ -266,17 +268,7 @@ class DebuggerAction(object):
|
||||
|
||||
class JerryDebugger(object):
|
||||
# pylint: disable=too-many-instance-attributes,too-many-statements,too-many-public-methods,no-self-use,redefined-variable-type
|
||||
def __init__(self, address, channel):
|
||||
|
||||
if ":" not in address:
|
||||
self.host = address
|
||||
self.port = 5001 # use default port
|
||||
else:
|
||||
self.host, self.port = address.split(":")
|
||||
self.port = int(self.port)
|
||||
|
||||
print("Connecting to: %s:%s" % (self.host, self.port))
|
||||
|
||||
def __init__(self, channel):
|
||||
self.prompt = False
|
||||
self.function_list = {}
|
||||
self.source = ''
|
||||
@@ -304,15 +296,7 @@ class JerryDebugger(object):
|
||||
self.non_interactive = False
|
||||
self.current_out = b""
|
||||
self.current_log = b""
|
||||
self.channel = None
|
||||
|
||||
protocol = Socket()
|
||||
if channel == "websocket":
|
||||
self.channel = WebSocket(address=(self.host, self.port), protocol=protocol)
|
||||
elif channel == "rawpacket":
|
||||
self.channel = RawPacket(address=(self.host, self.port), protocol=protocol)
|
||||
else:
|
||||
raise Exception("Unsupported communication channel")
|
||||
self.channel = channel
|
||||
|
||||
config_size = 8
|
||||
# The server will send the configuration message after connection established
|
||||
@@ -697,7 +681,6 @@ class JerryDebugger(object):
|
||||
# pylint: disable=too-many-branches,too-many-locals,too-many-statements,too-many-return-statements
|
||||
def process_messages(self):
|
||||
result = ""
|
||||
|
||||
while True:
|
||||
data = self.channel.get_message(False)
|
||||
if not self.non_interactive:
|
||||
@@ -846,6 +829,9 @@ class JerryDebugger(object):
|
||||
|
||||
return DebuggerAction(DebuggerAction.TEXT, result)
|
||||
|
||||
elif JERRY_DEBUGGER_CLOSE_CONNECTION:
|
||||
return DebuggerAction(DebuggerAction.END, "")
|
||||
|
||||
else:
|
||||
raise Exception("Unknown message")
|
||||
|
||||
|
||||
@@ -20,14 +20,13 @@ MAX_BUFFER_SIZE = 256
|
||||
|
||||
class RawPacket(object):
|
||||
""" Simplified transmission layer. """
|
||||
def __init__(self, address, protocol):
|
||||
def __init__(self, protocol):
|
||||
self.protocol = protocol
|
||||
self.data_buffer = b""
|
||||
self.address = address
|
||||
|
||||
def connect(self, config_size):
|
||||
""" Create connection. """
|
||||
self.protocol.connect(self.address)
|
||||
self.protocol.connect()
|
||||
self.data_buffer = b""
|
||||
|
||||
# It will return with the Network configurations, which has the following struct:
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import select
|
||||
import serial
|
||||
|
||||
class Serial(object):
|
||||
""" Create a new socket using the given address family, socket type and protocol number. """
|
||||
def __init__(self, serial_config):
|
||||
config = serial_config.split(',')
|
||||
config_size = len(config)
|
||||
|
||||
port = config[0] if config_size > 0 else "/dev/ttyUSB0"
|
||||
baudrate = config[1] if config_size > 1 else 115200
|
||||
bytesize = int(config[2]) if config_size > 2 else 8
|
||||
parity = config[3] if config_size > 3 else 'N'
|
||||
stopbits = int(config[4]) if config_size > 4 else 1
|
||||
|
||||
self.ser = serial.Serial(port=port, baudrate=baudrate, parity=parity,
|
||||
stopbits=stopbits, bytesize=bytesize, timeout=1)
|
||||
|
||||
def connect(self):
|
||||
""" Connect to the server, write a 'c' to the serial port """
|
||||
self.send_data('c')
|
||||
|
||||
def close(self):
|
||||
"""" close the serial port. """
|
||||
self.ser.close()
|
||||
|
||||
def receive_data(self, max_size=1024):
|
||||
""" The maximum amount of data to be received at once is specified by max_size. """
|
||||
return self.ser.read(max_size)
|
||||
|
||||
def send_data(self, data):
|
||||
""" Write data to the serial port. """
|
||||
return self.ser.write(data)
|
||||
|
||||
def ready(self):
|
||||
""" Monitor the file descriptor. """
|
||||
result = select.select([self.ser.fileno()], [], [], 0)[0]
|
||||
|
||||
return self.ser.fileno() in result
|
||||
@@ -17,17 +17,20 @@
|
||||
import socket
|
||||
import select
|
||||
|
||||
# pylint: disable=too-many-arguments,superfluous-parens
|
||||
class Socket(object):
|
||||
""" Create a new socket using the given address family, socket type and protocol number. """
|
||||
def __init__(self, socket_family=socket.AF_INET, socket_type=socket.SOCK_STREAM, proto=0, fileno=None):
|
||||
def __init__(self, address, socket_family=socket.AF_INET, socket_type=socket.SOCK_STREAM, proto=0, fileno=None):
|
||||
self.address = address
|
||||
self.socket = socket.socket(socket_family, socket_type, proto, fileno)
|
||||
|
||||
def connect(self, address):
|
||||
def connect(self):
|
||||
"""
|
||||
Connect to a remote socket at address (host, port).
|
||||
The format of address depends on the address family.
|
||||
"""
|
||||
self.socket.connect(address)
|
||||
print("Connecting to: %s:%s" % (self.address[0], self.address[1]))
|
||||
self.socket.connect(self.address)
|
||||
|
||||
def close(self):
|
||||
"""" Mark the socket closed. """
|
||||
|
||||
@@ -21,11 +21,10 @@ WEBSOCKET_BINARY_FRAME = 2
|
||||
WEBSOCKET_FIN_BIT = 0x80
|
||||
|
||||
class WebSocket(object):
|
||||
def __init__(self, address, protocol):
|
||||
def __init__(self, protocol):
|
||||
|
||||
self.data_buffer = b""
|
||||
self.protocol = protocol
|
||||
self.address = address
|
||||
|
||||
def __handshake(self):
|
||||
""" Client Handshake Request. """
|
||||
@@ -55,7 +54,7 @@ class WebSocket(object):
|
||||
|
||||
def connect(self, config_size):
|
||||
""" WebSockets connection. """
|
||||
self.protocol.connect(self.address)
|
||||
self.protocol.connect()
|
||||
self.data_buffer = b""
|
||||
self.__handshake()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user