iYoRoy's Develop Diary - Develop
type: channel
link: https://blog.iyoroy.cn/en/category/Develop/
items: Adapting NFC Functionality for QWRT on Xiaomi BE10000 Router
items: Configuring a Simple Multi-language Solution for Typecho
items: Cross-Platform Service Programming Diary Ep.2 - Inter-Process Communication (IPC)
items: Cross-Platform Service Programming Diary Ep.1 - Unified Logging Management
items: Querying DNS Records Using WINAPI in C++
items: Using Infrared Camera for Face Recognition on Xiaomi 845 Series with Custom ROMs
items: Adding KernelSU Support to Android 4.9 Kernel
items: Enabling EROFS Support for an Android ROM with Kernel 4.9

Adapting NFC Functionality for QWRT on Xiaomi BE10000 Router
type: item
date: 2026-05-25T15:18:00+00:00
description: English Translation Title: Adapting NFC Functionality for QWRT on Xiaomi BE10000 Router Analysis After flashing the Xiaomi BE10000 with QWRT, the device's network potential is indeed greatly unleashed. Advanced features such as 2.5G optical modules and SFP+ interfaces work perfectly. The only drawback is that the factory NFC "tap to connect to Wi-Fi" feature no longer works. After researching, the NFC tag is essentially an EEPROM chip mounted on the motherboard. Using i2cdetect for scanning: root@QWRT:~# i2cdetect -l i2c-1 i2c QUP I2C adapter I2C adapter i2c-2 i2c QUP I2C adapter I2C adapter i2c-0 i2c QUP I2C adapter I2C adapter root@QWRT:~# i2cdetect -y -r 0 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- 54 -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- The scan results quickly pinpoint the device attached to I2C bus 0 at physical address 0x54. NFC tap-to-connect-to-Wi-Fi uses standard NDEF format data (Ref: Wi-Fi Simple Configuration — ndeflib 0.3.2 documentation). Therefore, simply writing the data into the EEPROM according to the standard can restore the NFC tap-to-connect functionality. Implementation This article discusses only low-level hardware driver adaptation and NDEF standard protocol encapsulation for the OpenWrt/QWRT system. The hardware parameters mentioned are derived from public specification documents and generic I2C debugging tools. This project is for personal research interest and does not include or distribute any vendor-proprietary binary code. It is intended for technical exchange and learning only. Do not use for commercial purposes. Any risk of device damage resulting from attempts described herein shall be borne solely by the r…

Configuring a Simple Multi-language Solution for Typecho
type: item
date: 2025-11-19T14:10:00+00:00
description: I wanted to add internationalization support to my blog, providing a separate English version for each post and page. However, after searching online, I found that Typecho has poor support for i18n. Eventually, I designed my own solution and am documenting it here. This article assumes you have some basic understanding of PHP, Nginx, and Typecho's core logic. Analysis Requirements Need to provide both Chinese and English versions for each post and page. Need to configure a language switcher so users can easily switch languages on the frontend. Need search engines to correctly identify and index the multi-language versions of the content. Proposed Solution There are roughly two main schemes for distinguishing between Chinese and English content: Use a separate parameter, like accessing posts with /?lang=zh-CN and /?lang=en-US. However, this scheme is relatively difficult to implement and less friendly for search engine indexing. Distinguish via the URL path, e.g., https://<host>/article for the Chinese page and https://<host>/en/article for the English page. This is simpler to configure (essentially setting up two separate Typecho instances) and is more search engine friendly. The challenge is that comments and view counts need to be manually synchronized. After summarizing, I chose the second scheme and planned to implement multi-language support by creating a new Typecho instance directly under the /en/ path. Implementation Plan First, duplicate the blog instance into two copies: one for Chinese and one for English, then translate the English copy. Modify the frontend code to implement the language switcher. To ensure the article URLs between the two sites only differ by the /en prefix, the cid (content ID) for corresponding articles must be the same. Since cid is auto-incremented based on the order of creating posts and attachments, I plan to write a sync plugin. When a post is published on the Chinese site, it automatically inserts a corresponding article with th…

Cross-Platform Service Programming Diary Ep.2 - Inter-Process Communication (IPC)
type: item
date: 2025-05-19T03:54:00+00:00
description: Previously The previous article implemented unified log management. This article implements inter-process message communication, i.e., IPC. Analysis Windows On Windows, inter-process communication is primarily achieved through Pipes. Pipes are further divided into Named Pipes and Anonymous Pipes. Anonymous pipes are unidirectional and are typically used for communication between a parent and child process[2]. Named pipes, however, can be unidirectional or duplex and support one-to-many communication[3]. As the name implies, the only way to identify a named pipe is by its name, so two processes can communicate as long as they connect to the named pipe with the same name. We need to achieve bidirectional communication between processes, so we use named pipes. The general idea is: a process starts in server mode (receiver), creates a thread, creates a named pipe, and listens for messages within the pipe. When the pipe is connected, it reads data from it; when a process starts as a sender, it attempts to connect to a pipe with the same name and writes the message content. Linux On Linux, sockets are typically used for inter-process communication. However, unlike listening on a port, IPC usually involves listening on a sock file[5]. Common service applications like the Docker daemon and MySQL use this method. Thus, the general idea is as follows: a process started in server mode creates a socket listener and waits to receive messages from it; the sender connects to the socket and sends a message. Similar to the name of the named pipe mentioned above, the socket maps to a unique .sock file. The sender just needs to open this file to send the message. (In practice, it's not opened in the conventional file manner but using socket-specific methods[5].) Code Implementation Initialization To use a common main codebase, I used the same approach as the previous article, differentiating system types via macro definitions, placing the Windows and Linux code in the header files ser…

Cross-Platform Service Programming Diary Ep.1 - Unified Logging Management
type: item
date: 2025-04-18T16:19:00+00:00
description: A while ago, on a whim, I decided to write my own management program for a cross-platform console service-class application I was using, in order to add some features. Thus, I designed a simple service operation flow. {alert type="warning"} The views and solutions in this series of articles are designed by me based on my existing knowledge combined with assistance from DeepSeek. They have not been rigorously tested and do not guarantee feasibility or stability for use in production environments. {/alert} General Approach Roughly divided into several threads, used for: Logging Target application instance management (potentially more than one thread) Listening for IPC messages Processing received IPC messages (main process) This article focuses on the logging part. Design Rationale Why dedicate a separate thread to logging? My consideration is that since it's inherently a multi-threaded architecture, a unified logging module is necessary. If each thread prints independently, it's highly likely that two threads could write to the file or output to the console simultaneously, causing log chaos. Therefore, the general idea for logging is: Define a queue to store log content and level. Create a thread that continuously takes elements from the queue, deciding whether to print to the console or output to a file based on the set log level. External components push log content to the queue. Some Detailed Considerations Ensure portability by using the STL library as much as possible, e.g., using std::thread instead of pthread. Ensure thread safety, requiring protection of relevant variables with mutexes or similar mechanisms. Make the thread wait when the log queue is empty; thought of writing a blocking queue similar to Java's BlockingQueue. Specify a log level; only logs with a level meeting or exceeding this threshold will be saved or printed. Implement variadic arguments via va_list to give the logging function a usage experience similar to sprintf. Start Coding With the a…

Querying DNS Records Using WINAPI in C++
type: item
date: 2025-03-20T09:33:00+00:00
description: This article has been migrated from an old blog (a kind of cyber reincarnation). Corrections are welcome if any errors are found. Timeline {timeline} {timeline-item color="#50BFFF"} July 5, 2022: Published on the old blog, available on archive.org {/timeline-item} {timeline-item color="#50BFFF"} March 20, 2025: Migrated to the current blog {/timeline-item} {timeline-item color="#4F9E28"} Febuary 21, 2026: Added reminder for header and static library file links {/timeline-item} {/timeline} Background Multiple access endpoints were configured for an API to handle service unavailability in certain regions where access might be blocked. Initially, I considered creating a file within the website to store node information, but this approach proved unfeasible because regions with connectivity issues couldn't retrieve information about other endpoints. Then, the idea emerged to use DNS resolution records - specifically, a TXT record - to store the relevant node data for querying. Implementation Research After searching on Bing, I found that most existing articles use sockets to directly send query packets. However, these methods typically only retrieve A and CNAME records, which wasn't suitable for my needs. Finally, I focused on the DnsQuery function mentioned in MSDN and found a sample article: Use DnsQuery to Resolve Host Names. Function Analysis According to the official documentation, the function requires the header windns.h and needs to link against the libraries Ws2_32.lib and Dnsapi.lib. The function parameters are as follows: DNS_STATUS DnsQuery_A( [in] PCSTR pszName, [in] WORD wType, [in] DWORD Options, [in, out, optional] PVOID pExtra, [out, optional] PDNS_RECORD *ppQueryResults, [out, optional] PVOID *pReserved ); Parameter Explanation: pszName is the hostname to query. wType is the query type, such as A record, CNAME, TXT, etc. Specific constants are documented by MSDN: DNS Constants. Options literally means the query method. I used DNS_QUERY_STANDARD directly…

Using Infrared Camera for Face Recognition on Xiaomi 845 Series with Custom ROMs
type: item
date: 2025-03-06T14:57:00+00:00
description: Background The Xiaomi 845 series, specifically the Mi 8 and Mi 8 Pro (UDFPS), feature a dedicated front-facing infrared camera for facial recognition. This enables facial unlock functionality even in complete darkness. However, when using a custom ROM like LineageOS compiled from its standard device tree, the infrared camera remains inaccessible, forcing the system to rely on the standard front camera. Interestingly, PixelExperience ROMs successfully utilize this hardware. This article explores the reasons behind this discrepancy and outlines the solution. The Cause CameraID The first step is directing the face recognition module to use the infrared camera. Examining the PixelExperience device tree source code reveals an overlay that configures the face unlock service to use the camera with ID 5. https://github.com/PixelExperience-Devices/device_xiaomi_dipper/blob/fourteen/overlay/packages/apps/FaceUnlockService/app/src/main/res/values/config.xml <?xml version="1.0" encoding="utf-8"?> <resources> <integer name="override_front_cam_id">5</integer> <bool name="use_alternative_vendor_impl">true</bool> </resources> PixelExperience uses Motorola's face unlock solution. Many other custom ROMs, however, utilize AOSPA's ParanoidSense. Therefore, the PixelExperience overlay method isn't directly applicable. Inspecting the ParanoidSense source code shows that it uses a system property, ro.face.sense_service.camera_id, to identify which camera to use. https://github.com/AOSPA/android_packages_apps_ParanoidSense/blob/uvite/src/co/aospa/sense/camera/CameraUtil.kt#L32 val cameraIdProp = SystemProperties.get("ro.face.sense_service.camera_id") Thus, in theory, simply setting the ro.face.sense_service.camera_id property to 5 should direct it to the infrared camera. The vendor.camera.aux.packagelist Property Merely setting the CameraID property is insufficient; the face unlock module would simply fail to access the camera. Delving into the Android framework code reveals that the syste…

Adding KernelSU Support to Android 4.9 Kernel
type: item
date: 2024-12-26T16:18:00+00:00
description: Introduction KernelSU has been available for a while. Officially, it only supports GKI kernels, but the project provides integration guidelines for non-GKI kernels. The Xiaomi Mi 8 Pro, which I use, is based on the Android 4.9 kernel. Testing showed that directly using KernelSU's integration script caused issues, so I'm documenting the process here. Special thanks to: Developer Tomsec for providing the 4.9 kernel fix. Prerequisites Android Kernel source code. Here, we use LineageOS/android_kernel_xiaomi_sdm845 Network access to GitHub AnyKernel3 source code. You can refer to this repository: YoriInstitute/AnyKernel3-equuleus Cross-compiler. You can refer to this repository: https://github.com/YoriInstitute/AnyKernel3-equuleus/blob/13/.github/workflows/build.yml#L21-L23 A build server Let's Start Configuring the build environment won't be detailed here. You can integrate it directly into the boot.img when building the ROM, or compile it separately as an AnyKernel3 flashable zip. This guide uses the AnyKernel3 approach. Download Kernel Source Code and Cross-Compiler git clone https://github.com/KaguraiYoRoy/android_kernel_xiaomi_sdm845 -b lineage-20 sdm845 #Kernel source git clone https://android.googlesource.com/platform/prebuilts/clang/host/linux-x86 --depth=1 -b android-13.0.0_r43 clang #Clang git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9 -b android-10.0.0_r32 --depth=1 #aarch64 GCC git clone https://android.googlesource.com/platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9 -b android-10.0.0_r32 --depth=1 #arm GCC Different kernels might require different cross-compilers. Please adjust according to your specific case. {alert type="info"} When cloning the kernel source, --depth=1 wasn't used initially to facilitate easier cherry-picking later. If you plan to manually modify the kernel source instead of using cherry-pick, you can add this parameter to significantly reduce download time. {/al…

Enabling EROFS Support for an Android ROM with Kernel 4.9
type: item
date: 2024-12-25T15:26:00+00:00
description: Foreword As everyone knows, I'm a long-standing Mi 8 Pro (Under-Screen Fingerprint Edition) holdout I've always wanted to port erofs to this device (please search online for what erofs is). But after some research, I found out that erofs was merged into the Linux kernel in version 5.10, which means I have to manually integrate it into our 4.9 kernel. Materials Needed Android ROM Source Code: Using LineageOS 22.0 here. Android Kernel Source Code: Using the official LineageOS kernel for Xiaomi SDM845 devices: LineageOS/android_kernel_xiaomi_sdm845 Device Tree: Using the official LineageOS device trees, which include the sdm845-common part: LineageOS/android_device_xiaomi_sdm845-common and the device-specific part: LineageOS/android_device_xiaomi_equuleus A build server {alert type="info"} Note: Since I'm primarily focused on ROM building, this article mainly documents the process within that context. {/alert} Let's Start Setting up the Android ROM build environment won't be covered here, as there are plenty of guides online. Download the ROM source, device tree, and kernel source, and place them in the correct locations. Adding EROFS Support to the Kernel The code changes were picked from ReallySnow's msm-4.9 kernel (Thanks to ReallySnow for the support!). You can refer to these branches: https://github.com/ReallySnow/msm-4.9/tree/erofs https://github.com/YoriInstitute/android_kernel_xiaomi_sdm845/tree/lineage-22.0-erofs Before picking the commits, you need to resolve conflicts in the lz4 compression code. For the detailed relation chain, refer to: https://review.lineageos.org/c/LineageOS/android_kernel_xiaomi_sdm845/+/412614 I tried to submit these changes to LineageOS official, but obviously, they weren't merged x After picking the changes, enable erofs support in the kernel's defconfig file: Open $KERNEL_SOURCE/arch/arm64/configs/vendor/xiaomi/mi845_defconfig and add: CONFIG_EROFS_FS=y: commit 7ae5caab2c15982b3d3821c97e2f2e6126ca1281 (HEAD -> erofs, refs/published/…