diff --git a/scripts/gdb/README.md b/scripts/gdb/README.md new file mode 100644 index 0000000000..2f5eb59e85 --- /dev/null +++ b/scripts/gdb/README.md @@ -0,0 +1,20 @@ +# lvglgdb + +lvglgdb is a GDB script for LVGL. + +# Structure + +```mermaid +graph TD + lvgl["lvgl
(mem→python object)"] + gdb_cmds["gdb_cmds
(gdb commands)"] + lvglgdb["lvglgdb"] + + lvglgdb --> lvgl + lvglgdb --> gdb_cmds + gdb_cmds --> lvgl + + classDef pkg fill:white,stroke:gray + classDef core fill:white,stroke:gray + class lvglgdb,lvgl,gdb_cmds pkg +``` diff --git a/scripts/gdb/lvglgdb/__init__.py b/scripts/gdb/lvglgdb/__init__.py index f8b7bbe888..d861c390a3 100644 --- a/scripts/gdb/lvglgdb/__init__.py +++ b/scripts/gdb/lvglgdb/__init__.py @@ -1,22 +1,13 @@ -from .value import * -from .lvgl import * -from .lv_global import set_lvgl_instance -from .core.lv_obj import DumpObj -from .display.lv_display import DumpDisplayBuf -from .draw.lv_draw import InfoDrawUnit -from .misc.lv_style import InfoStyle -from .debugger import * +from .value import Value +from .lvgl import curr_inst, LVDisplay, LVDrawBuf, LVList, LVObject, dump_style_info +from . import cmds as cmds -# Debugger -Debugger() - -# Dumps -DumpObj() -DumpDisplayBuf() - -# Infos -InfoStyle() -InfoDrawUnit() - -# Set instance -set_lvgl_instance(None) +__all__ = [ + "curr_inst", + "LVDisplay", + "LVDrawBuf", + "LVList", + "LVObject", + "dump_style_info", + "Value", +] diff --git a/scripts/gdb/lvglgdb/cmds/__init__.py b/scripts/gdb/lvglgdb/cmds/__init__.py new file mode 100644 index 0000000000..aecc4e97aa --- /dev/null +++ b/scripts/gdb/lvglgdb/cmds/__init__.py @@ -0,0 +1,27 @@ +import gdb + +from .core import DumpObj +from .display import DumpDisplayBuf +from .draw import InfoDrawUnit +from .misc import InfoStyle +from .debugger import Debugger + +__all__ = [] + +# Set pagination off and python print-stack full +gdb.execute("set pagination off") +gdb.write("set pagination off\n") +gdb.execute("set python print-stack full") +gdb.write("set python print-stack full\n") + + +# Debugger +Debugger() + +# Dumps +DumpObj() +DumpDisplayBuf() + +# Infos +InfoStyle() +InfoDrawUnit() diff --git a/scripts/gdb/lvglgdb/cmds/core/__init__.py b/scripts/gdb/lvglgdb/cmds/core/__init__.py new file mode 100644 index 0000000000..854d087a70 --- /dev/null +++ b/scripts/gdb/lvglgdb/cmds/core/__init__.py @@ -0,0 +1,5 @@ +from .lv_obj import DumpObj + +__all__ = [ + "DumpObj", +] diff --git a/scripts/gdb/lvglgdb/cmds/core/lv_obj.py b/scripts/gdb/lvglgdb/cmds/core/lv_obj.py new file mode 100644 index 0000000000..9b98d58730 --- /dev/null +++ b/scripts/gdb/lvglgdb/cmds/core/lv_obj.py @@ -0,0 +1,63 @@ +import argparse +import gdb + +from lvglgdb.lvgl import curr_inst +from lvglgdb.lvgl import LVObject, dump_obj_info + + +class DumpObj(gdb.Command): + """dump obj tree from specified obj""" + + def __init__(self): + super(DumpObj, self).__init__( + "dump obj", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION + ) + + def dump_obj(self, obj: LVObject, depth=0, limit=None): + if not obj: + return + + # dump self + print(" " * depth, end="") + dump_obj_info(obj) + + if limit is not None and depth >= limit: + return + + # dump children + for child in obj.children: + self.dump_obj(child, depth + 1, limit=limit) + + def invoke(self, args, from_tty): + parser = argparse.ArgumentParser(description="Dump lvgl obj tree.") + parser.add_argument( + "-L", + "--level", + type=int, + default=None, + help="Limit the depth of the tree.", + ) + parser.add_argument( + "root", + type=str, + nargs="?", + default=None, + help="Optional root obj to dump.", + ) + try: + args = parser.parse_args(gdb.string_to_argv(args)) + except SystemExit: + return + + if args.root: + root = gdb.parse_and_eval(args.root) + root = LVObject(root) + self.dump_obj(root, limit=args.level) + else: + # dump all displays + depth = 0 + for disp in curr_inst().displays(): + print(f"Display {hex(disp)}") + for screen in disp.screens: + print(f'{" " * (depth + 1)}Screen@{hex(screen)}') + self.dump_obj(screen, depth=depth + 1, limit=args.level) diff --git a/scripts/gdb/lvglgdb/debugger.py b/scripts/gdb/lvglgdb/cmds/debugger.py similarity index 93% rename from scripts/gdb/lvglgdb/debugger.py rename to scripts/gdb/lvglgdb/cmds/debugger.py index 235ecdcddb..b29b65d9e2 100644 --- a/scripts/gdb/lvglgdb/debugger.py +++ b/scripts/gdb/lvglgdb/cmds/debugger.py @@ -57,7 +57,9 @@ class Debugger(gdb.Command): print("pydevd_pycharm module not found. Please install it using pip.") return - pydevd_pycharm.settrace(self.__host, port=self.__port, stdoutToServer=True, stderrToServer=True) + pydevd_pycharm.settrace( + self.__host, port=self.__port, stdoutToServer=True, stderrToServer=True + ) def connect_to_vscode(self): try: diff --git a/scripts/gdb/lvglgdb/cmds/display/__init__.py b/scripts/gdb/lvglgdb/cmds/display/__init__.py new file mode 100644 index 0000000000..43360b4a2f --- /dev/null +++ b/scripts/gdb/lvglgdb/cmds/display/__init__.py @@ -0,0 +1,5 @@ +from .lv_display import DumpDisplayBuf + +__all__ = [ + "DumpDisplayBuf", +] diff --git a/scripts/gdb/lvglgdb/display/lv_display.py b/scripts/gdb/lvglgdb/cmds/display/lv_display.py similarity index 51% rename from scripts/gdb/lvglgdb/display/lv_display.py rename to scripts/gdb/lvglgdb/cmds/display/lv_display.py index c203c80b85..0009134ca9 100644 --- a/scripts/gdb/lvglgdb/display/lv_display.py +++ b/scripts/gdb/lvglgdb/cmds/display/lv_display.py @@ -1,52 +1,8 @@ import argparse import gdb -from ..core.lv_obj import LVObject -from ..draw.lv_draw_buf import LVDrawBuf -from ..value import Value -from .. import lv_global - - -class LVDisplay(Value): - """LVGL display""" - - def __init__(self, disp: Value): - super().__init__(disp) - - @property - def hor_res(self) -> int: - """Get horizontal resolution in pixels""" - return int(self.super_value("hor_res")) - - @property - def ver_res(self) -> int: - """Get vertical resolution in pixels""" - return int(self.super_value("ver_res")) - - @property - def screens(self): - screens = self.super_value("screens") - for i in range(self.screen_cnt): - yield LVObject(screens[i]) - - # Buffer-related properties - @property - def buf_1(self): - """Get first draw buffer (may be None)""" - buf_ptr = self.super_value("buf_1") - return LVDrawBuf(buf_ptr) if buf_ptr else None - - @property - def buf_2(self): - """Get second draw buffer (may be None)""" - buf_ptr = self.super_value("buf_2") - return LVDrawBuf(buf_ptr) if buf_ptr else None - - @property - def buf_act(self): - """Get currently active draw buffer (may be None)""" - buf_ptr = self.super_value("buf_act") - return LVDrawBuf(buf_ptr) if buf_ptr else None +from lvglgdb.lvgl import curr_inst +from lvglgdb.lvgl import LVDrawBuf class DumpDisplayBuf(gdb.Command): @@ -80,7 +36,7 @@ class DumpDisplayBuf(gdb.Command): except SystemExit: return - display = lv_global.g_lvgl_instance.disp_default() + display = curr_inst().disp_default() if not display: print("Error: Invalid display pointer") return diff --git a/scripts/gdb/lvglgdb/cmds/draw/__init__.py b/scripts/gdb/lvglgdb/cmds/draw/__init__.py new file mode 100644 index 0000000000..9c31c8a938 --- /dev/null +++ b/scripts/gdb/lvglgdb/cmds/draw/__init__.py @@ -0,0 +1,5 @@ +from .lv_draw import InfoDrawUnit + +__all__ = [ + "InfoDrawUnit", +] diff --git a/scripts/gdb/lvglgdb/draw/lv_draw.py b/scripts/gdb/lvglgdb/cmds/draw/lv_draw.py similarity index 93% rename from scripts/gdb/lvglgdb/draw/lv_draw.py rename to scripts/gdb/lvglgdb/cmds/draw/lv_draw.py index 42befeab3b..9530a1ef59 100644 --- a/scripts/gdb/lvglgdb/draw/lv_draw.py +++ b/scripts/gdb/lvglgdb/cmds/draw/lv_draw.py @@ -1,7 +1,7 @@ import gdb -from .. import lv_global -from ..value import Value +from lvglgdb.value import Value +from lvglgdb.lvgl import curr_inst class InfoDrawUnit(gdb.Command): @@ -46,5 +46,5 @@ class InfoDrawUnit(gdb.Command): ) def invoke(self, args, from_tty): - for unit in lv_global.g_lvgl_instance.draw_units(): + for unit in curr_inst().draw_units(): self.dump_draw_unit(unit) diff --git a/scripts/gdb/lvglgdb/cmds/misc/__init__.py b/scripts/gdb/lvglgdb/cmds/misc/__init__.py new file mode 100644 index 0000000000..d8370d743a --- /dev/null +++ b/scripts/gdb/lvglgdb/cmds/misc/__init__.py @@ -0,0 +1,5 @@ +from .lv_style import InfoStyle + +__all__ = [ + "InfoStyle", +] diff --git a/scripts/gdb/lvglgdb/misc/lv_style.py b/scripts/gdb/lvglgdb/cmds/misc/lv_style.py similarity index 83% rename from scripts/gdb/lvglgdb/misc/lv_style.py rename to scripts/gdb/lvglgdb/cmds/misc/lv_style.py index 73ee0ee21b..5d86772713 100644 --- a/scripts/gdb/lvglgdb/misc/lv_style.py +++ b/scripts/gdb/lvglgdb/cmds/misc/lv_style.py @@ -1,8 +1,9 @@ import argparse import gdb -from ..value import Value -from ..core.lv_obj import LVObject +from lvglgdb.value import Value +from lvglgdb.lvgl import LVObject +from lvglgdb.lvgl import dump_style_info class InfoStyle(gdb.Command): @@ -37,9 +38,3 @@ class InfoStyle(gdb.Command): for style in LVObject(obj).styles: print(" ", end="") dump_style_info(style) - - -def dump_style_info(style: Value): - prop = int(style.prop) - value = style.value - print(f"{prop} = {value}") diff --git a/scripts/gdb/lvglgdb/display/__init__.py b/scripts/gdb/lvglgdb/display/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/scripts/gdb/lvglgdb/draw/__init__.py b/scripts/gdb/lvglgdb/draw/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/scripts/gdb/lvglgdb/lv_global.py b/scripts/gdb/lvglgdb/lv_global.py deleted file mode 100644 index e19f41c4d4..0000000000 --- a/scripts/gdb/lvglgdb/lv_global.py +++ /dev/null @@ -1,30 +0,0 @@ -from typing import Union -import gdb - -from .value import Value - -g_lvgl_instance = None - - -def set_lvgl_instance(lv_global: Union[gdb.Value, Value, None]): - global g_lvgl_instance - - if not lv_global: - try: - lv_global = Value(gdb.parse_and_eval("lv_global").address) - except gdb.error as e: - print(f"Failed to get lv_global: {e}") - return - - if not isinstance(lv_global, Value): - lv_global = Value(lv_global) - - inited = lv_global.inited - if not inited: - print( - "\x1b[31mlvgl is not initialized yet. Please call `set_lvgl_instance(None)` later.\x1b[0m" - ) - return - - from .lvgl import LVGL - g_lvgl_instance = LVGL(lv_global) diff --git a/scripts/gdb/lvglgdb/lvgl.py b/scripts/gdb/lvglgdb/lvgl.py deleted file mode 100644 index 41799fc000..0000000000 --- a/scripts/gdb/lvglgdb/lvgl.py +++ /dev/null @@ -1,44 +0,0 @@ -from typing import Iterator - -import gdb - -from .display.lv_display import LVDisplay -from .misc.lv_ll import LVList - -from .value import Value - -gdb.execute("set pagination off") -gdb.write("set pagination off\n") -gdb.execute("set python print-stack full") -gdb.write("set python print-stack full\n") - - -class LVGL: - """LVGL instance""" - - def __init__(self, lv_global: Value): - self.lv_global = lv_global.cast("lv_global_t", ptr=True) - - def displays(self) -> Iterator[LVDisplay]: - ll = self.lv_global.disp_ll - if not ll: - return - - for disp in LVList(ll, "lv_display_t"): - yield LVDisplay(disp) - - def disp_default(self): - disp_default = self.lv_global.disp_default - return LVDisplay(disp_default) if disp_default else None - - def screen_active(self): - disp = self.lv_global.disp_default - return disp.act_scr if disp else None - - def draw_units(self): - unit = self.lv_global.draw_info.unit_head - - # Iterate through all draw units - while unit: - yield unit - unit = unit.next diff --git a/scripts/gdb/lvglgdb/lvgl/__init__.py b/scripts/gdb/lvglgdb/lvgl/__init__.py new file mode 100644 index 0000000000..ac043bfbd5 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/__init__.py @@ -0,0 +1,14 @@ +from .core import LVObject, curr_inst, dump_obj_info +from .display import LVDisplay +from .draw import LVDrawBuf +from .misc import LVList, dump_style_info + +__all__ = [ + "LVObject", + "LVDisplay", + "LVDrawBuf", + "curr_inst", + "LVList", + "dump_style_info", + "dump_obj_info", +] diff --git a/scripts/gdb/lvglgdb/lvgl/core/__init__.py b/scripts/gdb/lvglgdb/lvgl/core/__init__.py new file mode 100644 index 0000000000..fa320a7fad --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/core/__init__.py @@ -0,0 +1,8 @@ +from .lv_obj import LVObject, dump_obj_info +from .lv_global import curr_inst + +__all__ = [ + "LVObject", + "curr_inst", + "dump_obj_info", +] diff --git a/scripts/gdb/lvglgdb/lvgl/core/lv_global.py b/scripts/gdb/lvglgdb/lvgl/core/lv_global.py new file mode 100644 index 0000000000..e62739725a --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/core/lv_global.py @@ -0,0 +1,107 @@ +import gdb +from typing import Optional, Union, Iterator, TYPE_CHECKING + +from lvglgdb.value import Value +from ..misc.lv_ll import LVList + +""" +LVGL global instance + +Note: + lv_global is the global instance of LVGL. + It will contain other components like display, draw unit, etc. + So if you want add a new component, please add it in this class. + And just import your component when you need it. Not expose to the whole file. +""" + +__all__ = ["curr_inst"] + +""" +Type hint for IDE, just imported at typechecking phase not in runtime. +""" +if TYPE_CHECKING: + from ..display.lv_display import LVDisplay + + +class LVGL: + """LVGL instance""" + + def __init__(self, lv_global: Value): + self.lv_global = lv_global.cast("lv_global_t", ptr=True) + + def displays(self) -> "Iterator[LVDisplay]": + ll = self.lv_global.disp_ll + if not ll: + return + + from ..display.lv_display import LVDisplay + + for disp in LVList(ll, "lv_display_t"): + yield LVDisplay(disp) + + def disp_default(self): + from ..display.lv_display import LVDisplay + + disp_default = self.lv_global.disp_default + return LVDisplay(disp_default) if disp_default else None + + def screen_active(self): + disp = self.lv_global.disp_default + return disp.act_scr if disp else None + + def draw_units(self): + unit = self.lv_global.draw_info.unit_head + + # Iterate through all draw units + while unit: + yield unit + unit = unit.next + + +class _LVGLSingleton: + __slots__ = ("_lvgl", "_ready") + + def __init__(self) -> None: + self._lvgl: Optional[object] = None + self._ready = False + + def ensure_init(self, lv_global: Union[gdb.Value, Value, None] = None) -> bool: + if self._ready: + return True + + if lv_global is None: + try: + lv_global = Value(gdb.parse_and_eval("lv_global").address) + except gdb.error as e: + print(f"Failed to get lv_global: {e}") + return False + elif not isinstance(lv_global, Value): + lv_global = Value(lv_global) + + if not lv_global.inited: + print( + "\x1b[31mlvgl is not initialized yet. " + "Please call `ensure_init()` later.\x1b[0m" + ) + return False + + self._lvgl = LVGL(lv_global) + self._ready = True + return True + + def __getattr__(self, name: str): + if not self._ready and not self.ensure_init(): + raise RuntimeError("LVGL singleton not ready") + return getattr(self._lvgl, name) + + def reset(self) -> None: + self._lvgl = None + self._ready = False + + +__curr_inst = _LVGLSingleton() + + +def curr_inst() -> _LVGLSingleton: + """Get the global instance of LVGL""" + return __curr_inst diff --git a/scripts/gdb/lvglgdb/core/lv_obj.py b/scripts/gdb/lvglgdb/lvgl/core/lv_obj.py similarity index 50% rename from scripts/gdb/lvglgdb/core/lv_obj.py rename to scripts/gdb/lvglgdb/lvgl/core/lv_obj.py index 74524ecfbb..7fbaccaedc 100644 --- a/scripts/gdb/lvglgdb/core/lv_obj.py +++ b/scripts/gdb/lvglgdb/lvgl/core/lv_obj.py @@ -1,8 +1,4 @@ -import argparse -import gdb - -from ..value import Value -from .. import lv_global +from lvglgdb.value import Value class LVObject(Value): @@ -70,64 +66,6 @@ class LVObject(Value): return self.spec_attr.children[index] if self.spec_attr else None -class DumpObj(gdb.Command): - """dump obj tree from specified obj""" - - def __init__(self): - super(DumpObj, self).__init__( - "dump obj", gdb.COMMAND_USER, gdb.COMPLETE_EXPRESSION - ) - - def dump_obj(self, obj: LVObject, depth=0, limit=None): - if not obj: - return - - # dump self - print(" " * depth, end="") - dump_obj_info(obj) - - if limit is not None and depth >= limit: - return - - # dump children - for child in obj.children: - self.dump_obj(child, depth + 1, limit=limit) - - def invoke(self, args, from_tty): - parser = argparse.ArgumentParser(description="Dump lvgl obj tree.") - parser.add_argument( - "-L", - "--level", - type=int, - default=None, - help="Limit the depth of the tree.", - ) - parser.add_argument( - "root", - type=str, - nargs="?", - default=None, - help="Optional root obj to dump.", - ) - try: - args = parser.parse_args(gdb.string_to_argv(args)) - except SystemExit: - return - - if args.root: - root = gdb.parse_and_eval(args.root) - root = LVObject(root) - self.dump_obj(root, limit=args.level) - else: - # dump all displays - depth = 0 - for disp in lv_global.g_lvgl_instance.displays(): - print(f"Display {hex(disp)}") - for screen in disp.screens: - print(f'{" " * (depth + 1)}Screen@{hex(screen)}') - self.dump_obj(screen, depth=depth + 1, limit=args.level) - - def dump_obj_info(obj: LVObject): clzname = obj.class_name coords = f"{obj.x1},{obj.y1},{obj.x2},{obj.y2}" diff --git a/scripts/gdb/lvglgdb/lvgl/display/__init__.py b/scripts/gdb/lvglgdb/lvgl/display/__init__.py new file mode 100644 index 0000000000..136d6ea665 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/display/__init__.py @@ -0,0 +1,5 @@ +from .lv_display import LVDisplay + +__all__ = [ + "LVDisplay", +] diff --git a/scripts/gdb/lvglgdb/lvgl/display/lv_display.py b/scripts/gdb/lvglgdb/lvgl/display/lv_display.py new file mode 100644 index 0000000000..e6643c572d --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/display/lv_display.py @@ -0,0 +1,45 @@ +from ..core.lv_obj import LVObject +from ..draw.lv_draw_buf import LVDrawBuf +from lvglgdb.value import Value + + +class LVDisplay(Value): + """LVGL display""" + + def __init__(self, disp: Value): + super().__init__(disp) + + @property + def hor_res(self) -> int: + """Get horizontal resolution in pixels""" + return int(self.super_value("hor_res")) + + @property + def ver_res(self) -> int: + """Get vertical resolution in pixels""" + return int(self.super_value("ver_res")) + + @property + def screens(self): + screens = self.super_value("screens") + for i in range(self.screen_cnt): + yield LVObject(screens[i]) + + # Buffer-related properties + @property + def buf_1(self): + """Get first draw buffer (may be None)""" + buf_ptr = self.super_value("buf_1") + return LVDrawBuf(buf_ptr) if buf_ptr else None + + @property + def buf_2(self): + """Get second draw buffer (may be None)""" + buf_ptr = self.super_value("buf_2") + return LVDrawBuf(buf_ptr) if buf_ptr else None + + @property + def buf_act(self): + """Get currently active draw buffer (may be None)""" + buf_ptr = self.super_value("buf_act") + return LVDrawBuf(buf_ptr) if buf_ptr else None diff --git a/scripts/gdb/lvglgdb/lvgl/draw/__init__.py b/scripts/gdb/lvglgdb/lvgl/draw/__init__.py new file mode 100644 index 0000000000..3cb93d1c11 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/draw/__init__.py @@ -0,0 +1,5 @@ +from .lv_draw_buf import LVDrawBuf + +__all__ = [ + "LVDrawBuf", +] diff --git a/scripts/gdb/lvglgdb/core/__init__.py b/scripts/gdb/lvglgdb/lvgl/draw/lv_draw.py similarity index 100% rename from scripts/gdb/lvglgdb/core/__init__.py rename to scripts/gdb/lvglgdb/lvgl/draw/lv_draw.py diff --git a/scripts/gdb/lvglgdb/draw/lv_draw_buf.py b/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_buf.py similarity index 96% rename from scripts/gdb/lvglgdb/draw/lv_draw_buf.py rename to scripts/gdb/lvglgdb/lvgl/draw/lv_draw_buf.py index 2dad2d530b..a587bc5ffe 100644 --- a/scripts/gdb/lvglgdb/draw/lv_draw_buf.py +++ b/scripts/gdb/lvglgdb/lvgl/draw/lv_draw_buf.py @@ -5,7 +5,7 @@ import gdb import numpy as np from PIL import Image -from ..value import Value +from lvglgdb.value import Value class LVDrawBuf(Value): @@ -143,7 +143,7 @@ class LVDrawBuf(Value): return False def _convert_to_image( - self, pixel_data: bytes, width: int, height: int, color_format: int + self, pixel_data: bytes, width: int, height: int, color_format: int ) -> Optional[Image.Image]: """ Convert raw pixel data to PIL Image based on color format. @@ -162,14 +162,18 @@ class LVDrawBuf(Value): # Convert RGB565 to RGB888 arr = np.frombuffer(pixel_data, dtype=np.uint8) arr = arr.reshape((height, width, 2)) - rgb565 = np.frombuffer(pixel_data, dtype=np.uint16).reshape((height, width)) + rgb565 = np.frombuffer(pixel_data, dtype=np.uint16).reshape( + (height, width) + ) r = (((rgb565 & 0xF800) >> 11) << 3).astype(np.uint8) g = ((rgb565 & 0x07E0) >> 3).astype(np.uint8) b = ((rgb565 & 0x001F) << 3).astype(np.uint8) return Image.fromarray(np.dstack((r, g, b)), "RGB") elif color_format == self._color_formats["RGB888"]: - arr = np.frombuffer(pixel_data, dtype=np.uint8).reshape(height, width, 3) + arr = np.frombuffer(pixel_data, dtype=np.uint8).reshape( + height, width, 3 + ) rgb_arr = arr[:, :, [2, 1, 0]] # BGR -> RGB return Image.fromarray(rgb_arr, "RGB") diff --git a/scripts/gdb/lvglgdb/lvgl/misc/__init__.py b/scripts/gdb/lvglgdb/lvgl/misc/__init__.py new file mode 100644 index 0000000000..bce06ebf31 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/misc/__init__.py @@ -0,0 +1,7 @@ +from .lv_ll import LVList +from .lv_style import dump_style_info + +__all__ = [ + "LVList", + "dump_style_info", +] diff --git a/scripts/gdb/lvglgdb/misc/lv_ll.py b/scripts/gdb/lvglgdb/lvgl/misc/lv_ll.py similarity index 97% rename from scripts/gdb/lvglgdb/misc/lv_ll.py rename to scripts/gdb/lvglgdb/lvgl/misc/lv_ll.py index 3f68c64743..abb038c88c 100644 --- a/scripts/gdb/lvglgdb/misc/lv_ll.py +++ b/scripts/gdb/lvglgdb/lvgl/misc/lv_ll.py @@ -1,7 +1,7 @@ from typing import Union import gdb -from ..value import Value +from lvglgdb.value import Value class LVList(Value): diff --git a/scripts/gdb/lvglgdb/lvgl/misc/lv_style.py b/scripts/gdb/lvglgdb/lvgl/misc/lv_style.py new file mode 100644 index 0000000000..eb621c3a37 --- /dev/null +++ b/scripts/gdb/lvglgdb/lvgl/misc/lv_style.py @@ -0,0 +1,7 @@ +from lvglgdb.value import Value + + +def dump_style_info(style: Value): + prop = int(style.prop) + value = style.value + print(f"{prop} = {value}") diff --git a/scripts/gdb/lvglgdb/misc/__init__.py b/scripts/gdb/lvglgdb/misc/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/scripts/gdb/lvglgdb/value.py b/scripts/gdb/lvglgdb/value.py index 9fad1bab20..e215feab31 100644 --- a/scripts/gdb/lvglgdb/value.py +++ b/scripts/gdb/lvglgdb/value.py @@ -4,7 +4,7 @@ from typing import Optional, Union class Value(gdb.Value): - def __init__(self, value: Union[gdb.Value, 'Value']): + def __init__(self, value: Union[gdb.Value, "Value"]): super().__init__(value) def __getitem__(self, key): @@ -19,14 +19,18 @@ class Value(gdb.Value): return Value(super().__getattribute__(key)) return Value(super().__getitem__(key)) - def cast(self, type_name: Union[str, gdb.Type], ptr: bool = False) -> Optional['Value']: + def cast( + self, type_name: Union[str, gdb.Type], ptr: bool = False + ) -> Optional["Value"]: try: - gdb_type = gdb.lookup_type(type_name) if isinstance(type_name, str) else type_name + gdb_type = ( + gdb.lookup_type(type_name) if isinstance(type_name, str) else type_name + ) if ptr: gdb_type = gdb_type.pointer() return Value(super().cast(gdb_type)) except gdb.error: return None - def super_value(self, attr: str) -> 'Value': + def super_value(self, attr: str) -> "Value": return self[attr]