{"id":473420,"date":"2025-09-02T16:27:51","date_gmt":"2025-09-02T16:27:51","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=473420"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=473420","title":{"rendered":"<span>GPIO \u2014 \u0442\u043e\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441, \u0430 \u0442\u0430\u043a\u0436\u0435 QEMU GPIODEV \u0438 GUSE<\/span>"},"content":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041a\u043e\u0433\u0434\u0430-\u0442\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u041f\u041e <a href=\"https:\/\/www.yadro.com\/?utm_source=habr&amp;utm_medium=referral&amp;utm_campaign=qemu_GPIO_P2_article310725\" rel=\"noopener noreferrer nofollow\">\u0432 YADRO<\/a> \u043c\u043d\u0435 \u0437\u0430\u0434\u0430\u043b\u0438 \u0432\u043e\u043f\u0440\u043e\u0441: \u00ab\u0410 \u043a\u0430\u043a \u0441 \u044d\u0442\u0438\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c?\u00bb. \u0420\u0435\u0447\u044c \u0448\u043b\u0430 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043e I2C \u0434\u043b\u044f QEMU, \u0430 \u043d\u0435 GPIO. \u0418 \u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0431\u044b\u043b \u043e\u0434\u0435\u0440\u0436\u0438\u043c \u0438\u0434\u0435\u0435\u0439 \u00ab\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0433\u043e\u00bb \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 QEMU \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435 \u0436\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u0430\u043a \u0438 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u0435\u0435? \u041d\u0435 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0442\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f \u043f\u043e\u0441\u044b\u043b\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e QMP, \u0430 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u0438 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u044b\u0439 gpioset\/gpioget \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 libgpiod \u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0441 \u044f\u0434\u0440\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u0437 tools\/gpio.<\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043b\u0438 \u044d\u0442\u043e \u0443 \u043c\u0435\u043d\u044f? \u0414\u0430, \u043d\u043e \u043a\u0430\u043a\u043e\u0439 \u0446\u0435\u043d\u043e\u0439\u2026<\/p>\n<h3>QEMU GPIODEV: \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u044d\u043d\u0442\u0440\u043e\u043f\u0438\u0438 \u2014 \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u0438 \u043f\u043b\u043e\u0445\u043e. <a href=\"https:\/\/habr.com\/ru\/companies\/yadro\/articles\/925860\/\" rel=\"noopener noreferrer nofollow\">\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e QMP \u2014 \u044d\u0442\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u043d\u0438\u0447\u0435\u0433\u043e. \u041d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 (\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u0443\u044e), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c\/\u043f\u0438\u0441\u0430\u0442\u044c \u0438 \u0443\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 poll() \/ pselect() \/ select() \/ epoll() \/ read().\u00a0<\/p>\n<p>\u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 GPIO \u043d\u0443\u0436\u0435\u043d \u00ab\u043a\u043b\u0435\u0439\u00bb, \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043d\u0430 \u0442\u043e\u0442, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441 chardev \u2014 \u043c\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0435\u0433\u043e \u043f\u0440\u044f\u043c\u043e \u0432 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 QEMU. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u00ab\u043a\u043b\u0435\u044f\u00bb \u2014 gpiodev. \u0412\u043e\u0442 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 GPIO UAPI \u0432 Linux:<\/p>\n<ul>\n<li>\n<p>\u0441\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u0438\u043d\u0438\u0439, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043b\u0438\u043d\u0438\u0438,<\/p>\n<\/li>\n<li>\n<p>\u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u0438\u043d\u0438\u0438,<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043b\u0438\u043d\u0438\u0438 (\u0432\u0445\u043e\u0434\/\u0432\u044b\u0445\u043e\u0434, \u0437\u0430\u043f\u0440\u043e\u0441\/\u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u0435).<\/p>\n<\/li>\n<\/ul>\n<p>\u00ab\u041a\u043b\u0435\u0439\u00bb \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0433\u0440\u0443\u043f\u043f, \u043f\u0435\u0440\u0432\u0430\u044f \u2014 \u044d\u0442\u043e \u0438\u043d\u0434\u0438\u0432\u0438\u0434\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f GPIO \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 gpiodev \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e:<\/p>\n<ul>\n<li>\n<p>LineInfoHandler() \u2014 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043b\u0438\u043d\u0438\u0438: \u0438\u043c\u044f, \u0444\u043b\u0430\u0433\u0438 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c,<\/p>\n<\/li>\n<li>\n<p>LineGetValueHandler() \u2014 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u0438\u043d\u0438\u0438: \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 0 \u0438\u043b\u0438 1,<\/p>\n<\/li>\n<li>\n<p>LineSetValueHandler() \u2014 \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u0438\u043d\u0438\u0438: 0 \u0438\u043b\u0438 1.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 GPIO UAPI \u043d\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 LineGetMultiValueHandler() \u0438 LineSetMultiValueHandler() \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u043d\u0438\u0439, \u043d\u043e \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c.<\/p>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u044b \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u043c \u0447\u0438\u043f\u043e\u043c \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u0441 gpiodev:<\/p>\n<pre><code>\/* qemu\/include\/gpiodev\/gpio-fe.h *\/ struct GpioBackend {     Gpiodev *gpio;     LineInfoHandler *line_info;     LineGetValueHandler *get_value;     LineSetValueHandler *set_value;     void *opaque; };<\/code><\/pre>\n<p>\u0412\u0442\u043e\u0440\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u2014 \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u044c GPIO \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 gpiodev \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u043b\u043e\u043a\u0438 QEMU, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u00ab\u0432\u043d\u0435\u0448\u043d\u0438\u0439\u00bb \u0434\u0430\u0442\u0447\u0438\u043a I2C:<\/p>\n<ul>\n<li>\n<p>qemu_gpio_fe_line_event() \u2014 \u043b\u0438\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430 \u0441\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435,<\/p>\n<\/li>\n<li>\n<p>qemu_gpio_fe_config_event() \u2014 \u043b\u0438\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430 \u0441\u0432\u043e\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0430\u043c\u044b\u0435 \u043f\u0435\u0440\u0432\u044b\u0435 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u044b gpiodev \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0438\u0437 <em>uapi\/linux\/gpio.h<\/em> \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u043d\u043e \u043f\u043e\u0437\u0436\u0435 \u044f \u043e\u0442 \u043d\u0438\u0445 \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 gpiodev \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0439\u0442\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b.<\/p>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f gpiodev \u043a\u0430\u0436\u0434\u044b\u0439 \u0447\u0438\u043f \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code>bool qemu_gpio_fe_init(GpioBackend *b, Gpiodev *s, uint32_t nlines,                        const char *name, const char *label,                        Error **errp);<\/code><\/pre>\n<p>\u0427\u0438\u043f \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0441\u0432\u043e\u0435 \u0438\u043c\u044f, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u0438\u043d\u0438\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c <em>-gpiodev<\/em>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435:<\/p>\n<pre><code>void qemu_gpio_fe_set_handlers(GpioBackend *b,                                LineInfoHandler *line_info,                                LineGetValueHandler *get_value,                                LineSetValueHandler *set_value,                                void *opaque);<\/code><\/pre>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/185\/d30\/4cb\/185d304cb152d72d56fe774bf85ede9d.png\" alt=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 GPIODEV\" title=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 GPIODEV\" width=\"453\" height=\"387\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/185\/d30\/4cb\/185d304cb152d72d56fe774bf85ede9d.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/185\/d30\/4cb\/185d304cb152d72d56fe774bf85ede9d.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 GPIODEV<\/figcaption><\/div>\n<\/figure>\n<p>\u042d\u0442\u043e\u0433\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0446\u0435\u043b\u0435\u0439. \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f ASPEED \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<blockquote>\n<p><strong>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p>qemu v10.0.0:<\/p>\n<ul>\n<li>\n<p>\u043c\u043e\u0434\u0435\u043b\u0438 MMIO\/PCI GPIO,<\/p>\n<\/li>\n<li>\n<p>\u043c\u0430\u0448\u0438\u043d\u0430 RISC-V virt \u0441 MMIO GPIO \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 dtb,<\/p>\n<\/li>\n<li>\n<p>gpiodev \u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u0430\u043c\u0438 CHARDEV, CUSE, GUSE,<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>buildroot 2025.02.2 \u0432\u0430\u043d\u0438\u043b\u044c\u043d\u044b\u0439 (\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438),<\/p>\n<\/li>\n<li>\n<p>qemu-gpio-tools \u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0434\u043b\u044f chardev,<\/p>\n<\/li>\n<li>\n<p>libgpiod \u2014 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f CUSE \u0438 GUSE,<\/p>\n<\/li>\n<li>\n<p>libfuse \u2014 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 GUSE,<\/p>\n<\/li>\n<li>\n<p>linux v6.12: <\/p>\n<ul>\n<li>\n<p>\u043f\u0430\u0442\u0447\u0438 \u0434\u043b\u044f dtb-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0439,<\/p>\n<\/li>\n<li>\n<p>\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f QEMU MMIO\/PCIE GPIO,<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0434\u0443\u043b\u044c GUSE.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground?branch=nshubin%2Fgpiodev\" rel=\"noopener noreferrer nofollow\">\u2192 \u0421\u043a\u0430\u0447\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442-\u043e\u0431\u0435\u0440\u0442\u043a\u0443<\/a> (\u0447\u0430\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0443\u0436\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f GUSE)<\/p>\n<\/blockquote>\n<h3>\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430<\/h3>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0435\u043c ASPEED ast2600-evb \u2014 \u043e\u0434\u043d\u043e\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440 (SBC), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 (\u0443\u0432\u0435\u0440\u044f\u044e, \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u2014 \u0441\u043b\u0435\u0434\u0438\u0442\u0435 \u0437\u0430 \u043d\u0430\u0448\u0438\u043c \u0431\u043b\u043e\u0433\u043e\u043c) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u043e \u044d\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u0432 QEMU \u043c\u0430\u0448\u0438\u043d\u043e\u0439 \u0441 \u0441\u0430\u043c\u044b\u043c \u0448\u0438\u0440\u043e\u043a\u0438\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0439\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u0432 ASPEED ast2600-evb \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u0440\u0435\u0436\u0438\u043c\u0430 I2C slave.<\/p>\n<p>\u041f\u0440\u0438\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e <a href=\"https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/\" rel=\"noopener noreferrer nofollow\">\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b<\/a> \u0434\u043b\u044f ASPEED, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e QEMU:<\/p>\n<pre><code>$ git clone -b nshubin\/qemu-gpiodev https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground $ git submodule update --init --depth 1 -- qemu $ make .build-qemu $ wget https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/68d857b3-f61b-482e-b9e4-70e7cb551ea4\/download -O initramfs.cpio.xz $ wget https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/acd48054-e894-40c4-a351-bafb447353bb\/download -O zImage $ wget https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/8c4d2cec-12c9-4cdb-ba41-cf564abced95\/download -O aspeed-ast2600-evb.dtb<\/code><\/pre>\n<p>\u041e\u0431\u0449\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430:<\/p>\n<pre><code>host $ build-qemu\/qemu-system-arm -M ast2600-evb,bmc-console=uart5 \\     -kernel buildroot_aspeed\/build\/linux-6.12.17\/arch\/arm\/boot\/zImage \\     -dtb .\/buildroot_aspeed\/images\/aspeed-ast2600-evb.dtb \\     -initrd buildroot_aspeed\/images\/rootfs.cpio.xz \\     -nographic -serial mon:stdio<\/code><\/pre>\n<p>\u041d\u0430\u0431\u043e\u0440 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f gpiodev \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u043e\u0439 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435.<\/p>\n<h3>CHARDEV<\/h3>\n<p>\u041d\u0430\u0447\u043d\u0443 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0439\u0434\u0443 \u043a \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e ASPEED ast2600-evb: <\/p>\n<pre><code># \u043d\u0435\u0431\u0445\u043e\u0434\u0438\u043c\u044b qemu-gpio-tools host $ make .build-qemu-gpio-tools host $ build-qemu\/qemu-system-arm -M ast2600-evb,bmc-console=uart5 \\ -kernel buildroot_aspeed\/build\/linux-6.12.17\/arch\/arm\/boot\/zImage \\ -dtb .\/buildroot_aspeed\/images\/aspeed-ast2600-evb.dtb \\ -initrd buildroot_aspeed\/images\/rootfs.cpio.xz \\ -nographic -serial mon:stdio \\ -gpiodev chardev,id=aspeed-gpio0,chardev=gpio0 \\ -chardev socket,path=\/tmp\/gpio0,id=gpio0,server=on,wait=off \\ -d guest_errors<\/code><\/pre>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0445\u043e\u0434\u043e\u0432\/\u0432\u044b\u0445\u043e\u0434\u043e\u0432 \u0434\u043b\u044f aspeed-gpio0:<\/p>\n<pre><code>host $ qemu-gpio-tools\/lsgpio -n \/tmp\/gpio0 sending 0x8044b401 GPIO chip: aspeed-gpio0, \"ASPEED GPIO\", 208 GPIO lines         line  0: \"gpioA0\" unused [input] [...]         line 207: \"gpioZ7\" unused [input]<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u0445\u043e\u0434\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u043e\u0437\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0445\u043e\u0441\u0442\u0430:<\/p>\n<pre><code>host $ .\/gpio-hammer -n \/tmp\/gpio0 -o 8   qemu # gpiomon -c 0 8 gpio_reg_direction: 0x0 0x0   36.791326811rising  gpiochip0 8 37.679910405falling gpiochip0 8 38.568927503rising  gpiochip0 8 39.457922388falling gpiochip0 8 40.346842481rising  gpiochip0 8 [...]<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043b\u0438\u043d\u0438\u0438, \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 \u0433\u043e\u0441\u0442\u0435\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0445\u043e\u0441\u0442\u0435:<\/p>\n<pre><code>qemu # gpioset -c 0 8=0 ^C qemu # gpioset -c 0 8=1 ^C   host $ .\/gpio-event-mon -n \/tmp\/gpio0 -o 8 No flags specified, listening on both rising and falling edges Monitoring line 8 on \/tmp\/gpio0 Initial line value: 0 GPIO EVENT at 572196930648 on line 8 (0|0) falling edge GPIO EVENT at 574302333416 on line 8 (0|0) rising edge<\/code><\/pre>\n<p>gpiodev-chardev \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043d\u0430\u0434 -chardev, \u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0440\u0445 \u043b\u044e\u0431\u043e\u0433\u043e \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0430, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e -chardev: stdio, serial, pipe, pty, socket \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u2014 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e -chardev socket \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b qemu-gpio-tools, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043f\u043e\u0432\u0435\u0440\u0445 UNIX-\u0441\u043e\u043a\u0435\u0442\u0430 (\u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u0438\u0437 \u043d\u0430\u0431\u043e\u0440\u0430 tools\/gpio \u0432 Linux). \u042d\u0442\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0435 \u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u044b\u043b\u043e \u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e socat, \u043d\u043e, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435.<\/p>\n<figure class=\"full-width\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/201\/64f\/a0b\/20164fa0b9738822baec1f1adc45a3cf.png\" alt=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CHARDEV\" title=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CHARDEV\" width=\"551\" height=\"416\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/201\/64f\/a0b\/20164fa0b9738822baec1f1adc45a3cf.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/201\/64f\/a0b\/20164fa0b9738822baec1f1adc45a3cf.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CHARDEV<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 \u0441\u0438\u043b\u0430, \u0438 \u0441\u043b\u0430\u0431\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u0430: \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0443\u0442\u0438\u043b\u0438\u0442\u044b, \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043c\u044b \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c.<\/p>\n<h3>FUSE<\/h3>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u00ab\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0433\u043e\u00bb \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 i2c-dev, gpiochip, spidev \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b ioctl() \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432\u0441\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0437\u0430\u0432\u044f\u0437\u0430\u043d\u044b \u043d\u0430 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438.\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0447\u0442\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e, \u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0432\u044b\u0437\u0432\u0430\u0442\u044c\u00a0 ioctl() \u044f \u043d\u0435 \u0437\u043d\u0430\u044e \u2014 \u044d\u0442\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0443 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0438\u043b\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u044f\u0434\u0440\u0430. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u044f\u0434\u0440\u0430.<\/p>\n<p>\u0418 \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f FUSE, \u0430 \u0442\u043e\u0447\u043d\u0435\u0435, \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c CUSE (Userland Character Device Library).<\/p>\n<h4>CUSE<\/h4>\n<p>\u0422\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u043e \u043d\u0430\u0447\u043d\u0443 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e \u043f\u043b\u0430\u0442\u044b ASPEED ast2600-evb \u0432 QEMU \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c gpiodev \u0447\u0435\u0440\u0435\u0437 CUSE:<\/p>\n<pre><code># \u043d\u0435\u0431\u0445\u043e\u0434\u0438\u043c libgpiod \u0441 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\u043c\u0438 host $ make .build-libgpiod host $ sudo build-qemu\/qemu-system-arm -M ast2600-evb,bmc-console=uart5 \\ -kernel buildroot_aspeed\/build\/linux-6.12.17\/arch\/arm\/boot\/zImage \\ -dtb .\/buildroot_aspeed\/images\/aspeed-ast2600-evb.dtb \\ -initrd buildroot_aspeed\/images\/rootfs.cpio.xz \\ -nographic -serial mon:stdio \\ -gpiodev cuse,id=aspeed-gpio0,devname=gpiochip10 \\ -d guest_errors<\/code><\/pre>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0445\u043e\u0434\u043e\u0432\/\u0432\u044b\u0445\u043e\u0434\u043e\u0432 \u0434\u043b\u044f aspeed-gpio0:<\/p>\n<pre><code>host $ sudo libgpiod\/tools\/gpioinfo -c 10         line   0:       \"gpioA0\"                input         [...]         line 207:       \"gpioZ7\"                input<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0433\u043e\u0441\u0442\u044f:<\/p>\n<pre><code>host $ sudo libgpiod\/tools\/gpioset -t 0 -c 10 8=1 9=1 10=1 host $ sudo libgpiod\/tools\/gpioset -t 0 -c 10 8=0 9=0 10=0   qemu # gpiomon -c 0 8 9 10 69.422108579rising  gpiochip0 9 69.422015591rising  gpiochip0 8 69.422173796rising  gpiochip0 10 124.508747142   falling gpiochip0 9 124.508841782   falling gpiochip0 10 124.508572457   falling gpiochip0 8<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0445\u043e\u0441\u0442\u0430:<\/p>\n<pre><code>qemu # gpioset -t 0 -c 0 8=1 9=1 10=1 qemu # gpioset -t 0 -c 0 8=0 9=0 10=0   host $ sudo libgpiod\/tools\/gpiomon -c 10 8 9 10 1749204303.043403870rising  aspeed-gpio0 8 1749204303.043546291rising  aspeed-gpio0 9 1749204303.043650331rising  aspeed-gpio0 10 1749204308.437501487falling aspeed-gpio0 8 1749204308.437650077falling aspeed-gpio0 9 1749204308.437757098falling aspeed-gpio0 10<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <strong>sudo<\/strong>: \u043d\u0430\u043c \u043d\u0443\u0436\u0435\u043d \u0434\u043e\u0441\u0442\u0443\u043f \u043a \/dev\/cuse, \u0430 \u0437\u0430\u0442\u0435\u043c \u2014 \u043a \/dev\/gpiochip10. \u0414\u043e\u0441\u0442\u0443\u043f \u043c\u043e\u0436\u043d\u043e \u043e\u0431\u0435\u0441\u043f\u0435\u0447\u0438\u0442\u044c\u00a0\u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e udev-rules \u0438\u043b\u0438 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0438\u0437\u0430\u0446\u0438\u0438. \u041a\u043e\u0434 \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u0432 \u0444\u0430\u0439\u043b\u0435 qemu\/gpiodev\/gpio-cuse.c \u2014 \u043d\u0430 \u043c\u043e\u0439 \u0432\u0437\u0433\u043b\u044f\u0434, \u043e\u043d \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 GPIO UAPI. \u0422\u0435\u043c \u0431\u043e\u043b\u0435\u0435, \u043c\u044b \u043d\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c CUSE_UNRESTRICTED_IOCTL, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u0438\u043b\u044c\u043d\u043e \u0443\u0441\u043b\u043e\u0436\u043d\u044f\u0435\u0442 ioctl(), \u0434\u0435\u043b\u0430\u044f \u0435\u0433\u043e \u0434\u0432\u0443\u0445- \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0442\u0440\u0435\u0445\u0441\u0442\u0430\u0434\u0438\u0439\u043d\u044b\u043c. \u0412 \u043e\u0431\u0449\u0435\u043c \u0432\u0438\u0434\u0435 \u044d\u0442\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:  <\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1d\/35f\/5b2\/c1d35f5b206d26c9125762ac1c7b817b.png\" alt=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CUSE\" title=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CUSE\" width=\"425\" height=\"632\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/c1d\/35f\/5b2\/c1d35f5b206d26c9125762ac1c7b817b.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/c1d\/35f\/5b2\/c1d35f5b206d26c9125762ac1c7b817b.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CUSE<\/figcaption><\/div>\n<\/figure>\n<p>\u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u043a \u0438\u0442\u043e\u0433\u0443 \u0438 \u043d\u0430\u0447\u043d\u0435\u043c \u0441 \u043f\u0440\u0430\u0432\u043e\u043a, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0443\u0436\u043d\u044b \u0434\u043b\u044f libgpiod:<\/p>\n<ul>\n<li>\n<p>libgpiod \u2014 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0430\u0440\u0430\u043d\u043e\u0438\u0434\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u00ab\u0443\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c\u00bb \u0435\u0435 \u0432\u0438\u0434\u0435\u0442\u044c gpiochip \u043f\u043e \u043d\u0435\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \u043f\u0443\u0442\u044f\u043c \u0432 \/sys\/class\/cuse, \u0441\u043e\u0432\u043c\u0435\u0441\u0442\u043d\u043e \u0441\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u044b\u043c \/sys\/bus\/gpio,<\/p>\n<\/li>\n<li>\n<p>\u0437\u0430\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0435 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u0442 \u0436\u0435 \u0441\u0430\u043c\u044b\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440 \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043b\u0438\u043d\u0438\u0439, \u0442\u0430\u043a \u043a\u0430\u043a \u0443 CUSE \u043d\u0435\u0442 \u043c\u0435\u0445\u0430\u043d\u0438\u0437\u043c\u043e\u0432 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043d\u043e\u0432\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0445 \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440\u043e\u0432.<\/p>\n<\/li>\n<\/ul>\n<p>\u0427\u0442\u043e \u0441\u0430\u043c\u043e\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e\u0435, \u043f\u043e\u043a\u0430 \u0443 \u043d\u0430\u0441 \u0432 \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u0438 \u00ab\u043f\u0440\u0438\u0436\u0438\u043b\u0441\u044f\u00bb \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u0432\u0430\u0440\u0438\u0430\u043d\u0442. \u0421\u043a\u043e\u0440\u0435\u0435 \u0432\u0441\u0435\u0433\u043e, \u044d\u0442\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043e \u0441 \u0442\u0435\u043c, \u0447\u0442\u043e \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0435 \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u043e\u0432 \u0434\u043b\u044f \u043e\u0434\u043d\u043e\u0433\u043e \u0447\u0438\u043f\u0430, \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d Python, \u0430 \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0430 CUSE \u0435\u0441\u0442\u044c \u0443\u0436\u0435 \u0434\u0430\u0432\u043d\u043e \u0438 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0432\u043e \u0432\u0441\u0435\u0445 \u0434\u0438\u0441\u0442\u0440\u0438\u0431\u0443\u0442\u0438\u0432\u0430\u0445.<\/p>\n<h4>GUSE<\/h4>\n<p>\u041d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u0432\u0435\u0442\u043a\u0443 \u0432 libgpiod, \u0441\u043e\u0431\u0440\u0430\u0442\u044c libfuse \u0438 \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043b\u044f \u044f\u0434\u0440\u0430 \u0445\u043e\u0441\u0442\u0430. \u0412\u043e\u043e\u0431\u0449\u0435, \u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043d\u0435 \u0440\u0435\u043a\u043e\u043c\u0435\u043d\u0434\u0443\u044e, \u0442\u0430\u043a \u043a\u0430\u043a \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u043e \u043c\u043e\u0434\u0443\u043b\u044f \u044f\u0434\u0440\u0430 \u043d\u0430 \u0443\u0440\u043e\u0432\u043d\u0435 PoC \u2014 \u0442\u043e\u043b\u044c\u043a\u043e \u0435\u0441\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u0441\u0438\u043b\u044c\u043d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0438 \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u0435 QEMU.\u00a0<\/p>\n<p>\u042f \u0441\u043e\u0431\u0440\u0430\u043b GUSE \u043d\u0430 <a href=\"https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground?branch=nshubin%2Fgpiodev-guse\" rel=\"noopener noreferrer nofollow\">\u043e\u0442\u0434\u0435\u043b\u044c\u043d\u043e\u0439 \u0432\u0435\u0442\u043a\u0435<\/a>. libfuse \u0438 guse \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e, \u0442\u0430\u043a \u043a\u0430\u043a \u043f\u0435\u0440\u0432\u044b\u0439 \u0438\u0434\u0435\u0442 \u0434\u043b\u044f QEMU, \u0430 \u0432\u0442\u043e\u0440\u043e\u0439 \u043c\u044b \u0433\u0440\u0443\u0437\u0438\u043c \u0432 \u044f\u0434\u0440\u043e \u0445\u043e\u0441\u0442\u0430:<\/p>\n<pre><code># QEMU \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0440\u0430\u0442\u044c host $ rm -rf build-qemu &amp;&amp; make .build-qemu # libgpiod \u043d\u0443\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0441\u043e\u0431\u0440\u0430\u0442\u044c host $ make -C libgpiod clean &amp;&amp; make .build-libgpiod # \u041c\u043e\u0434\u0443\u043b\u044c \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u043e\u0434 \u0442\u0435\u043a\u0443\u0449\u0435\u0435 \u044f\u0434\u0440\u043e host $ make -C guse # \u0418\u043b\u0438 \u043f\u043e\u0434 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u0439 \u043b\u0438\u043d\u0443\u043a\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0431\u0443\u0434\u0435\u043c \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0442\u044c \u0432\u043d\u0443\u0442\u0440\u0438 QEMU host $ make guse\/guse.ko # \u0412 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c \u043c\u043e\u0434\u0443\u043b\u044c \u0432 \u044f\u0434\u0440\u043e (\u0438\u043b\u0438 \u0442\u0435\u043a\u0443\u0449\u0435\u0435, \u0430 \u0435\u0449\u0435 \u043b\u0443\u0447\u0448\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 QEMU) host\/guest $ sudo insmod guse.ko host\/guest $ sudo build-qemu\/qemu-system-arm -M ast2600-evb,bmc-console=uart5 \\ -kernel buildroot_aspeed\/build\/linux-6.12.17\/arch\/arm\/boot\/zImage \\ -dtb .\/buildroot_aspeed\/images\/aspeed-ast2600-evb.dtb \\ -initrd buildroot_aspeed\/images\/rootfs.cpio.xz \\ -nographic -serial mon:stdio \\ -gpiodev guse,id=aspeed-gpio0,devname=gpiochip10 \\ -d guest_errors<\/code><\/pre>\n<p>\u041f\u0440\u0438\u043c\u0435\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u044f \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043d\u0435 \u0431\u0443\u0434\u0443, \u0442\u0430\u043a \u043a\u0430\u043a \u043e\u043d\u0438 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u044b CUSE.<\/p>\n<figure class=\"\"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/82c\/8e2\/3b9\/82c8e23b9bcbcdf1381cd90833b27d00.png\" alt=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 GUSE\" title=\"\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 GUSE\" width=\"410\" height=\"614\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/82c\/8e2\/3b9\/82c8e23b9bcbcdf1381cd90833b27d00.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/82c\/8e2\/3b9\/82c8e23b9bcbcdf1381cd90833b27d00.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 GUSE<\/figcaption><\/div>\n<\/figure>\n<p>\u041a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u043e, \u0434\u044c\u044f\u0432\u043e\u043b \u043a\u0440\u043e\u0435\u0442\u0441\u044f \u0432 \u0434\u0435\u0442\u0430\u043b\u044f\u0445.<\/p>\n<p>\u041d\u0430\u0447\u043d\u0443 \u0441 \u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u043d\u043e\u0432\u043e\u0441\u0442\u0435\u0439: \u0434\u043b\u044f libgpiod \u043d\u0443\u0436\u043d\u0430 \u0432\u0441\u0435\u0433\u043e \u043e\u0434\u043d\u0430 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0430\u044f \u043f\u0440\u0430\u0432\u043a\u0430, \u0447\u0442\u043e\u0431\u044b \u00ab\u0443\u0433\u043e\u0432\u043e\u0440\u0438\u0442\u044c\u00bb \u0435\u0433\u043e \u0432\u0438\u0434\u0435\u0442\u044c \/sys\/class\/guse. \u042f \u0443\u0436\u0435 \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b, \u0447\u0442\u043e libgpiod \u2014 \u043f\u0430\u0440\u0430\u043d\u043e\u0438\u0434\u0430\u043b\u044c\u043d\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430. \u0414\u0435\u043b\u043e \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0440\u0430\u0437\u043d\u0438\u0446\u044b \u043c\u0435\u0436\u0434\u0443 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u043c \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e\u043c \u0438 \u044d\u043c\u0443\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0434\u043b\u044f libgpiod \u043f\u0440\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043d\u0435\u0442.<\/p>\n<p>\u0410 \u043f\u043b\u043e\u0445\u0438\u0435 \u043d\u043e\u0432\u043e\u0441\u0442\u0438 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u044e\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c:<\/p>\n<ul>\n<li>\n<p>\u0441\u0434\u0435\u043b\u0430\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u043c\u043e\u0434\u0443\u043b\u044c \u044f\u0434\u0440\u0430 guse, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0443\u043c\u0435\u0435\u0442 \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0442\u044c <em>GPIO_V2_GET_LINE_IOCTL<\/em> \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441 \u0437\u0430\u043f\u0440\u043e\u0448\u0435\u043d\u043d\u044b\u043c\u0438 \u043b\u0438\u043d\u0438\u044f\u043c\u0438 \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0439 \u0434\u0435c\u043a\u0440\u0438\u043f\u0442\u043e\u0440,<\/p>\n<\/li>\n<li>\n<p>\u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0443 guse \u0432 libfuse.<\/p>\n<\/li>\n<\/ul>\n<p>\u0418\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0447\u0430\u0441\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0439 FUSE \u043c\u043e\u0434\u0443\u043b\u044e \u044f\u0434\u0440\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u0430, \u043e\u043d \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0441\u044f \u0441\u0442\u0440\u0430\u043d\u043d\u044b\u043c \u2014 \u043d\u043e\u0432\u044b\u0435 \u0444\u0430\u0439\u043b\u044b \u0432 FUSE \u043d\u0430\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043d\u0435\u043b\u044c\u0437\u044f, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043d\u0435 \u043f\u0440\u0438\u0448\u043b\u043e\u0441\u044c \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u0444\u043b\u0430\u0433 \u0432 inode, \u0447\u0442\u043e\u0431\u044b \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c \u0444\u0430\u0439\u043b\u043e\u0432\u044b\u0435 \u0434\u0435\u0441\u043a\u0440\u0438\u043f\u0442\u043e\u0440\u044b \u0434\u043b\u044f gpiochip \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043b\u044f GPIO_V2_GET_LINE_IOCTL.<\/p>\n<p>\u0412\u043f\u0440\u043e\u0447\u0435\u043c, \u043c\u043d\u0435 \u044d\u0442\u043e \u0431\u044b\u043b\u043e \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u043e \u043f\u043e\u0447\u0442\u0438 \u0441 \u0441\u0430\u043c\u043e\u0433\u043e \u043d\u0430\u0447\u0430\u043b\u0430, \u043d\u043e \u0432\u0441\u0435 \u0436\u0435 \u044f \u0440\u0435\u0448\u0438\u043b \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u0438\u043b\u0438 \u043c\u0435\u043d\u0435\u0435 \u0440\u0430\u0431\u043e\u0447\u0438\u0439 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f GUSE.<\/p>\n<h3>\u041c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f VIRTUAL MMIO\/PCI GPIO<\/h3>\n<p>\u041d\u0430\u0447\u043d\u0435\u043c \u0441 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u0438 \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438. \u0422\u0430\u043a \u043a\u0430\u043a \u0443 \u043d\u0430\u0441 \u043e\u0431\u0449\u0438\u0439 \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442 \u0434\u043b\u044f MMIO- \u0438 PCI-\u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0443 \u043d\u0438\u0445 \u0442\u043e\u0436\u0435 \u043e\u0431\u0449\u0430\u044f:<\/p>\n<pre><code>static void gpio_realize(DeviceState *dev, Error **errp) {     GpioState *s = GPIO(dev);     Object *backend;     Gpiodev *gpio;       if (dev-&gt;id) {         backend = object_resolve_path_type(dev-&gt;id, TYPE_GPIODEV, NULL);         if (backend) {             gpio = GPIODEV(backend);             qemu_gpio_fe_init(&amp;s-&gt;gpiodev, gpio, s-&gt;nr_lines, dev-&gt;id,                               \"VIRTUAL MMIO GPIO\", NULL);             qemu_gpio_fe_set_handlers(&amp;s-&gt;gpiodev, mmio_gpio_line_info,                                       mmio_gpio_get_line,                                       mmio_gpio_set_line, s);         }     } }<\/code><\/pre>\n<p>\u041c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u0438\u043d\u0438\u0439, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u0441\u043f\u043e\u0441\u043e\u0431 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u043c\u043e\u0434\u0435\u043b\u044c\u044e.<\/p>\n<p>\u0414\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u0437\u0430\u043f\u0440\u043e\u0441 \u043e \u0441\u0442\u0430\u0442\u0443\u0441\u0435 \u043b\u0438\u043d\u0438\u0439 (\u0431\u0435\u0437 \u0438\u043c\u0435\u043d\u043e\u0432\u0430\u043d\u0438\u044f \u043a\u0430\u0436\u0434\u043e\u0439), \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c, \u0432 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430 DIR_OUT, \u043c\u044b \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043b\u0438 \u043b\u0438\u043d\u0438\u044f \u0432\u0445\u043e\u0434\u043e\u043c \u0438\u043b\u0438 \u0432\u044b\u0445\u043e\u0434\u043e\u043c:<\/p>\n<pre><code>static void mmio_gpio_line_info(void *opaque, gpio_line_info *info) {     uint32_t offset = info-&gt;offset;     GpioState *s = GPIO(opaque);       if (test_bit32(offset, &amp;s-&gt;regs[R_GPIO_QEMU_DIR_OUT])) {         info-&gt;flags |= GPIO_LINE_FLAG_OUTPUT;     } else {         info-&gt;flags |= GPIO_LINE_FLAG_INPUT;     } }<\/code><\/pre>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u0438\u043d\u0438\u0438:<\/p>\n<pre><code>static int mmio_gpio_get_line(void *opaque, uint32_t offset) {     GpioState *s = GPIO(opaque);       return test_bit32(offset, &amp;s-&gt;regs[R_GPIO_QEMU_DATA]); }<\/code><\/pre>\n<p>\u0410 \u044d\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0437\u0430\u0434\u0430\u0435\u0442 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u2014 \u043c\u044b \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c \u043c\u0435\u0442\u043e\u0434, \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0430\u043d\u0435\u0435 \u0434\u043b\u044f QMP:<\/p>\n<pre><code>static int mmio_gpio_set_line(void *opaque, uint32_t offset, uint8_t value) {     GpioState *s = GPIO(opaque);       mmio_gpio_set_pin(s, offset, value);       return 0; }<\/code><\/pre>\n<p>\u041c\u044b \u043d\u0435 \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u044b\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0431\u0438\u0442 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0435 DATA \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e, \u043d\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431 \u044d\u0442\u043e\u043c \u0447\u0435\u0440\u0435\u0437 \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435.<\/p>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u044b\u0448\u0435 \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u0437\u0430 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043c\u043e\u0434\u0435\u043b\u0438, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 QEMU, \u043d\u043e \u043d\u0430\u043c \u0442\u0430\u043a\u0436\u0435 \u043d\u0443\u0436\u043d\u043e \u0441\u0438\u0433\u043d\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0433\u043e\u0441\u0442\u044f \u0432 QEMU. \u0417\u0430 \u044d\u0442\u043e \u043e\u0442\u0432\u0435\u0447\u0430\u044e\u0442 \u043c\u0435\u0442\u043e\u0434\u044b mmio_gpio_line_event() \u0438 mmio_gpio_config_event().\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u0445\u043e\u0434\u0430 low-&gt;high \u0438\u043b\u0438 high-&gt;low, \u0442\u043e \u043c\u044b \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u043c \u043e\u0431 \u044d\u0442\u043e\u043c gpiodev:<\/p>\n<pre><code>static uint64_t mmio_gpio_set(RegisterInfo *reg, uint64_t val) {     [...]     unsigned bit = test_and_set_bit32(idx, &amp;s-&gt;regs[R_GPIO_QEMU_DATA]);     if (!bit) { +   mmio_gpio_line_event(s, idx, GPIO_EVENT_RISING_EDGE);         qemu_irq_raise(s-&gt;output[idx]);     }     [...] }   static uint64_t mmio_gpio_clear(RegisterInfo *reg, uint64_t val) {     [...]     unsigned bit = test_and_clear_bit32(idx, &amp;s-&gt;regs[R_GPIO_QEMU_DATA]);     if (bit) { +   mmio_gpio_line_event(s, idx, GPIO_EVENT_FALLING_EDGE);         qemu_irq_lower(s-&gt;output[idx]);     }     [...] }<\/code><\/pre>\n<p>\u0422\u0430\u043a \u043a\u0430\u043a \u0441\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u043e \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u043a\u043b\u0438\u0435\u043d\u0442\u0430\u0445 \u0441\u043e\u0434\u0435\u0440\u0436\u0438\u0442 gpiodev, \u0430 \u043d\u0435 \u0441\u0430\u043c\u0430 \u043c\u043e\u0434\u0435\u043b\u044c, \u0442\u043e \u043d\u0443\u0436\u043d\u043e \u0432\u0441\u0435\u0433\u0434\u0430 \u0441\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f\u0445 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0432 mmio_gpio_out():<\/p>\n<pre><code>static uint64_t mmio_gpio_out(RegisterInfo *reg, uint64_t val) {     GpioState *s = GPIO(reg-&gt;opaque);     uint32_t val32 = val;     uint32_t changed = val ^ s-&gt;regs[R_GPIO_QEMU_DIR_OUT];     unsigned idx;       \/* for each bit in val32 changed *\/     idx = find_first_bit((unsigned long *)&amp;changed, s-&gt;nr_lines);     while (idx &lt; s-&gt;nr_lines) {         mmio_gpio_config_event(s, idx);           idx = find_next_bit((unsigned long *)&amp;val32, s-&gt;nr_lines, idx + 1);     }       \/* simply apply what was set *\/     return val; }<\/code><\/pre>\n<p>\u041c\u044b \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u0438 mmio_gpio_out() \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u0434\u043b\u044f gpiodev, \u0442\u0430\u043a \u043a\u0430\u043a \u0442\u0435\u043f\u0435\u0440\u044c, \u0432 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0432\u0435\u0440\u0441\u0438\u0438, \u043d\u0443\u0436\u043d\u043e \u0440\u0430\u0437\u043b\u0438\u0447\u0430\u0442\u044c, \u043a\u0430\u043a\u0430\u044f \u043b\u0438\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e.  <\/p>\n<h3>\u041c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f ASPEED GPIO  <\/h3>\n<p>\u0423 ASPEED ast2600-evb \u0435\u0441\u0442\u044c \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u0438 \u0432 \u043f\u043b\u0430\u043d\u0435 \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0430 \u0432\u0445\u043e\u0434\u043e\u0432\/\u0432\u044b\u0445\u043e\u0434\u043e\u0432 \u043d\u0430 \u043f\u043e\u0440\u0442: \u0438\u0445 208 \u0441 \u043e\u0434\u043d\u0438\u043c \u043e\u0431\u0449\u0438\u043c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u0435\u043c. \u041f\u043e\u0440\u0442\u044b \u0432\u0438\u0434\u043d\u044b \u043a\u0430\u043a \u043e\u0434\u0438\u043d gpiochip, \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0438 \u044d\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u00ab\u043e\u0434\u043d\u043e\u043f\u043b\u0430\u0442\u043d\u0438\u043a\u0430\u00bb \u0432 QEMU. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u043e\u043b\u0443\u0447\u0438\u043b\u0430\u0441\u044c \u0437\u0430\u043f\u0443\u0442\u0430\u043d\u043d\u0430\u044f, \u0430 \u0432\u043c\u0435\u0441\u0442\u0435 \u0441 \u043d\u0435\u0439 \u0438 aspeed_gpio_line_info(), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u043d\u0430\u043c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u0430\u0436\u0434\u043e\u0439 \u043b\u0438\u043d\u0438\u0438:  <\/p>\n<pre><code>static void aspeed_gpio_line_info(void *opaque, gpio_line_info *info) {     AspeedGPIOState *s = ASPEED_GPIO(opaque);     AspeedGPIOClass *agc = ASPEED_GPIO_GET_CLASS(s);     uint32_t group_idx = 0, pin_idx = 0, idx = 0;     uint32_t offset = info-&gt;offset;     const GPIOSetProperties *props;     bool direction;     const char *group;     int i, set_idx, grp_idx, pin;       for (i = 0; i &lt; ASPEED_GPIO_MAX_NR_SETS; i++) {         props = &amp;agc-&gt;props[i];         uint32_t skip = ~(props-&gt;input | props-&gt;output);         for (int j = 0; j &lt; ASPEED_GPIOS_PER_SET; j++) {             if (skip &gt;&gt; j &amp; 1) {                 continue;             }               group_idx = j \/ GPIOS_PER_GROUP;             pin_idx = j % GPIOS_PER_GROUP;             if (idx == offset) {                 goto found;             }               idx++;         }     }       return;   found:     group = &amp;props-&gt;group_label[group_idx][0];     set_idx = get_set_idx(s, group, &amp;grp_idx);     snprintf(info-&gt;name, sizeof(info-&gt;name), \"gpio%s%d\", group, pin_idx);     pin =  pin_idx + group_idx * GPIOS_PER_GROUP;     direction = !!(s-&gt;sets[set_idx].direction &amp; BIT_ULL(pin));       if (direction) {         info-&gt;flags |= GPIO_LINE_FLAG_OUTPUT;     } else {         info-&gt;flags |= GPIO_LINE_FLAG_INPUT;     } }<\/code><\/pre>\n<p>\u0421\u043b\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0438\u0437-\u0437\u0430 \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u043c\u043e\u0434\u0435\u043b\u044c \u043f\u0440\u043e\u0435\u043a\u0442\u0438\u0440\u043e\u0432\u0430\u043b\u0430\u0441\u044c \u043a\u0430\u043a \u0443\u043d\u0438\u0432\u0435\u0440\u0441\u0430\u043b\u044c\u043d\u0430\u044f \u2014 \u0441 \u0443\u0447\u0435\u0442\u043e\u043c \u0442\u043e\u0433\u043e, \u0447\u0442\u043e \u0432 \u043c\u0430\u0441\u0441\u0438\u0432\u0435 \u043b\u0438\u043d\u0438\u0439 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u043f\u0443\u0441\u043a\u0438. \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0432 ast2500 \u0432 \u0431\u0430\u043d\u043a\u0435 Y \u0447\u0430\u0441\u0442\u044c \u043b\u0438\u043d\u0438\u0439 \u043d\u0435 \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u0441\u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u0430 \u043a\u0430\u043a \u0432\u0445\u043e\u0434 \u0438\u043b\u0438 \u0432\u044b\u0445\u043e\u0434. \u0418\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u0444\u0430\u043a\u0442 \u0438 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u0442\u0441\u044f \u0432 \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0438 uint32_t skip = ~(props-&gt;input | props-&gt;output);.<\/p>\n<p>\u0417\u0434\u0435\u0441\u044c \u0435\u0441\u0442\u044c \u044f\u0432\u043d\u044b\u0439 \u043d\u0430\u043c\u0435\u043a \u0434\u043b\u044f gpiodev \u043d\u0430 \u0442\u043e, \u0447\u0442\u043e \u0441\u0442\u043e\u0438\u0442 \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u0443\u044e \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430 \u043b\u0438\u043d\u0438\u0439 \u2014 aspeed_gpio_lines_info() \u2014 \u0438 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e\u0431\u043e \u0432\u0441\u0435\u0445 \u043b\u0438\u043d\u0438\u044f\u0445 \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438, \u0430 \u043d\u0435 \u043f\u0435\u0440\u0435\u0431\u0438\u0440\u0430\u0442\u044c \u0438\u0445 \u043f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435, \u0447\u0442\u043e\u0431\u044b \u0441\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u0438 \u043e \u0441\u043e\u0431\u044b\u0442\u0438\u044f\u0445 \u043d\u0430 \u043b\u0438\u043d\u0438\u0438, \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u043c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 aspeed_gpio_line_event() \u0438 aspeed_gpio_config_event():<\/p>\n<pre><code>static void aspeed_gpio_line_event(AspeedGPIOState *s, uint32_t set_idx, uint32_t pin_idx) {     uint32_t offset = set_idx * ASPEED_GPIOS_PER_SET + pin_idx;     QEMUGpioLineEvent event = GPIO_EVENT_FALLING_EDGE;       if (aspeed_gpio_get_pin_level(s, set_idx, pin_idx)) {         event = GPIO_EVENT_RISING_EDGE;     }       qemu_gpio_fe_line_event(&amp;s-&gt;gpiodev, offset, event); }   static void aspeed_gpio_config_event(AspeedGPIOState *s, uint32_t set_idx, uint32_t pin_idx) {     uint32_t offset = set_idx * ASPEED_GPIOS_PER_SET + pin_idx;       qemu_gpio_fe_config_event(&amp;s-&gt;gpiodev, offset, GPIO_LINE_CHANGED_CONFIG); }<\/code><\/pre>\n<p>\u0422\u0443\u0442 \u0443\u0436\u0435 \u043d\u0435\u0442 \u043d\u0438\u0447\u0435\u0433\u043e \u0441\u043b\u043e\u0436\u043d\u043e\u0433\u043e: aspeed_gpio_line_event() \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u0432 aspeed_gpio_update() \u2014 \u043d\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435, \u0435\u0441\u043b\u0438 \u043f\u0440\u043e\u0438\u0437\u043e\u0448\u043b\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u0410 aspeed_gpio_config_event() \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u0445\u043e\u0434\/\u0432\u044b\u0445\u043e\u0434, \u0442\u043e \u0435\u0441\u0442\u044c \u043f\u0440\u0438 \u0437\u0430\u043f\u0438\u0441\u0438 \u0432 \u0440\u0435\u0433\u0438\u0441\u0442\u0440 *_DIRECTION.<\/p>\n<p>\u0414\u043b\u044f aspeed_gpio_get\/set_line() \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u0435 \u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0447\u0442\u043e \u0438 \u0434\u043b\u044f \u043c\u0430\u043d\u0438\u043f\u0443\u043b\u044f\u0446\u0438\u0439 \u0447\u0435\u0440\u0435\u0437 QMP:<\/p>\n<pre><code>static int aspeed_gpio_get_line(void *opaque, uint32_t offset) {     AspeedGPIOState *s = ASPEED_GPIO(opaque);     int set_idx, pin_idx;       set_idx = offset \/ ASPEED_GPIOS_PER_SET;     pin_idx = offset % ASPEED_GPIOS_PER_SET;       return aspeed_gpio_get_pin_level(s, set_idx, pin_idx); }   static int aspeed_gpio_set_line(void *opaque, uint32_t offset, uint8_t value) {     AspeedGPIOState *s = ASPEED_GPIO(opaque);     int set_idx, pin_idx;       set_idx = offset \/ ASPEED_GPIOS_PER_SET;     pin_idx = offset % ASPEED_GPIOS_PER_SET;       aspeed_gpio_set_pin_level(s, set_idx, pin_idx, value);       return 0; }<\/code><\/pre>\n<p>\u041d\u0430\u043a\u043e\u043d\u0435\u0446, \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0430\u0446\u0438\u044f \u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f, \u043f\u0440\u0438\u0447\u0435\u043c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0447\u043d\u0430 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0434\u043b\u044f virtual gpio:<\/p>\n<pre><code>static void aspeed_gpio_realize(DeviceState *dev, Error **errp) [...]     if (d-&gt;id) {         backend = object_resolve_path_type(d-&gt;id, TYPE_GPIODEV, NULL);         if (backend) {             gpio = GPIODEV(backend);             qemu_gpio_fe_init(&amp;s-&gt;gpiodev, gpio, agc-&gt;nr_gpio_pins, d-&gt;id,                               \"ASPEED GPIO\", NULL);             qemu_gpio_fe_set_handlers(&amp;s-&gt;gpiodev, aspeed_gpio_line_info,                                       aspeed_gpio_get_line,                                       aspeed_gpio_set_line, s);         }     } [...] }<\/code><\/pre>\n<h3>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0441 CUSE\/GUSE \u044f \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u043b \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f gpiosim\/gpiomockup, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u044f\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f GPIO \u0438 libgpiod. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u043e\u043d\u0438 \u043e\u043a\u0430\u0437\u0430\u043b\u0438\u0441\u044c \u0432\u0435\u0441\u044c\u043c\u0430 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u043c\u0438:<\/p>\n<ul>\n<li>\n<p>\u043d\u0435\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0439 \u0441\u0432\u044f\u0437\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b configfs \u043f\u0440\u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0447\u0438\u043f\u0430,<\/p>\n<\/li>\n<li>\n<p>\u043d\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 \u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e \u0432\u0445\u043e\u0434\u0430\/\u0432\u044b\u0445\u043e\u0434\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b configfs,<\/p>\n<\/li>\n<li>\n<p>\u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u043e \u0444\u0430\u0439\u043b\u043e\u0432 \u0432 configfs, \u0447\u0442\u043e \u0438\u0440\u043e\u043d\u0438\u0447\u043d\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 \u0441\u0442\u0430\u0440\u044b\u0439 GPIO sysfs, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e GPIO UAPI \u043a\u0430\u043a \u0440\u0430\u0437 \u0438 \u043f\u0440\u0438\u0437\u044b\u0432\u0430\u0435\u0442 \u043e\u0442\u043a\u0430\u0437\u0430\u0442\u044c\u0441\u044f.<\/p>\n<\/li>\n<\/ul>\n<p>\u041e\u0434\u043d\u0430\u043a\u043e, gpiosim\/gpiomockup \u043f\u0440\u0438\u0432\u0435\u043b\u0438 \u043c\u0435\u043d\u044f \u043a \u043c\u044b\u0441\u043b\u0438:\u00a0\u0435\u0441\u043b\u0438 \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043d\u0435 \u043e\u0431\u043e\u0439\u0442\u0438\u0441\u044c \u0431\u0435\u0437 \u043c\u043e\u0434\u0443\u043b\u044f \u044f\u0434\u0440\u0430, \u043c\u043e\u0436\u043d\u043e \u0445\u043e\u0442\u044f \u0431\u044b \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u00ab\u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u0443\u044e\u00bb \u043f\u0430\u0440\u0443 gpiochip \u0441\u043e \u0441\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u043c \u2014 \u043e\u0434\u0438\u043d \u043c\u043e\u0436\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 QEMU, \u0430 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0445\u043e\u0441\u0442\u0430. \u041f\u0440\u0430\u0432\u0434\u0430, \u0438 \u0443 \u044d\u0442\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u0435\u0441\u0442\u044c \u043e\u0447\u0435\u0432\u0438\u0434\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441. \u041e\u0434\u043d\u043e \u0434\u0435\u043b\u043e, \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0434\u043e\u0441\u0442\u0438\u0433\u0430\u0435\u0442\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e \u0437\u0430 \u0441\u0447\u0435\u0442 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0439 \u0432 QEMU, \u0438 \u0441\u043e\u0432\u0441\u0435\u043c \u0434\u0440\u0443\u0433\u043e\u0435 \u2014 \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u0447\u0442\u043e-\u0442\u043e \u043c\u0435\u043d\u044f\u0442\u044c.<\/p>\n<p>CUSE \u0432 \u0438\u0442\u043e\u0433\u0435 \u043f\u043e\u043a\u0430\u0437\u0430\u043b \u0441\u0435\u0431\u044f \u0445\u043e\u0440\u043e\u0448\u043e, \u043d\u043e \u043d\u0435 \u0434\u043b\u044f GPIO, \u0430 \u0434\u043b\u044f I2C \u2014 \u0432\u043e\u0442 \u0442\u0430\u043c \u043c\u044b \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e\u0435 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u0437\u0430 \u0441\u0440\u0430\u0432\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e \u043d\u0438\u0437\u043a\u0443\u044e \u0446\u0435\u043d\u0443. \u041e\u0441\u043d\u043e\u0432\u043d\u043e\u0435 \u043f\u0440\u0438\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u2014 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u043e\u0435 \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043f\u0440\u043e\u0448\u0438\u0432\u043e\u043a \u0434\u043b\u044f \u043c\u0438\u043a\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u043e\u0442\u0434\u0435\u043b\u043e\u043c \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u041f\u041e \u0432 YADRO, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0432\u044b\u044f\u0432\u043b\u044f\u0442\u044c \u0447\u0430\u0441\u0442\u044c \u043e\u0448\u0438\u0431\u043e\u043a \u0435\u0449\u0435 \u0434\u043e \u0442\u0435\u0441\u0442\u043e\u0432 \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u043c \u0436\u0435\u043b\u0435\u0437\u0435. \u041e \u043f\u043e\u043b\u043d\u043e\u0439 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u0438 \u043c\u0438\u043a\u0440\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u043b\u0435\u0440\u043e\u0432 \u0438 \u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u043c I2C \u0440\u0430\u0441\u0441\u043a\u0430\u0436\u0435\u043c \u043f\u043e\u0437\u0436\u0435 \u2014 \u0441\u043b\u0435\u0434\u0438\u0442\u0435 \u0437\u0430 \u043d\u043e\u0432\u044b\u043c\u0438 \u0441\u0442\u0430\u0442\u044c\u044f\u043c\u0438 \u0432 \u043d\u0430\u0448\u0435\u043c \u0431\u043b\u043e\u0433\u0435.<\/p>\n<p>\u0412 \u0438\u0442\u043e\u0433\u0435 \u044f \u0440\u0435\u0448\u0438\u043b, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u0443\u0436 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u043c\u0435\u043d\u044f\u0442\u044c \u0447\u0442\u043e-\u0442\u043e \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u043c\u0438 QEMU, \u043f\u043e\u0447\u0435\u043c\u0443 \u0431\u044b \u043d\u0435 \u0441\u0434\u0435\u043b\u0430\u0442\u044c \u044d\u0442\u043e \u043a\u0430\u0440\u0434\u0438\u043d\u0430\u043b\u044c\u043d\u043e \u0438 \u0441 \u0440\u0430\u0437\u043c\u0430\u0445\u043e\u043c? \u0422\u043e\u0433\u0434\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0441 chardev \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043f\u0440\u0438\u0432\u043b\u0435\u043a\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0435\u0441\u043b\u0438:<\/p>\n<ul>\n<li>\n<p>\u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0432\u0430\u0442\u044c\u0441\u044f \u0442\u043e\u043b\u044c\u043a\u043e QEMU, \u0430 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043f\u0440\u043e\u0442\u043e\u043a\u043e\u043b, \u043f\u043e\u0434\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 GPIO \u0432 \u0446\u0435\u043b\u043e\u043c \u2014 \u043a\u0430\u043a, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440, \u0434\u043b\u044f MOXA ioLogik,<\/p>\n<\/li>\n<li>\n<p>\u0441\u0434\u0435\u043b\u0430\u0442\u044c \u0435\u0433\u043e \u043f\u0440\u0438\u0433\u043e\u0434\u043d\u044b\u043c \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c, \u043d\u043e \u0438 \u0434\u043b\u044f \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u044b\u0445,<\/p>\n<\/li>\n<li>\n<p>\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0433\u043e \u0432 \u0432\u0438\u0434\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044f, \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438, \u0430 \u0442\u0430\u043a\u0436\u0435 \u043e\u0431\u0432\u044f\u0437\u043e\u043a \u0434\u043b\u044f Python \u0438 \u0434\u0440\u0443\u0433\u0438\u0445 \u044f\u0437\u044b\u043a\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u0438\u043d\u0442\u0435\u0433\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0431\u043e\u043b\u044c\u0448\u0438\u0435 \u0441\u0438\u0441\u0442\u0435\u043c\u044b.<\/p>\n<\/li>\n<\/ul>\n<p>\u0413\u043e\u0442\u043e\u0432\u043e\u0433\u043e \u0440\u0435\u0448\u0435\u043d\u0438\u044f \u044f \u043d\u0435 \u043d\u0430\u0448\u0435\u043b, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u0431\u0443\u0434\u0443 \u0440\u0430\u0434, \u0435\u0441\u043b\u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u0435\u0441\u044c \u0441\u0432\u043e\u0438\u043c\u0438 \u0441\u043e\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f\u043c\u0438 \u0432 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u044f\u0445.<\/p>\n<\/div>\n<\/div>\n<\/div>\n<p><!----><!----><\/div>\n<p><!----><!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/925864\/\"> https:\/\/habr.com\/ru\/articles\/925864\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><!--[--><!--]--><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<p>\u041a\u043e\u0433\u0434\u0430-\u0442\u043e \u0432 \u043e\u0442\u0434\u0435\u043b\u0435 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0432\u0441\u0442\u0440\u0430\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e \u041f\u041e <a href=\"https:\/\/www.yadro.com\/?utm_source=habr&amp;utm_medium=referral&amp;utm_campaign=qemu_GPIO_P2_article310725\" rel=\"noopener noreferrer nofollow\">\u0432 YADRO<\/a> \u043c\u043d\u0435 \u0437\u0430\u0434\u0430\u043b\u0438 \u0432\u043e\u043f\u0440\u043e\u0441: \u00ab\u0410 \u043a\u0430\u043a \u0441 \u044d\u0442\u0438\u043c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c?\u00bb. \u0420\u0435\u0447\u044c \u0448\u043b\u0430 \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u043e I2C \u0434\u043b\u044f QEMU, \u0430 \u043d\u0435 GPIO. \u0418 \u044f \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0432\u0440\u0435\u043c\u044f \u0431\u044b\u043b \u043e\u0434\u0435\u0440\u0436\u0438\u043c \u0438\u0434\u0435\u0435\u0439 \u00ab\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0433\u043e\u00bb \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0441 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u0430\u043c\u0438 \u0432\u043d\u0443\u0442\u0440\u0438 QEMU \u2014 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0442\u0435 \u0436\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u0430\u043a \u0438 \u0434\u043b\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0445 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u0435\u043a\u0440\u0430\u0441\u043d\u0435\u0435? \u041d\u0435 \u043a\u0430\u043a\u043e\u0439-\u0442\u043e \u0442\u0430\u043c \u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f \u043f\u043e\u0441\u044b\u043b\u043a\u0438 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u043f\u043e QMP, \u0430 \u0437\u043d\u0430\u043a\u043e\u043c\u044b\u0439 \u0438 \u0446\u0435\u043b\u043e\u0441\u0442\u043d\u044b\u0439 gpioset\/gpioget \u0438\u0437 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 libgpiod \u0438\u043b\u0438 \u043f\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u043c\u044b\u0435 \u0441 \u044f\u0434\u0440\u043e\u043c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0438\u0437 tools\/gpio.<\/p>\n<p>\u041f\u043e\u043b\u0443\u0447\u0438\u043b\u043e\u0441\u044c \u043b\u0438 \u044d\u0442\u043e \u0443 \u043c\u0435\u043d\u044f? \u0414\u0430, \u043d\u043e \u043a\u0430\u043a\u043e\u0439 \u0446\u0435\u043d\u043e\u0439\u2026<\/p>\n<h3>QEMU GPIODEV: \u0432\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/h3>\n<p>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u044d\u043d\u0442\u0440\u043e\u043f\u0438\u0438 \u2014 \u044d\u0442\u043e \u043d\u0435 \u0442\u0430\u043a \u0443\u0436 \u0438 \u043f\u043b\u043e\u0445\u043e. <a href=\"https:\/\/habr.com\/ru\/companies\/yadro\/articles\/925860\/\" rel=\"noopener noreferrer nofollow\">\u0412 \u043f\u0440\u043e\u0448\u043b\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0435<\/a> \u043c\u044b \u043f\u0440\u0438\u0448\u043b\u0438 \u043a \u0432\u044b\u0432\u043e\u0434\u0443, \u0447\u0442\u043e QMP \u2014 \u044d\u0442\u043e \u043b\u0443\u0447\u0448\u0435, \u0447\u0435\u043c \u043d\u0438\u0447\u0435\u0433\u043e. \u041d\u043e \u0445\u043e\u0447\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c\u0448\u0435\u0433\u043e \u2014 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438\u043b\u0438 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0443 (\u0436\u0435\u043b\u0430\u0442\u0435\u043b\u044c\u043d\u043e, \u0443\u0436\u0435 \u0433\u043e\u0442\u043e\u0432\u0443\u044e), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0443\u043c\u0435\u0435\u0442 \u0447\u0438\u0442\u0430\u0442\u044c\/\u043f\u0438\u0441\u0430\u0442\u044c \u0438 \u0443\u0437\u043d\u0430\u0432\u0430\u0442\u044c \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0447\u0435\u0440\u0435\u0437 poll() \/ pselect() \/ select() \/ epoll() \/ read().\u00a0<\/p>\n<p>\u0412 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043c\u043e\u0434\u0435\u043b\u0438 GPIO \u043d\u0443\u0436\u0435\u043d \u00ab\u043a\u043b\u0435\u0439\u00bb, \u043f\u043e\u0445\u043e\u0436\u0438\u0439 \u043d\u0430 \u0442\u043e\u0442, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0441 chardev \u2014 \u043c\u044b \u0432\u043a\u043b\u044e\u0447\u0430\u0435\u043c \u0435\u0433\u043e \u043f\u0440\u044f\u043c\u043e \u0432 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 QEMU. \u041e\u0447\u0435\u0432\u0438\u0434\u043d\u043e\u0435 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0442\u0430\u043a\u043e\u0433\u043e \u00ab\u043a\u043b\u0435\u044f\u00bb \u2014 gpiodev. \u0412\u043e\u0442 \u0435\u0433\u043e \u043e\u0441\u043d\u043e\u0432\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0441\u0435\u0439\u0447\u0430\u0441 \u043f\u043e\u0447\u0442\u0438 \u043f\u043e\u043b\u043d\u043e\u0441\u0442\u044c\u044e \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 GPIO UAPI \u0432 Linux:<\/p>\n<ul>\n<li>\n<p>\u0441\u043e\u043e\u0431\u0449\u0430\u0442\u044c \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u0438\u043d\u0438\u0439, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e, \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0439 \u043b\u0438\u043d\u0438\u0438,<\/p>\n<\/li>\n<li>\n<p>\u0447\u0438\u0442\u0430\u0442\u044c \u0438 \u0437\u0430\u0434\u0430\u0432\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u0438\u043d\u0438\u0438,<\/p>\n<\/li>\n<li>\n<p>\u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u0442\u044c \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0438 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u0438 \u043b\u0438\u043d\u0438\u0438 (\u0432\u0445\u043e\u0434\/\u0432\u044b\u0445\u043e\u0434, \u0437\u0430\u043f\u0440\u043e\u0441\/\u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u0435).<\/p>\n<\/li>\n<\/ul>\n<p>\u00ab\u041a\u043b\u0435\u0439\u00bb \u0441\u043e\u0441\u0442\u043e\u0438\u0442 \u0438\u0437 \u0434\u0432\u0443\u0445 \u0433\u0440\u0443\u043f\u043f, \u043f\u0435\u0440\u0432\u0430\u044f \u2014 \u044d\u0442\u043e \u0438\u043d\u0434\u0438\u0432\u0438\u0434\u0443\u0430\u043b\u044c\u043d\u044b\u0435 \u0434\u043b\u044f \u043a\u0430\u0436\u0434\u043e\u0433\u043e \u043c\u043e\u0434\u0443\u043b\u044f GPIO \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 gpiodev \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442, \u0447\u0442\u043e\u0431\u044b \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e:<\/p>\n<ul>\n<li>\n<p>LineInfoHandler() \u2014 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u043e \u043b\u0438\u043d\u0438\u0438: \u0438\u043c\u044f, \u0444\u043b\u0430\u0433\u0438 \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u0438\u0442\u0435\u043b\u044c,<\/p>\n<\/li>\n<li>\n<p>LineGetValueHandler() \u2014 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u0438\u043d\u0438\u0438: \u0443\u0441\u043b\u043e\u0432\u043d\u044b\u0439 0 \u0438\u043b\u0438 1,<\/p>\n<\/li>\n<li>\n<p>LineSetValueHandler() \u2014 \u0437\u0430\u0434\u0430\u0442\u044c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043b\u0438\u043d\u0438\u0438: 0 \u0438\u043b\u0438 1.<\/p>\n<\/li>\n<\/ul>\n<p>\u041f\u043e \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0438 \u0441 GPIO UAPI \u043d\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0442\u0430\u043a\u0436\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 LineGetMultiValueHandler() \u0438 LineSetMultiValueHandler() \u0434\u043b\u044f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0438 \u0432\u044b\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043b\u0438\u043d\u0438\u0439, \u043d\u043e \u044f \u0440\u0435\u0448\u0438\u043b \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0438\u0442\u044c\u0441\u044f \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c.<\/p>\n<p>\u0417\u0430\u043f\u0440\u043e\u0441\u044b \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0435\u043d\u044b \u0432 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u0443, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u043a\u0430\u0436\u0434\u044b\u043c \u0447\u0438\u043f\u043e\u043c \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u0441 gpiodev:<\/p>\n<pre><code>\/* qemu\/include\/gpiodev\/gpio-fe.h *\/ struct GpioBackend {     Gpiodev *gpio;     LineInfoHandler *line_info;     LineGetValueHandler *get_value;     LineSetValueHandler *set_value;     void *opaque; };<\/code><\/pre>\n<p>\u0412\u0442\u043e\u0440\u0430\u044f \u0433\u0440\u0443\u043f\u043f\u0430 \u2014 \u044d\u0442\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u043c\u043e\u0434\u0443\u043b\u044c GPIO \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 gpiodev \u043e\u0431 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0438 \u0441\u0432\u043e\u0435\u0433\u043e \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f. \u041a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0438\u0437\u043c\u0435\u043d\u0438\u0442\u044c \u044d\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c\u044b\u0439 \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u043e\u0440 \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u0435 \u0431\u043b\u043e\u043a\u0438 QEMU, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 \u00ab\u0432\u043d\u0435\u0448\u043d\u0438\u0439\u00bb \u0434\u0430\u0442\u0447\u0438\u043a I2C:<\/p>\n<ul>\n<li>\n<p>qemu_gpio_fe_line_event() \u2014 \u043b\u0438\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430 \u0441\u0432\u043e\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435,<\/p>\n<\/li>\n<li>\n<p>qemu_gpio_fe_config_event() \u2014 \u043b\u0438\u043d\u0438\u044f \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u0430 \u0441\u0432\u043e\u044e \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u044e.<\/p>\n<\/li>\n<\/ul>\n<p>\u0421\u0430\u043c\u044b\u0435 \u043f\u0435\u0440\u0432\u044b\u0435 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u044b gpiodev \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043b\u0438 \u0441\u0442\u0440\u0443\u043a\u0442\u0443\u0440\u044b \u0438\u0437 <em>uapi\/linux\/gpio.h<\/em> \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e, \u043d\u043e \u043f\u043e\u0437\u0436\u0435 \u044f \u043e\u0442 \u043d\u0438\u0445 \u043e\u0442\u043a\u0430\u0437\u0430\u043b\u0441\u044f, \u043a\u043e\u0433\u0434\u0430 \u043f\u043e\u043d\u044f\u043b, \u0447\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 gpiodev \u043c\u043e\u0436\u0435\u0442 \u0432\u044b\u0439\u0442\u0438 \u0437\u0430 \u043f\u0440\u0435\u0434\u0435\u043b\u044b \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u043e\u0439 \u043c\u0430\u0448\u0438\u043d\u044b.<\/p>\n<p>\u0414\u043b\u044f \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f gpiodev \u043a\u0430\u0436\u0434\u044b\u0439 \u0447\u0438\u043f \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0441\u0432\u043e\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441:<\/p>\n<pre><code>bool qemu_gpio_fe_init(GpioBackend *b, Gpiodev *s, uint32_t nlines,                        const char *name, const char *label,                        Error **errp);<\/code><\/pre>\n<p>\u0427\u0438\u043f \u0441\u043e\u043e\u0431\u0449\u0430\u0435\u0442 \u0441\u0432\u043e\u0435 \u0438\u043c\u044f, \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u043e \u043b\u0438\u043d\u0438\u0439, \u0430 \u0442\u0430\u043a\u0436\u0435 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0441\u043e\u0431\u043e\u0439 \u0438 \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u044b\u043c <em>-gpiodev<\/em>.<\/p>\n<p>\u0414\u0430\u043b\u0435\u0435 \u043d\u0443\u0436\u043d\u043e \u0437\u0430\u0440\u0435\u0433\u0438\u0441\u0442\u0440\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0437\u0430\u043f\u0440\u043e\u0441\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u044b \u0443\u043f\u043e\u043c\u0438\u043d\u0430\u043b\u0438 \u0440\u0430\u043d\u0435\u0435:<\/p>\n<pre><code>void qemu_gpio_fe_set_handlers(GpioBackend *b,                                LineInfoHandler *line_info,                                LineGetValueHandler *get_value,                                LineSetValueHandler *set_value,                                void *opaque);<\/code><\/pre>\n<figure class=\"\">\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 GPIODEV<\/figcaption><\/div>\n<\/figure>\n<p>\u042d\u0442\u043e\u0433\u043e \u0432\u043f\u043e\u043b\u043d\u0435 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0434\u043b\u044f \u043d\u0430\u0448\u0438\u0445 \u0446\u0435\u043b\u0435\u0439. \u041f\u0440\u0438\u043c\u0435\u0440 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f ASPEED \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u0432 \u043a\u043e\u043d\u0446\u0435 \u0441\u0442\u0430\u0442\u044c\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u043c \u043a \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u044e \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432 \u0432\u043d\u0435\u0448\u043d\u0438\u0445 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441\u043e\u0432.<\/p>\n<blockquote>\n<p><strong>\u041a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u043f\u0440\u043e\u0435\u043a\u0442\u0430:<\/strong><\/p>\n<ul>\n<li>\n<p>qemu v10.0.0:<\/p>\n<ul>\n<li>\n<p>\u043c\u043e\u0434\u0435\u043b\u0438 MMIO\/PCI GPIO,<\/p>\n<\/li>\n<li>\n<p>\u043c\u0430\u0448\u0438\u043d\u0430 RISC-V virt \u0441 MMIO GPIO \u0438 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 dtb,<\/p>\n<\/li>\n<li>\n<p>gpiodev \u0441 \u0431\u044d\u043a\u0435\u043d\u0434\u0430\u043c\u0438 CHARDEV, CUSE, GUSE,<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li>\n<p>buildroot 2025.02.2 \u0432\u0430\u043d\u0438\u043b\u044c\u043d\u044b\u0439 (\u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043f\u0440\u0435\u0434\u044b\u0434\u0443\u0449\u0435\u0439 \u0438\u0442\u0435\u0440\u0430\u0446\u0438\u0438),<\/p>\n<\/li>\n<li>\n<p>qemu-gpio-tools \u2014 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u044b \u0434\u043b\u044f chardev,<\/p>\n<\/li>\n<li>\n<p>libgpiod \u2014 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f CUSE \u0438 GUSE,<\/p>\n<\/li>\n<li>\n<p>libfuse \u2014 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u043a\u0438 GUSE,<\/p>\n<\/li>\n<li>\n<p>linux v6.12: <\/p>\n<ul>\n<li>\n<p>\u043f\u0430\u0442\u0447\u0438 \u0434\u043b\u044f dtb-\u0438\u043d\u044a\u0435\u043a\u0446\u0438\u0439,<\/p>\n<\/li>\n<li>\n<p>\u0434\u0440\u0430\u0439\u0432\u0435\u0440 \u0434\u043b\u044f QEMU MMIO\/PCIE GPIO,<\/p>\n<\/li>\n<li>\n<p>\u043c\u043e\u0434\u0443\u043b\u044c GUSE.<\/p>\n<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<p><a href=\"https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground?branch=nshubin%2Fgpiodev\" rel=\"noopener noreferrer nofollow\">\u2192 \u0421\u043a\u0430\u0447\u0430\u0442\u044c \u043f\u0440\u043e\u0435\u043a\u0442-\u043e\u0431\u0435\u0440\u0442\u043a\u0443<\/a> (\u0447\u0430\u0441\u0442\u044c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u043e\u0432 \u043d\u0443\u0436\u043d\u0430 \u0442\u043e\u043b\u044c\u043a\u043e \u0434\u043b\u044f GUSE)<\/p>\n<\/blockquote>\n<h3>\u041c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u0430\u044f \u0441\u0431\u043e\u0440\u043a\u0430<\/h3>\n<p>\u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u0432\u043e\u0437\u044c\u043c\u0435\u043c ASPEED ast2600-evb \u2014 \u043e\u0434\u043d\u043e\u043f\u043b\u0430\u0442\u043d\u044b\u0439 \u043a\u043e\u043c\u043f\u044c\u044e\u0442\u0435\u0440 (SBC), \u043a\u043e\u0442\u043e\u0440\u044b\u0439 (\u0443\u0432\u0435\u0440\u044f\u044e, \u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u2014 \u0441\u043b\u0435\u0434\u0438\u0442\u0435 \u0437\u0430 \u043d\u0430\u0448\u0438\u043c \u0431\u043b\u043e\u0433\u043e\u043c) \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043d\u0430\u0438\u0431\u043e\u043b\u0435\u0435 \u043f\u043e\u043b\u043d\u043e \u044d\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c\u043e\u0439 \u0432 QEMU \u043c\u0430\u0448\u0438\u043d\u043e\u0439 \u0441 \u0441\u0430\u043c\u044b\u043c \u0448\u0438\u0440\u043e\u043a\u0438\u043c \u043d\u0430\u0431\u043e\u0440\u043e\u043c \u043f\u0435\u0440\u0438\u0444\u0435\u0440\u0438\u0439\u043d\u044b\u0445 \u0431\u043b\u043e\u043a\u043e\u0432. \u0422\u0430\u043a\u0436\u0435 \u0432 ASPEED ast2600-evb \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u0430 \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044f \u0440\u0435\u0436\u0438\u043c\u0430 I2C slave.<\/p>\n<p>\u041f\u0440\u0438\u043a\u043b\u0430\u0434\u044b\u0432\u0430\u044e <a href=\"https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/\" rel=\"noopener noreferrer nofollow\">\u0430\u0440\u0442\u0435\u0444\u0430\u043a\u0442\u044b<\/a> \u0434\u043b\u044f ASPEED, \u0442\u0430\u043a \u043a\u0430\u043a \u0434\u043b\u044f \u043f\u0440\u0438\u043c\u0435\u0440\u0430 \u043d\u0443\u0436\u043d\u043e \u0441\u043e\u0431\u0440\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e QEMU:<\/p>\n<pre><code>$ git clone -b nshubin\/qemu-gpiodev https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground $ git submodule update --init --depth 1 -- qemu $ make .build-qemu $ wget https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/68d857b3-f61b-482e-b9e4-70e7cb551ea4\/download -O initramfs.cpio.xz $ wget https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/acd48054-e894-40c4-a351-bafb447353bb\/download -O zImage $ wget https:\/\/gitflic.ru\/project\/maquefel\/qemu-gpio-playground\/release\/f34da376-f208-4b0b-943c-0d183f038da8\/8c4d2cec-12c9-4cdb-ba41-cf564abced95\/download -O aspeed-ast2600-evb.dtb<\/code><\/pre>\n<p>\u041e\u0431\u0449\u0430\u044f \u0441\u0442\u0440\u043e\u043a\u0430 \u0437\u0430\u043f\u0443\u0441\u043a\u0430:<\/p>\n<pre><code>host $ build-qemu\/qemu-system-arm -M ast2600-evb,bmc-console=uart5 \\     -kernel buildroot_aspeed\/build\/linux-6.12.17\/arch\/arm\/boot\/zImage \\     -dtb .\/buildroot_aspeed\/images\/aspeed-ast2600-evb.dtb \\     -initrd buildroot_aspeed\/images\/rootfs.cpio.xz \\     -nographic -serial mon:stdio<\/code><\/pre>\n<p>\u041d\u0430\u0431\u043e\u0440 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0445 \u043a\u043e\u043c\u0430\u043d\u0434 \u0434\u043b\u044f \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f gpiodev \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u0442\u043e\u0433\u043e, \u043a\u0430\u043a\u043e\u0439 \u0432\u043d\u0435\u0448\u043d\u0438\u0439 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0432\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0435.<\/p>\n<h3>CHARDEV<\/h3>\n<p>\u041d\u0430\u0447\u043d\u0443 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432, \u0430 \u043f\u043e\u0442\u043e\u043c \u043f\u0435\u0440\u0435\u0439\u0434\u0443 \u043a \u043f\u043e\u044f\u0441\u043d\u0435\u043d\u0438\u044f\u043c. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e ASPEED ast2600-evb: <\/p>\n<pre><code># \u043d\u0435\u0431\u0445\u043e\u0434\u0438\u043c\u044b qemu-gpio-tools host $ make .build-qemu-gpio-tools host $ build-qemu\/qemu-system-arm -M ast2600-evb,bmc-console=uart5 \\ -kernel buildroot_aspeed\/build\/linux-6.12.17\/arch\/arm\/boot\/zImage \\ -dtb .\/buildroot_aspeed\/images\/aspeed-ast2600-evb.dtb \\ -initrd buildroot_aspeed\/images\/rootfs.cpio.xz \\ -nographic -serial mon:stdio \\ -gpiodev chardev,id=aspeed-gpio0,chardev=gpio0 \\ -chardev socket,path=\/tmp\/gpio0,id=gpio0,server=on,wait=off \\ -d guest_errors<\/code><\/pre>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0445\u043e\u0434\u043e\u0432\/\u0432\u044b\u0445\u043e\u0434\u043e\u0432 \u0434\u043b\u044f aspeed-gpio0:<\/p>\n<pre><code>host $ qemu-gpio-tools\/lsgpio -n \/tmp\/gpio0 sending 0x8044b401 GPIO chip: aspeed-gpio0, \"ASPEED GPIO\", 208 GPIO lines         line  0: \"gpioA0\" unused [input] [...]         line 207: \"gpioZ7\" unused [input]<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0438 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u0432\u0445\u043e\u0434\u043e\u0432 \u043e\u0431\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043f\u0440\u0438 \u0432\u043e\u0437\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0438 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0445\u043e\u0441\u0442\u0430:<\/p>\n<pre><code>host $ .\/gpio-hammer -n \/tmp\/gpio0 -o 8   qemu # gpiomon -c 0 8 gpio_reg_direction: 0x0 0x0   36.791326811rising  gpiochip0 8 37.679910405falling gpiochip0 8 38.568927503rising  gpiochip0 8 39.457922388falling gpiochip0 8 40.346842481rising  gpiochip0 8 [...]<\/code><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c, \u0447\u0442\u043e \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u044f \u043b\u0438\u043d\u0438\u0438, \u0438\u043d\u0438\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 \u0433\u043e\u0441\u0442\u0435\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u043e\u0442\u0441\u043b\u0435\u0436\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0445\u043e\u0441\u0442\u0435:<\/p>\n<pre><code>qemu # gpioset -c 0 8=0 ^C qemu # gpioset -c 0 8=1 ^C   host $ .\/gpio-event-mon -n \/tmp\/gpio0 -o 8 No flags specified, listening on both rising and falling edges Monitoring line 8 on \/tmp\/gpio0 Initial line value: 0 GPIO EVENT at 572196930648 on line 8 (0|0) falling edge GPIO EVENT at 574302333416 on line 8 (0|0) rising edge<\/code><\/pre>\n<p>gpiodev-chardev \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u043d\u0430\u0434\u0441\u0442\u0440\u043e\u0439\u043a\u0443 \u043d\u0430\u0434 -chardev, \u0442\u043e \u0435\u0441\u0442\u044c \u0442\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u043c\u043e\u0436\u0435\u0442 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043f\u043e\u0432\u0435\u0440\u0445 \u043b\u044e\u0431\u043e\u0433\u043e \u0442\u0440\u0430\u043d\u0441\u043f\u043e\u0440\u0442\u0430, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0435\u043c\u043e\u0433\u043e -chardev: stdio, serial, pipe, pty, socket \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435. \u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438 \u2014 \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e -chardev socket \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b qemu-gpio-tools, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u044f \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043b \u043f\u043e\u0432\u0435\u0440\u0445 UNIX-\u0441\u043e\u043a\u0435\u0442\u0430 (\u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u043f\u0435\u0440\u0435\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0435 \u0443\u0442\u0438\u043b\u0438\u0442\u044b \u0438\u0437 \u043d\u0430\u0431\u043e\u0440\u0430 tools\/gpio \u0432 Linux). \u042d\u0442\u043e, \u043a\u043e\u043d\u0435\u0447\u043d\u043e, \u043d\u0435 \u0442\u043e \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u043d\u0435\u043b\u044c\u0437\u044f \u0431\u044b\u043b\u043e \u0431\u044b \u043e\u0431\u043e\u0439\u0442\u0438 \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e socat, \u043d\u043e, \u0442\u0435\u043c \u043d\u0435 \u043c\u0435\u043d\u0435\u0435.<\/p>\n<figure class=\"full-width\">\n<div><figcaption>\u0414\u0438\u0430\u0433\u0440\u0430\u043c\u043c\u0430 CHARDEV<\/figcaption><\/div>\n<\/figure>\n<p>\u0412 \u044d\u0442\u043e\u043c \u043e\u0434\u043d\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u043e \u0438 \u0441\u0438\u043b\u0430, \u0438 \u0441\u043b\u0430\u0431\u043e\u0441\u0442\u044c \u043f\u043e\u0434\u0445\u043e\u0434\u0430: \u0441 \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u043e\u0440\u043e\u043d\u044b, \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0435 \u0443\u0442\u0438\u043b\u0438\u0442\u044b, \u0441 \u0434\u0440\u0443\u0433\u043e\u0439 \u2014 \u043c\u044b \u043d\u0435 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c.<\/p>\n<h3>FUSE<\/h3>\n<p>\u041f\u0440\u043e\u0431\u043b\u0435\u043c\u0430 \u00ab\u043f\u0440\u043e\u0437\u0440\u0430\u0447\u043d\u043e\u0433\u043e\u00bb \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0442\u043e\u043c, \u0447\u0442\u043e \u0432\u0441\u0435 i2c-dev, gpiochip, spidev \u0438 \u0442\u0430\u043a \u0434\u0430\u043b\u0435\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0434\u043b\u044f \u0441\u0432\u043e\u0435\u0439 \u0440\u0430\u0431\u043e\u0442\u044b ioctl() \u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u0432\u0441\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0438 \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b \u0437\u0430\u0432\u044f\u0437\u0430\u043d\u044b \u043d\u0430 \u0435\u0433\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438.\u00a0<\/p>\n<p>\u0415\u0441\u043b\u0438 \u0447\u0442\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 \u0437\u0430\u043f\u0438\u0441\u044c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0435\u0433\u043a\u043e, \u0442\u043e \u0441\u043f\u043e\u0441\u043e\u0431\u0430 \u0432\u044b\u0437\u0432\u0430\u0442\u044c\u00a0 ioctl() \u044f \u043d\u0435 \u0437\u043d\u0430\u044e \u2014 \u044d\u0442\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u0443 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432 \u0438\u043b\u0438 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432 \u044f\u0434\u0440\u0430. \u041f\u043e\u043b\u0443\u0447\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0432 \u043b\u044e\u0431\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u044f\u0434\u0440\u0430.<\/p>\n<p>\u0418 \u0437\u0434\u0435\u0441\u044c \u043d\u0430\u043c \u043f\u0440\u0438\u0433\u043e\u0434\u0438\u0442\u0441\u044f FUSE, \u0430 \u0442\u043e\u0447\u043d\u0435\u0435, \u0435\u0433\u043e \u0447\u0430\u0441\u0442\u044c \u043f\u043e\u0434 \u043d\u0430\u0437\u0432\u0430\u043d\u0438\u0435\u043c CUSE (Userland Character Device Library).<\/p>\n<h4>CUSE<\/h4>\n<p>\u0422\u0440\u0430\u0434\u0438\u0446\u0438\u043e\u043d\u043d\u043e \u043d\u0430\u0447\u043d\u0443 \u0441 \u043f\u0440\u0438\u043c\u0435\u0440\u043e\u0432. \u0417\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u043c \u044d\u043c\u0443\u043b\u044f\u0446\u0438\u044e \u043f\u043b\u0430\u0442\u044b ASPEED ast2600-evb \u0432 QEMU \u0441 \u043f\u043e\u0434\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435\u043c gpiodev \u0447\u0435\u0440\u0435\u0437 CUSE:<\/p>\n<pre><code># \u043d\u0435\u0431\u0445\u043e\u0434\u0438\u043c libgpiod \u0441 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f\u043c\u0438 host $ make .build-libgpiod host $ sudo build-qemu\/qemu-system-arm -M ast2600-evb,bmc-console=uart5 \\ -kernel buildroot_aspeed\/build\/linux-6.12.17\/arch\/arm\/boot\/zImage \\ -dtb .\/buildroot_aspeed\/images\/aspeed-ast2600-evb.dtb \\ -initrd buildroot_aspeed\/images\/rootfs.cpio.xz \\ -nographic -serial mon:stdio \\ -gpiodev cuse,id=aspeed-gpio0,devname=gpiochip10 \\ -d guest_errors<\/code><\/pre>\n<p>\u0412\u044b\u0432\u043e\u0434\u0438\u043c \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0445\u043e\u0434\u043e\u0432\/\u0432\u044b\u0445\u043e\u0434\u043e\u0432 \u0434\u043b\u044f aspeed-gpio0:<\/p>\n<pre><code>host $ sudo libgpiod\/tools\/gpioinfo -c 10         line   0:       \"gpioA0\"                input         [...]         line 207:       \"gpioZ7\"                input<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0433\u043e\u0441\u0442\u044f:<\/p>\n<pre><code>host $ sudo libgpiod\/tools\/gpioset -t 0 -c 10 8=1 9=1 10=1 host $ sudo libgpiod\/tools\/gpioset -t 0 -c 10 8=0 9=0 10=0   qemu # gpiomon -c 0 8 9 10 69.422108579rising  gpiochip0 9 69.422015591rising  gpiochip0 8 69.422173796rising  gpiochip0 10 124.508747142   falling gpiochip0 9 124.508841782   falling gpiochip0 10 124.508572457   falling gpiochip0 8<\/code><\/pre>\n<p>\u041f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0440\u0435\u0440\u044b\u0432\u0430\u043d\u0438\u044f \u0434\u043b\u044f \u0445\u043e\u0441\u0442\u0430:<\/p>\n<pre><code>qemu # gpioset -t 0 -c 0 8=1 9=1 10=1 qemu # gpioset -t 0 -c 0 8=0 9=0 10=0   host $ sudo libgpiod\/tools\/gpiomon -c 10 8 9 10 1749204303.043403870rising  aspeed-gpio0 8 1749204303.043546291rising  aspeed-gpio0 9 1749204303.043650331rising  aspeed-gpio0 10 1749204308.437501487falling aspeed-gpio0 8 1749204308.437650077falling aspeed-gpio0 9 1749204308.437757098falling aspeed-gpio0 10<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435 \u043d\u0430 <strong>sudo<\/strong>: \u043d\u0430\u043c<\/p>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-473420","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/473420","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=473420"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/473420\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=473420"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=473420"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=473420"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}