在 Ubuntu 中获取有关 FrameBuffer 的信息时,Python 和 C 程序的结果不一致

问题描述 投票:0回答:1

所以,我想调用 ioctl

FBIOGET_FSCREENINFO
并得到结果。我有 fbsetfbset - 显示和修改帧缓冲区设备设置) 结果作为事实来源。 C 代码与 fbset 匹配的结果。 Python 代码的结果在
line_length
字段中不匹配。我已经在两个变体中转储了相同的原始字节。在
line_length
偏移上,我有值
0x00000016
。但在 Python 中它变成了
0x16000000
,而在 C 中它变成了
0x00001600
。我所说的“成为”是指当我在结构中观看它时。根据
fbset
,正确的值为
0x00001600
(12 月为 5632) 同时,
smem_len
以及
line_length
之前的所有其他值看起来都不错。所有这些值都被翻转了(在原始字节字符串中,我看到
00 00 42 00
表示
smem_len
但在变量中它的值是
00 42 00 00
。对于
visual
也是如此:raw:
02 00 00 00
,在 var:
00 00 00 02
中) 。为这两种情况挖掘原始字节(ioctl 调用的结果)
72 61 64 65 6f 6e 64 72 6d 66 62 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 00 00 00 00 00 00 00 00 00 02 00 00 00 01 00 01 00 00 00 00 00 00 16 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
为了在 Python 中映射结构,我使用了this

C代码:

#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/fb.h>
#include <sys/ioctl.h>
#include <sys/mman.h>

void print_hex_bytes(const void *ptr, size_t size) {
    const unsigned char *byte_ptr = (const unsigned char *)ptr;

    for (size_t i = 0; i < size; i++) {
        printf("%02x ", byte_ptr[i]);
    }

    printf("\n");
}

int main()
{
    int fbfd;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;

    /* Open the framebuffer device file for reading and writing. */
    fbfd = open("/dev/fb0", O_RDWR);
    if (fbfd == -1)
    {
        perror("Failed to open framebuffer device");
        exit(1);
    }
    printf("The framebuffer device opened.\n");

    /* Get variable screen information. */
    if (ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo))
    {
        close(fbfd);
        perror("Failed to read fixed information");
        exit(2);
    }
    printf("FIXED SCREEN INFOR total=%x\n", finfo);
    print_hex_bytes(&finfo, sizeof(finfo));
    print_hex_bytes(&finfo.line_length, sizeof(finfo.line_length));
    printf("id=%s size=%d hex=%032x\n", finfo.id, sizeof(finfo.id), finfo.id);
    printf("smem_start=%d size=%d hex=%016x\n", finfo.smem_start, sizeof(finfo.smem_start), finfo.smem_start);
    printf("smem_len=%d size=%d hex=%08x\n", finfo.smem_len, sizeof(finfo.smem_len), finfo.smem_len);
    printf("type=%d size=%d hex=%08x\n", finfo.type, sizeof(finfo.type), finfo.type);
    printf("type_aux=%d size=%d hex=%08x\n", finfo.type_aux, sizeof(finfo.type_aux),finfo.type_aux);
    printf("visual=%d size=%d hex=%08x\n", finfo.visual, sizeof(finfo.visual),finfo.visual);
    printf("xpanstep=%d size=%d hex=%04x\n", finfo.xpanstep, sizeof(finfo.xpanstep),finfo.xpanstep);
    printf("ypanstep=%d size=%d hex=%04x\n", finfo.ypanstep, sizeof(finfo.ypanstep),finfo.ypanstep);
    printf("ywrapstep=%d size=%d hex=%04x\n", finfo.ywrapstep, sizeof(finfo.ywrapstep),finfo.ywrapstep);
    printf("line_length=%d size=%d hex=%08x\n\n", finfo.line_length, sizeof(finfo.line_length), finfo.line_length);
    printf("mmio_start=%d size=%d\n", finfo.mmio_start, sizeof(finfo.mmio_start));
    printf("mmio_len=%d\n", finfo.mmio_len);
    printf("accel=%d\n", finfo.accel);
    printf("capabilities=%d\n", finfo.capabilities);
    printf("reserved=%d\n", finfo.reserved);

    /* Blank display. */
    if (ioctl(fbfd, FBIOBLANK, 0))
    {
        close(fbfd);
        perror("Failed to blank display");
        exit(3);
    }

    /* Close file descriptor. */
    close(fbfd);

    return 0;
}

Python代码:

import os
import fcntl
from construct import Struct, Container, Int16un, Int32un, Int64ul, Bytes

fb_bitfield_struct = Struct(
    "offset" / Int32un, # type: ignore
    "length" / Int32un, # type: ignore
    "msb_right" / Int32un, # type: ignore
)

FBIOGET_VSCREENINFO_struct = {
    "xres" : Int32un, # type: ignore # visible resolution
    "yres" : Int32un, # type: ignore 
    "xres_virtual" : Int32un, # type: ignore # virtual resolution
    "xoffset" : Int32un, # type: ignore # offset from virtual to visible
    "yoffset" : Int32un, # type: ignore # resolution
    "bits_per_pixel" : Int32un, # type: ignore # guess what
    "grayscale" : Int32un, # type: ignore # 0 = color, 1 = grayscale, >1 = FOURCC
    "red" : fb_bitfield_struct, # bitfield in fb mem if true color,
    "green" : fb_bitfield_struct, # else only length is significant
    "blue" : fb_bitfield_struct,
    "transp" : fb_bitfield_struct, # transparency
    "nonstd" : Int32un, # type: ignore # != 0 Non standard pixel format
    "activate" : Int32un, # type: ignore # see FB_ACTIVATE_*
    "height" : Int32un, # type: ignore # height of picture in mm
    "width" : Int32un, # type: ignore # width of picture in mm
    "accel_flags" : Int32un, # type: ignore # (OBSOLETE) see fb_info.flags
    # Timing: All values in pixclocks, except pixclock (of course)
    "pixclock" : Int32un, # type: ignore # pixel clock in ps (pico seconds)
    "left_margin" : Int32un, # type: ignore # time from sync to picture
    "right_margin" : Int32un, # type: ignore # time from picture to sync
    "upper_margin" : Int32un, # type: ignore # time from sync to picture
    "lower_margin" : Int32un, # type: ignore
    "hsync_len" : Int32un, # type: ignore # length of horizontal sync
    "vsync_len" : Int32un, # type: ignore # length of vertical sync
    "sync" : Int32un, # type: ignore # see FB_SYNC_*
    "vmode" : Int32un, # type: ignore # see FB_VMODE_*
    "rotate" : Int32un, # type: ignore # angle we rotate counter clockwise
    "colorspace" : Int32un, # type: ignore # colorspace for FOURCC-based modes
    "reserved" : Int32un, # type: ignore # Reserved for future compatibility
}

FBIOGET_FSCREENINFO_struct = {
    "id": Bytes(16), #identification string eg "TT Builtin" 
    "smem_start": Int64ul,  # Start of frame buffer mem
                            # (physical address) */
    "smem_len": Int32un, # Length of frame buffer mem
    "type": Int32un, # see FB_TYPE_*       
    "type_aux": Int32un, # Interleave for interleaved Planes
    "visual": Int32un, # see FB_VISUAL_*      
    "xpanstep": Int16un, # zero if no hardware panning 
    "ypanstep": Int16un, # zero if no hardware panning 
    "ywrapstep": Int16un, # zero if no hardware ywrap   
    "line_length": Int32un, # length of a line in bytes   
    "mmio_start": Int64ul, # Start of Memory Mapped I/O
                            # (physical address)
    "mmio_len": Int32un, # Length of Memory Mapped I/O 
    "accel": Int32un, # Indicate to driver which
                    # specific chip/card we have
    "capabilities": Int16un, # see FB_CAP_*        
    "reserved": Int16un, # Reserved for future compatibility
}

calls_map = {
    "FBIOGET_VSCREENINFO": {
        "address": 0x4600,
        "format": FBIOGET_VSCREENINFO_struct
    },
    "FBIOGET_FSCREENINFO": {
        "address": 0x4602,
        "format": FBIOGET_FSCREENINFO_struct
    }
}

def fbioctl_get(dev_path, call_name):
    if call_name not in calls_map:
        print(f'Call {call_name} not implemented')
        return -1
    fbfd = os.open(dev_path, os.O_RDWR)
    if fbfd == -1:
        print("Failed to open framebuffer device")
        return -1
    print("The framebuffer device opened.")

    call_map = calls_map[call_name]

    print(f'Addr={call_map["address"]}')

    data_struct = Struct(**call_map["format"])

    result_data = fcntl.ioctl(fbfd, call_map["address"], '\b0'*int(Struct.sizeof(data_struct)/2))   
    print(f'result={in_hex(result_data)} real_size={len(result_data)} size={Struct.sizeof(data_struct)}')

    os.close(fbfd)

    return data_struct.parse(result_data)

def in_hex(data):
    b_data = data
    if isinstance(data, int):
        b_data = data.to_bytes((data.bit_length() + 7) // 8)
    return ' '.join(f'{byte:02x}' for byte in b_data)

def main():
    #vinfo = fbioctl_get('/dev/fb0', 'FBIOGET_VSCREENINFO')
    finfo = fbioctl_get('/dev/fb0', 'FBIOGET_FSCREENINFO')
    for key in FBIOGET_FSCREENINFO_struct.keys():
        print(f'{key}={finfo[key]} hex={in_hex(finfo[key])}') # type: ignore

if __name__ == "__main__":
    main()

我想要的是让Python和C代码得到正确的结果,与

fbset
相同。我尝试调整缓冲区长度、类型,但没有任何帮助。

python c python-3.x operating-system framebuffer
1个回答
0
投票

您需要使用construct.ByteSwapped(subcon)交换字节顺序。 看看这个:https://construct.readthedocs.io/en/latest/api/tunneling.html#construct.ByteSwapped

Github问题:https://github.com/construct/construct/issues/1022

但是使用这个会更好:https://docs.python.org/3/library/struct.html#struct.calcsize

© www.soinside.com 2019 - 2024. All rights reserved.