mirror of
https://github.com/bolucat/Archive.git
synced 2026-04-22 16:07:49 +08:00
Update On Thu Jan 29 20:06:00 CET 2026
This commit is contained in:
@@ -1255,3 +1255,4 @@ Update On Sun Jan 25 19:40:50 CET 2026
|
||||
Update On Mon Jan 26 19:49:29 CET 2026
|
||||
Update On Tue Jan 27 19:51:58 CET 2026
|
||||
Update On Wed Jan 28 19:49:27 CET 2026
|
||||
Update On Thu Jan 29 20:05:52 CET 2026
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ require (
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
|
||||
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141
|
||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443
|
||||
github.com/metacubex/tls v0.1.0
|
||||
github.com/metacubex/tls v0.1.2
|
||||
github.com/metacubex/utls v1.8.4
|
||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f
|
||||
github.com/mroth/weightedrand/v2 v2.1.0
|
||||
|
||||
+2
-2
@@ -141,8 +141,8 @@ github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141 h1:DK2l6m2Fc85H2Bhi
|
||||
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141/go.mod h1:/yI4OiGOSn0SURhZdJF3CbtPg3nwK700bG8TZLMBvAg=
|
||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o=
|
||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||
github.com/metacubex/tls v0.1.0 h1:1kjR/1q2uU1cZIwiHYEnWzS4L+0Cu1/X3yfIQ76BzNY=
|
||||
github.com/metacubex/tls v0.1.0/go.mod h1:0XeVdL0cBw+8i5Hqy3lVeP9IyD/LFTq02ExvHM6rzEM=
|
||||
github.com/metacubex/tls v0.1.2 h1:qM0ATVnPFts5kZNTb+TukdaJ3hIf1ZVgKnXJCGfBmGI=
|
||||
github.com/metacubex/tls v0.1.2/go.mod h1:0XeVdL0cBw+8i5Hqy3lVeP9IyD/LFTq02ExvHM6rzEM=
|
||||
github.com/metacubex/utls v1.8.4 h1:HmL9nUApDdWSkgUyodfwF6hSjtiwCGGdyhaSpEejKpg=
|
||||
github.com/metacubex/utls v1.8.4/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko=
|
||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk=
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"manifest_version": 1,
|
||||
"latest": {
|
||||
"mihomo": "v1.19.19",
|
||||
"mihomo_alpha": "alpha-d18a14a",
|
||||
"mihomo_alpha": "alpha-e45c896",
|
||||
"clash_rs": "v0.9.4",
|
||||
"clash_premium": "2023-09-05-gdcc8d87",
|
||||
"clash_rs_alpha": "0.9.4-alpha+sha.001aa41"
|
||||
@@ -69,5 +69,5 @@
|
||||
"linux-armv7hf": "clash-armv7-unknown-linux-gnueabihf"
|
||||
}
|
||||
},
|
||||
"updated_at": "2026-01-27T22:22:01.219Z"
|
||||
"updated_at": "2026-01-28T22:22:39.173Z"
|
||||
}
|
||||
|
||||
@@ -152,6 +152,13 @@ define U-Boot/rock-4se-rk3399
|
||||
radxa_rock-4se
|
||||
endef
|
||||
|
||||
define U-Boot/rock-4c-plus-rk3399
|
||||
$(U-Boot/rk3399/Default)
|
||||
NAME:=ROCK 4C+
|
||||
BUILD_DEVICES:= \
|
||||
radxa_rock-4c-plus
|
||||
endef
|
||||
|
||||
define U-Boot/rock-pi-4-rk3399
|
||||
$(U-Boot/rk3399/Default)
|
||||
NAME:=Rock Pi 4
|
||||
@@ -381,15 +388,6 @@ define U-Boot/generic-rk3576
|
||||
friendlyarm_nanopi-r76s
|
||||
endef
|
||||
|
||||
define U-Boot/nanopi-m5-rk3576
|
||||
$(U-Boot/rk3576/Default)
|
||||
NAME:=NanoPi M5
|
||||
BUILD_DEVICES:= \
|
||||
friendlyarm_nanopi-m5 \
|
||||
friendlyarm_nanopi-r76s
|
||||
IDB_PRE_BUILD:=1
|
||||
endef
|
||||
|
||||
define U-Boot/rock-4d-rk3576
|
||||
$(U-Boot/rk3576/Default)
|
||||
NAME:=ROCK 4D
|
||||
@@ -512,7 +510,6 @@ UBOOT_TARGETS := \
|
||||
rock-3b-rk3568 \
|
||||
station-p2-rk3568 \
|
||||
generic-rk3576 \
|
||||
nanopi-m5-rk3576 \
|
||||
rock-4d-rk3576 \
|
||||
sige5-rk3576 \
|
||||
generic-rk3588 \
|
||||
@@ -533,6 +530,7 @@ UBOOT_TARGETS := \
|
||||
nanopc-t4-rk3399 \
|
||||
nanopi-r4s-rk3399 \
|
||||
nanopi-r4se-rk3399 \
|
||||
rock-4c-plus-rk3399 \
|
||||
rock-pi-4-rk3399 \
|
||||
rock-4se-rk3399 \
|
||||
rockpro64-rk3399 \
|
||||
@@ -562,12 +560,8 @@ define Build/InstallDev
|
||||
ifneq ($(USE_RKBIN),)
|
||||
$(STAGING_DIR_IMAGE)/loaderimage --pack --uboot $(PKG_BUILD_DIR)/u-boot-dtb.bin $(PKG_BUILD_DIR)/uboot.img 0x800000
|
||||
$(CP) $(PKG_BUILD_DIR)/uboot.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-uboot.img
|
||||
else
|
||||
ifneq ($(IDB_PRE_BUILD),)
|
||||
$(CP) ./files/$(BUILD_VARIANT)-idbloader.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-idbloader.img
|
||||
else
|
||||
$(CP) $(PKG_BUILD_DIR)/idbloader.img $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-idbloader.img
|
||||
endif
|
||||
$(CP) $(PKG_BUILD_DIR)/u-boot.itb $(STAGING_DIR_IMAGE)/$(BUILD_VARIANT)-u-boot.itb
|
||||
endif
|
||||
endef
|
||||
|
||||
Binary file not shown.
+121
@@ -0,0 +1,121 @@
|
||||
From 6b152999908b526c73b2ce91ecf444bae892796e Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Wed, 29 Jan 2025 22:36:27 +0000
|
||||
Subject: [PATCH 1/7] rockchip: mkimage: Split size_and_off and size_and_nimage
|
||||
|
||||
Split 32-bit size_and_off and size_and_nimage fields of the v2 image
|
||||
format header into their own 16-bit size, offset and num_images fields.
|
||||
|
||||
Set num_images based on number of images passed by the datafile
|
||||
parameter and size based on the offset to the hash field to fix using a
|
||||
single init data file and no boot data file for the v2 image format.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
tools/rkcommon.c | 44 ++++++++++++++++++++++++--------------------
|
||||
1 file changed, 24 insertions(+), 20 deletions(-)
|
||||
|
||||
--- a/tools/rkcommon.c
|
||||
+++ b/tools/rkcommon.c
|
||||
@@ -34,15 +34,16 @@ enum hash_type {
|
||||
/**
|
||||
* struct image_entry
|
||||
*
|
||||
- * @size_and_off: [31:16]image size;[15:0]image offset
|
||||
- * @address: default as 0xFFFFFFFF
|
||||
+ * @offset: image offset (unit as 512 byte blocks)
|
||||
+ * @size: image size (unit as 512 byte blocks)
|
||||
+ * @address: load address (default as 0xFFFFFFFF)
|
||||
* @flag: no use
|
||||
* @counter: no use
|
||||
* @hash: hash of image
|
||||
- *
|
||||
*/
|
||||
struct image_entry {
|
||||
- uint32_t size_and_off;
|
||||
+ uint16_t offset;
|
||||
+ uint16_t size;
|
||||
uint32_t address;
|
||||
uint32_t flag;
|
||||
uint32_t counter;
|
||||
@@ -56,16 +57,17 @@ struct image_entry {
|
||||
* This is stored at SD card block 64 (where each block is 512 bytes)
|
||||
*
|
||||
* @magic: Magic (must be RK_MAGIC_V2)
|
||||
- * @size_and_nimage: [31:16]number of images;[15:0]
|
||||
- * offset to hash field of header(unit as 4Byte)
|
||||
- * @boot_flag: [3:0]hash type(0:none,1:sha256,2:sha512)
|
||||
- * @signature: hash or signature for header info
|
||||
- *
|
||||
+ * @size: offset to hash field of header (unit as 4 bytes)
|
||||
+ * @num_images: number of images
|
||||
+ * @boot_flag: [3:0] hash type (0:none, 1:sha256, 2:sha512)
|
||||
+ * @images: images
|
||||
+ * @hash: hash or signature for header info
|
||||
*/
|
||||
struct header0_info_v2 {
|
||||
uint32_t magic;
|
||||
uint8_t reserved[4];
|
||||
- uint32_t size_and_nimage;
|
||||
+ uint16_t size;
|
||||
+ uint16_t num_images;
|
||||
uint32_t boot_flag;
|
||||
uint8_t reserved1[104];
|
||||
struct image_entry images[4];
|
||||
@@ -350,17 +352,18 @@ static void rkcommon_set_header0_v2(void
|
||||
printf("Image Type: Rockchip %s boot image\n",
|
||||
rkcommon_get_spl_hdr(params));
|
||||
memset(buf, '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
|
||||
- hdr->magic = cpu_to_le32(RK_MAGIC_V2);
|
||||
- hdr->size_and_nimage = cpu_to_le32((2 << 16) + 384);
|
||||
+ hdr->magic = cpu_to_le32(RK_MAGIC_V2);
|
||||
hdr->boot_flag = cpu_to_le32(HASH_SHA256);
|
||||
sector_offset = 4;
|
||||
image_size_array[0] = spl_params.init_size;
|
||||
image_size_array[1] = spl_params.boot_size;
|
||||
|
||||
for (i = 0; i < 2; i++) {
|
||||
+ if (!image_size_array[i])
|
||||
+ break;
|
||||
image_sector_count = image_size_array[i] / RK_BLK_SIZE;
|
||||
- hdr->images[i].size_and_off = cpu_to_le32((image_sector_count
|
||||
- << 16) + sector_offset);
|
||||
+ hdr->images[i].offset = cpu_to_le16(sector_offset);
|
||||
+ hdr->images[i].size = cpu_to_le16(image_sector_count);
|
||||
hdr->images[i].address = 0xFFFFFFFF;
|
||||
hdr->images[i].counter = cpu_to_le32(i + 1);
|
||||
image_ptr = buf + sector_offset * RK_BLK_SIZE;
|
||||
@@ -369,6 +372,8 @@ static void rkcommon_set_header0_v2(void
|
||||
sector_offset = sector_offset + image_sector_count;
|
||||
}
|
||||
|
||||
+ hdr->num_images = cpu_to_le16(i);
|
||||
+ hdr->size = cpu_to_le16(offsetof(typeof(*hdr), hash) / sizeof(uint32_t));
|
||||
do_sha256_hash(buf, (void *)hdr->hash - buf, hdr->hash);
|
||||
}
|
||||
|
||||
@@ -515,10 +520,8 @@ void rkcommon_print_header(const void *b
|
||||
return;
|
||||
}
|
||||
|
||||
- init_size = header0_v2.images[0].size_and_off >> 16;
|
||||
- init_size = init_size * RK_BLK_SIZE;
|
||||
- boot_size = header0_v2.images[1].size_and_off >> 16;
|
||||
- boot_size = boot_size * RK_BLK_SIZE;
|
||||
+ init_size = le16_to_cpu(header0_v2.images[0].size) * RK_BLK_SIZE;
|
||||
+ boot_size = le16_to_cpu(header0_v2.images[1].size) * RK_BLK_SIZE;
|
||||
} else {
|
||||
ret = rkcommon_parse_header(buf, &header0, &spl_info);
|
||||
|
||||
@@ -532,8 +535,9 @@ void rkcommon_print_header(const void *b
|
||||
}
|
||||
|
||||
image_type = ret;
|
||||
- init_size = header0.init_size * RK_BLK_SIZE;
|
||||
- boot_size = header0.init_boot_size * RK_BLK_SIZE - init_size;
|
||||
+ init_size = le16_to_cpu(header0.init_size) * RK_BLK_SIZE;
|
||||
+ boot_size = le16_to_cpu(header0.init_boot_size) * RK_BLK_SIZE -
|
||||
+ init_size;
|
||||
|
||||
printf("Image Type: Rockchip %s (%s) boot image\n",
|
||||
spl_info->spl_hdr,
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
From beea345ad405bd236d15d53da1256eaa95014c7b Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Wed, 29 Jan 2025 22:36:28 +0000
|
||||
Subject: [PATCH 2/7] rockchip: mkimage: Print image information for all
|
||||
embedded images
|
||||
|
||||
The v2 image format can embed up to 4 data files compared to the two
|
||||
init and boot data files using the older image format.
|
||||
|
||||
Add support for displaying more of the image header information that
|
||||
exists in the v2 image format, e.g. image load address and flag.
|
||||
|
||||
Example for v2 image format:
|
||||
|
||||
> tools/mkimage -l rk3576_idblock_v1.09.107.img
|
||||
Rockchip Boot Image (v2)
|
||||
Image 1: 4096 @ 0x1000
|
||||
- Load address: 0x3ffc0000
|
||||
Image 2: 77824 @ 0x2000
|
||||
- Load address: 0x3ff81000
|
||||
Image 3: 262144 @ 0x15000
|
||||
|
||||
Example for older image format:
|
||||
|
||||
> tools/mkimage -l u-boot-rockchip.bin
|
||||
Rockchip RK32 (SD/MMC) Boot Image
|
||||
Init Data: 20480 @ 0x800
|
||||
Boot Data: 112640 @ 0x5800
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
tools/rkcommon.c | 41 +++++++++++++++++++++++++++++++----------
|
||||
1 file changed, 31 insertions(+), 10 deletions(-)
|
||||
|
||||
--- a/tools/rkcommon.c
|
||||
+++ b/tools/rkcommon.c
|
||||
@@ -349,8 +349,6 @@ static void rkcommon_set_header0_v2(void
|
||||
uint8_t *image_ptr = NULL;
|
||||
int i;
|
||||
|
||||
- printf("Image Type: Rockchip %s boot image\n",
|
||||
- rkcommon_get_spl_hdr(params));
|
||||
memset(buf, '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
|
||||
hdr->magic = cpu_to_le32(RK_MAGIC_V2);
|
||||
hdr->boot_flag = cpu_to_le32(HASH_SHA256);
|
||||
@@ -504,6 +502,29 @@ int rkcommon_verify_header(unsigned char
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
+static void rkcommon_print_header_v2(const struct header0_info_v2 *hdr)
|
||||
+{
|
||||
+ uint32_t val;
|
||||
+ int i;
|
||||
+
|
||||
+ printf("Rockchip Boot Image (v2)\n");
|
||||
+
|
||||
+ for (i = 0; i < le16_to_cpu(hdr->num_images); i++) {
|
||||
+ printf("Image %u: %u @ 0x%x\n",
|
||||
+ le32_to_cpu(hdr->images[i].counter),
|
||||
+ le16_to_cpu(hdr->images[i].size) * RK_BLK_SIZE,
|
||||
+ le16_to_cpu(hdr->images[i].offset) * RK_BLK_SIZE);
|
||||
+
|
||||
+ val = le32_to_cpu(hdr->images[i].address);
|
||||
+ if (val != 0xFFFFFFFF)
|
||||
+ printf("- Load address: 0x%x\n", val);
|
||||
+
|
||||
+ val = le32_to_cpu(hdr->images[i].flag);
|
||||
+ if (val)
|
||||
+ printf("- Flag: 0x%x\n", val);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void rkcommon_print_header(const void *buf, struct image_tool_params *params)
|
||||
{
|
||||
struct header0_info header0;
|
||||
@@ -520,8 +541,7 @@ void rkcommon_print_header(const void *b
|
||||
return;
|
||||
}
|
||||
|
||||
- init_size = le16_to_cpu(header0_v2.images[0].size) * RK_BLK_SIZE;
|
||||
- boot_size = le16_to_cpu(header0_v2.images[1].size) * RK_BLK_SIZE;
|
||||
+ rkcommon_print_header_v2(&header0_v2);
|
||||
} else {
|
||||
ret = rkcommon_parse_header(buf, &header0, &spl_info);
|
||||
|
||||
@@ -539,15 +559,16 @@ void rkcommon_print_header(const void *b
|
||||
boot_size = le16_to_cpu(header0.init_boot_size) * RK_BLK_SIZE -
|
||||
init_size;
|
||||
|
||||
- printf("Image Type: Rockchip %s (%s) boot image\n",
|
||||
- spl_info->spl_hdr,
|
||||
+ printf("Rockchip %s (%s) Boot Image\n", spl_info->spl_hdr,
|
||||
(image_type == IH_TYPE_RKSD) ? "SD/MMC" : "SPI");
|
||||
- }
|
||||
|
||||
- printf("Init Data Size: %d bytes\n", init_size);
|
||||
+ printf("Init Data: %d @ 0x%x\n", init_size,
|
||||
+ le16_to_cpu(header0.init_offset) * RK_BLK_SIZE);
|
||||
|
||||
- if (boot_size != RK_MAX_BOOT_SIZE)
|
||||
- printf("Boot Data Size: %d bytes\n", boot_size);
|
||||
+ if (boot_size != RK_MAX_BOOT_SIZE)
|
||||
+ printf("Boot Data: %d @ 0x%x\n", boot_size, init_size +
|
||||
+ le16_to_cpu(header0.init_offset) * RK_BLK_SIZE);
|
||||
+ }
|
||||
}
|
||||
|
||||
void rkcommon_rc4_encode_spl(void *buf, unsigned int offset, unsigned int size)
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
From cad4d0d7d04f71e9b8cc7704254abe74e7b17b50 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Wed, 29 Jan 2025 22:36:29 +0000
|
||||
Subject: [PATCH 3/7] rockchip: mkimage: Print boot0 and boot1 parameters
|
||||
|
||||
The v2 image format embeds boot0 and boot1 parameters, the vendor tool
|
||||
boot_merger may write these parameters based on the rkboot miniall.ini
|
||||
files.
|
||||
|
||||
E.g. a RK3576 boot image may contain a boot1 parameter that signals
|
||||
BootROM or vendor blobs to use 1 GHz instead of the regular 24 MHz rate
|
||||
for the high precision timer.
|
||||
|
||||
Add support for printing boot0 and boot1 parameters, e.g.:
|
||||
|
||||
> tools/mkimage -l rk3576_idblock_v1.09.107.img
|
||||
Rockchip Boot Image (v2)
|
||||
Boot1 2: 0x100
|
||||
Image 1: 4096 @ 0x1000
|
||||
- Load address: 0x3ffc0000
|
||||
Image 2: 77824 @ 0x2000
|
||||
- Load address: 0x3ff81000
|
||||
Image 3: 262144 @ 0x15000
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
tools/rkcommon.c | 18 +++++++++++++++++-
|
||||
1 file changed, 17 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/tools/rkcommon.c
|
||||
+++ b/tools/rkcommon.c
|
||||
@@ -62,6 +62,8 @@ struct image_entry {
|
||||
* @boot_flag: [3:0] hash type (0:none, 1:sha256, 2:sha512)
|
||||
* @images: images
|
||||
* @hash: hash or signature for header info
|
||||
+ *
|
||||
+ * Other fields are not used by U-Boot
|
||||
*/
|
||||
struct header0_info_v2 {
|
||||
uint32_t magic;
|
||||
@@ -69,7 +71,9 @@ struct header0_info_v2 {
|
||||
uint16_t size;
|
||||
uint16_t num_images;
|
||||
uint32_t boot_flag;
|
||||
- uint8_t reserved1[104];
|
||||
+ uint8_t reserved1[32];
|
||||
+ uint32_t boot0_param[10];
|
||||
+ uint32_t boot1_param[8];
|
||||
struct image_entry images[4];
|
||||
uint8_t reserved2[1064];
|
||||
uint8_t hash[512];
|
||||
@@ -509,6 +513,18 @@ static void rkcommon_print_header_v2(con
|
||||
|
||||
printf("Rockchip Boot Image (v2)\n");
|
||||
|
||||
+ for (i = 0; i < ARRAY_SIZE(hdr->boot0_param); i++) {
|
||||
+ val = le32_to_cpu(hdr->boot0_param[i]);
|
||||
+ if (val)
|
||||
+ printf("Boot0 %d: 0x%x\n", i, val);
|
||||
+ }
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(hdr->boot1_param); i++) {
|
||||
+ val = le32_to_cpu(hdr->boot1_param[i]);
|
||||
+ if (val)
|
||||
+ printf("Boot1 %d: 0x%x\n", i, val);
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < le16_to_cpu(hdr->num_images); i++) {
|
||||
printf("Image %u: %u @ 0x%x\n",
|
||||
le32_to_cpu(hdr->images[i].counter),
|
||||
+208
@@ -0,0 +1,208 @@
|
||||
From 3df6b71b8226dfd34d587b01d0674a22ef4ca440 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Wed, 29 Jan 2025 22:36:30 +0000
|
||||
Subject: [PATCH 4/7] rockchip: mkimage: Add option to change image offset
|
||||
alignment
|
||||
|
||||
The vendor boot_merger tool support a ALIGN parameter that is used to
|
||||
define offset alignment of the embedded images.
|
||||
|
||||
Vendor use this for RK3576 to change offset alignment from the common
|
||||
2 KiB to 4 KiB, presumably it may have something to do with UFS.
|
||||
Testing with eMMC has shown that using a 512-byte alignment also work.
|
||||
|
||||
Add support for overriding offset alignment in case this is needed for
|
||||
e.g. RK3576 in the future.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
tools/rkcommon.c | 75 +++++++++++++++++++++++++++++++-----------------
|
||||
tools/rkcommon.h | 2 --
|
||||
2 files changed, 49 insertions(+), 28 deletions(-)
|
||||
|
||||
--- a/tools/rkcommon.c
|
||||
+++ b/tools/rkcommon.c
|
||||
@@ -140,6 +140,7 @@ struct spl_info {
|
||||
const uint32_t spl_size;
|
||||
const bool spl_rc4;
|
||||
const uint32_t header_ver;
|
||||
+ const uint32_t align;
|
||||
};
|
||||
|
||||
static struct spl_info spl_infos[] = {
|
||||
@@ -199,14 +200,19 @@ static struct spl_info *rkcommon_get_spl
|
||||
return NULL;
|
||||
}
|
||||
|
||||
-static int rkcommon_get_aligned_size(struct image_tool_params *params,
|
||||
- const char *fname)
|
||||
+static bool rkcommon_is_header_v2(struct image_tool_params *params)
|
||||
{
|
||||
- int size;
|
||||
+ struct spl_info *info = rkcommon_get_spl_info(params->imagename);
|
||||
|
||||
- size = imagetool_get_filesize(params, fname);
|
||||
- if (size < 0)
|
||||
- return -1;
|
||||
+ return (info->header_ver == RK_HEADER_V2);
|
||||
+}
|
||||
+
|
||||
+static int rkcommon_get_aligned_size(struct image_tool_params *params, int size)
|
||||
+{
|
||||
+ struct spl_info *info = rkcommon_get_spl_info(params->imagename);
|
||||
+
|
||||
+ if (info->align)
|
||||
+ return ROUND(size, info->align * RK_BLK_SIZE);
|
||||
|
||||
/*
|
||||
* Pad to a 2KB alignment, as required for init/boot size by the ROM
|
||||
@@ -215,6 +221,27 @@ static int rkcommon_get_aligned_size(str
|
||||
return ROUND(size, RK_SIZE_ALIGN);
|
||||
}
|
||||
|
||||
+static int rkcommon_get_header_size(struct image_tool_params *params)
|
||||
+{
|
||||
+ int header_size = rkcommon_is_header_v2(params) ?
|
||||
+ sizeof(struct header0_info_v2) :
|
||||
+ sizeof(struct header0_info);
|
||||
+
|
||||
+ return rkcommon_get_aligned_size(params, header_size);
|
||||
+}
|
||||
+
|
||||
+static int rkcommon_get_aligned_filesize(struct image_tool_params *params,
|
||||
+ const char *fname)
|
||||
+{
|
||||
+ int size;
|
||||
+
|
||||
+ size = imagetool_get_filesize(params, fname);
|
||||
+ if (size < 0)
|
||||
+ return -1;
|
||||
+
|
||||
+ return rkcommon_get_aligned_size(params, size);
|
||||
+}
|
||||
+
|
||||
int rkcommon_check_params(struct image_tool_params *params)
|
||||
{
|
||||
int i, size;
|
||||
@@ -237,14 +264,14 @@ int rkcommon_check_params(struct image_t
|
||||
spl_params.boot_file += 1;
|
||||
}
|
||||
|
||||
- size = rkcommon_get_aligned_size(params, spl_params.init_file);
|
||||
+ size = rkcommon_get_aligned_filesize(params, spl_params.init_file);
|
||||
if (size < 0)
|
||||
return EXIT_FAILURE;
|
||||
spl_params.init_size = size;
|
||||
|
||||
/* Boot file is optional, and only for back-to-bootrom functionality. */
|
||||
if (spl_params.boot_file) {
|
||||
- size = rkcommon_get_aligned_size(params, spl_params.boot_file);
|
||||
+ size = rkcommon_get_aligned_filesize(params, spl_params.boot_file);
|
||||
if (size < 0)
|
||||
return EXIT_FAILURE;
|
||||
spl_params.boot_size = size;
|
||||
@@ -301,13 +328,6 @@ bool rkcommon_need_rc4_spl(struct image_
|
||||
return info->spl_rc4;
|
||||
}
|
||||
|
||||
-static bool rkcommon_is_header_v2(struct image_tool_params *params)
|
||||
-{
|
||||
- struct spl_info *info = rkcommon_get_spl_info(params->imagename);
|
||||
-
|
||||
- return (info->header_ver == RK_HEADER_V2);
|
||||
-}
|
||||
-
|
||||
static void do_sha256_hash(uint8_t *buf, uint32_t size, uint8_t *out)
|
||||
{
|
||||
sha256_context ctx;
|
||||
@@ -320,12 +340,13 @@ static void do_sha256_hash(uint8_t *buf,
|
||||
static void rkcommon_set_header0(void *buf, struct image_tool_params *params)
|
||||
{
|
||||
struct header0_info *hdr = buf;
|
||||
- uint32_t init_boot_size;
|
||||
+ uint32_t init_boot_size, init_offset;
|
||||
|
||||
- memset(buf, '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
|
||||
+ init_offset = rkcommon_get_header_size(params) / RK_BLK_SIZE;
|
||||
+ memset(buf, '\0', init_offset * RK_BLK_SIZE);
|
||||
hdr->magic = cpu_to_le32(RK_MAGIC);
|
||||
hdr->disable_rc4 = cpu_to_le32(!rkcommon_need_rc4_spl(params));
|
||||
- hdr->init_offset = cpu_to_le16(RK_INIT_OFFSET);
|
||||
+ hdr->init_offset = cpu_to_le16(init_offset);
|
||||
hdr->init_size = cpu_to_le16(spl_params.init_size / RK_BLK_SIZE);
|
||||
|
||||
/*
|
||||
@@ -353,10 +374,10 @@ static void rkcommon_set_header0_v2(void
|
||||
uint8_t *image_ptr = NULL;
|
||||
int i;
|
||||
|
||||
- memset(buf, '\0', RK_INIT_OFFSET * RK_BLK_SIZE);
|
||||
+ sector_offset = rkcommon_get_header_size(params) / RK_BLK_SIZE;
|
||||
+ memset(buf, '\0', sector_offset * RK_BLK_SIZE);
|
||||
hdr->magic = cpu_to_le32(RK_MAGIC_V2);
|
||||
hdr->boot_flag = cpu_to_le32(HASH_SHA256);
|
||||
- sector_offset = 4;
|
||||
image_size_array[0] = spl_params.init_size;
|
||||
image_size_array[1] = spl_params.boot_size;
|
||||
|
||||
@@ -382,11 +403,12 @@ static void rkcommon_set_header0_v2(void
|
||||
void rkcommon_set_header(void *buf, struct stat *sbuf, int ifd,
|
||||
struct image_tool_params *params)
|
||||
{
|
||||
- struct header1_info *hdr = buf + RK_SPL_HDR_START;
|
||||
-
|
||||
if (rkcommon_is_header_v2(params)) {
|
||||
rkcommon_set_header0_v2(buf, params);
|
||||
} else {
|
||||
+ int header_size = rkcommon_get_header_size(params);
|
||||
+ struct header1_info *hdr = buf + header_size;
|
||||
+
|
||||
rkcommon_set_header0(buf, params);
|
||||
|
||||
/* Set up the SPL name (i.e. copy spl_hdr over) */
|
||||
@@ -394,12 +416,12 @@ void rkcommon_set_header(void *buf, str
|
||||
memcpy(&hdr->magic, rkcommon_get_spl_hdr(params), RK_SPL_HDR_SIZE);
|
||||
|
||||
if (rkcommon_need_rc4_spl(params))
|
||||
- rkcommon_rc4_encode_spl(buf, RK_SPL_HDR_START,
|
||||
+ rkcommon_rc4_encode_spl(buf, header_size,
|
||||
spl_params.init_size);
|
||||
|
||||
if (spl_params.boot_file) {
|
||||
if (rkcommon_need_rc4_spl(params))
|
||||
- rkcommon_rc4_encode_spl(buf + RK_SPL_HDR_START,
|
||||
+ rkcommon_rc4_encode_spl(buf + header_size,
|
||||
spl_params.init_size,
|
||||
spl_params.boot_size);
|
||||
}
|
||||
@@ -624,7 +646,7 @@ int rkcommon_vrec_header(struct image_to
|
||||
* 4 bytes of these images can safely be overwritten using the
|
||||
* boot magic.
|
||||
*/
|
||||
- tparams->header_size = RK_SPL_HDR_START;
|
||||
+ tparams->header_size = rkcommon_get_header_size(params);
|
||||
|
||||
/* Allocate, clear and install the header */
|
||||
tparams->hdr = malloc(tparams->header_size);
|
||||
@@ -642,7 +664,8 @@ int rkcommon_vrec_header(struct image_to
|
||||
params->orig_file_size = tparams->header_size +
|
||||
spl_params.init_size + spl_params.boot_size;
|
||||
|
||||
- params->file_size = ROUND(params->orig_file_size, RK_SIZE_ALIGN);
|
||||
+ params->file_size = rkcommon_get_aligned_size(params,
|
||||
+ params->orig_file_size);
|
||||
|
||||
/* Ignoring pad len, since we are using our own copy_image() */
|
||||
return 0;
|
||||
--- a/tools/rkcommon.h
|
||||
+++ b/tools/rkcommon.h
|
||||
@@ -10,9 +10,7 @@
|
||||
enum {
|
||||
RK_BLK_SIZE = 512,
|
||||
RK_SIZE_ALIGN = 2048,
|
||||
- RK_INIT_OFFSET = 4,
|
||||
RK_MAX_BOOT_SIZE = 512 << 10,
|
||||
- RK_SPL_HDR_START = RK_INIT_OFFSET * RK_BLK_SIZE,
|
||||
RK_SPL_HDR_SIZE = 4,
|
||||
};
|
||||
|
||||
+202
@@ -0,0 +1,202 @@
|
||||
From ed28c9e3d54cbf25dea55030c2f5a889ae3da915 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Wed, 29 Jan 2025 22:36:31 +0000
|
||||
Subject: [PATCH 5/7] rockchip: mkimage: Add support for up to 4 input files
|
||||
|
||||
The v2 image format can support up to 4 embedded images that can be
|
||||
loaded by the BootROM using the back-to-bootrom method.
|
||||
|
||||
Currently two input files can be passed in using the datafile parameter,
|
||||
separated by a colon (":").
|
||||
|
||||
Extend the datafile parameter parsing to support up to 4 input files
|
||||
separated by a colon (":") for use with the v2 image format.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
tools/rkcommon.c | 93 +++++++++++++++++++++++-------------------------
|
||||
1 file changed, 44 insertions(+), 49 deletions(-)
|
||||
|
||||
--- a/tools/rkcommon.c
|
||||
+++ b/tools/rkcommon.c
|
||||
@@ -166,17 +166,15 @@ static struct spl_info spl_infos[] = {
|
||||
/**
|
||||
* struct spl_params - spl params parsed in check_params()
|
||||
*
|
||||
- * @init_file: Init data file path
|
||||
- * @init_size: Aligned size of init data in bytes
|
||||
- * @boot_file: Boot data file path
|
||||
- * @boot_size: Aligned size of boot data in bytes
|
||||
+ * @file: image file path
|
||||
+ * @size: aligned size of image in bytes
|
||||
*/
|
||||
|
||||
struct spl_params {
|
||||
- char *init_file;
|
||||
- uint32_t init_size;
|
||||
- char *boot_file;
|
||||
- uint32_t boot_size;
|
||||
+ struct {
|
||||
+ char *file;
|
||||
+ uint32_t size;
|
||||
+ } images[4];
|
||||
};
|
||||
|
||||
static struct spl_params spl_params = { 0 };
|
||||
@@ -256,31 +254,32 @@ int rkcommon_check_params(struct image_t
|
||||
if (!rkcommon_get_spl_info(params->imagename))
|
||||
goto err_spl_info;
|
||||
|
||||
- spl_params.init_file = params->datafile;
|
||||
+ spl_params.images[0].file = params->datafile;
|
||||
+ for (i = 1; i < ARRAY_SIZE(spl_params.images); i++) {
|
||||
+ spl_params.images[i].file =
|
||||
+ strchr(spl_params.images[i - 1].file, ':');
|
||||
+ if (!spl_params.images[i].file)
|
||||
+ break;
|
||||
|
||||
- spl_params.boot_file = strchr(spl_params.init_file, ':');
|
||||
- if (spl_params.boot_file) {
|
||||
- *spl_params.boot_file = '\0';
|
||||
- spl_params.boot_file += 1;
|
||||
+ *spl_params.images[i].file = '\0';
|
||||
+ spl_params.images[i].file += 1;
|
||||
}
|
||||
|
||||
- size = rkcommon_get_aligned_filesize(params, spl_params.init_file);
|
||||
- if (size < 0)
|
||||
- return EXIT_FAILURE;
|
||||
- spl_params.init_size = size;
|
||||
+ for (i = 0; i < ARRAY_SIZE(spl_params.images); i++) {
|
||||
+ if (!spl_params.images[i].file)
|
||||
+ break;
|
||||
|
||||
- /* Boot file is optional, and only for back-to-bootrom functionality. */
|
||||
- if (spl_params.boot_file) {
|
||||
- size = rkcommon_get_aligned_filesize(params, spl_params.boot_file);
|
||||
+ size = rkcommon_get_aligned_filesize(params,
|
||||
+ spl_params.images[i].file);
|
||||
if (size < 0)
|
||||
return EXIT_FAILURE;
|
||||
- spl_params.boot_size = size;
|
||||
+ spl_params.images[i].size = size;
|
||||
}
|
||||
|
||||
- if (spl_params.init_size > rkcommon_get_spl_size(params)) {
|
||||
+ if (spl_params.images[0].size > rkcommon_get_spl_size(params)) {
|
||||
fprintf(stderr,
|
||||
"Error: SPL image is too large (size %#x than %#x)\n",
|
||||
- spl_params.init_size, rkcommon_get_spl_size(params));
|
||||
+ spl_params.images[0].size, rkcommon_get_spl_size(params));
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -347,7 +346,7 @@ static void rkcommon_set_header0(void *b
|
||||
hdr->magic = cpu_to_le32(RK_MAGIC);
|
||||
hdr->disable_rc4 = cpu_to_le32(!rkcommon_need_rc4_spl(params));
|
||||
hdr->init_offset = cpu_to_le16(init_offset);
|
||||
- hdr->init_size = cpu_to_le16(spl_params.init_size / RK_BLK_SIZE);
|
||||
+ hdr->init_size = cpu_to_le16(spl_params.images[0].size / RK_BLK_SIZE);
|
||||
|
||||
/*
|
||||
* init_boot_size needs to be set, as it is read by the BootROM
|
||||
@@ -357,10 +356,11 @@ static void rkcommon_set_header0(void *b
|
||||
* see https://lists.denx.de/pipermail/u-boot/2017-May/293267.html
|
||||
* for a more detailed explanation by Andy Yan
|
||||
*/
|
||||
- if (spl_params.boot_file)
|
||||
- init_boot_size = spl_params.init_size + spl_params.boot_size;
|
||||
+ if (spl_params.images[1].file)
|
||||
+ init_boot_size = spl_params.images[0].size +
|
||||
+ spl_params.images[1].size;
|
||||
else
|
||||
- init_boot_size = spl_params.init_size + RK_MAX_BOOT_SIZE;
|
||||
+ init_boot_size = spl_params.images[0].size + RK_MAX_BOOT_SIZE;
|
||||
hdr->init_boot_size = cpu_to_le16(init_boot_size / RK_BLK_SIZE);
|
||||
|
||||
rc4_encode(buf, RK_BLK_SIZE, rc4_key);
|
||||
@@ -370,7 +370,6 @@ static void rkcommon_set_header0_v2(void
|
||||
{
|
||||
struct header0_info_v2 *hdr = buf;
|
||||
uint32_t sector_offset, image_sector_count;
|
||||
- uint32_t image_size_array[2];
|
||||
uint8_t *image_ptr = NULL;
|
||||
int i;
|
||||
|
||||
@@ -378,19 +377,17 @@ static void rkcommon_set_header0_v2(void
|
||||
memset(buf, '\0', sector_offset * RK_BLK_SIZE);
|
||||
hdr->magic = cpu_to_le32(RK_MAGIC_V2);
|
||||
hdr->boot_flag = cpu_to_le32(HASH_SHA256);
|
||||
- image_size_array[0] = spl_params.init_size;
|
||||
- image_size_array[1] = spl_params.boot_size;
|
||||
|
||||
- for (i = 0; i < 2; i++) {
|
||||
- if (!image_size_array[i])
|
||||
+ for (i = 0; i < ARRAY_SIZE(spl_params.images); i++) {
|
||||
+ if (!spl_params.images[i].size)
|
||||
break;
|
||||
- image_sector_count = image_size_array[i] / RK_BLK_SIZE;
|
||||
+ image_sector_count = spl_params.images[i].size / RK_BLK_SIZE;
|
||||
hdr->images[i].offset = cpu_to_le16(sector_offset);
|
||||
hdr->images[i].size = cpu_to_le16(image_sector_count);
|
||||
hdr->images[i].address = 0xFFFFFFFF;
|
||||
hdr->images[i].counter = cpu_to_le32(i + 1);
|
||||
image_ptr = buf + sector_offset * RK_BLK_SIZE;
|
||||
- do_sha256_hash(image_ptr, image_size_array[i],
|
||||
+ do_sha256_hash(image_ptr, spl_params.images[i].size,
|
||||
hdr->images[i].hash);
|
||||
sector_offset = sector_offset + image_sector_count;
|
||||
}
|
||||
@@ -417,13 +414,13 @@ void rkcommon_set_header(void *buf, str
|
||||
|
||||
if (rkcommon_need_rc4_spl(params))
|
||||
rkcommon_rc4_encode_spl(buf, header_size,
|
||||
- spl_params.init_size);
|
||||
+ spl_params.images[0].size);
|
||||
|
||||
- if (spl_params.boot_file) {
|
||||
+ if (spl_params.images[1].file) {
|
||||
if (rkcommon_need_rc4_spl(params))
|
||||
rkcommon_rc4_encode_spl(buf + header_size,
|
||||
- spl_params.init_size,
|
||||
- spl_params.boot_size);
|
||||
+ spl_params.images[0].size,
|
||||
+ spl_params.images[1].size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -661,8 +658,9 @@ int rkcommon_vrec_header(struct image_to
|
||||
* We need to store the original file-size (i.e. before padding), as
|
||||
* imagetool does not set this during its adjustment of file_size.
|
||||
*/
|
||||
- params->orig_file_size = tparams->header_size +
|
||||
- spl_params.init_size + spl_params.boot_size;
|
||||
+ params->orig_file_size = tparams->header_size;
|
||||
+ for (int i = 0; i < ARRAY_SIZE(spl_params.images); i++)
|
||||
+ params->orig_file_size += spl_params.images[i].size;
|
||||
|
||||
params->file_size = rkcommon_get_aligned_size(params,
|
||||
params->orig_file_size);
|
||||
@@ -749,16 +747,13 @@ err_close:
|
||||
|
||||
int rockchip_copy_image(int ifd, struct image_tool_params *params)
|
||||
{
|
||||
- int ret;
|
||||
-
|
||||
- ret = copy_file(params, ifd, spl_params.init_file,
|
||||
- spl_params.init_size);
|
||||
- if (ret)
|
||||
- return ret;
|
||||
+ int i, ret;
|
||||
|
||||
- if (spl_params.boot_file) {
|
||||
- ret = copy_file(params, ifd, spl_params.boot_file,
|
||||
- spl_params.boot_size);
|
||||
+ for (i = 0; i < ARRAY_SIZE(spl_params.images); i++) {
|
||||
+ if (!spl_params.images[i].size)
|
||||
+ break;
|
||||
+ ret = copy_file(params, ifd, spl_params.images[i].file,
|
||||
+ spl_params.images[i].size);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
From 54d7a09689d795110d93e64ee630e121b20bc269 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Wed, 29 Jan 2025 22:36:32 +0000
|
||||
Subject: [PATCH 6/7] rockchip: mkimage: Add option for image load address and
|
||||
flag
|
||||
|
||||
The v2 image format supports defining a load address and flag for each
|
||||
embedded image.
|
||||
|
||||
Add initial support for writing the image load address and flag to the
|
||||
v2 image format header.
|
||||
|
||||
This may later be used for RK3576 to embed a minimal initial image that
|
||||
if required to fix booting from SD-card due to a BootROM issue.
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
tools/rkcommon.c | 7 ++++++-
|
||||
1 file changed, 6 insertions(+), 1 deletion(-)
|
||||
|
||||
--- a/tools/rkcommon.c
|
||||
+++ b/tools/rkcommon.c
|
||||
@@ -168,12 +168,16 @@ static struct spl_info spl_infos[] = {
|
||||
*
|
||||
* @file: image file path
|
||||
* @size: aligned size of image in bytes
|
||||
+ * @address: image load address
|
||||
+ * @flag: no use
|
||||
*/
|
||||
|
||||
struct spl_params {
|
||||
struct {
|
||||
char *file;
|
||||
uint32_t size;
|
||||
+ uint32_t address;
|
||||
+ uint32_t flag;
|
||||
} images[4];
|
||||
};
|
||||
|
||||
@@ -384,7 +388,8 @@ static void rkcommon_set_header0_v2(void
|
||||
image_sector_count = spl_params.images[i].size / RK_BLK_SIZE;
|
||||
hdr->images[i].offset = cpu_to_le16(sector_offset);
|
||||
hdr->images[i].size = cpu_to_le16(image_sector_count);
|
||||
- hdr->images[i].address = 0xFFFFFFFF;
|
||||
+ hdr->images[i].address = spl_params.images[i].address ?: 0xFFFFFFFF;
|
||||
+ hdr->images[i].flag = spl_params.images[i].flag;
|
||||
hdr->images[i].counter = cpu_to_le32(i + 1);
|
||||
image_ptr = buf + sector_offset * RK_BLK_SIZE;
|
||||
do_sha256_hash(image_ptr, spl_params.images[i].size,
|
||||
+112
@@ -0,0 +1,112 @@
|
||||
From d43031c4045ef8aaf29c467b910207e721dabce0 Mon Sep 17 00:00:00 2001
|
||||
From: Jonas Karlman <jonas@kwiboo.se>
|
||||
Date: Tue, 28 Jan 2025 01:30:12 +0000
|
||||
Subject: [PATCH 7/7] WIP: rockchip: mkimage: Add rk3576 align and sd-card
|
||||
workaround
|
||||
|
||||
The BootROM on RK3576 has an issue loading boot images from an SD-card.
|
||||
This issue can be worked around by injecting an initial boot image
|
||||
before TPL that:
|
||||
|
||||
writel(0x3ffff800, 0x3ff803b0)
|
||||
|
||||
Prepend an image containing binary code that does this and return to
|
||||
BootROM to load next image, TPL.
|
||||
|
||||
TODO: embed the binary code into rkcommon.c
|
||||
|
||||
Signed-off-by: Jonas Karlman <jonas@kwiboo.se>
|
||||
---
|
||||
rk3576-boost.bin | Bin 0 -> 24 bytes
|
||||
rk3576-boost.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
tools/rkcommon.c | 18 ++++++++++++++++-
|
||||
3 files changed, 66 insertions(+), 1 deletion(-)
|
||||
create mode 100644 rk3576-boost.bin
|
||||
create mode 100644 rk3576-boost.c
|
||||
|
||||
--- /dev/null
|
||||
+++ b/rk3576-boost.c
|
||||
@@ -0,0 +1,49 @@
|
||||
+// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
+// Copyright Contributors to the U-Boot project.
|
||||
+
|
||||
+/*
|
||||
+ * Generate assembly code for the c code in this file:
|
||||
+ * aarch64-linux-gnu-gcc -nostdlib -ffreestanding -Os -S -o rk3576-boost.S rk3576-boost.c
|
||||
+ *
|
||||
+ * Compile assembly code and extract the AArch64 binary code:
|
||||
+ * aarch64-linux-gnu-as -o rk3576-boost.o rk3576-boost.S
|
||||
+ * aarch64-linux-gnu-objcopy -O binary -j .text rk3576-boost.o rk3576-boost.bin
|
||||
+ */
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+#define SYS_SRAM_BASE 0x3ff80000
|
||||
+#define OFFSET 0x03b0
|
||||
+
|
||||
+int _start(void)
|
||||
+{
|
||||
+ uint32_t *sram = (void*)(SYS_SRAM_BASE + OFFSET);
|
||||
+
|
||||
+ /* set unknown value in sram to fix boot from sdmmc */
|
||||
+ *(sram) = 0x3ffff800;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ .arch armv8-a
|
||||
+ .file "rk3576-boost.c"
|
||||
+ .text
|
||||
+ .align 2
|
||||
+ .global _start
|
||||
+ .type _start, %function
|
||||
+_start:
|
||||
+.LFB0:
|
||||
+ .cfi_startproc
|
||||
+ mov x0, 944
|
||||
+ mov w1, 1073739776
|
||||
+ movk x0, 0x3ff8, lsl 16
|
||||
+ str w1, [x0]
|
||||
+ mov w0, 0
|
||||
+ ret
|
||||
+ .cfi_endproc
|
||||
+.LFE0:
|
||||
+ .size _start, .-_start
|
||||
+ .ident "GCC: (Ubuntu 13.3.0-6ubuntu2~24.04) 13.3.0"
|
||||
+ .section .note.GNU-stack,"",@progbits
|
||||
+*/
|
||||
--- a/tools/rkcommon.c
|
||||
+++ b/tools/rkcommon.c
|
||||
@@ -159,7 +159,7 @@ static struct spl_info spl_infos[] = {
|
||||
{ "rv1126", "110B", 0x10000 - 0x1000, false, RK_HEADER_V1 },
|
||||
{ "rk3528", "RK35", 0x10000 - 0x1000, false, RK_HEADER_V2 },
|
||||
{ "rk3568", "RK35", 0x10000 - 0x1000, false, RK_HEADER_V2 },
|
||||
- { "rk3576", "RK35", 0x80000 - 0x1000, false, RK_HEADER_V2 },
|
||||
+ { "rk3576", "RK35", 0x80000 - 0x1000, false, RK_HEADER_V2, 8 },
|
||||
{ "rk3588", "RK35", 0x100000 - 0x1000, false, RK_HEADER_V2 },
|
||||
};
|
||||
|
||||
@@ -287,6 +287,22 @@ int rkcommon_check_params(struct image_t
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
+ if (!strcmp(params->imagename, "rk3576")) {
|
||||
+ size = rkcommon_get_aligned_filesize(params, "rk3576-boost.bin");
|
||||
+ if (size < 0)
|
||||
+ return EXIT_SUCCESS;
|
||||
+
|
||||
+ for (i = ARRAY_SIZE(spl_params.images) - 1; i > 0; i--) {
|
||||
+ spl_params.images[i] = spl_params.images[i - 1];
|
||||
+ }
|
||||
+
|
||||
+ spl_params.images[0].file = "rk3576-boost.bin";
|
||||
+ spl_params.images[0].size = size;
|
||||
+
|
||||
+ spl_params.images[0].address = 0x3ffc0000;
|
||||
+ spl_params.images[1].address = 0x3ff81000;
|
||||
+ }
|
||||
+
|
||||
return EXIT_SUCCESS;
|
||||
|
||||
err_spl_info:
|
||||
Binary file not shown.
+755
@@ -0,0 +1,755 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
|
||||
* Copyright (c) 2019 Radxa Limited
|
||||
* Copyright (c) 2022 Amarula Solutions(India)
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <dt-bindings/leds/common.h>
|
||||
#include "rk3399-t.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Radxa ROCK 4C+";
|
||||
compatible = "radxa,rock-4c-plus", "rockchip,rk3399";
|
||||
|
||||
aliases {
|
||||
ethernet0 = &gmac;
|
||||
mmc0 = &sdhci;
|
||||
mmc1 = &sdmmc;
|
||||
led-boot = &led_blue;
|
||||
led-failsafe = &led_blue;
|
||||
led-running = &led_blue;
|
||||
led-upgrade = &led_blue;
|
||||
};
|
||||
|
||||
chosen {
|
||||
stdout-path = "serial2:1500000n8";
|
||||
};
|
||||
|
||||
clkin_gmac: external-gmac-clock {
|
||||
compatible = "fixed-clock";
|
||||
clock-frequency = <125000000>;
|
||||
clock-output-names = "clkin_gmac";
|
||||
#clock-cells = <0>;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&user_led1 &user_led2>;
|
||||
|
||||
/* USER_LED1 */
|
||||
led-0 {
|
||||
function = LED_FUNCTION_POWER;
|
||||
color = <LED_COLOR_ID_GREEN>;
|
||||
default-state = "on";
|
||||
gpios = <&gpio3 RK_PD4 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
/* USER_LED2 */
|
||||
led_blue: led-1 {
|
||||
function = LED_FUNCTION_STATUS;
|
||||
color = <LED_COLOR_ID_BLUE>;
|
||||
gpios = <&gpio3 RK_PD5 GPIO_ACTIVE_HIGH>;
|
||||
};
|
||||
};
|
||||
|
||||
rk809-sound {
|
||||
compatible = "simple-audio-card";
|
||||
simple-audio-card,format = "i2s";
|
||||
simple-audio-card,name = "Analog RK809";
|
||||
simple-audio-card,mclk-fs = <256>;
|
||||
|
||||
simple-audio-card,cpu {
|
||||
sound-dai = <&i2s0>;
|
||||
};
|
||||
|
||||
simple-audio-card,codec {
|
||||
sound-dai = <&rk809>;
|
||||
};
|
||||
};
|
||||
|
||||
sdio_pwrseq: sdio-pwrseq {
|
||||
compatible = "mmc-pwrseq-simple";
|
||||
clocks = <&rk809 1>;
|
||||
clock-names = "ext_clock";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&wifi_enable_h>;
|
||||
reset-gpios = <&gpio0 RK_PB2 GPIO_ACTIVE_LOW>;
|
||||
};
|
||||
|
||||
vcc_3v3: regulator-vcc-3v3 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc_3v3";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
vin-supply = <&vcc3v3_sys>;
|
||||
};
|
||||
|
||||
vcc3v3_phy1: regulator-vcc3v3-phy1 {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc3v3_phy1";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
vin-supply = <&vcc_3v3>;
|
||||
};
|
||||
|
||||
vcc5v0_host1: regulator-vcc5v0-host {
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-high;
|
||||
gpio = <&gpio3 RK_PD6 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vcc5v0_host_en>;
|
||||
regulator-name = "vcc5v0_host1";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
vin-supply = <&vcc5v0_host0_s0>;
|
||||
};
|
||||
|
||||
vcc5v0_sys: regulator-vcc5v0-sys {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vcc5v0_sys";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <5000000>;
|
||||
regulator-max-microvolt = <5000000>;
|
||||
};
|
||||
|
||||
vcc5v0_typec: regulator-vcc5v0-typec {
|
||||
compatible = "regulator-fixed";
|
||||
enable-active-high;
|
||||
gpio = <&gpio1 RK_PA3 GPIO_ACTIVE_HIGH>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&vcc5v0_typec0_en>;
|
||||
regulator-name = "vcc5v0_typec";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
|
||||
vdd_log: regulator-vdd-log {
|
||||
compatible = "regulator-fixed";
|
||||
regulator-name = "vdd_log";
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <950000>;
|
||||
regulator-max-microvolt = <950000>;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
};
|
||||
};
|
||||
|
||||
&cpu_l0 {
|
||||
cpu-supply = <&vdd_cpu_l>;
|
||||
};
|
||||
|
||||
&cpu_l1 {
|
||||
cpu-supply = <&vdd_cpu_l>;
|
||||
};
|
||||
|
||||
&cpu_l2 {
|
||||
cpu-supply = <&vdd_cpu_l>;
|
||||
};
|
||||
|
||||
&cpu_l3 {
|
||||
cpu-supply = <&vdd_cpu_l>;
|
||||
};
|
||||
|
||||
&cpu_b0 {
|
||||
cpu-supply = <&vdd_cpu_b>;
|
||||
};
|
||||
|
||||
&cpu_b1 {
|
||||
cpu-supply = <&vdd_cpu_b>;
|
||||
};
|
||||
|
||||
&emmc_phy {
|
||||
rockchip,enable-strobe-pulldown;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gmac {
|
||||
assigned-clocks = <&cru SCLK_RMII_SRC>;
|
||||
assigned-clock-parents = <&clkin_gmac>;
|
||||
clock_in_out = "input";
|
||||
phy-supply = <&vcc3v3_phy1>;
|
||||
phy-mode = "rgmii";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&rgmii_pins>;
|
||||
snps,reset-gpio = <&gpio3 RK_PB7 GPIO_ACTIVE_LOW>;
|
||||
snps,reset-active-low;
|
||||
snps,reset-delays-us = <0 10000 50000>;
|
||||
tx_delay = <0x2a>;
|
||||
rx_delay = <0x21>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpu {
|
||||
mali-supply = <&vdd_gpu>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi {
|
||||
avdd-0v9-supply = <&vcc_0v9_s0>;
|
||||
avdd-1v8-supply = <&vcc_1v8_s0>;
|
||||
ddc-i2c-bus = <&i2c3>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&hdmi_cec>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&hdmi_sound {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
i2c-scl-falling-time-ns = <30>;
|
||||
i2c-scl-rising-time-ns = <180>;
|
||||
clock-frequency = <400000>;
|
||||
|
||||
rk809: pmic@20 {
|
||||
compatible = "rockchip,rk809";
|
||||
reg = <0x20>;
|
||||
interrupt-parent = <&gpio1>;
|
||||
interrupts = <RK_PC5 IRQ_TYPE_LEVEL_LOW>;
|
||||
#clock-cells = <1>;
|
||||
clock-names = "mclk";
|
||||
clocks = <&cru SCLK_I2S_8CH_OUT>;
|
||||
clock-output-names = "rk808-clkout1", "rk808-clkout2";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pmic_int_l>, <&i2s_8ch_mclk>;
|
||||
system-power-controller;
|
||||
#sound-dai-cells = <0>;
|
||||
wakeup-source;
|
||||
|
||||
vcc1-supply = <&vcc5v0_sys>;
|
||||
vcc2-supply = <&vcc5v0_sys>;
|
||||
vcc3-supply = <&vcc5v0_sys>;
|
||||
vcc4-supply = <&vcc5v0_sys>;
|
||||
vcc5-supply = <&vcc_buck5_s3>;
|
||||
vcc6-supply = <&vcc_buck5_s3>;
|
||||
vcc7-supply = <&vcc5v0_sys>;
|
||||
vcc8-supply = <&vcc3v3_sys>;
|
||||
vcc9-supply = <&vcc5v0_sys>;
|
||||
|
||||
regulators {
|
||||
vdd_center: DCDC_REG1 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <750000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-initial-mode = <0x2>;
|
||||
regulator-name = "vdd_center";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
regulator-suspend-microvolt = <900000>;
|
||||
};
|
||||
};
|
||||
|
||||
vdd_cpu_l: DCDC_REG2 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <750000>;
|
||||
regulator-max-microvolt = <1350000>;
|
||||
regulator-ramp-delay = <6001>;
|
||||
regulator-initial-mode = <0x2>;
|
||||
regulator-name = "vdd_cpu_l";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_ddr: DCDC_REG3 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-name = "vcc_ddr";
|
||||
regulator-initial-mode = <0x2>;
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc3v3_sys: DCDC_REG4 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-initial-mode = <0x2>;
|
||||
regulator-name = "vcc3v3_sys";
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_buck5_s3: DCDC_REG5 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-name = "vcc_buck5_s3";
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <3300000>;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_0v9_s3: LDO_REG1 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <900000>;
|
||||
regulator-name = "vcc_0v9_s3";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_1v8_s3: LDO_REG2 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-name = "vcc_1v8_s3";
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <1800000>;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_0v9_s0: LDO_REG3 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <900000>;
|
||||
regulator-max-microvolt = <900000>;
|
||||
regulator-name = "vcc_0v9_s0";
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
regulator-suspend-microvolt = <900000>;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_1v8_s0: LDO_REG4 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <1800000>;
|
||||
regulator-name = "vcc_1v8_s0";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_mipi: LDO_REG5 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-name = "vcc_mipi";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_1v5_s0: LDO_REG6 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1500000>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-name = "vcc_1v5_s0";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_3v0_s0: LDO_REG7 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3000000>;
|
||||
regulator-max-microvolt = <3000000>;
|
||||
regulator-name = "vcc_3v0_s0";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_sdio_s0: LDO_REG8 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <1800000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-name = "vcc_sdio_s0";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc_cam: LDO_REG9 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-min-microvolt = <3300000>;
|
||||
regulator-max-microvolt = <3300000>;
|
||||
regulator-name = "vcc_cam";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vcc5v0_host0_s0: SWITCH_REG1 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-name = "vcc5v0_host0_s0";
|
||||
regulator-state-mem {
|
||||
regulator-on-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
lcd_3v3: SWITCH_REG2 {
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
regulator-name = "lcd_3v3";
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
vdd_cpu_b: regulator@40 {
|
||||
compatible = "silergy,syr827";
|
||||
reg = <0x40>;
|
||||
fcs,suspend-voltage-selector = <1>;
|
||||
pinctrl-0 = <&vsel1_gpio>;
|
||||
vsel-gpios = <&gpio1 RK_PC1 GPIO_ACTIVE_HIGH>;
|
||||
regulator-name = "vdd_cpu_b";
|
||||
regulator-min-microvolt = <712500>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-ramp-delay = <1000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
|
||||
vdd_gpu: regulator@41 {
|
||||
compatible = "silergy,syr828";
|
||||
reg = <0x41>;
|
||||
fcs,suspend-voltage-selector = <1>;
|
||||
pinctrl-0 = <&vsel2_gpio>;
|
||||
vsel-gpios = <&gpio1 RK_PB6 GPIO_ACTIVE_HIGH>;
|
||||
regulator-name = "vdd_gpu";
|
||||
regulator-min-microvolt = <712500>;
|
||||
regulator-max-microvolt = <1500000>;
|
||||
regulator-ramp-delay = <1000>;
|
||||
regulator-always-on;
|
||||
regulator-boot-on;
|
||||
vin-supply = <&vcc5v0_sys>;
|
||||
regulator-initial-mode = <1>; /* 1:force PWM 2:auto */
|
||||
regulator-state-mem {
|
||||
regulator-off-in-suspend;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&i2c3 {
|
||||
i2c-scl-rising-time-ns = <450>;
|
||||
i2c-scl-falling-time-ns = <15>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2s0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2s0_8ch_bus {
|
||||
rockchip,pins =
|
||||
<3 RK_PD0 1 &pcfg_pull_none>,
|
||||
<3 RK_PD2 1 &pcfg_pull_none>,
|
||||
<3 RK_PD3 1 &pcfg_pull_none>,
|
||||
<3 RK_PD7 1 &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
&i2s0_8ch_bus_bclk_off {
|
||||
rockchip,pins =
|
||||
<3 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>,
|
||||
<3 RK_PD2 1 &pcfg_pull_none>,
|
||||
<3 RK_PD3 1 &pcfg_pull_none>,
|
||||
<3 RK_PD7 1 &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
&i2s2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&io_domains {
|
||||
audio-supply = <&vcc_1v8_s0>;
|
||||
bt656-supply = <&vcc_3v0_s0>;
|
||||
gpio1830-supply = <&vcc_3v0_s0>;
|
||||
sdmmc-supply = <&vcc_sdio_s0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
bt {
|
||||
bt_enable_h: bt-enable-h {
|
||||
rockchip,pins = <0 RK_PB1 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
bt_host_wake_l: bt-host-wake-l {
|
||||
rockchip,pins = <0 RK_PA4 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
bt_wake_l: bt-wake-l {
|
||||
rockchip,pins = <2 RK_PD3 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
|
||||
i2s0 {
|
||||
i2s_8ch_mclk: i2s-8ch-mclk {
|
||||
rockchip,pins = <4 RK_PA0 1 &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
|
||||
leds {
|
||||
user_led1: user-led1 {
|
||||
rockchip,pins = <3 RK_PD4 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
user_led2: user-led2 {
|
||||
rockchip,pins = <3 RK_PD5 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
|
||||
pmic {
|
||||
pmic_int_l: pmic-int-l {
|
||||
rockchip,pins = <1 RK_PC5 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
};
|
||||
|
||||
vsel1_gpio: vsel1-gpio-pin {
|
||||
rockchip,pins = <1 RK_PC1 RK_FUNC_GPIO &pcfg_pull_down>;
|
||||
};
|
||||
|
||||
vsel2_gpio: vsel2-gpio-pin {
|
||||
rockchip,pins = <1 RK_PB6 RK_FUNC_GPIO &pcfg_pull_down>;
|
||||
};
|
||||
};
|
||||
|
||||
sdmmc {
|
||||
sdmmc_bus4: sdmmc-bus4 {
|
||||
rockchip,pins = <4 8 1 &pcfg_pull_up_8ma>,
|
||||
<4 9 1 &pcfg_pull_up_8ma>,
|
||||
<4 10 1 &pcfg_pull_up_8ma>,
|
||||
<4 11 1 &pcfg_pull_up_8ma>;
|
||||
};
|
||||
|
||||
sdmmc_clk: sdmmc-clk {
|
||||
rockchip,pins = <4 12 1 &pcfg_pull_none_18ma>;
|
||||
};
|
||||
|
||||
sdmmc_cmd: sdmmc-cmd {
|
||||
rockchip,pins = <4 13 1 &pcfg_pull_up_8ma>;
|
||||
};
|
||||
};
|
||||
|
||||
usb-typec {
|
||||
vcc5v0_typec0_en: vcc5v0-typec-en {
|
||||
rockchip,pins = <1 RK_PA3 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
};
|
||||
};
|
||||
|
||||
usb2 {
|
||||
vcc5v0_host_en: vcc5v0-host-en {
|
||||
rockchip,pins = <3 RK_PD6 RK_FUNC_GPIO &pcfg_pull_up>;
|
||||
};
|
||||
};
|
||||
|
||||
wifi {
|
||||
wifi_enable_h: wifi-enable-h {
|
||||
rockchip,pins = <0 RK_PB2 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
|
||||
wifi_host_wake_l: wifi-host-wake-l {
|
||||
rockchip,pins = <0 RK_PA3 RK_FUNC_GPIO &pcfg_pull_none>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&pmu_io_domains {
|
||||
pmu1830-supply = <&vcc_3v0_s0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&saradc {
|
||||
status = "okay";
|
||||
vref-supply = <&vcc_1v8_s3>;
|
||||
};
|
||||
|
||||
&sdhci {
|
||||
max-frequency = <150000000>;
|
||||
bus-width = <8>;
|
||||
mmc-hs400-1_8v;
|
||||
mmc-hs400-enhanced-strobe;
|
||||
non-removable;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&sdio0 {
|
||||
#address-cells = <1>;
|
||||
#size-cells = <0>;
|
||||
bus-width = <4>;
|
||||
clock-frequency = <50000000>;
|
||||
cap-sdio-irq;
|
||||
cap-sd-highspeed;
|
||||
keep-power-in-suspend;
|
||||
mmc-pwrseq = <&sdio_pwrseq>;
|
||||
non-removable;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdio0_bus4 &sdio0_cmd &sdio0_clk>;
|
||||
sd-uhs-sdr104;
|
||||
status = "okay";
|
||||
|
||||
brcmf: wifi@1 {
|
||||
compatible = "brcm,bcm4329-fmac";
|
||||
reg = <1>;
|
||||
interrupt-parent = <&gpio0>;
|
||||
interrupts = <RK_PA3 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-names = "host-wake";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&wifi_host_wake_l>;
|
||||
};
|
||||
};
|
||||
|
||||
&sdmmc {
|
||||
bus-width = <4>;
|
||||
cap-mmc-highspeed;
|
||||
cap-sd-highspeed;
|
||||
card-detect-delay = <800>;
|
||||
disable-wp;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&sdmmc_clk &sdmmc_cmd &sdmmc_bus4>;
|
||||
cd-gpios = <&gpio0 RK_PA7 GPIO_ACTIVE_LOW>;
|
||||
vqmmc-supply = <&vcc_sdio_s0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&tcphy0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&tcphy1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&tsadc {
|
||||
rockchip,hw-tshut-mode = <1>;
|
||||
rockchip,hw-tshut-polarity = <1>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&u2phy0 {
|
||||
status = "okay";
|
||||
|
||||
u2phy0_otg: otg-port {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
u2phy0_host: host-port {
|
||||
phy-supply = <&vcc5v0_host1>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&u2phy1 {
|
||||
status = "okay";
|
||||
|
||||
u2phy1_otg: otg-port {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
u2phy1_host: host-port {
|
||||
phy-supply = <&vcc5v0_host1>;
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&uart0_xfer &uart0_cts &uart0_rts>;
|
||||
status = "okay";
|
||||
|
||||
bluetooth {
|
||||
compatible = "brcm,bcm4345c5";
|
||||
clocks = <&rk809 1>;
|
||||
clock-names = "lpo";
|
||||
device-wakeup-gpios = <&gpio2 RK_PD3 GPIO_ACTIVE_HIGH>;
|
||||
host-wakeup-gpios = <&gpio0 RK_PA4 GPIO_ACTIVE_HIGH>;
|
||||
shutdown-gpios = <&gpio0 RK_PB1 GPIO_ACTIVE_HIGH>;
|
||||
max-speed = <1500000>;
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&bt_host_wake_l &bt_wake_l &bt_enable_h>;
|
||||
vbat-supply = <&vcc3v3_sys>;
|
||||
vddio-supply = <&vcc_1v8_s3>;
|
||||
};
|
||||
};
|
||||
|
||||
&uart2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb_host0_ehci {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb_host0_ohci {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb_host1_ehci {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usb_host1_ohci {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbdrd3_0 {
|
||||
extcon = <&u2phy0>;
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbdrd_dwc3_0 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
&usbdrd3_1 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&usbdrd_dwc3_1 {
|
||||
status = "okay";
|
||||
dr_mode = "host";
|
||||
};
|
||||
|
||||
&vopb {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vopb_mmu {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vopl {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&vopl_mmu {
|
||||
status = "okay";
|
||||
};
|
||||
@@ -0,0 +1,116 @@
|
||||
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
|
||||
/*
|
||||
* Copyright (c) 2016-2017 Fuzhou Rockchip Electronics Co., Ltd
|
||||
* Copyright (c) 2022 Radxa Limited
|
||||
*/
|
||||
|
||||
#include "rk3399-base.dtsi"
|
||||
|
||||
/ {
|
||||
cluster0_opp: opp-table-0 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = /bits/ 64 <408000000>;
|
||||
opp-microvolt = <875000 875000 1250000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
opp-microvolt = <875000 875000 1250000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = /bits/ 64 <816000000>;
|
||||
opp-microvolt = <900000 900000 1250000>;
|
||||
};
|
||||
opp03 {
|
||||
opp-hz = /bits/ 64 <1008000000>;
|
||||
opp-microvolt = <975000 975000 1250000>;
|
||||
};
|
||||
};
|
||||
|
||||
cluster1_opp: opp-table-1 {
|
||||
compatible = "operating-points-v2";
|
||||
opp-shared;
|
||||
|
||||
opp00 {
|
||||
opp-hz = /bits/ 64 <408000000>;
|
||||
opp-microvolt = <875000 875000 1250000>;
|
||||
clock-latency-ns = <40000>;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
opp-microvolt = <875000 875000 1250000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = /bits/ 64 <816000000>;
|
||||
opp-microvolt = <875000 875000 1250000>;
|
||||
};
|
||||
opp03 {
|
||||
opp-hz = /bits/ 64 <1008000000>;
|
||||
opp-microvolt = <925000 925000 1250000>;
|
||||
};
|
||||
opp04 {
|
||||
opp-hz = /bits/ 64 <1200000000>;
|
||||
opp-microvolt = <1000000 1000000 1250000>;
|
||||
};
|
||||
opp05 {
|
||||
opp-hz = /bits/ 64 <1416000000>;
|
||||
opp-microvolt = <1075000 1075000 1250000>;
|
||||
};
|
||||
opp06 {
|
||||
opp-hz = /bits/ 64 <1512000000>;
|
||||
opp-microvolt = <1150000 1150000 1250000>;
|
||||
};
|
||||
};
|
||||
|
||||
gpu_opp_table: opp-table-2 {
|
||||
compatible = "operating-points-v2";
|
||||
|
||||
opp00 {
|
||||
opp-hz = /bits/ 64 <200000000>;
|
||||
opp-microvolt = <875000 875000 1150000>;
|
||||
};
|
||||
opp01 {
|
||||
opp-hz = /bits/ 64 <300000000>;
|
||||
opp-microvolt = <875000 875000 1150000>;
|
||||
};
|
||||
opp02 {
|
||||
opp-hz = /bits/ 64 <400000000>;
|
||||
opp-microvolt = <875000 875000 1150000>;
|
||||
};
|
||||
opp03 {
|
||||
opp-hz = /bits/ 64 <600000000>;
|
||||
opp-microvolt = <975000 975000 1150000>;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
&cpu_l0 {
|
||||
operating-points-v2 = <&cluster0_opp>;
|
||||
};
|
||||
|
||||
&cpu_l1 {
|
||||
operating-points-v2 = <&cluster0_opp>;
|
||||
};
|
||||
|
||||
&cpu_l2 {
|
||||
operating-points-v2 = <&cluster0_opp>;
|
||||
};
|
||||
|
||||
&cpu_l3 {
|
||||
operating-points-v2 = <&cluster0_opp>;
|
||||
};
|
||||
|
||||
&cpu_b0 {
|
||||
operating-points-v2 = <&cluster1_opp>;
|
||||
};
|
||||
|
||||
&cpu_b1 {
|
||||
operating-points-v2 = <&cluster1_opp>;
|
||||
};
|
||||
|
||||
&gpu {
|
||||
operating-points-v2 = <&gpu_opp_table>;
|
||||
};
|
||||
@@ -172,7 +172,7 @@ define Device/friendlyarm_nanopi-m5
|
||||
DEVICE_MODEL := NanoPi M5
|
||||
SOC := rk3576
|
||||
DEVICE_DTS := rk3576-nanopi-m5
|
||||
UBOOT_DEVICE_NAME := nanopi-m5-rk3576
|
||||
UBOOT_DEVICE_NAME := generic-rk3576
|
||||
DEVICE_PACKAGES := kmod-gpio-button-hotplug
|
||||
IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata
|
||||
endef
|
||||
@@ -302,7 +302,7 @@ define Device/friendlyarm_nanopi-r76s
|
||||
DEVICE_MODEL := NanoPi R76S
|
||||
SOC := rk3576
|
||||
DEVICE_DTS := rk3576-nanopi-r76s
|
||||
UBOOT_DEVICE_NAME := nanopi-m5-rk3576
|
||||
UBOOT_DEVICE_NAME := generic-rk3576
|
||||
DEVICE_PACKAGES := kmod-gpio-button-hotplug kmod-r8125
|
||||
IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata
|
||||
endef
|
||||
@@ -524,6 +524,15 @@ define Device/radxa_rock-3c
|
||||
endef
|
||||
TARGET_DEVICES += radxa_rock-3c
|
||||
|
||||
define Device/radxa_rock-4c-plus
|
||||
DEVICE_VENDOR := Radxa
|
||||
DEVICE_MODEL := ROCK 4C+
|
||||
SOC := rk3399
|
||||
IMAGE/sysupgrade.img.gz := boot-common | boot-script | pine64-img | gzip | append-metadata
|
||||
UBOOT_DEVICE_NAME := rock-4c-plus-rk3399
|
||||
endef
|
||||
TARGET_DEVICES += radxa_rock-4c-plus
|
||||
|
||||
define Device/radxa_rock-pi-4a
|
||||
DEVICE_VENDOR := Radxa
|
||||
DEVICE_MODEL := ROCK Pi 4A
|
||||
|
||||
+1
-1
@@ -38,7 +38,7 @@ require (
|
||||
github.com/metacubex/sing-wireguard v0.0.0-20250503063753-2dc62acc626f
|
||||
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141
|
||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443
|
||||
github.com/metacubex/tls v0.1.0
|
||||
github.com/metacubex/tls v0.1.2
|
||||
github.com/metacubex/utls v1.8.4
|
||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f
|
||||
github.com/mroth/weightedrand/v2 v2.1.0
|
||||
|
||||
+2
-2
@@ -141,8 +141,8 @@ github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141 h1:DK2l6m2Fc85H2Bhi
|
||||
github.com/metacubex/smux v0.0.0-20260105030934-d0c8756d3141/go.mod h1:/yI4OiGOSn0SURhZdJF3CbtPg3nwK700bG8TZLMBvAg=
|
||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443 h1:H6TnfM12tOoTizYE/qBHH3nEuibIelmHI+BVSxVJr8o=
|
||||
github.com/metacubex/tfo-go v0.0.0-20251130171125-413e892ac443/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
|
||||
github.com/metacubex/tls v0.1.0 h1:1kjR/1q2uU1cZIwiHYEnWzS4L+0Cu1/X3yfIQ76BzNY=
|
||||
github.com/metacubex/tls v0.1.0/go.mod h1:0XeVdL0cBw+8i5Hqy3lVeP9IyD/LFTq02ExvHM6rzEM=
|
||||
github.com/metacubex/tls v0.1.2 h1:qM0ATVnPFts5kZNTb+TukdaJ3hIf1ZVgKnXJCGfBmGI=
|
||||
github.com/metacubex/tls v0.1.2/go.mod h1:0XeVdL0cBw+8i5Hqy3lVeP9IyD/LFTq02ExvHM6rzEM=
|
||||
github.com/metacubex/utls v1.8.4 h1:HmL9nUApDdWSkgUyodfwF6hSjtiwCGGdyhaSpEejKpg=
|
||||
github.com/metacubex/utls v1.8.4/go.mod h1:kncGGVhFaoGn5M3pFe3SXhZCzsbCJayNOH4UEqTKTko=
|
||||
github.com/metacubex/wireguard-go v0.0.0-20250820062549-a6cecdd7f57f h1:FGBPRb1zUabhPhDrlKEjQ9lgIwQ6cHL4x8M9lrERhbk=
|
||||
|
||||
@@ -85,7 +85,7 @@ function get_containers()
|
||||
end
|
||||
for ii,iv in ipairs(images) do
|
||||
if iv.Id == v.ImageID then
|
||||
data[index]["_image"] = iv.RepoTags and iv.RepoTags[1] or (next(iv.RepoDigests) and (iv.RepoDigests[1]:gsub("(.-)@.+", "%1") .. ":<none>")) or ""
|
||||
data[index]["_image"] = (iv.RepoTags and iv.RepoTags[1]) or (iv.RepoDigests and next(iv.RepoDigests) and (iv.RepoDigests[1]:gsub("(.-)@.+", "%1") .. ":<none>")) or "<none>:<none>"
|
||||
end
|
||||
end
|
||||
data[index]["_id_name"] = '<a href='..luci.dispatcher.build_url("admin/docker/container/"..v.Id)..' class="dockerman_link" title="'..translate("Container detail")..'">'.. data[index]["_name"] .. "<br><font color='#9f9f9f'>ID: " .. data[index]["_id"]
|
||||
|
||||
@@ -87,6 +87,7 @@ function index()
|
||||
entry({"admin", "services", appname, "save_node_order"}, call("save_node_order")).leaf = true
|
||||
entry({"admin", "services", appname, "save_node_list_opt"}, call("save_node_list_opt")).leaf = true
|
||||
entry({"admin", "services", appname, "update_rules"}, call("update_rules")).leaf = true
|
||||
entry({"admin", "services", appname, "rollback_rules"}, call("rollback_rules")).leaf = true
|
||||
entry({"admin", "services", appname, "subscribe_del_node"}, call("subscribe_del_node")).leaf = true
|
||||
entry({"admin", "services", appname, "subscribe_del_all"}, call("subscribe_del_all")).leaf = true
|
||||
entry({"admin", "services", appname, "subscribe_manual"}, call("subscribe_manual")).leaf = true
|
||||
@@ -611,6 +612,19 @@ function update_rules()
|
||||
http_write_json()
|
||||
end
|
||||
|
||||
function rollback_rules()
|
||||
local arg_type = http.formvalue("type")
|
||||
if arg_type ~= "geoip" and arg_type ~= "geosite" then
|
||||
http_write_json_error()
|
||||
return
|
||||
end
|
||||
local bak_dir = "/tmp/bak_v2ray/"
|
||||
local geo_dir = (uci:get(appname, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/")
|
||||
fs.move(bak_dir .. arg_type .. ".dat", geo_dir .. arg_type .. ".dat")
|
||||
fs.rmdir(bak_dir)
|
||||
http_write_json_ok()
|
||||
end
|
||||
|
||||
function server_user_status()
|
||||
local e = {}
|
||||
e.index = http.formvalue("index")
|
||||
|
||||
@@ -121,17 +121,6 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
local vid = v.id
|
||||
s:tab("Shunt", translate("Shunt Rule"))
|
||||
s:tab("ShuntDNS", translate("Shunt Rule") .. " DNS")
|
||||
-- shunt node type, Sing-Box or Xray
|
||||
local type = s:taboption("Shunt", ListValue, vid .. "-type", translate("Type"))
|
||||
if has_singbox then
|
||||
type:value("sing-box", translate("Sing-Box"))
|
||||
end
|
||||
if has_xray then
|
||||
type:value("Xray", translate("Xray"))
|
||||
end
|
||||
type.cfgvalue = get_cfgvalue(v.id, "type")
|
||||
type.write = get_write(v.id, "type")
|
||||
|
||||
-- pre-proxy
|
||||
o = s:taboption("Shunt", Flag, vid .. "-preproxy_enabled", translate("Preproxy"))
|
||||
o:depends("node", v.id)
|
||||
@@ -169,18 +158,15 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o.cfgvalue = get_cfgvalue(v.id, "main_node")
|
||||
o.write = get_write(v.id, "main_node")
|
||||
|
||||
o = s:taboption("ShuntDNS", Flag, vid .. "-fakedns", "FakeDNS")
|
||||
o = s:taboption("ShuntDNS", Flag, vid .. "-fakedns", '<a style="color:#FF8C00">FakeDNS</a>', translate("Use FakeDNS work in the domain that proxy.") .. "<br>" ..
|
||||
translate("Suitable scenarios for let the node servers get the target domain names.") .. "<br>" ..
|
||||
translate("Such as: DNS unlocking of streaming media, reducing DNS query latency, etc.")
|
||||
)
|
||||
o:depends("node", v.id)
|
||||
o.cfgvalue = get_cfgvalue(v.id, "fakedns")
|
||||
o.write = get_write(v.id, "fakedns")
|
||||
o.remove = get_remove(v.id, "fakedns")
|
||||
|
||||
if (has_singbox and has_xray) or (v.type == "sing-box" and not has_singbox) or (v.type == "Xray" and not has_xray) then
|
||||
type:depends("node", v.id)
|
||||
else
|
||||
type:depends({ __hide = true }) -- Always hidden.
|
||||
end
|
||||
|
||||
m.uci:foreach(appname, "shunt_rules", function(e)
|
||||
local id = e[".name"]
|
||||
local node_option = vid .. "-" .. id .. "_node"
|
||||
@@ -204,7 +190,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
|
||||
o:value("", translate("Close (Not use)"))
|
||||
pt:value("main", translate("Use preproxy node"))
|
||||
|
||||
local fakedns_tag = s:taboption("ShuntDNS", Flag, vid .. "-".. id .. "_fakedns", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. "FakeDNS"))
|
||||
local fakedns_tag = s:taboption("ShuntDNS", Flag, vid .. "-".. id .. "_fakedns", string.format('* <a style="color:#FF8C00">%s</a>', e.remarks))
|
||||
fakedns_tag.cfgvalue = get_cfgvalue(v.id, id .. "_fakedns")
|
||||
fakedns_tag.write = get_write(v.id, id .. "_fakedns")
|
||||
fakedns_tag.remove = get_remove(v.id, id .. "_fakedns")
|
||||
|
||||
@@ -272,7 +272,10 @@ if load_shunt_options then -- [[ Shunt Start ]]
|
||||
o.default = o.keylist[1]
|
||||
end
|
||||
|
||||
o = s:option(Flag, _n("fakedns"), "FakeDNS")
|
||||
o = s:option(Flag, _n("fakedns"), '<a style="color:#FF8C00">FakeDNS</a>', translate("Use FakeDNS work in the domain that proxy.") .. "<br>" ..
|
||||
translate("Suitable scenarios for let the node servers get the target domain names.") .. "<br>" ..
|
||||
translate("Such as: DNS unlocking of streaming media, reducing DNS query latency, etc.")
|
||||
)
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
end
|
||||
m.uci:foreach(appname, "shunt_rules", function(e)
|
||||
@@ -292,7 +295,7 @@ if load_shunt_options then -- [[ Shunt Start ]]
|
||||
pt:value("", translate("Close (Not use)"))
|
||||
pt:value("main", translate("Use preproxy node"))
|
||||
|
||||
local fakedns_tag = s:option(Flag, _n(e[".name"] .. "_fakedns"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. "FakeDNS"), translate("Use FakeDNS work in the domain that proxy."))
|
||||
local fakedns_tag = s:option(Flag, _n(e[".name"] .. "_fakedns"), string.format('* <a style="color:#FF8C00">%s</a>', e.remarks .. " " .. "FakeDNS"))
|
||||
|
||||
for k, v in pairs(socks_list) do
|
||||
o:value(v.id, v.remark)
|
||||
|
||||
+5
-2
@@ -249,7 +249,10 @@ if load_shunt_options then -- [[ Shunt Start ]]
|
||||
o.default = o.keylist[1]
|
||||
end
|
||||
|
||||
o = s:option(Flag, _n("fakedns"), "FakeDNS")
|
||||
o = s:option(Flag, _n("fakedns"), '<a style="color:#FF8C00">FakeDNS</a>', translate("Use FakeDNS work in the domain that proxy.") .. "<br>" ..
|
||||
translate("Suitable scenarios for let the node servers get the target domain names.") .. "<br>" ..
|
||||
translate("Such as: DNS unlocking of streaming media, reducing DNS query latency, etc.")
|
||||
)
|
||||
o:depends({ [_n("protocol")] = "_shunt" })
|
||||
end
|
||||
m.uci:foreach(appname, "shunt_rules", function(e)
|
||||
@@ -269,7 +272,7 @@ if load_shunt_options then -- [[ Shunt Start ]]
|
||||
pt:value("", translate("Close (Not use)"))
|
||||
pt:value("main", translate("Use preproxy node"))
|
||||
|
||||
local fakedns_tag = s:option(Flag, _n(e[".name"] .. "_fakedns"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. "FakeDNS"), translate("Use FakeDNS work in the domain that proxy."))
|
||||
local fakedns_tag = s:option(Flag, _n(e[".name"] .. "_fakedns"), string.format('* <a style="color:#FF8C00">%s</a>', e.remarks .. " " .. "FakeDNS"))
|
||||
|
||||
for k, v in pairs(socks_list) do
|
||||
o:value(v.id, v.remark)
|
||||
|
||||
@@ -113,8 +113,6 @@ window.lv_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
(function(){
|
||||
@@ -143,3 +141,5 @@ window.lv_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
|
||||
})();
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -108,7 +108,6 @@ end
|
||||
<span id="count-<%=self.option%>" style="color:#666;"><%:Selected:%> <span style='color:red;'><%=selected_count%>/<%=total_count%></span></span>
|
||||
</div>
|
||||
</div>
|
||||
<%+cbi/valuefooter%>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
@@ -129,3 +128,5 @@ end
|
||||
})();
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -126,8 +126,6 @@ window.v_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
|
||||
<script type="text/javascript">
|
||||
//<![CDATA[
|
||||
(function(){
|
||||
@@ -157,3 +155,5 @@ window.v_dropdown_data["<%=cbid%>"] = <%=json.stringify(dropdown_data)%>;
|
||||
})();
|
||||
//]]>
|
||||
</script>
|
||||
|
||||
<%+cbi/valuefooter%>
|
||||
@@ -129,7 +129,7 @@ local api = self.api
|
||||
hiddenSelect.addEventListener("change", function(el){
|
||||
let new_val = el.target.value
|
||||
const new_hasItem = shunt_list.find(element => element.id == new_val);
|
||||
if (new_hasItem || (o_hasItem && !new_hasItem)) {
|
||||
if (new_hasItem) {
|
||||
XHR.get('<%=api.url("update_node")%>', {
|
||||
id: "<%=self.global_cfgid%>",
|
||||
data: JSON.stringify({
|
||||
|
||||
@@ -27,7 +27,7 @@ local api = self.api
|
||||
if (el.value.startsWith("_") || (o_val.startsWith("_") && !el.value.startsWith("_"))) {
|
||||
let name_split = el.name.split(".");
|
||||
let name = name_split[name_split.length - 1];
|
||||
let save = false;
|
||||
let save = true;
|
||||
if (save) {
|
||||
update_node({
|
||||
protocol: getOption(name).value
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
<%
|
||||
local api = require "luci.passwall2.api"
|
||||
local fs = api.fs
|
||||
local has_old_geoip = fs.access("/tmp/bak_v2ray/geoip.dat")
|
||||
local has_old_geosite = fs.access("/tmp/bak_v2ray/geosite.dat")
|
||||
-%>
|
||||
<script src="<%=resource%>/view/<%=api.appname%>/Sortable.min.js?v=26.1.9"></script>
|
||||
|
||||
@@ -48,7 +51,14 @@ local api = require "luci.passwall2.api"
|
||||
<input class="cbi-input-checkbox" type="checkbox" name="geosite" value="1" />
|
||||
geosite
|
||||
</label>
|
||||
<br><br><input class="btn cbi-button cbi-button-apply" type="button" id="update_rules_btn" onclick="update_rules(this)" value="<%:Manually update%>" />
|
||||
<br><br>
|
||||
<input class="btn cbi-button cbi-button-apply" type="button" id="update_rules_btn" onclick="update_rules(this)" value="<%:Manually update%>" />
|
||||
<% if has_old_geoip then %>
|
||||
<input class="btn cbi-button cbi-button-reset" type="button" onclick="rollback_rules(this, 'geoip')" value="<%:Rollback%> GeoIP" />
|
||||
<% end %>
|
||||
<% if has_old_geosite then %>
|
||||
<input class="btn cbi-button cbi-button-reset" type="button" onclick="rollback_rules(this, 'geosite')" value="<%:Rollback%> Geosite" />
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -120,6 +130,27 @@ local api = require "luci.passwall2.api"
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function rollback_rules(btn, type) {
|
||||
let ori_val = btn.value;
|
||||
btn.disabled = true;
|
||||
btn.value = '<%:Rollbacking...%>';
|
||||
XHR.get('<%=api.url("rollback_rules")%>', {
|
||||
type: type
|
||||
},
|
||||
function(x, data) {
|
||||
if(x && x.status == 200 && data.code == 1) {
|
||||
alert("<%:Success%>");
|
||||
btn.style.display = "none";
|
||||
} else {
|
||||
alert("<%:Error%>");
|
||||
btn.disabled = false;
|
||||
btn.value = ori_val;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
//分流规则添加拖拽排序
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
function initSortableForTable() {
|
||||
|
||||
@@ -169,6 +169,12 @@ msgstr "远程查询策略"
|
||||
msgid "Use FakeDNS work in the domain that proxy."
|
||||
msgstr "需要代理的域名使用 FakeDNS。"
|
||||
|
||||
msgid "Suitable scenarios for let the node servers get the target domain names."
|
||||
msgstr "适合让节点服务器获取目标域名的场景。"
|
||||
|
||||
msgid "Such as: DNS unlocking of streaming media, reducing DNS query latency, etc."
|
||||
msgstr "例如:流媒体的 DNS 解锁、减少 DNS 查询延迟等。"
|
||||
|
||||
msgid "Domain Override"
|
||||
msgstr "域名重写"
|
||||
|
||||
@@ -286,6 +292,9 @@ msgstr "清空所有节点"
|
||||
msgid "Are you sure to clear all nodes?"
|
||||
msgstr "你确定要清空所有节点吗?"
|
||||
|
||||
msgid "Success"
|
||||
msgstr "成功"
|
||||
|
||||
msgid "Error"
|
||||
msgstr "错误"
|
||||
|
||||
@@ -841,6 +850,12 @@ msgstr "规则版本"
|
||||
msgid "Manually update"
|
||||
msgstr "手动更新"
|
||||
|
||||
msgid "Rollback"
|
||||
msgstr "回滚"
|
||||
|
||||
msgid "Rollbacking..."
|
||||
msgstr "回滚中..."
|
||||
|
||||
msgid "Enable auto update rules"
|
||||
msgstr "开启自动更新规则"
|
||||
|
||||
@@ -1957,8 +1972,8 @@ msgstr "Socks节点:[%s]%s,启动 %s:%s"
|
||||
msgid "To enable experimental IPv6 transparent proxy (TProxy), please ensure your node and type support IPv6!"
|
||||
msgstr "开启实验性IPv6透明代理(TProxy),请确认您的节点及类型支持IPv6!"
|
||||
|
||||
msgid "[%s] process %s error, skip!"
|
||||
msgstr "【%s】 进程 %s 错误,跳过!"
|
||||
msgid "[%s] process %s error, skip this transparent proxy!"
|
||||
msgstr "【%s】 进程 %s 错误,跳过此透明代理!"
|
||||
|
||||
msgid "Analyzing the node configuration of the Socks service..."
|
||||
msgstr "分析 Socks 服务的节点配置..."
|
||||
|
||||
@@ -169,6 +169,12 @@ msgstr "遠程查詢策略"
|
||||
msgid "Use FakeDNS work in the domain that proxy."
|
||||
msgstr "需要代理的域名使用 FakeDNS。"
|
||||
|
||||
msgid "Suitable scenarios for let the node servers get the target domain names."
|
||||
msgstr "適合讓節點伺服器取得目標網域的場景。"
|
||||
|
||||
msgid "Such as: DNS unlocking of streaming media, reducing DNS query latency, etc."
|
||||
msgstr "例如:流媒體的 DNS 解鎖、減少 DNS 查詢延遲等。"
|
||||
|
||||
msgid "Domain Override"
|
||||
msgstr "域名重寫"
|
||||
|
||||
@@ -286,6 +292,9 @@ msgstr "清空所有節點"
|
||||
msgid "Are you sure to clear all nodes?"
|
||||
msgstr "你確定要清空所有節點吗?"
|
||||
|
||||
msgid "Success"
|
||||
msgstr "成功"
|
||||
|
||||
msgid "Error"
|
||||
msgstr "錯誤"
|
||||
|
||||
@@ -841,6 +850,12 @@ msgstr "規則版本"
|
||||
msgid "Manually update"
|
||||
msgstr "手動更新"
|
||||
|
||||
msgid "Rollback"
|
||||
msgstr "回滾"
|
||||
|
||||
msgid "Rollbacking..."
|
||||
msgstr "回滾中..."
|
||||
|
||||
msgid "Enable auto update rules"
|
||||
msgstr "開啟自動更新規則"
|
||||
|
||||
@@ -1957,8 +1972,8 @@ msgstr "Socks節點:[%s]%s,啟動 %s:%s"
|
||||
msgid "To enable experimental IPv6 transparent proxy (TProxy), please ensure your node and type support IPv6!"
|
||||
msgstr "開啟實驗性IPv6透明代理(TProxy),請確認您的節點及類型支持IPv6!"
|
||||
|
||||
msgid "[%s] process %s error, skip!"
|
||||
msgstr "【%s】 進程 %s 錯誤,跳過!"
|
||||
msgid "[%s] process %s error, skip this transparent proxy!"
|
||||
msgstr "【%s】 進程 %s 錯誤,跳過此透明代理!"
|
||||
|
||||
msgid "Analyzing the node configuration of the Socks service..."
|
||||
msgstr "分析 Socks 服務的節點配置..."
|
||||
|
||||
@@ -223,10 +223,14 @@ run_xray() {
|
||||
local _json_arg="$(json_dump)"
|
||||
lua $UTIL_XRAY gen_config "${_json_arg}" > $config_file
|
||||
|
||||
$XRAY_BIN run -test -c "$config_file" > $log_file; local status=$?
|
||||
test_log_file=$log_file
|
||||
[ "$test_log_file" = "/dev/null" ] && test_log_file="${TMP_PATH}/test.log"
|
||||
|
||||
$XRAY_BIN run -test -c "$config_file" > $test_log_file; local status=$?
|
||||
if [ "${status}" == 0 ]; then
|
||||
ln_run "$XRAY_BIN" xray $log_file run -c "$config_file"
|
||||
else
|
||||
_error_log_file=$test_log_file
|
||||
return ${status}
|
||||
fi
|
||||
}
|
||||
@@ -357,10 +361,14 @@ run_singbox() {
|
||||
local _json_arg="$(json_dump)"
|
||||
lua $UTIL_SINGBOX gen_config "${_json_arg}" > $config_file
|
||||
|
||||
$SINGBOX_BIN check -c "$config_file" > $log_file 2>&1; local status=$?
|
||||
test_log_file=$log_file
|
||||
[ "$test_log_file" = "/dev/null" ] && test_log_file="${TMP_PATH}/test.log"
|
||||
|
||||
$SINGBOX_BIN check -c "$config_file" > $test_log_file 2>&1; local status=$?
|
||||
if [ "${status}" == 0 ]; then
|
||||
ln_run "$SINGBOX_BIN" "sing-box" "${log_file}" run -c "$config_file"
|
||||
else
|
||||
_error_log_file=$test_log_file
|
||||
return ${status}
|
||||
fi
|
||||
}
|
||||
@@ -669,7 +677,9 @@ run_global() {
|
||||
if [ "$status" == 0 ]; then
|
||||
log 0 ${dns_msg}
|
||||
else
|
||||
log_i18n 0 "[%s] process %s error, skip!" $(i18n "Global") "${V2RAY_CONFIG}"
|
||||
log_i18n 0 "[%s] process %s error, skip this transparent proxy!" $(i18n "Global") "${V2RAY_CONFIG}"
|
||||
cat ${_error_log_file} >> ${LOG_FILE}
|
||||
unset _error_log_file
|
||||
ENABLED_DEFAULT_ACL=0
|
||||
return 1
|
||||
fi
|
||||
@@ -1092,7 +1102,9 @@ acl_app() {
|
||||
write_ipset_direct=${write_ipset_direct} config_file=${config_file}
|
||||
local status=$?
|
||||
if [ "$status" != 0 ]; then
|
||||
log_i18n 2 "[%s] process %s error, skip!" "${remarks}" "${config_file}"
|
||||
log_i18n 2 "[%s] process %s error, skip this transparent proxy!" "${remarks}" "${config_file}"
|
||||
cat ${_error_log_file} >> ${LOG_FILE}
|
||||
unset _error_log_file
|
||||
continue
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -20,6 +20,7 @@ local geoip_url = uci:get(name, "@global_rules[0]", "geoip_url") or "https://git
|
||||
local geosite_url = uci:get(name, "@global_rules[0]", "geosite_url") or "https://github.com/Loyalsoldier/v2ray-rules-dat/releases/latest/download/geosite.dat"
|
||||
local asset_location = uci:get(name, "@global_rules[0]", "v2ray_location_asset") or "/usr/share/v2ray/"
|
||||
asset_location = asset_location:match("/$") and asset_location or (asset_location .. "/")
|
||||
local backup_path = "/tmp/bak_v2ray/"
|
||||
|
||||
if arg3 == "cron" then
|
||||
arg2 = nil
|
||||
@@ -98,7 +99,7 @@ local function fetch_geofile(geo_name, geo_type, url)
|
||||
local content = f:read("*l")
|
||||
f:close()
|
||||
if content then
|
||||
content = content:gsub(down_filename, tmp_path)
|
||||
content = content:gsub("(%x+)%s+.+", "%1 " .. tmp_path)
|
||||
f = io.open(sha_path, "w")
|
||||
if f then
|
||||
f:write(content)
|
||||
@@ -128,7 +129,8 @@ local function fetch_geofile(geo_name, geo_type, url)
|
||||
if sret_tmp == 200 then
|
||||
if sha_verify then
|
||||
if verify_sha256(sha_path) then
|
||||
sys.call(string.format("mkdir -p %s && cp -f %s %s", asset_location, tmp_path, asset_path))
|
||||
sys.call(string.format("mkdir -p %s && mv -f %s %s", backup_path, asset_path, backup_path))
|
||||
sys.call(string.format("mkdir -p %s && mv -f %s %s", asset_location, tmp_path, asset_path))
|
||||
reboot = 1
|
||||
log(1, api.i18n.translatef("%s update success.", geo_type))
|
||||
else
|
||||
@@ -140,7 +142,8 @@ local function fetch_geofile(geo_name, geo_type, url)
|
||||
log(1, api.i18n.translatef("%s version is the same and does not need to be updated.", geo_type))
|
||||
return 0
|
||||
end
|
||||
sys.call(string.format("mkdir -p %s && cp -f %s %s", asset_location, tmp_path, asset_path))
|
||||
sys.call(string.format("mkdir -p %s && mv -f %s %s", backup_path, asset_path, backup_path))
|
||||
sys.call(string.format("mkdir -p %s && mv -f %s %s", asset_location, tmp_path, asset_path))
|
||||
reboot = 1
|
||||
log(1, api.i18n.translatef("%s update success.", geo_type))
|
||||
end
|
||||
|
||||
@@ -17,17 +17,17 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
debugEnabled bool
|
||||
target string
|
||||
platform string
|
||||
//withTailscale bool
|
||||
debugEnabled bool
|
||||
target string
|
||||
platform string
|
||||
// withTailscale bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
flag.BoolVar(&debugEnabled, "debug", false, "enable debug")
|
||||
flag.StringVar(&target, "target", "android", "target platform")
|
||||
flag.StringVar(&platform, "platform", "", "specify platform")
|
||||
//flag.BoolVar(&withTailscale, "with-tailscale", false, "build tailscale for iOS and tvOS")
|
||||
// flag.BoolVar(&withTailscale, "with-tailscale", false, "build tailscale for iOS and tvOS")
|
||||
}
|
||||
|
||||
func main() {
|
||||
@@ -48,7 +48,7 @@ var (
|
||||
debugFlags []string
|
||||
sharedTags []string
|
||||
darwinTags []string
|
||||
//memcTags []string
|
||||
// memcTags []string
|
||||
notMemcTags []string
|
||||
debugTags []string
|
||||
)
|
||||
@@ -65,7 +65,7 @@ func init() {
|
||||
|
||||
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_naive_outbound", "with_clash_api", "with_conntrack", "badlinkname", "tfogo_checklinkname0")
|
||||
darwinTags = append(darwinTags, "with_dhcp", "grpcnotrace")
|
||||
//memcTags = append(memcTags, "with_tailscale")
|
||||
// memcTags = append(memcTags, "with_tailscale")
|
||||
sharedTags = append(sharedTags, "with_tailscale", "ts_omit_logtail", "ts_omit_ssh", "ts_omit_drive", "ts_omit_taildrop", "ts_omit_webclient", "ts_omit_doctor", "ts_omit_capture", "ts_omit_kube", "ts_omit_aws", "ts_omit_synology", "ts_omit_bird")
|
||||
notMemcTags = append(notMemcTags, "with_low_memory")
|
||||
debugTags = append(debugTags, "debug")
|
||||
@@ -165,7 +165,7 @@ func buildAndroid() {
|
||||
|
||||
// Build main variant (SDK 23)
|
||||
mainTags := append([]string{}, sharedTags...)
|
||||
//mainTags = append(mainTags, memcTags...)
|
||||
// mainTags = append(mainTags, memcTags...)
|
||||
if debugEnabled {
|
||||
mainTags = append(mainTags, debugTags...)
|
||||
}
|
||||
@@ -177,7 +177,7 @@ func buildAndroid() {
|
||||
|
||||
// Build legacy variant (SDK 21, no naive outbound)
|
||||
legacyTags := filterTags(sharedTags, "with_naive_outbound")
|
||||
//legacyTags = append(legacyTags, memcTags...)
|
||||
// legacyTags = append(legacyTags, memcTags...)
|
||||
if debugEnabled {
|
||||
legacyTags = append(legacyTags, debugTags...)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,16 @@ icon: material/alert-decagram
|
||||
|
||||
#### 1.12.18
|
||||
|
||||
* Add fallback routing rule for `auto_redirect` **1**
|
||||
* Fixes and improvements
|
||||
|
||||
**1**:
|
||||
|
||||
Adds a fallback iproute2 rule checked after system default rules (32766: main, 32767: default),
|
||||
ensuring traffic is routed to the sing-box table when no route is found in system tables.
|
||||
|
||||
The rule index can be customized via `auto_redirect_iproute2_fallback_rule_index` (default: 32768).
|
||||
|
||||
#### 1.13.0-beta.6
|
||||
|
||||
* Update uTLS to v1.8.2 **1**
|
||||
|
||||
@@ -6,7 +6,8 @@ icon: material/new-box
|
||||
|
||||
:material-plus: [auto_redirect_reset_mark](#auto_redirect_reset_mark)
|
||||
:material-plus: [auto_redirect_nfqueue](#auto_redirect_nfqueue)
|
||||
:material-plus: [exclude_mptcp](#exclude_mptcp)
|
||||
:material-plus: [exclude_mptcp](#exclude_mptcp)
|
||||
:material-plus: [auto_redirect_iproute2_fallback_rule_index](#auto_redirect_iproute2_fallback_rule_index)
|
||||
|
||||
!!! quote "Changes in sing-box 1.12.0"
|
||||
|
||||
@@ -71,6 +72,7 @@ icon: material/new-box
|
||||
"auto_redirect_output_mark": "0x2024",
|
||||
"auto_redirect_reset_mark": "0x2025",
|
||||
"auto_redirect_nfqueue": 100,
|
||||
"auto_redirect_iproute2_fallback_rule_index": 32768,
|
||||
"exclude_mptcp": false,
|
||||
"loopback_address": [
|
||||
"10.7.0.1"
|
||||
@@ -303,6 +305,17 @@ NFQueue number used by `auto_redirect` pre-matching.
|
||||
|
||||
`100` is used by default.
|
||||
|
||||
#### auto_redirect_iproute2_fallback_rule_index
|
||||
|
||||
!!! question "Since sing-box 1.12.18"
|
||||
|
||||
Linux iproute2 fallback rule index generated by `auto_redirect`.
|
||||
|
||||
This rule is checked after system default rules (32766: main, 32767: default),
|
||||
routing traffic to the sing-box table only when no route is found in system tables.
|
||||
|
||||
`32768` is used by default.
|
||||
|
||||
#### exclude_mptcp
|
||||
|
||||
!!! question "Since sing-box 1.13.0"
|
||||
|
||||
@@ -6,7 +6,8 @@ icon: material/new-box
|
||||
|
||||
:material-plus: [auto_redirect_reset_mark](#auto_redirect_reset_mark)
|
||||
:material-plus: [auto_redirect_nfqueue](#auto_redirect_nfqueue)
|
||||
:material-plus: [exclude_mptcp](#exclude_mptcp)
|
||||
:material-plus: [exclude_mptcp](#exclude_mptcp)
|
||||
:material-plus: [auto_redirect_iproute2_fallback_rule_index](#auto_redirect_iproute2_fallback_rule_index)
|
||||
|
||||
!!! quote "sing-box 1.12.0 中的更改"
|
||||
|
||||
@@ -71,6 +72,7 @@ icon: material/new-box
|
||||
"auto_redirect_output_mark": "0x2024",
|
||||
"auto_redirect_reset_mark": "0x2025",
|
||||
"auto_redirect_nfqueue": 100,
|
||||
"auto_redirect_iproute2_fallback_rule_index": 32768,
|
||||
"exclude_mptcp": false,
|
||||
"loopback_address": [
|
||||
"10.7.0.1"
|
||||
@@ -302,13 +304,24 @@ tun 接口的 IPv6 前缀。
|
||||
|
||||
默认使用 `100`。
|
||||
|
||||
#### auto_redirect_iproute2_fallback_rule_index
|
||||
|
||||
!!! question "自 sing-box 1.12.18 起"
|
||||
|
||||
`auto_redirect` 生成的 iproute2 回退规则索引。
|
||||
|
||||
此规则在系统默认规则(32766: main,32767: default)之后检查,
|
||||
仅当系统路由表中未找到路由时才将流量路由到 sing-box 路由表。
|
||||
|
||||
默认使用 `32768`。
|
||||
|
||||
#### exclude_mptcp
|
||||
|
||||
!!! question "自 sing-box 1.13.0 起"
|
||||
|
||||
!!! quote ""
|
||||
|
||||
仅支持 Linux,且需要 nftables,`auto_route` 和 `auto_redirect` 已启用。
|
||||
仅支持 Linux,且需要 nftables,`auto_route` 和 `auto_redirect` 已启用。
|
||||
|
||||
由于协议限制,MPTCP 无法被透明代理。
|
||||
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ require (
|
||||
github.com/sagernet/sing-shadowsocks v0.2.8
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
|
||||
github.com/sagernet/sing-tun v0.8.0-beta.14
|
||||
github.com/sagernet/sing-tun v0.8.0-beta.15
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1
|
||||
github.com/sagernet/tailscale v1.92.4-sing-box-1.13-mod.6
|
||||
|
||||
+2
-2
@@ -222,8 +222,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.1 h1:dWV9OXCeFPuYGHb6IRqlSptVnSzOelnq
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.1/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75l64tm9WvEFrYRE1t0YxoFdWQqw/h7Uhzj0vJ+w=
|
||||
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
|
||||
github.com/sagernet/sing-tun v0.8.0-beta.14 h1:LlIhiynP1aggwDYeHDa+JeJAuptYy+OtQU+hPiHTXbY=
|
||||
github.com/sagernet/sing-tun v0.8.0-beta.14/go.mod h1:+HAK/y9GZljdT0KYKMYDR8MjjqnqDDQZYp5ZZQoRzS8=
|
||||
github.com/sagernet/sing-tun v0.8.0-beta.15 h1:R5PMHCXuSUs5g6aor4UhxfaIx+t6yofAYB9YAea7UZM=
|
||||
github.com/sagernet/sing-tun v0.8.0-beta.15/go.mod h1:+HAK/y9GZljdT0KYKMYDR8MjjqnqDDQZYp5ZZQoRzS8=
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1 h1:aSwUNYUkVyVvdmBSufR8/nRFonwJeKSIROxHcm5br9o=
|
||||
github.com/sagernet/sing-vmess v0.2.8-0.20250909125414-3aed155119a1/go.mod h1:P11scgTxMxVVQ8dlM27yNm3Cro40mD0+gHbnqrNGDuY=
|
||||
github.com/sagernet/smux v1.5.50-sing-box-mod.1 h1:XkJcivBC9V4wBjiGXIXZ229aZCU1hzcbp6kSkkyQ478=
|
||||
|
||||
+31
-30
@@ -11,36 +11,37 @@ import (
|
||||
)
|
||||
|
||||
type TunInboundOptions struct {
|
||||
InterfaceName string `json:"interface_name,omitempty"`
|
||||
MTU uint32 `json:"mtu,omitempty"`
|
||||
Address badoption.Listable[netip.Prefix] `json:"address,omitempty"`
|
||||
AutoRoute bool `json:"auto_route,omitempty"`
|
||||
IPRoute2TableIndex int `json:"iproute2_table_index,omitempty"`
|
||||
IPRoute2RuleIndex int `json:"iproute2_rule_index,omitempty"`
|
||||
AutoRedirect bool `json:"auto_redirect,omitempty"`
|
||||
AutoRedirectInputMark FwMark `json:"auto_redirect_input_mark,omitempty"`
|
||||
AutoRedirectOutputMark FwMark `json:"auto_redirect_output_mark,omitempty"`
|
||||
AutoRedirectResetMark FwMark `json:"auto_redirect_reset_mark,omitempty"`
|
||||
AutoRedirectNFQueue uint16 `json:"auto_redirect_nfqueue,omitempty"`
|
||||
ExcludeMPTCP bool `json:"exclude_mptcp,omitempty"`
|
||||
LoopbackAddress badoption.Listable[netip.Addr] `json:"loopback_address,omitempty"`
|
||||
StrictRoute bool `json:"strict_route,omitempty"`
|
||||
RouteAddress badoption.Listable[netip.Prefix] `json:"route_address,omitempty"`
|
||||
RouteAddressSet badoption.Listable[string] `json:"route_address_set,omitempty"`
|
||||
RouteExcludeAddress badoption.Listable[netip.Prefix] `json:"route_exclude_address,omitempty"`
|
||||
RouteExcludeAddressSet badoption.Listable[string] `json:"route_exclude_address_set,omitempty"`
|
||||
IncludeInterface badoption.Listable[string] `json:"include_interface,omitempty"`
|
||||
ExcludeInterface badoption.Listable[string] `json:"exclude_interface,omitempty"`
|
||||
IncludeUID badoption.Listable[uint32] `json:"include_uid,omitempty"`
|
||||
IncludeUIDRange badoption.Listable[string] `json:"include_uid_range,omitempty"`
|
||||
ExcludeUID badoption.Listable[uint32] `json:"exclude_uid,omitempty"`
|
||||
ExcludeUIDRange badoption.Listable[string] `json:"exclude_uid_range,omitempty"`
|
||||
IncludeAndroidUser badoption.Listable[int] `json:"include_android_user,omitempty"`
|
||||
IncludePackage badoption.Listable[string] `json:"include_package,omitempty"`
|
||||
ExcludePackage badoption.Listable[string] `json:"exclude_package,omitempty"`
|
||||
UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"`
|
||||
Stack string `json:"stack,omitempty"`
|
||||
Platform *TunPlatformOptions `json:"platform,omitempty"`
|
||||
InterfaceName string `json:"interface_name,omitempty"`
|
||||
MTU uint32 `json:"mtu,omitempty"`
|
||||
Address badoption.Listable[netip.Prefix] `json:"address,omitempty"`
|
||||
AutoRoute bool `json:"auto_route,omitempty"`
|
||||
IPRoute2TableIndex int `json:"iproute2_table_index,omitempty"`
|
||||
IPRoute2RuleIndex int `json:"iproute2_rule_index,omitempty"`
|
||||
AutoRedirect bool `json:"auto_redirect,omitempty"`
|
||||
AutoRedirectInputMark FwMark `json:"auto_redirect_input_mark,omitempty"`
|
||||
AutoRedirectOutputMark FwMark `json:"auto_redirect_output_mark,omitempty"`
|
||||
AutoRedirectResetMark FwMark `json:"auto_redirect_reset_mark,omitempty"`
|
||||
AutoRedirectNFQueue uint16 `json:"auto_redirect_nfqueue,omitempty"`
|
||||
AutoRedirectFallbackRuleIndex int `json:"auto_redirect_iproute2_fallback_rule_index,omitempty"`
|
||||
ExcludeMPTCP bool `json:"exclude_mptcp,omitempty"`
|
||||
LoopbackAddress badoption.Listable[netip.Addr] `json:"loopback_address,omitempty"`
|
||||
StrictRoute bool `json:"strict_route,omitempty"`
|
||||
RouteAddress badoption.Listable[netip.Prefix] `json:"route_address,omitempty"`
|
||||
RouteAddressSet badoption.Listable[string] `json:"route_address_set,omitempty"`
|
||||
RouteExcludeAddress badoption.Listable[netip.Prefix] `json:"route_exclude_address,omitempty"`
|
||||
RouteExcludeAddressSet badoption.Listable[string] `json:"route_exclude_address_set,omitempty"`
|
||||
IncludeInterface badoption.Listable[string] `json:"include_interface,omitempty"`
|
||||
ExcludeInterface badoption.Listable[string] `json:"exclude_interface,omitempty"`
|
||||
IncludeUID badoption.Listable[uint32] `json:"include_uid,omitempty"`
|
||||
IncludeUIDRange badoption.Listable[string] `json:"include_uid_range,omitempty"`
|
||||
ExcludeUID badoption.Listable[uint32] `json:"exclude_uid,omitempty"`
|
||||
ExcludeUIDRange badoption.Listable[string] `json:"exclude_uid_range,omitempty"`
|
||||
IncludeAndroidUser badoption.Listable[int] `json:"include_android_user,omitempty"`
|
||||
IncludePackage badoption.Listable[string] `json:"include_package,omitempty"`
|
||||
ExcludePackage badoption.Listable[string] `json:"exclude_package,omitempty"`
|
||||
UDPTimeout UDPTimeoutCompat `json:"udp_timeout,omitempty"`
|
||||
Stack string `json:"stack,omitempty"`
|
||||
Platform *TunPlatformOptions `json:"platform,omitempty"`
|
||||
InboundOptions
|
||||
|
||||
// Deprecated: removed
|
||||
|
||||
@@ -174,6 +174,7 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
if ruleIndex == 0 {
|
||||
ruleIndex = tun.DefaultIPRoute2RuleIndex
|
||||
}
|
||||
autoRedirectFallbackRuleIndex := options.AutoRedirectFallbackRuleIndex
|
||||
inputMark := uint32(options.AutoRedirectInputMark)
|
||||
if inputMark == 0 {
|
||||
inputMark = tun.DefaultAutoRedirectInputMark
|
||||
@@ -200,35 +201,36 @@ func NewInbound(ctx context.Context, router adapter.Router, logger log.ContextLo
|
||||
logger: logger,
|
||||
inboundOptions: options.InboundOptions,
|
||||
tunOptions: tun.Options{
|
||||
Name: options.InterfaceName,
|
||||
MTU: tunMTU,
|
||||
GSO: enableGSO,
|
||||
Inet4Address: inet4Address,
|
||||
Inet6Address: inet6Address,
|
||||
AutoRoute: options.AutoRoute,
|
||||
IPRoute2TableIndex: tableIndex,
|
||||
IPRoute2RuleIndex: ruleIndex,
|
||||
AutoRedirectInputMark: inputMark,
|
||||
AutoRedirectOutputMark: outputMark,
|
||||
AutoRedirectResetMark: resetMark,
|
||||
AutoRedirectNFQueue: nfQueue,
|
||||
ExcludeMPTCP: options.ExcludeMPTCP,
|
||||
Inet4LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is4),
|
||||
Inet6LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is6),
|
||||
StrictRoute: options.StrictRoute,
|
||||
IncludeInterface: options.IncludeInterface,
|
||||
ExcludeInterface: options.ExcludeInterface,
|
||||
Inet4RouteAddress: inet4RouteAddress,
|
||||
Inet6RouteAddress: inet6RouteAddress,
|
||||
Inet4RouteExcludeAddress: inet4RouteExcludeAddress,
|
||||
Inet6RouteExcludeAddress: inet6RouteExcludeAddress,
|
||||
IncludeUID: includeUID,
|
||||
ExcludeUID: excludeUID,
|
||||
IncludeAndroidUser: options.IncludeAndroidUser,
|
||||
IncludePackage: options.IncludePackage,
|
||||
ExcludePackage: options.ExcludePackage,
|
||||
InterfaceMonitor: networkManager.InterfaceMonitor(),
|
||||
EXP_MultiPendingPackets: multiPendingPackets,
|
||||
Name: options.InterfaceName,
|
||||
MTU: tunMTU,
|
||||
GSO: enableGSO,
|
||||
Inet4Address: inet4Address,
|
||||
Inet6Address: inet6Address,
|
||||
AutoRoute: options.AutoRoute,
|
||||
IPRoute2TableIndex: tableIndex,
|
||||
IPRoute2RuleIndex: ruleIndex,
|
||||
IPRoute2AutoRedirectFallbackRuleIndex: autoRedirectFallbackRuleIndex,
|
||||
AutoRedirectInputMark: inputMark,
|
||||
AutoRedirectOutputMark: outputMark,
|
||||
AutoRedirectResetMark: resetMark,
|
||||
AutoRedirectNFQueue: nfQueue,
|
||||
ExcludeMPTCP: options.ExcludeMPTCP,
|
||||
Inet4LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is4),
|
||||
Inet6LoopbackAddress: common.Filter(options.LoopbackAddress, netip.Addr.Is6),
|
||||
StrictRoute: options.StrictRoute,
|
||||
IncludeInterface: options.IncludeInterface,
|
||||
ExcludeInterface: options.ExcludeInterface,
|
||||
Inet4RouteAddress: inet4RouteAddress,
|
||||
Inet6RouteAddress: inet6RouteAddress,
|
||||
Inet4RouteExcludeAddress: inet4RouteExcludeAddress,
|
||||
Inet6RouteExcludeAddress: inet6RouteExcludeAddress,
|
||||
IncludeUID: includeUID,
|
||||
ExcludeUID: excludeUID,
|
||||
IncludeAndroidUser: options.IncludeAndroidUser,
|
||||
IncludePackage: options.IncludePackage,
|
||||
ExcludePackage: options.ExcludePackage,
|
||||
InterfaceMonitor: networkManager.InterfaceMonitor(),
|
||||
EXP_MultiPendingPackets: multiPendingPackets,
|
||||
},
|
||||
udpTimeout: udpTimeout,
|
||||
stack: options.Stack,
|
||||
|
||||
@@ -21,13 +21,13 @@ define Download/geoip
|
||||
HASH:=ed2de9add79623e2e5dbc5930ee39cc7037a7c6e0ecd58ba528b6f73d61457b5
|
||||
endef
|
||||
|
||||
GEOSITE_VER:=20260128050754
|
||||
GEOSITE_VER:=20260129053508
|
||||
GEOSITE_FILE:=dlc.dat.$(GEOSITE_VER)
|
||||
define Download/geosite
|
||||
URL:=https://github.com/v2fly/domain-list-community/releases/download/$(GEOSITE_VER)/
|
||||
URL_FILE:=dlc.dat
|
||||
FILE:=$(GEOSITE_FILE)
|
||||
HASH:=90582c09fed4583bae5a3645182034abecc134ae13176fe8754a8ae53fea26d7
|
||||
HASH:=792b3745f5a16d5e5cc7a24a762027e7f39bb612651a0ff362801bc09b74ff88
|
||||
endef
|
||||
|
||||
GEOSITE_IRAN_VER:=202601260049
|
||||
|
||||
@@ -12,8 +12,8 @@ android {
|
||||
applicationId = "com.v2ray.ang"
|
||||
minSdk = 24
|
||||
targetSdk = 36
|
||||
versionCode = 706
|
||||
versionName = "2.0.6"
|
||||
versionCode = 707
|
||||
versionName = "2.0.7"
|
||||
multiDexEnabled = true
|
||||
|
||||
val abiFilterList = (properties["ABI_FILTERS"] as? String)?.split(';')
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.ui
|
||||
package com.v2ray.ang.contracts
|
||||
|
||||
/**
|
||||
* A common Adapter -> host callback interface that includes common actions: edit, remove and refresh.
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.ui
|
||||
package com.v2ray.ang.contracts
|
||||
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.service
|
||||
package com.v2ray.ang.contracts
|
||||
|
||||
import android.app.Service
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.service
|
||||
package com.v2ray.ang.contracts
|
||||
|
||||
/**
|
||||
* Interface that defines the control operations for tun2socks implementations.
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.v2ray.ang.dto
|
||||
|
||||
data class AssetUrlCache(
|
||||
val guid: String,
|
||||
val assetUrl: AssetUrlItem
|
||||
)
|
||||
@@ -5,6 +5,7 @@ import com.v2ray.ang.AppConfig.PORT_SOCKS
|
||||
import com.v2ray.ang.AppConfig.TAG_BLOCKED
|
||||
import com.v2ray.ang.AppConfig.TAG_DIRECT
|
||||
import com.v2ray.ang.AppConfig.TAG_PROXY
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.util.Utils
|
||||
|
||||
data class ProfileItem(
|
||||
@@ -42,6 +43,7 @@ data class ProfileItem(
|
||||
var insecure: Boolean? = null,
|
||||
var echConfigList: String? = null,
|
||||
var echForceQuery: String? = null,
|
||||
var pinnedCA256: String? = null,
|
||||
|
||||
var publicKey: String? = null,
|
||||
var shortId: String? = null,
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
package com.v2ray.ang.dto
|
||||
|
||||
data class SubscriptionCache(
|
||||
val guid: String,
|
||||
val subscription: SubscriptionItem
|
||||
)
|
||||
@@ -2,6 +2,7 @@ package com.v2ray.ang.dto
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
|
||||
data class V2rayConfig(
|
||||
var remarks: String? = null,
|
||||
@@ -271,6 +272,7 @@ data class V2rayConfig(
|
||||
val enableSessionResumption: Boolean? = null,
|
||||
var echConfigList: String? = null,
|
||||
var echForceQuery: String? = null,
|
||||
var pinnedPeerCertSha256: String? = null,
|
||||
// REALITY settings
|
||||
val show: Boolean = false,
|
||||
var publicKey: String? = null,
|
||||
|
||||
+2
-3
@@ -1,8 +1,7 @@
|
||||
package com.v2ray.ang.dto
|
||||
package com.v2ray.ang.enums
|
||||
|
||||
import com.v2ray.ang.AppConfig
|
||||
|
||||
|
||||
enum class EConfigType(val value: Int, val protocolScheme: String) {
|
||||
VMESS(1, AppConfig.VMESS),
|
||||
CUSTOM(2, AppConfig.CUSTOM),
|
||||
@@ -21,4 +20,4 @@ enum class EConfigType(val value: Int, val protocolScheme: String) {
|
||||
companion object {
|
||||
fun fromInt(value: Int) = entries.firstOrNull { it.value == value }
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.dto
|
||||
package com.v2ray.ang.enums
|
||||
|
||||
enum class Language(val code: String) {
|
||||
AUTO("auto"),
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.dto
|
||||
package com.v2ray.ang.enums
|
||||
|
||||
enum class NetworkType(val type: String) {
|
||||
TCP("tcp"),
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.dto
|
||||
package com.v2ray.ang.enums
|
||||
|
||||
import android.Manifest
|
||||
import android.os.Build
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.dto
|
||||
package com.v2ray.ang.enums
|
||||
|
||||
enum class RoutingType(val fileName: String) {
|
||||
WHITE("custom_routing_white"),
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
package com.v2ray.ang.dto
|
||||
package com.v2ray.ang.enums
|
||||
|
||||
/**
|
||||
* VPN interface address configuration enum class
|
||||
@@ -11,6 +11,7 @@ import com.v2ray.ang.AngApplication
|
||||
import es.dmoral.toasty.Toasty
|
||||
import java.io.Serializable
|
||||
import java.net.URI
|
||||
import java.util.Locale
|
||||
|
||||
val Context.v2RayApplication: AngApplication?
|
||||
get() = applicationContext as? AngApplication
|
||||
@@ -92,7 +93,7 @@ fun Long.toTrafficString(): String {
|
||||
size /= DIVISOR
|
||||
unitIndex++
|
||||
}
|
||||
return String.format("%.1f %s", size, units[unitIndex])
|
||||
return String.format(Locale.getDefault(), "%.1f %s", size, units[unitIndex])
|
||||
}
|
||||
|
||||
val URI.idnHost: String
|
||||
@@ -105,6 +106,13 @@ val URI.idnHost: String
|
||||
*/
|
||||
fun String?.removeWhiteSpace(): String? = this?.replace(" ", "")
|
||||
|
||||
/**
|
||||
* Returns null if the string is null or blank, otherwise returns the string itself.
|
||||
*
|
||||
* @return The string or null.
|
||||
*/
|
||||
fun String?.nullIfBlank(): String? = this?.takeIf { it.isNotBlank() }
|
||||
|
||||
/**
|
||||
* Converts the string to a Long value, or returns 0 if the conversion fails.
|
||||
*
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig
|
||||
import com.v2ray.ang.util.JsonUtil
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.NetworkType
|
||||
import com.v2ray.ang.enums.NetworkType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.extension.isNotNullEmpty
|
||||
import com.v2ray.ang.extension.nullIfBlank
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.util.HttpUtil
|
||||
import com.v2ray.ang.util.Utils
|
||||
@@ -83,6 +83,7 @@ open class FmtBase {
|
||||
config.fingerPrint = queryParam["fp"]
|
||||
config.alpn = queryParam["alpn"]
|
||||
config.echConfigList = queryParam["ech"]
|
||||
config.pinnedCA256 = queryParam["pcs"]
|
||||
config.publicKey = queryParam["pbk"]
|
||||
config.shortId = queryParam["sid"]
|
||||
config.spiderX = queryParam["spx"]
|
||||
@@ -99,15 +100,16 @@ open class FmtBase {
|
||||
fun getQueryDic(config: ProfileItem): HashMap<String, String> {
|
||||
val dicQuery = HashMap<String, String>()
|
||||
dicQuery["security"] = config.security?.ifEmpty { "none" }.orEmpty()
|
||||
config.sni.let { if (it.isNotNullEmpty()) dicQuery["sni"] = it.orEmpty() }
|
||||
config.alpn.let { if (it.isNotNullEmpty()) dicQuery["alpn"] = it.orEmpty() }
|
||||
config.echConfigList.let { if (it.isNotNullEmpty()) dicQuery["ech"] = it.orEmpty() }
|
||||
config.fingerPrint.let { if (it.isNotNullEmpty()) dicQuery["fp"] = it.orEmpty() }
|
||||
config.publicKey.let { if (it.isNotNullEmpty()) dicQuery["pbk"] = it.orEmpty() }
|
||||
config.shortId.let { if (it.isNotNullEmpty()) dicQuery["sid"] = it.orEmpty() }
|
||||
config.spiderX.let { if (it.isNotNullEmpty()) dicQuery["spx"] = it.orEmpty() }
|
||||
config.mldsa65Verify.let { if (it.isNotNullEmpty()) dicQuery["pqv"] = it.orEmpty() }
|
||||
config.flow.let { if (it.isNotNullEmpty()) dicQuery["flow"] = it.orEmpty() }
|
||||
config.sni?.nullIfBlank()?.let { dicQuery["sni"] = it }
|
||||
config.alpn?.nullIfBlank()?.let { dicQuery["alpn"] = it }
|
||||
config.echConfigList?.nullIfBlank()?.let { dicQuery["ech"] = it }
|
||||
config.pinnedCA256?.nullIfBlank()?.let { dicQuery["pcs"] = it }
|
||||
config.fingerPrint?.nullIfBlank()?.let { dicQuery["fp"] = it }
|
||||
config.publicKey?.nullIfBlank()?.let { dicQuery["pbk"] = it }
|
||||
config.shortId?.nullIfBlank()?.let { dicQuery["sid"] = it }
|
||||
config.spiderX?.nullIfBlank()?.let { dicQuery["spx"] = it }
|
||||
config.mldsa65Verify?.nullIfBlank()?.let { dicQuery["pqv"] = it }
|
||||
config.flow?.nullIfBlank()?.let { dicQuery["flow"] = it }
|
||||
// Add two keys for compatibility: "insecure" and "allowInsecure"
|
||||
if (config.security == AppConfig.TLS) {
|
||||
val insecureFlag = if (config.insecure == true) "1" else "0"
|
||||
@@ -121,42 +123,42 @@ open class FmtBase {
|
||||
when (networkType) {
|
||||
NetworkType.TCP -> {
|
||||
dicQuery["headerType"] = config.headerType?.ifEmpty { "none" }.orEmpty()
|
||||
config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() }
|
||||
config.host?.nullIfBlank()?.let { dicQuery["host"] = it }
|
||||
}
|
||||
|
||||
NetworkType.KCP -> {
|
||||
dicQuery["headerType"] = config.headerType?.ifEmpty { "none" }.orEmpty()
|
||||
config.seed.let { if (it.isNotNullEmpty()) dicQuery["seed"] = it.orEmpty() }
|
||||
config.seed?.nullIfBlank()?.let { dicQuery["seed"] = it }
|
||||
}
|
||||
|
||||
NetworkType.WS, NetworkType.HTTP_UPGRADE -> {
|
||||
config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() }
|
||||
config.path.let { if (it.isNotNullEmpty()) dicQuery["path"] = it.orEmpty() }
|
||||
config.host?.nullIfBlank()?.let { dicQuery["host"] = it }
|
||||
config.path?.nullIfBlank()?.let { dicQuery["path"] = it }
|
||||
}
|
||||
|
||||
NetworkType.XHTTP -> {
|
||||
config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() }
|
||||
config.path.let { if (it.isNotNullEmpty()) dicQuery["path"] = it.orEmpty() }
|
||||
config.xhttpMode.let { if (it.isNotNullEmpty()) dicQuery["mode"] = it.orEmpty() }
|
||||
config.xhttpExtra.let { if (it.isNotNullEmpty()) dicQuery["extra"] = it.orEmpty() }
|
||||
config.host?.nullIfBlank()?.let { dicQuery["host"] = it }
|
||||
config.path?.nullIfBlank()?.let { dicQuery["path"] = it }
|
||||
config.xhttpMode?.nullIfBlank()?.let { dicQuery["mode"] = it }
|
||||
config.xhttpExtra?.nullIfBlank()?.let { dicQuery["extra"] = it }
|
||||
}
|
||||
|
||||
NetworkType.HTTP, NetworkType.H2 -> {
|
||||
dicQuery["type"] = "http"
|
||||
config.host.let { if (it.isNotNullEmpty()) dicQuery["host"] = it.orEmpty() }
|
||||
config.path.let { if (it.isNotNullEmpty()) dicQuery["path"] = it.orEmpty() }
|
||||
config.host?.nullIfBlank()?.let { dicQuery["host"] = it }
|
||||
config.path?.nullIfBlank()?.let { dicQuery["path"] = it }
|
||||
}
|
||||
|
||||
// NetworkType.QUIC -> {
|
||||
// dicQuery["headerType"] = config.headerType?.ifEmpty { "none" }.orEmpty()
|
||||
// config.quicSecurity.let { if (it.isNotNullEmpty()) dicQuery["quicSecurity"] = it.orEmpty() }
|
||||
// config.quicKey.let { if (it.isNotNullEmpty()) dicQuery["key"] = it.orEmpty() }
|
||||
// config.quicSecurity?.nullIfBlank()?.let { dicQuery["quicSecurity"] = it }
|
||||
// config.quicKey?.nullIfBlank()?.let { dicQuery["key"] = it }
|
||||
// }
|
||||
|
||||
NetworkType.GRPC -> {
|
||||
config.mode.let { if (it.isNotNullEmpty()) dicQuery["mode"] = it.orEmpty() }
|
||||
config.authority.let { if (it.isNotNullEmpty()) dicQuery["authority"] = it.orEmpty() }
|
||||
config.serviceName.let { if (it.isNotNullEmpty()) dicQuery["serviceName"] = it.orEmpty() }
|
||||
config.mode?.nullIfBlank()?.let { dicQuery["mode"] = it }
|
||||
config.authority?.nullIfBlank()?.let { dicQuery["authority"] = it }
|
||||
config.serviceName?.nullIfBlank()?.let { dicQuery["serviceName"] = it }
|
||||
}
|
||||
|
||||
else -> {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.extension.isNotNullEmpty
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.NetworkType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.NetworkType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean.StreamSettingsBean
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean.StreamSettingsBean.UdpMasksBean.UdpMasksSettingsBean
|
||||
import com.v2ray.ang.extension.idnHost
|
||||
import com.v2ray.ang.extension.isNotNullEmpty
|
||||
import com.v2ray.ang.extension.nullIfBlank
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.V2rayConfigManager
|
||||
import com.v2ray.ang.util.Utils
|
||||
@@ -61,8 +62,8 @@ object Hysteria2Fmt : FmtBase() {
|
||||
val dicQuery = HashMap<String, String>()
|
||||
|
||||
config.security.let { if (it != null) dicQuery["security"] = it }
|
||||
config.sni.let { if (it.isNotNullEmpty()) dicQuery["sni"] = it.orEmpty() }
|
||||
config.alpn.let { if (it.isNotNullEmpty()) dicQuery["alpn"] = it.orEmpty() }
|
||||
config.sni?.nullIfBlank()?.let { dicQuery["sni"] = it }
|
||||
config.alpn?.nullIfBlank()?.let { dicQuery["alpn"] = it }
|
||||
config.insecure.let { dicQuery["insecure"] = if (it == true) "1" else "0" }
|
||||
|
||||
if (config.obfsPassword.isNotNullEmpty()) {
|
||||
|
||||
@@ -2,8 +2,8 @@ package com.v2ray.ang.fmt
|
||||
|
||||
import android.util.Log
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.NetworkType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.NetworkType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.extension.idnHost
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.extension.idnHost
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.NetworkType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.NetworkType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.extension.idnHost
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.extension.idnHost
|
||||
|
||||
@@ -3,13 +3,13 @@ package com.v2ray.ang.fmt
|
||||
import android.text.TextUtils
|
||||
import android.util.Log
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.NetworkType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.NetworkType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.dto.VmessQRCode
|
||||
import com.v2ray.ang.extension.idnHost
|
||||
import com.v2ray.ang.extension.isNotNullEmpty
|
||||
import com.v2ray.ang.extension.nullIfBlank
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.V2rayConfigManager
|
||||
import com.v2ray.ang.util.JsonUtil
|
||||
@@ -132,8 +132,8 @@ object VmessFmt : FmtBase() {
|
||||
else -> {}
|
||||
}
|
||||
|
||||
config.host.let { if (it.isNotNullEmpty()) vmessQRCode.host = it.orEmpty() }
|
||||
config.path.let { if (it.isNotNullEmpty()) vmessQRCode.path = it.orEmpty() }
|
||||
config.host?.nullIfBlank()?.let { vmessQRCode.host = it }
|
||||
config.path?.nullIfBlank()?.let { vmessQRCode.path = it }
|
||||
|
||||
vmessQRCode.tls = config.security.orEmpty()
|
||||
vmessQRCode.sni = config.sni.orEmpty()
|
||||
|
||||
@@ -2,10 +2,11 @@ package com.v2ray.ang.fmt
|
||||
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean
|
||||
import com.v2ray.ang.extension.idnHost
|
||||
import com.v2ray.ang.extension.nullIfBlank
|
||||
import com.v2ray.ang.extension.removeWhiteSpace
|
||||
import com.v2ray.ang.handler.V2rayConfigManager
|
||||
import com.v2ray.ang.util.Utils
|
||||
@@ -32,7 +33,7 @@ object WireguardFmt : FmtBase() {
|
||||
config.secretKey = uri.userInfo.orEmpty()
|
||||
config.localAddress = queryParam["address"] ?: WIREGUARD_LOCAL_ADDRESS_V4
|
||||
config.publicKey = queryParam["publickey"].orEmpty()
|
||||
config.preSharedKey = queryParam["presharedkey"]?.takeIf { it.isNotEmpty() }
|
||||
config.preSharedKey = queryParam["presharedkey"]?.nullIfBlank()
|
||||
config.mtu = Utils.parseInt(queryParam["mtu"] ?: AppConfig.WIREGUARD_LOCAL_MTU)
|
||||
config.reserved = queryParam["reserved"] ?: "0,0,0"
|
||||
|
||||
@@ -84,7 +85,7 @@ object WireguardFmt : FmtBase() {
|
||||
config.localAddress = interfaceParams["address"] ?: WIREGUARD_LOCAL_ADDRESS_V4
|
||||
config.mtu = Utils.parseInt(interfaceParams["mtu"] ?: AppConfig.WIREGUARD_LOCAL_MTU)
|
||||
config.publicKey = peerParams["publickey"].orEmpty()
|
||||
config.preSharedKey = peerParams["presharedkey"]?.takeIf { it.isNotEmpty() }
|
||||
config.preSharedKey = peerParams["presharedkey"]?.nullIfBlank()
|
||||
val endpoint = peerParams["endpoint"].orEmpty()
|
||||
val endpointParts = endpoint.split(":", limit = 2)
|
||||
if (endpointParts.size == 2) {
|
||||
@@ -113,7 +114,7 @@ object WireguardFmt : FmtBase() {
|
||||
wireguard.address = (profileItem.localAddress ?: WIREGUARD_LOCAL_ADDRESS_V4).split(",")
|
||||
wireguard.peers?.firstOrNull()?.let { peer ->
|
||||
peer.publicKey = profileItem.publicKey.orEmpty()
|
||||
peer.preSharedKey = profileItem.preSharedKey?.takeIf { it.isNotEmpty() }
|
||||
peer.preSharedKey = profileItem.preSharedKey?.nullIfBlank()
|
||||
peer.endpoint = Utils.getIpv6Address(profileItem.server) + ":${profileItem.serverPort}"
|
||||
}
|
||||
wireguard.mtu = profileItem.mtu
|
||||
|
||||
@@ -7,8 +7,9 @@ import android.util.Log
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.AppConfig.HY2
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.SubscriptionCache
|
||||
import com.v2ray.ang.dto.SubscriptionItem
|
||||
import com.v2ray.ang.fmt.CustomFmt
|
||||
import com.v2ray.ang.fmt.Hysteria2Fmt
|
||||
@@ -399,28 +400,28 @@ object AngConfigManager {
|
||||
* @param it The subscription item.
|
||||
* @return The number of configurations updated.
|
||||
*/
|
||||
fun updateConfigViaSub(it: Pair<String, SubscriptionItem>): Int {
|
||||
fun updateConfigViaSub(it: SubscriptionCache): Int {
|
||||
try {
|
||||
if (TextUtils.isEmpty(it.first)
|
||||
|| TextUtils.isEmpty(it.second.remarks)
|
||||
|| TextUtils.isEmpty(it.second.url)
|
||||
if (TextUtils.isEmpty(it.guid)
|
||||
|| TextUtils.isEmpty(it.subscription.remarks)
|
||||
|| TextUtils.isEmpty(it.subscription.url)
|
||||
) {
|
||||
return 0
|
||||
}
|
||||
if (!it.second.enabled) {
|
||||
if (!it.subscription.enabled) {
|
||||
return 0
|
||||
}
|
||||
val url = HttpUtil.toIdnUrl(it.second.url)
|
||||
val url = HttpUtil.toIdnUrl(it.subscription.url)
|
||||
if (!Utils.isValidUrl(url)) {
|
||||
return 0
|
||||
}
|
||||
if (!it.second.allowInsecureUrl) {
|
||||
if (!it.subscription.allowInsecureUrl) {
|
||||
if (!Utils.isValidSubUrl(url)) {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
Log.i(AppConfig.TAG, url)
|
||||
val userAgent = it.second.userAgent
|
||||
val userAgent = it.subscription.userAgent
|
||||
|
||||
var configText = try {
|
||||
val httpPort = SettingsManager.getHttpPort()
|
||||
@@ -440,11 +441,11 @@ object AngConfigManager {
|
||||
if (configText.isEmpty()) {
|
||||
return 0
|
||||
}
|
||||
val count = parseConfigViaSub(configText, it.first, false)
|
||||
val count = parseConfigViaSub(configText, it.guid, false)
|
||||
if (count > 0) {
|
||||
it.second.lastUpdated = System.currentTimeMillis()
|
||||
MmkvManager.encodeSubscription(it.first, it.second)
|
||||
Log.i(AppConfig.TAG, "Subscription updated: ${it.second.remarks}, $count configs")
|
||||
it.subscription.lastUpdated = System.currentTimeMillis()
|
||||
MmkvManager.encodeSubscription(it.guid, it.subscription)
|
||||
Log.i(AppConfig.TAG, "Subscription updated: ${it.subscription.remarks}, $count configs")
|
||||
}
|
||||
return count
|
||||
} catch (e: Exception) {
|
||||
@@ -481,7 +482,7 @@ object AngConfigManager {
|
||||
private fun importUrlAsSubscription(url: String): Int {
|
||||
val subscriptions = MmkvManager.decodeSubscriptions()
|
||||
subscriptions.forEach {
|
||||
if (it.second.url == url) {
|
||||
if (it.subscription.url == url) {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,12 @@ package com.v2ray.ang.handler
|
||||
import com.tencent.mmkv.MMKV
|
||||
import com.v2ray.ang.AppConfig.PREF_IS_BOOTED
|
||||
import com.v2ray.ang.AppConfig.PREF_ROUTING_RULESET
|
||||
import com.v2ray.ang.dto.AssetUrlCache
|
||||
import com.v2ray.ang.dto.AssetUrlItem
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.RulesetItem
|
||||
import com.v2ray.ang.dto.ServerAffiliationInfo
|
||||
import com.v2ray.ang.dto.SubscriptionCache
|
||||
import com.v2ray.ang.dto.SubscriptionItem
|
||||
import com.v2ray.ang.dto.WebDavConfig
|
||||
import com.v2ray.ang.util.JsonUtil
|
||||
@@ -309,15 +311,15 @@ object MmkvManager {
|
||||
*
|
||||
* @return The list of subscriptions.
|
||||
*/
|
||||
fun decodeSubscriptions(): List<Pair<String, SubscriptionItem>> {
|
||||
fun decodeSubscriptions(): List<SubscriptionCache> {
|
||||
initSubsList()
|
||||
|
||||
val subscriptions = mutableListOf<Pair<String, SubscriptionItem>>()
|
||||
val subscriptions = mutableListOf<SubscriptionCache>()
|
||||
decodeSubsList().forEach { key ->
|
||||
val json = subStorage.decodeString(key)
|
||||
if (!json.isNullOrBlank()) {
|
||||
val item = JsonUtil.fromJson(json, SubscriptionItem::class.java)?: SubscriptionItem()
|
||||
subscriptions.add(Pair(key, item))
|
||||
subscriptions.add(SubscriptionCache(key, item))
|
||||
}
|
||||
}
|
||||
return subscriptions
|
||||
@@ -397,16 +399,16 @@ object MmkvManager {
|
||||
*
|
||||
* @return The list of asset URLs.
|
||||
*/
|
||||
fun decodeAssetUrls(): List<Pair<String, AssetUrlItem>> {
|
||||
val assetUrlItems = mutableListOf<Pair<String, AssetUrlItem>>()
|
||||
fun decodeAssetUrls(): List<AssetUrlCache> {
|
||||
val assetUrlItems = mutableListOf<AssetUrlCache>()
|
||||
assetStorage.allKeys()?.forEach { key ->
|
||||
val json = assetStorage.decodeString(key)
|
||||
if (!json.isNullOrBlank()) {
|
||||
val item = JsonUtil.fromJson(json, AssetUrlItem::class.java)?: AssetUrlItem()
|
||||
assetUrlItems.add(Pair(key, item))
|
||||
assetUrlItems.add(AssetUrlCache(key, item))
|
||||
}
|
||||
}
|
||||
return assetUrlItems.sortedBy { (_, value) -> value.addedTime }
|
||||
return assetUrlItems.sortedBy { it.assetUrl.addedTime }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,13 +11,13 @@ import com.v2ray.ang.AppConfig.GEOIP_PRIVATE
|
||||
import com.v2ray.ang.AppConfig.GEOSITE_PRIVATE
|
||||
import com.v2ray.ang.AppConfig.TAG_DIRECT
|
||||
import com.v2ray.ang.AppConfig.VPN
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.Language
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.Language
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.RoutingType
|
||||
import com.v2ray.ang.enums.RoutingType
|
||||
import com.v2ray.ang.dto.RulesetItem
|
||||
import com.v2ray.ang.dto.V2rayConfig
|
||||
import com.v2ray.ang.dto.VpnInterfaceAddressConfig
|
||||
import com.v2ray.ang.enums.VpnInterfaceAddressConfig
|
||||
import com.v2ray.ang.handler.MmkvManager.decodeServerConfig
|
||||
import com.v2ray.ang.handler.MmkvManager.decodeServerList
|
||||
import com.v2ray.ang.util.JsonUtil
|
||||
|
||||
@@ -36,10 +36,10 @@ object SubscriptionUpdater {
|
||||
override suspend fun doWork(): Result {
|
||||
Log.i(AppConfig.TAG, "subscription automatic update starting")
|
||||
|
||||
val subs = MmkvManager.decodeSubscriptions().filter { it.second.autoUpdate }
|
||||
val subs = MmkvManager.decodeSubscriptions().filter { it.subscription.autoUpdate }
|
||||
|
||||
for (sub in subs) {
|
||||
val subItem = sub.second
|
||||
val subItem = sub.subscription
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
notification.setChannelId(AppConfig.SUBSCRIPTION_UPDATE_CHANNEL)
|
||||
@@ -53,7 +53,7 @@ object SubscriptionUpdater {
|
||||
}
|
||||
notificationManager.notify(3, notification.build())
|
||||
Log.i(AppConfig.TAG, "subscription automatic update: ---${subItem.remarks}")
|
||||
AngConfigManager.updateConfigViaSub(Pair(sub.first, subItem))
|
||||
AngConfigManager.updateConfigViaSub(sub)
|
||||
notification.setContentText("Updating ${subItem.remarks}")
|
||||
}
|
||||
notificationManager.cancel(3)
|
||||
|
||||
@@ -10,10 +10,10 @@ import android.util.Log
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.service.ServiceControl
|
||||
import com.v2ray.ang.contracts.ServiceControl
|
||||
import com.v2ray.ang.service.V2RayProxyOnlyService
|
||||
import com.v2ray.ang.service.V2RayVpnService
|
||||
import com.v2ray.ang.util.MessageUtil
|
||||
@@ -151,6 +151,7 @@ object V2RayServiceManager {
|
||||
}
|
||||
|
||||
try {
|
||||
NotificationManager.showNotification(currentConfig)
|
||||
coreController.startLoop(result.content, tunFd)
|
||||
} catch (e: Exception) {
|
||||
Log.e(AppConfig.TAG, "Failed to start Core loop", e)
|
||||
@@ -165,7 +166,7 @@ object V2RayServiceManager {
|
||||
|
||||
try {
|
||||
MessageUtil.sendMsg2UI(service, AppConfig.MSG_STATE_START_SUCCESS, "")
|
||||
NotificationManager.showNotification(currentConfig)
|
||||
//NotificationManager.showNotification(currentConfig)
|
||||
NotificationManager.startSpeedNotification(currentConfig)
|
||||
|
||||
} catch (e: Exception) {
|
||||
|
||||
@@ -6,8 +6,8 @@ import android.util.Log
|
||||
import com.google.gson.JsonArray
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.dto.ConfigResult
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.NetworkType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.NetworkType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.dto.RulesetItem
|
||||
import com.v2ray.ang.dto.V2rayConfig
|
||||
@@ -16,6 +16,7 @@ import com.v2ray.ang.dto.V2rayConfig.OutboundBean.OutSettingsBean
|
||||
import com.v2ray.ang.dto.V2rayConfig.OutboundBean.StreamSettingsBean
|
||||
import com.v2ray.ang.dto.V2rayConfig.RoutingBean.RulesBean
|
||||
import com.v2ray.ang.extension.isNotNullEmpty
|
||||
import com.v2ray.ang.extension.nullIfBlank
|
||||
import com.v2ray.ang.fmt.HttpFmt
|
||||
import com.v2ray.ang.fmt.Hysteria2Fmt
|
||||
import com.v2ray.ang.fmt.ShadowsocksFmt
|
||||
@@ -1296,28 +1297,21 @@ object V2rayConfigManager {
|
||||
} else {
|
||||
profileItem.sni
|
||||
}
|
||||
val fingerprint = profileItem.fingerPrint
|
||||
val alpns = profileItem.alpn
|
||||
val echConfigList = profileItem.echConfigList
|
||||
val echForceQuery = profileItem.echForceQuery
|
||||
val publicKey = profileItem.publicKey
|
||||
val shortId = profileItem.shortId
|
||||
val spiderX = profileItem.spiderX
|
||||
val mldsa65Verify = profileItem.mldsa65Verify
|
||||
|
||||
streamSettings.security = if (streamSecurity.isEmpty()) null else streamSecurity
|
||||
streamSettings.security = streamSecurity.nullIfBlank()
|
||||
if (streamSettings.security == null) return
|
||||
val tlsSetting = StreamSettingsBean.TlsSettingsBean(
|
||||
allowInsecure = allowInsecure,
|
||||
serverName = if (sni.isNullOrEmpty()) null else sni,
|
||||
fingerprint = if (fingerprint.isNullOrEmpty()) null else fingerprint,
|
||||
alpn = if (alpns.isNullOrEmpty()) null else alpns.split(",").map { it.trim() }.filter { it.isNotEmpty() },
|
||||
echConfigList = if (echConfigList.isNullOrEmpty()) null else echConfigList,
|
||||
echForceQuery = if (echForceQuery.isNullOrEmpty()) null else echForceQuery,
|
||||
publicKey = if (publicKey.isNullOrEmpty()) null else publicKey,
|
||||
shortId = if (shortId.isNullOrEmpty()) null else shortId,
|
||||
spiderX = if (spiderX.isNullOrEmpty()) null else spiderX,
|
||||
mldsa65Verify = if (mldsa65Verify.isNullOrEmpty()) null else mldsa65Verify,
|
||||
serverName = sni.nullIfBlank(),
|
||||
fingerprint = profileItem.fingerPrint.nullIfBlank(),
|
||||
alpn = profileItem.alpn?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }.takeIf { !it.isNullOrEmpty() },
|
||||
echConfigList = profileItem.echConfigList.nullIfBlank(),
|
||||
echForceQuery = profileItem.echForceQuery.nullIfBlank(),
|
||||
pinnedPeerCertSha256 = profileItem.pinnedCA256.nullIfBlank(),
|
||||
publicKey = profileItem.publicKey.nullIfBlank(),
|
||||
shortId = profileItem.shortId.nullIfBlank(),
|
||||
spiderX = profileItem.spiderX.nullIfBlank(),
|
||||
mldsa65Verify = profileItem.mldsa65Verify.nullIfBlank(),
|
||||
)
|
||||
if (streamSettings.security == AppConfig.TLS) {
|
||||
streamSettings.tlsSettings = tlsSetting
|
||||
|
||||
+4
-1
@@ -1,7 +1,10 @@
|
||||
package com.v2ray.ang.handler
|
||||
package com.v2ray.ang.helper
|
||||
|
||||
import androidx.preference.PreferenceDataStore
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.SettingsChangeManager
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
|
||||
/**
|
||||
* PreferenceDataStore implementation that bridges AndroidX Preference framework to MMKV storage.
|
||||
@@ -6,7 +6,7 @@ import androidx.activity.result.contract.ActivityResultContracts
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.dto.PermissionType
|
||||
import com.v2ray.ang.enums.PermissionType
|
||||
import com.v2ray.ang.extension.toast
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.content.Context
|
||||
import android.os.ParcelFileDescriptor
|
||||
import android.util.Log
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.contracts.Tun2SocksControl
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
import java.io.File
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.app.Service
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.IBinder
|
||||
import com.v2ray.ang.contracts.ServiceControl
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
import com.v2ray.ang.handler.V2RayServiceManager
|
||||
import com.v2ray.ang.util.MyContextWrapper
|
||||
|
||||
@@ -18,6 +18,8 @@ import androidx.annotation.RequiresApi
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.AppConfig.LOOPBACK
|
||||
import com.v2ray.ang.BuildConfig
|
||||
import com.v2ray.ang.contracts.ServiceControl
|
||||
import com.v2ray.ang.contracts.Tun2SocksControl
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.NotificationManager
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
@@ -76,7 +78,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
||||
}
|
||||
|
||||
override fun onRevoke() {
|
||||
stopV2Ray()
|
||||
stopAllService()
|
||||
}
|
||||
|
||||
// override fun onLowMemory() {
|
||||
@@ -105,11 +107,15 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
||||
Log.e(AppConfig.TAG, "Failed to create VPN interface")
|
||||
return
|
||||
}
|
||||
V2RayServiceManager.startCoreLoop(mInterface)
|
||||
if (!V2RayServiceManager.startCoreLoop(mInterface)) {
|
||||
Log.e(AppConfig.TAG, "Failed to start V2Ray core loop")
|
||||
stopAllService()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
override fun stopService() {
|
||||
stopV2Ray(true)
|
||||
stopAllService(true)
|
||||
}
|
||||
|
||||
override fun vpnProtect(socket: Int): Boolean {
|
||||
@@ -130,10 +136,14 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
||||
private fun setupVpnService() {
|
||||
val prepare = prepare(this)
|
||||
if (prepare != null) {
|
||||
Log.e(AppConfig.TAG, "VPN preparation failed")
|
||||
stopSelf()
|
||||
return
|
||||
}
|
||||
|
||||
if (configureVpnService() != true) {
|
||||
Log.e(AppConfig.TAG, "VPN configuration failed")
|
||||
stopSelf()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -170,7 +180,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
||||
return true
|
||||
} catch (e: Exception) {
|
||||
Log.e(AppConfig.TAG, "Failed to establish VPN interface", e)
|
||||
stopV2Ray()
|
||||
stopAllService()
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -311,11 +321,7 @@ class V2RayVpnService : VpnService(), ServiceControl {
|
||||
tun2SocksService?.startTun2Socks()
|
||||
}
|
||||
|
||||
/**
|
||||
* Stops the V2Ray service.
|
||||
* @param isForced Whether to force stop the service.
|
||||
*/
|
||||
private fun stopV2Ray(isForced: Boolean = true) {
|
||||
private fun stopAllService(isForced: Boolean = true) {
|
||||
// val configName = defaultDPreference.getPrefString(PREF_CURR_CONFIG_GUID, "")
|
||||
// val emptyInfo = VpnNetworkInfo()
|
||||
// val info = loadVpnNetworkInfo(configName, emptyInfo)!! + (lastNetworkInfo ?: emptyInfo)
|
||||
|
||||
@@ -27,7 +27,7 @@ import java.io.File
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
|
||||
class BackupActivity : BaseActivity() {
|
||||
class BackupActivity : HelperBaseActivity() {
|
||||
private val binding by lazy { ActivityBackupBinding.inflate(layoutInflater) }
|
||||
|
||||
private val config_backup_options: Array<out String> by lazy {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package com.v2ray.ang.ui
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MenuItem
|
||||
@@ -20,10 +19,6 @@ import com.v2ray.ang.R
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
import com.v2ray.ang.helper.CustomDividerItemDecoration
|
||||
import com.v2ray.ang.util.MyContextWrapper
|
||||
import com.v2ray.ang.dto.PermissionType
|
||||
import com.v2ray.ang.helper.FileChooserHelper
|
||||
import com.v2ray.ang.helper.PermissionHelper
|
||||
import com.v2ray.ang.helper.QRCodeScannerHelper
|
||||
import com.v2ray.ang.util.Utils
|
||||
|
||||
|
||||
@@ -41,15 +36,9 @@ import com.v2ray.ang.util.Utils
|
||||
abstract class BaseActivity : AppCompatActivity() {
|
||||
// Progress indicator that sits at the bottom of the toolbar
|
||||
private var progressBar: LinearProgressIndicator? = null
|
||||
private lateinit var fileChooser : FileChooserHelper
|
||||
private lateinit var permissionRequester : PermissionHelper
|
||||
private lateinit var qrCodeScanner : QRCodeScannerHelper
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
fileChooser = FileChooserHelper(this)
|
||||
permissionRequester = PermissionHelper(this)
|
||||
qrCodeScanner = QRCodeScannerHelper(this)
|
||||
|
||||
supportActionBar?.setDisplayHomeAsUpEnabled(true)
|
||||
if (!Utils.getDarkModeStatus(this)) {
|
||||
@@ -224,61 +213,4 @@ abstract class BaseActivity : AppCompatActivity() {
|
||||
protected fun isLoadingVisible(): Boolean {
|
||||
return progressBar?.visibility == View.VISIBLE
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if permission is granted and request it if not.
|
||||
* Convenience method that delegates to permissionRequester.
|
||||
*
|
||||
* @param permissionType The type of permission to check and request
|
||||
* @param onGranted Callback to execute when permission is granted
|
||||
*/
|
||||
protected fun checkAndRequestPermission(
|
||||
permissionType: PermissionType,
|
||||
onGranted: () -> Unit
|
||||
) {
|
||||
permissionRequester.request(permissionType, onGranted)
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch file chooser with ACTION_GET_CONTENT intent.
|
||||
* Convenience method that delegates to fileChooser helper.
|
||||
*
|
||||
* @param mimeType MIME type filter for files
|
||||
* @param onResult Callback invoked with the selected file URI (null if cancelled)
|
||||
*/
|
||||
protected fun launchFileChooser(
|
||||
mimeType: String = "*/*",
|
||||
onResult: (Uri?) -> Unit
|
||||
) {
|
||||
checkAndRequestPermission(PermissionType.READ_STORAGE) {
|
||||
fileChooser.launch(mimeType, onResult)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch document creator to create a new file at user-selected location.
|
||||
* Convenience method that delegates to fileChooser helper.
|
||||
* Note: No permission check needed as CreateDocument uses Storage Access Framework.
|
||||
*
|
||||
* @param fileName Default file name for the new document
|
||||
* @param onResult Callback invoked with the created file URI (null if cancelled)
|
||||
*/
|
||||
protected fun launchCreateDocument(
|
||||
fileName: String,
|
||||
onResult: (Uri?) -> Unit
|
||||
) {
|
||||
fileChooser.createDocument(fileName, onResult)
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch QR code scanner with camera permission check.
|
||||
* Convenience method that delegates to qrCodeScanner helper.
|
||||
*
|
||||
* @param onResult Callback invoked with the scan result string (null if cancelled or failed)
|
||||
*/
|
||||
protected fun launchQRCodeScanner(onResult: (String?) -> Unit) {
|
||||
checkAndRequestPermission(PermissionType.CAMERA) {
|
||||
qrCodeScanner.launch(onResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,9 +13,10 @@ import androidx.recyclerview.widget.GridLayoutManager
|
||||
import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.contracts.MainAdapterListener
|
||||
import com.v2ray.ang.databinding.FragmentGroupServerBinding
|
||||
import com.v2ray.ang.databinding.ItemQrcodeBinding
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.extension.toastError
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package com.v2ray.ang.ui
|
||||
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import com.v2ray.ang.enums.PermissionType
|
||||
import com.v2ray.ang.helper.FileChooserHelper
|
||||
import com.v2ray.ang.helper.PermissionHelper
|
||||
import com.v2ray.ang.helper.QRCodeScannerHelper
|
||||
|
||||
/**
|
||||
* HelperBaseActivity extends BaseActivity and provides additional helpers for
|
||||
* activities that need file chooser, permission requesting, or QR code scanning functionality.
|
||||
*
|
||||
* Activities that don't need these features should extend BaseActivity directly.
|
||||
* Activities that need file selection, permissions, or QR code scanning should extend this class.
|
||||
*
|
||||
* Additional Responsibilities:
|
||||
* - Provide file chooser helpers for selecting and creating files.
|
||||
* - Provide permission request helpers with callbacks.
|
||||
* - Provide QR code scanning helpers with camera permission handling.
|
||||
*/
|
||||
abstract class HelperBaseActivity : BaseActivity() {
|
||||
private lateinit var fileChooser : FileChooserHelper
|
||||
private lateinit var permissionRequester : PermissionHelper
|
||||
private lateinit var qrCodeScanner : QRCodeScannerHelper
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
fileChooser = FileChooserHelper(this)
|
||||
permissionRequester = PermissionHelper(this)
|
||||
qrCodeScanner = QRCodeScannerHelper(this)
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if permission is granted and request it if not.
|
||||
* Convenience method that delegates to permissionRequester.
|
||||
*
|
||||
* @param permissionType The type of permission to check and request
|
||||
* @param onGranted Callback to execute when permission is granted
|
||||
*/
|
||||
protected fun checkAndRequestPermission(
|
||||
permissionType: PermissionType,
|
||||
onGranted: () -> Unit
|
||||
) {
|
||||
permissionRequester.request(permissionType, onGranted)
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch file chooser with ACTION_GET_CONTENT intent.
|
||||
* Convenience method that delegates to fileChooser helper.
|
||||
*
|
||||
* @param mimeType MIME type filter for files
|
||||
* @param onResult Callback invoked with the selected file URI (null if cancelled)
|
||||
*/
|
||||
protected fun launchFileChooser(
|
||||
mimeType: String = "*/*",
|
||||
onResult: (Uri?) -> Unit
|
||||
) {
|
||||
checkAndRequestPermission(PermissionType.READ_STORAGE) {
|
||||
fileChooser.launch(mimeType, onResult)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch document creator to create a new file at user-selected location.
|
||||
* Convenience method that delegates to fileChooser helper.
|
||||
* Note: No permission check needed as CreateDocument uses Storage Access Framework.
|
||||
*
|
||||
* @param fileName Default file name for the new document
|
||||
* @param onResult Callback invoked with the created file URI (null if cancelled)
|
||||
*/
|
||||
protected fun launchCreateDocument(
|
||||
fileName: String,
|
||||
onResult: (Uri?) -> Unit
|
||||
) {
|
||||
fileChooser.createDocument(fileName, onResult)
|
||||
}
|
||||
|
||||
/**
|
||||
* Launch QR code scanner with camera permission check.
|
||||
* Convenience method that delegates to qrCodeScanner helper.
|
||||
*
|
||||
* @param onResult Callback invoked with the scan result string (null if cancelled or failed)
|
||||
*/
|
||||
protected fun launchQRCodeScanner(onResult: (String?) -> Unit) {
|
||||
checkAndRequestPermission(PermissionType.CAMERA) {
|
||||
qrCodeScanner.launch(onResult)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -24,7 +24,8 @@ import com.google.android.material.tabs.TabLayoutMediator
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.databinding.ActivityMainBinding
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.PermissionType
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.extension.toastError
|
||||
import com.v2ray.ang.handler.AngConfigManager
|
||||
@@ -32,7 +33,6 @@ import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.SettingsChangeManager
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
import com.v2ray.ang.handler.V2RayServiceManager
|
||||
import com.v2ray.ang.dto.PermissionType
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.viewmodel.MainViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -40,7 +40,7 @@ import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class MainActivity : BaseActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
class MainActivity : HelperBaseActivity(), NavigationView.OnNavigationItemSelectedListener {
|
||||
private val binding by lazy {
|
||||
ActivityMainBinding.inflate(layoutInflater)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.contracts.MainAdapterListener
|
||||
import com.v2ray.ang.databinding.ItemRecyclerFooterBinding
|
||||
import com.v2ray.ang.databinding.ItemRecyclerMainBinding
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
|
||||
@@ -8,6 +8,7 @@ import androidx.lifecycle.lifecycleScope
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.databinding.ActivityRoutingEditBinding
|
||||
import com.v2ray.ang.dto.RulesetItem
|
||||
import com.v2ray.ang.extension.nullIfBlank
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.extension.toastSuccess
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
@@ -62,14 +63,11 @@ class RoutingEditActivity : BaseActivity() {
|
||||
rulesetItem.apply {
|
||||
remarks = binding.etRemarks.text.toString()
|
||||
locked = binding.chkLocked.isChecked
|
||||
domain = binding.etDomain.text.toString().takeIf { it.isNotEmpty() }
|
||||
?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }
|
||||
ip = binding.etIp.text.toString().takeIf { it.isNotEmpty() }
|
||||
?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }
|
||||
protocol = binding.etProtocol.text.toString().takeIf { it.isNotEmpty() }
|
||||
?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }
|
||||
port = binding.etPort.text.toString().takeIf { it.isNotEmpty() }
|
||||
network = binding.etNetwork.text.toString().takeIf { it.isNotEmpty() }
|
||||
domain = binding.etDomain.text.toString().nullIfBlank()?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }
|
||||
ip = binding.etIp.text.toString().nullIfBlank()?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }
|
||||
protocol = binding.etProtocol.text.toString().nullIfBlank()?.split(",")?.map { it.trim() }?.filter { it.isNotEmpty() }
|
||||
port = binding.etPort.text.toString().nullIfBlank()
|
||||
network = binding.etNetwork.text.toString().nullIfBlank()
|
||||
outboundTag = outbound_tag[binding.spOutboundTag.selectedItemPosition]
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.contracts.BaseAdapterListener
|
||||
import com.v2ray.ang.databinding.ActivityRoutingSettingBinding
|
||||
import com.v2ray.ang.extension.toastError
|
||||
import com.v2ray.ang.extension.toastSuccess
|
||||
@@ -20,14 +21,13 @@ import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
import com.v2ray.ang.helper.SimpleItemTouchHelperCallback
|
||||
import com.v2ray.ang.util.JsonUtil
|
||||
import com.v2ray.ang.dto.PermissionType
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.viewmodel.RoutingSettingsViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
|
||||
class RoutingSettingActivity : BaseActivity() {
|
||||
class RoutingSettingActivity : HelperBaseActivity() {
|
||||
private val binding by lazy { ActivityRoutingSettingBinding.inflate(layoutInflater) }
|
||||
private val ownerActivity: RoutingSettingActivity
|
||||
get() = this
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.view.isVisible
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.v2ray.ang.contracts.BaseAdapterListener
|
||||
import com.v2ray.ang.databinding.ItemRecyclerRoutingSettingBinding
|
||||
import com.v2ray.ang.helper.ItemTouchHelperAdapter
|
||||
import com.v2ray.ang.helper.ItemTouchHelperViewHolder
|
||||
|
||||
@@ -7,7 +7,7 @@ import com.v2ray.ang.extension.toastError
|
||||
import com.v2ray.ang.extension.toastSuccess
|
||||
import com.v2ray.ang.handler.AngConfigManager
|
||||
|
||||
class ScScannerActivity : BaseActivity() {
|
||||
class ScScannerActivity : HelperBaseActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
@@ -11,15 +11,13 @@ import com.v2ray.ang.R
|
||||
import com.v2ray.ang.databinding.ActivityNoneBinding
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.dto.PermissionType
|
||||
import com.v2ray.ang.extension.toastError
|
||||
import com.v2ray.ang.util.QRCodeDecoder
|
||||
import io.github.g00fy2.quickie.QRResult
|
||||
import io.github.g00fy2.quickie.ScanCustomCode
|
||||
import io.github.g00fy2.quickie.config.BarcodeFormat
|
||||
import io.github.g00fy2.quickie.config.ScannerConfig
|
||||
|
||||
class ScannerActivity : BaseActivity() {
|
||||
class ScannerActivity : HelperBaseActivity() {
|
||||
private val binding by lazy { ActivityNoneBinding.inflate(layoutInflater) }
|
||||
|
||||
private val scanQrCode = registerForActivityResult(ScanCustomCode(), ::handleResult)
|
||||
|
||||
@@ -20,8 +20,8 @@ import com.v2ray.ang.AppConfig.TLS
|
||||
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_ADDRESS_V4
|
||||
import com.v2ray.ang.AppConfig.WIREGUARD_LOCAL_MTU
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.dto.NetworkType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.enums.NetworkType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.extension.isNotNullEmpty
|
||||
import com.v2ray.ang.extension.toast
|
||||
@@ -137,6 +137,8 @@ class ServerActivity : BaseActivity() {
|
||||
private val container_ech_config_list: LinearLayout? by lazy { findViewById(R.id.lay_ech_config_list) }
|
||||
private val sp_ech_force_query: Spinner? by lazy { findViewById(R.id.sp_ech_force_query) }
|
||||
private val container_ech_force_query: LinearLayout? by lazy { findViewById(R.id.lay_ech_force_query) }
|
||||
private val et_pinned_ca256: EditText? by lazy { findViewById(R.id.et_pinned_ca256) }
|
||||
private val container_pinned_ca256: LinearLayout? by lazy { findViewById(R.id.lay_pinned_ca256) }
|
||||
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
@@ -274,7 +276,8 @@ class ServerActivity : BaseActivity() {
|
||||
container_spider_x,
|
||||
container_mldsa65_verify,
|
||||
container_ech_config_list,
|
||||
container_ech_force_query
|
||||
container_ech_force_query,
|
||||
container_pinned_ca256
|
||||
).forEach { it?.visibility = View.GONE }
|
||||
}
|
||||
|
||||
@@ -286,7 +289,8 @@ class ServerActivity : BaseActivity() {
|
||||
container_alpn,
|
||||
container_allow_insecure,
|
||||
container_ech_config_list,
|
||||
container_ech_force_query
|
||||
container_ech_force_query,
|
||||
container_pinned_ca256
|
||||
).forEach { it?.visibility = View.VISIBLE }
|
||||
listOf(
|
||||
container_public_key,
|
||||
@@ -306,7 +310,8 @@ class ServerActivity : BaseActivity() {
|
||||
container_alpn,
|
||||
container_allow_insecure,
|
||||
container_ech_config_list,
|
||||
container_ech_force_query
|
||||
container_ech_force_query,
|
||||
container_pinned_ca256
|
||||
).forEach { it?.visibility = View.GONE }
|
||||
listOf(
|
||||
container_public_key,
|
||||
@@ -394,6 +399,7 @@ class ServerActivity : BaseActivity() {
|
||||
val index = Utils.arrayFind(echForceQuerys, it)
|
||||
index.let { sp_ech_force_query?.setSelection(if (it >= 0) it else 0) }
|
||||
}
|
||||
et_pinned_ca256?.text = Utils.getEditable(config.pinnedCA256)
|
||||
} else if (config.security == REALITY) {
|
||||
et_public_key?.text = Utils.getEditable(config.publicKey.orEmpty())
|
||||
et_short_id?.text = Utils.getEditable(config.shortId.orEmpty())
|
||||
@@ -566,6 +572,7 @@ class ServerActivity : BaseActivity() {
|
||||
val mldsa65Verify = et_mldsa65_verify?.text?.toString()
|
||||
val echConfigList = et_ech_config_list?.text?.toString()
|
||||
val echForceQueryIndex = sp_ech_force_query?.selectedItemPosition ?: 0
|
||||
val pinnedCA256 = et_pinned_ca256?.text?.toString()
|
||||
|
||||
val allowInsecure =
|
||||
if (allowInsecureField == null || allowinsecures[allowInsecureField].isBlank()) {
|
||||
@@ -585,6 +592,7 @@ class ServerActivity : BaseActivity() {
|
||||
config.mldsa65Verify = mldsa65Verify
|
||||
config.echConfigList = echConfigList
|
||||
config.echForceQuery = echForceQuerys[echForceQueryIndex]
|
||||
config.pinnedCA256 = pinnedCA256
|
||||
}
|
||||
|
||||
private fun transportTypes(network: String?): Array<out String> {
|
||||
|
||||
@@ -11,7 +11,7 @@ import com.blacksquircle.ui.language.json.JsonLanguage
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.databinding.ActivityServerCustomConfigBinding
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.extension.toastSuccess
|
||||
|
||||
@@ -8,7 +8,7 @@ import android.widget.ArrayAdapter
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.databinding.ActivityServerGroupBinding
|
||||
import com.v2ray.ang.dto.EConfigType
|
||||
import com.v2ray.ang.enums.EConfigType
|
||||
import com.v2ray.ang.dto.ProfileItem
|
||||
import com.v2ray.ang.extension.toast
|
||||
import com.v2ray.ang.extension.toastSuccess
|
||||
@@ -119,13 +119,13 @@ class ServerGroupActivity : BaseActivity() {
|
||||
val displayList = mutableListOf(getString(R.string.filter_config_all)) //none
|
||||
subIds.clear()
|
||||
subIds.add("") // index 0 => All
|
||||
subs.forEach { (id, item) ->
|
||||
subs.forEach { sub ->
|
||||
val name = when {
|
||||
item.remarks.isNotBlank() -> item.remarks
|
||||
else -> id
|
||||
sub.subscription.remarks.isNotBlank() -> sub.subscription.remarks
|
||||
else -> sub.guid
|
||||
}
|
||||
displayList.add(name)
|
||||
subIds.add(id)
|
||||
subIds.add(sub.guid)
|
||||
}
|
||||
val subAdapter = ArrayAdapter(this, android.R.layout.simple_spinner_item, displayList)
|
||||
subAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
|
||||
|
||||
@@ -15,7 +15,7 @@ import com.v2ray.ang.AppConfig.VPN
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.extension.toLongEx
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.MmkvPreferenceDataStore
|
||||
import com.v2ray.ang.helper.MmkvPreferenceDataStore
|
||||
import com.v2ray.ang.handler.SubscriptionUpdater
|
||||
import com.v2ray.ang.util.Utils
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
@@ -14,6 +14,7 @@ import androidx.recyclerview.widget.ItemTouchHelper
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.contracts.BaseAdapterListener
|
||||
import com.v2ray.ang.databinding.ActivitySubSettingBinding
|
||||
import com.v2ray.ang.databinding.ItemQrcodeBinding
|
||||
import com.v2ray.ang.extension.toast
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.v2ray.ang.contracts.BaseAdapterListener
|
||||
import com.v2ray.ang.databinding.ItemRecyclerSubSettingBinding
|
||||
import com.v2ray.ang.helper.ItemTouchHelperAdapter
|
||||
import com.v2ray.ang.helper.ItemTouchHelperViewHolder
|
||||
@@ -21,8 +22,8 @@ class SubSettingRecyclerAdapter(
|
||||
|
||||
override fun onBindViewHolder(holder: MainViewHolder, position: Int) {
|
||||
val subscriptions = viewModel.getAll()
|
||||
val subId = subscriptions[position].first
|
||||
val subItem = subscriptions[position].second
|
||||
val subId = subscriptions[position].guid
|
||||
val subItem = subscriptions[position].subscription
|
||||
holder.itemSubSettingBinding.tvName.text = subItem.remarks
|
||||
holder.itemSubSettingBinding.tvUrl.text = subItem.url
|
||||
holder.itemSubSettingBinding.chkEnable.isChecked = subItem.enabled
|
||||
|
||||
@@ -23,7 +23,8 @@ class TaskerActivity : BaseActivity() {
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
setContentView(binding.root)
|
||||
//setContentView(binding.root)
|
||||
setContentViewWithToolbar(binding.root, showHomeAsUp = true, title = "")
|
||||
|
||||
//add def value
|
||||
lstData.add("Default")
|
||||
|
||||
@@ -14,6 +14,7 @@ import androidx.lifecycle.lifecycleScope
|
||||
import androidx.recyclerview.widget.LinearLayoutManager
|
||||
import com.v2ray.ang.AppConfig
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.contracts.BaseAdapterListener
|
||||
import com.v2ray.ang.databinding.ActivityUserAssetBinding
|
||||
import com.v2ray.ang.dto.AssetUrlItem
|
||||
import com.v2ray.ang.extension.toast
|
||||
@@ -21,7 +22,6 @@ import com.v2ray.ang.extension.toastError
|
||||
import com.v2ray.ang.extension.toastSuccess
|
||||
import com.v2ray.ang.handler.MmkvManager
|
||||
import com.v2ray.ang.handler.SettingsManager
|
||||
import com.v2ray.ang.dto.PermissionType
|
||||
import com.v2ray.ang.util.Utils
|
||||
import com.v2ray.ang.viewmodel.UserAssetViewModel
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -29,7 +29,7 @@ import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import java.io.File
|
||||
|
||||
class UserAssetActivity : BaseActivity() {
|
||||
class UserAssetActivity : HelperBaseActivity() {
|
||||
private val binding by lazy { ActivityUserAssetBinding.inflate(layoutInflater) }
|
||||
private val ownerActivity: UserAssetActivity
|
||||
get() = this
|
||||
@@ -103,7 +103,7 @@ class UserAssetActivity : BaseActivity() {
|
||||
)
|
||||
|
||||
val assetList = MmkvManager.decodeAssetUrls()
|
||||
if (assetList.any { it.second.remarks == assetItem.remarks && it.first != assetId }) {
|
||||
if (assetList.any { it.assetUrl.remarks == assetItem.remarks && it.guid != assetId }) {
|
||||
toast(R.string.msg_remark_is_duplicate)
|
||||
} else {
|
||||
MmkvManager.encodeAsset(assetId, assetItem)
|
||||
@@ -212,10 +212,10 @@ class UserAssetActivity : BaseActivity() {
|
||||
}
|
||||
|
||||
override fun onRemove(guid: String, position: Int) {
|
||||
val asset = viewModel.getAsset(position)?.takeIf { it.first == guid }
|
||||
?: viewModel.getAssets().find { it.first == guid }
|
||||
val asset = viewModel.getAsset(position)?.takeIf { it.guid == guid }
|
||||
?: viewModel.getAssets().find { it.guid == guid }
|
||||
?: return
|
||||
val file = extDir.listFiles()?.find { it.name == asset.second.remarks }
|
||||
val file = extDir.listFiles()?.find { it.name == asset.assetUrl.remarks }
|
||||
|
||||
AlertDialog.Builder(ownerActivity).setMessage(R.string.del_config_comfirm)
|
||||
.setPositiveButton(android.R.string.ok) { _, _ ->
|
||||
|
||||
@@ -6,6 +6,7 @@ import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.v2ray.ang.R
|
||||
import com.v2ray.ang.contracts.BaseAdapterListener
|
||||
import com.v2ray.ang.databinding.ItemRecyclerUserAssetBinding
|
||||
import com.v2ray.ang.extension.toTrafficString
|
||||
import com.v2ray.ang.viewmodel.UserAssetViewModel
|
||||
@@ -34,9 +35,9 @@ class UserAssetAdapter(
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: UserAssetViewHolder, position: Int) {
|
||||
val item = viewModel.getAsset(position) ?: return
|
||||
val file = extDir.listFiles()?.find { it.name == item.second.remarks }
|
||||
val file = extDir.listFiles()?.find { it.name == item.assetUrl.remarks }
|
||||
|
||||
holder.itemUserAssetBinding.assetName.text = item.second.remarks
|
||||
holder.itemUserAssetBinding.assetName.text = item.assetUrl.remarks
|
||||
|
||||
if (file != null) {
|
||||
val dateFormat = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM)
|
||||
@@ -47,10 +48,10 @@ class UserAssetAdapter(
|
||||
holder.itemUserAssetBinding.root.context.getString(R.string.msg_file_not_found)
|
||||
}
|
||||
|
||||
if (item.second.locked == true) {
|
||||
if (item.assetUrl.locked == true) {
|
||||
holder.itemUserAssetBinding.layoutEdit.visibility = View.GONE
|
||||
} else {
|
||||
holder.itemUserAssetBinding.layoutEdit.visibility = if (item.second.url == "file") {
|
||||
holder.itemUserAssetBinding.layoutEdit.visibility = if (item.assetUrl.url == "file") {
|
||||
View.GONE
|
||||
} else {
|
||||
View.VISIBLE
|
||||
@@ -58,10 +59,10 @@ class UserAssetAdapter(
|
||||
}
|
||||
|
||||
holder.itemUserAssetBinding.layoutEdit.setOnClickListener {
|
||||
adapterListener?.onEdit(item.first, position)
|
||||
adapterListener?.onEdit(item.guid, position)
|
||||
}
|
||||
holder.itemUserAssetBinding.layoutRemove.setOnClickListener {
|
||||
adapterListener?.onRemove(item.first, position)
|
||||
adapterListener?.onRemove(item.guid, position)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user