mirror of
https://github.com/bolucat/Archive.git
synced 2025-09-26 20:21:35 +08:00
Update On Sat Nov 2 19:33:11 CET 2024
This commit is contained in:
1
.github/update.log
vendored
1
.github/update.log
vendored
@@ -812,3 +812,4 @@ Update On Tue Oct 29 19:36:45 CET 2024
|
|||||||
Update On Wed Oct 30 19:35:20 CET 2024
|
Update On Wed Oct 30 19:35:20 CET 2024
|
||||||
Update On Thu Oct 31 19:36:27 CET 2024
|
Update On Thu Oct 31 19:36:27 CET 2024
|
||||||
Update On Fri Nov 1 19:37:29 CET 2024
|
Update On Fri Nov 1 19:37:29 CET 2024
|
||||||
|
Update On Sat Nov 2 19:33:00 CET 2024
|
||||||
|
@@ -25,7 +25,7 @@ var convertCmd = &cobra.Command{
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := instance.Init(configFile); err != nil {
|
if err := instance.InitConfig(configFile); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
16
geoip/go.mod
16
geoip/go.mod
@@ -5,10 +5,10 @@ go 1.23
|
|||||||
toolchain go1.23.2
|
toolchain go1.23.2
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/klauspost/compress v1.17.10
|
github.com/klauspost/compress v1.17.11
|
||||||
github.com/maxmind/mmdbwriter v1.0.0
|
github.com/maxmind/mmdbwriter v1.0.0
|
||||||
github.com/oschwald/maxminddb-golang v1.13.1
|
github.com/oschwald/maxminddb-golang v1.13.1
|
||||||
github.com/sagernet/sing-box v1.9.7
|
github.com/sagernet/sing-box v1.10.1
|
||||||
github.com/spf13/cobra v1.8.1
|
github.com/spf13/cobra v1.8.1
|
||||||
github.com/tailscale/hujson v0.0.0-20241010212012-29efb4a0184b
|
github.com/tailscale/hujson v0.0.0-20241010212012-29efb4a0184b
|
||||||
github.com/tidwall/gjson v1.18.0
|
github.com/tidwall/gjson v1.18.0
|
||||||
@@ -20,15 +20,15 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||||
github.com/kr/text v0.2.0 // indirect
|
github.com/kr/text v0.2.0 // indirect
|
||||||
github.com/miekg/dns v1.1.59 // indirect
|
github.com/miekg/dns v1.1.62 // indirect
|
||||||
github.com/sagernet/sing v0.4.3 // indirect
|
github.com/sagernet/sing v0.5.0-rc.2 // indirect
|
||||||
github.com/sagernet/sing-dns v0.2.3 // indirect
|
github.com/sagernet/sing-dns v0.3.0-rc.2 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/pretty v1.2.0 // indirect
|
||||||
golang.org/x/mod v0.18.0 // indirect
|
golang.org/x/mod v0.19.0 // indirect
|
||||||
golang.org/x/net v0.25.0 // indirect
|
golang.org/x/net v0.27.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.25.0 // indirect
|
golang.org/x/sys v0.25.0 // indirect
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
|
golang.org/x/tools v0.23.0 // indirect
|
||||||
)
|
)
|
||||||
|
40
geoip/go.sum
40
geoip/go.sum
@@ -10,14 +10,14 @@ github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a h1:fEBsGL/sjAuJrgah5X
|
|||||||
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
github.com/google/pprof v0.0.0-20231101202521-4ca4178f5c7a/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||||
github.com/klauspost/compress v1.17.10 h1:oXAz+Vh0PMUvJczoi+flxpnBEPxoER1IaAnU/NMPtT0=
|
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||||
github.com/klauspost/compress v1.17.10/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/maxmind/mmdbwriter v1.0.0 h1:bieL4P6yaYaHvbtLSwnKtEvScUKKD6jcKaLiTM3WSMw=
|
github.com/maxmind/mmdbwriter v1.0.0 h1:bieL4P6yaYaHvbtLSwnKtEvScUKKD6jcKaLiTM3WSMw=
|
||||||
github.com/maxmind/mmdbwriter v1.0.0/go.mod h1:noBMCUtyN5PUQ4H8ikkOvGSHhzhLok51fON2hcrpKj8=
|
github.com/maxmind/mmdbwriter v1.0.0/go.mod h1:noBMCUtyN5PUQ4H8ikkOvGSHhzhLok51fON2hcrpKj8=
|
||||||
github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs=
|
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||||
github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk=
|
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
|
||||||
@@ -33,12 +33,12 @@ github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58
|
|||||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||||
github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU=
|
github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU=
|
||||||
github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q=
|
github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q=
|
||||||
github.com/sagernet/sing v0.4.3 h1:Ty/NAiNnVd6844k7ujlL5lkzydhcTH5Psc432jXA4Y8=
|
github.com/sagernet/sing v0.5.0-rc.2 h1:tIrs6pRbjJWvI0ITRSg47P1wosY+iSuHpw9t5/hBx+Q=
|
||||||
github.com/sagernet/sing v0.4.3/go.mod h1:ieZHA/+Y9YZfXs2I3WtuwgyCZ6GPsIR7HdKb1SdEnls=
|
github.com/sagernet/sing v0.5.0-rc.2/go.mod h1:ARkL0gM13/Iv5VCZmci/NuoOlePoIsW0m7BWfln/Hak=
|
||||||
github.com/sagernet/sing-box v1.9.7 h1:+vA+xjbZuE7drPrkBRPPL/++Jz3ZcL5AExCR9LKAUVM=
|
github.com/sagernet/sing-box v1.10.1 h1:J3H0TzF0LGC4uOR62TpSuAhhHkv3Bx5M5F5kK5JB+WA=
|
||||||
github.com/sagernet/sing-box v1.9.7/go.mod h1:1eZ08ofoql6NdYCkBJXICbqhWr1SzQkrxGy1p6RcY/U=
|
github.com/sagernet/sing-box v1.10.1/go.mod h1:Nk9Ww0M1ulUsbfd5d4dfMBfJ0Audmm6m5+YYdvdpcZQ=
|
||||||
github.com/sagernet/sing-dns v0.2.3 h1:YzeBUn2tR38F7HtvGEQ0kLRLmZWMEgi/+7wqa4Twb1k=
|
github.com/sagernet/sing-dns v0.3.0-rc.2 h1:z1yROBxd/6wik5h53Sz5df1DSmbPTaOu/Z0wAmyXGoQ=
|
||||||
github.com/sagernet/sing-dns v0.2.3/go.mod h1:BJpJv6XLnrUbSyIntOT6DG9FW0f4fETmPAHvNjOprLg=
|
github.com/sagernet/sing-dns v0.3.0-rc.2/go.mod h1:TqLIelI+FAbVEdiTRolhGLOwvhVjY7oT+wezlOJUQ7M=
|
||||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||||
@@ -55,22 +55,22 @@ github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
|||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba h1:0b9z3AuHCjxk0x/opv64kcgZLBseWJUpBw5I82+2U4M=
|
||||||
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
go4.org/netipx v0.0.0-20231129151722-fdeea329fbba/go.mod h1:PLyyIXexvUFg3Owu6p/WfdlivPbZJsZdgWZlrGope/Y=
|
||||||
golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
|
golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
|
||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
|
||||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f h1:99ci1mjWVBWwJiEKYY6jWa4d2nTQVIEhZIptnrVb1XY=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
|
||||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f/go.mod h1:/lliqkxwWAhPjf5oSOIJup2XcqJaw8RGS6k3TGEc7GI=
|
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
|
||||||
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
|
golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8=
|
||||||
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||||
golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
|
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d h1:vU5i/LfpvrRCpgM/VPfJLg5KjxD3E+hfT1SH+d9zLwg=
|
golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg=
|
||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI=
|
||||||
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
google.golang.org/protobuf v1.35.1 h1:m3LfL6/Ca+fqnjnlqQXNpFPABW1UD7mjh8KO2mKFytA=
|
||||||
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
google.golang.org/protobuf v1.35.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
@@ -10,6 +10,7 @@ import (
|
|||||||
|
|
||||||
type Container interface {
|
type Container interface {
|
||||||
GetEntry(name string) (*Entry, bool)
|
GetEntry(name string) (*Entry, bool)
|
||||||
|
Len() int
|
||||||
Add(entry *Entry, opts ...IgnoreIPOption) error
|
Add(entry *Entry, opts ...IgnoreIPOption) error
|
||||||
Remove(entry *Entry, rCase CaseRemove, opts ...IgnoreIPOption) error
|
Remove(entry *Entry, rCase CaseRemove, opts ...IgnoreIPOption) error
|
||||||
Loop() <-chan *Entry
|
Loop() <-chan *Entry
|
||||||
@@ -41,6 +42,13 @@ func (c *container) GetEntry(name string) (*Entry, bool) {
|
|||||||
return val, true
|
return val, true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *container) Len() int {
|
||||||
|
if !c.isValid() {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
return len(c.entries)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *container) Loop() <-chan *Entry {
|
func (c *container) Loop() <-chan *Entry {
|
||||||
ch := make(chan *Entry, 300)
|
ch := make(chan *Entry, 300)
|
||||||
go func() {
|
go func() {
|
||||||
|
@@ -9,21 +9,31 @@ import (
|
|||||||
"github.com/tailscale/hujson"
|
"github.com/tailscale/hujson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Instance struct {
|
type Instance interface {
|
||||||
config *config
|
InitConfig(configFile string) error
|
||||||
|
InitConfigFromBytes(content []byte) error
|
||||||
|
AddInput(InputConverter)
|
||||||
|
AddOutput(OutputConverter)
|
||||||
|
ResetInput()
|
||||||
|
ResetOutput()
|
||||||
|
RunInput(Container) error
|
||||||
|
RunOutput(Container) error
|
||||||
|
Run() error
|
||||||
|
}
|
||||||
|
|
||||||
|
type instance struct {
|
||||||
input []InputConverter
|
input []InputConverter
|
||||||
output []OutputConverter
|
output []OutputConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewInstance() (*Instance, error) {
|
func NewInstance() (Instance, error) {
|
||||||
return &Instance{
|
return &instance{
|
||||||
config: new(config),
|
|
||||||
input: make([]InputConverter, 0),
|
input: make([]InputConverter, 0),
|
||||||
output: make([]OutputConverter, 0),
|
output: make([]OutputConverter, 0),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) Init(configFile string) error {
|
func (i *instance) InitConfig(configFile string) error {
|
||||||
var content []byte
|
var content []byte
|
||||||
var err error
|
var err error
|
||||||
configFile = strings.TrimSpace(configFile)
|
configFile = strings.TrimSpace(configFile)
|
||||||
@@ -36,50 +46,48 @@ func (i *Instance) Init(configFile string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return i.InitConfigFromBytes(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *instance) InitConfigFromBytes(content []byte) error {
|
||||||
|
config := new(config)
|
||||||
|
|
||||||
// Support JSON with comments and trailing commas
|
// Support JSON with comments and trailing commas
|
||||||
content, _ = hujson.Standardize(content)
|
content, _ = hujson.Standardize(content)
|
||||||
|
|
||||||
if err := json.Unmarshal(content, &i.config); err != nil {
|
if err := json.Unmarshal(content, &config); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, input := range i.config.Input {
|
for _, input := range config.Input {
|
||||||
i.input = append(i.input, input.converter)
|
i.input = append(i.input, input.converter)
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, output := range i.config.Output {
|
for _, output := range config.Output {
|
||||||
i.output = append(i.output, output.converter)
|
i.output = append(i.output, output.converter)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) InitFromBytes(content []byte) error {
|
func (i *instance) AddInput(ic InputConverter) {
|
||||||
// Support JSON with comments and trailing commas
|
i.input = append(i.input, ic)
|
||||||
content, _ = hujson.Standardize(content)
|
|
||||||
|
|
||||||
if err := json.Unmarshal(content, &i.config); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, input := range i.config.Input {
|
|
||||||
i.input = append(i.input, input.converter)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, output := range i.config.Output {
|
|
||||||
i.output = append(i.output, output.converter)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *Instance) Run() error {
|
func (i *instance) AddOutput(oc OutputConverter) {
|
||||||
if len(i.input) == 0 || len(i.output) == 0 {
|
i.output = append(i.output, oc)
|
||||||
return errors.New("input type and output type must be specified")
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
func (i *instance) ResetInput() {
|
||||||
|
i.input = make([]InputConverter, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *instance) ResetOutput() {
|
||||||
|
i.output = make([]OutputConverter, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *instance) RunInput(container Container) error {
|
||||||
var err error
|
var err error
|
||||||
container := NewContainer()
|
|
||||||
for _, ic := range i.input {
|
for _, ic := range i.input {
|
||||||
container, err = ic.Input(container)
|
container, err = ic.Input(container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -87,6 +95,10 @@ func (i *Instance) Run() error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *instance) RunOutput(container Container) error {
|
||||||
for _, oc := range i.output {
|
for _, oc := range i.output {
|
||||||
if err := oc.Output(container); err != nil {
|
if err := oc.Output(container); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -95,3 +107,21 @@ func (i *Instance) Run() error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (i *instance) Run() error {
|
||||||
|
if len(i.input) == 0 || len(i.output) == 0 {
|
||||||
|
return errors.New("input type and output type must be specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
container := NewContainer()
|
||||||
|
|
||||||
|
if err := i.RunInput(container); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := i.RunOutput(container); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
171
geoip/lookup.go
171
geoip/lookup.go
@@ -9,6 +9,12 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Loyalsoldier/geoip/lib"
|
"github.com/Loyalsoldier/geoip/lib"
|
||||||
|
"github.com/Loyalsoldier/geoip/plugin/maxmind"
|
||||||
|
"github.com/Loyalsoldier/geoip/plugin/mihomo"
|
||||||
|
"github.com/Loyalsoldier/geoip/plugin/plaintext"
|
||||||
|
"github.com/Loyalsoldier/geoip/plugin/singbox"
|
||||||
|
"github.com/Loyalsoldier/geoip/plugin/special"
|
||||||
|
"github.com/Loyalsoldier/geoip/plugin/v2ray"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -61,10 +67,6 @@ var lookupCmd = &cobra.Command{
|
|||||||
|
|
||||||
// Get searchlist
|
// Get searchlist
|
||||||
searchList, _ := cmd.Flags().GetStringSlice("searchlist")
|
searchList, _ := cmd.Flags().GetStringSlice("searchlist")
|
||||||
searchListStr := strings.Join(searchList, `", "`)
|
|
||||||
if searchListStr != "" {
|
|
||||||
searchListStr = fmt.Sprint(`"`, searchListStr, `"`) // `"cn", "en"`
|
|
||||||
}
|
|
||||||
|
|
||||||
switch len(args) > 0 {
|
switch len(args) > 0 {
|
||||||
case true: // With search arg, run in once mode
|
case true: // With search arg, run in once mode
|
||||||
@@ -74,11 +76,33 @@ var lookupCmd = &cobra.Command{
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(format, name, uri, dir, search, searchListStr)
|
instance, err := lib.NewInstance()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.AddInput(getInputForLookup(format, name, uri, dir))
|
||||||
|
instance.AddOutput(getOutputForLookup(search, searchList...))
|
||||||
|
|
||||||
|
if err := instance.Run(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
case false: // No search arg, run in REPL mode
|
case false: // No search arg, run in REPL mode
|
||||||
|
instance, err := lib.NewInstance()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
instance.AddInput(getInputForLookup(format, name, uri, dir))
|
||||||
|
|
||||||
|
container := lib.NewContainer()
|
||||||
|
if err := instance.RunInput(container); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println(`Enter IP or CIDR (type "exit" to quit):`)
|
fmt.Println(`Enter IP or CIDR (type "exit" to quit):`)
|
||||||
fmt.Print(">> ")
|
fmt.Print(">> ")
|
||||||
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
search := strings.ToLower(strings.TrimSpace(scanner.Text()))
|
search := strings.ToLower(strings.TrimSpace(scanner.Text()))
|
||||||
@@ -98,7 +122,12 @@ var lookupCmd = &cobra.Command{
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
execute(format, name, uri, dir, search, searchListStr)
|
instance.ResetOutput()
|
||||||
|
instance.AddOutput(getOutputForLookup(search, searchList...))
|
||||||
|
|
||||||
|
if err := instance.RunOutput(container); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
fmt.Print(">> ")
|
fmt.Print(">> ")
|
||||||
@@ -127,47 +156,99 @@ func isValidIPOrCIDR(search string) bool {
|
|||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func execute(format, name, uri, dir, search, searchListStr string) {
|
func getInputForLookup(format, name, uri, dir string) lib.InputConverter {
|
||||||
config := generateConfigForLookup(format, name, uri, dir, search, searchListStr)
|
var input lib.InputConverter
|
||||||
|
|
||||||
instance, err := lib.NewInstance()
|
switch strings.ToLower(format) {
|
||||||
if err != nil {
|
case strings.ToLower(maxmind.TypeMaxmindMMDBIn):
|
||||||
log.Fatal(err)
|
input = &maxmind.MaxmindMMDBIn{
|
||||||
}
|
Type: maxmind.TypeMaxmindMMDBIn,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
if err := instance.InitFromBytes([]byte(config)); err != nil {
|
Description: maxmind.DescMaxmindMMDBIn,
|
||||||
log.Fatal(err)
|
URI: uri,
|
||||||
}
|
|
||||||
|
|
||||||
if err := instance.Run(); err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func generateConfigForLookup(format, name, uri, dir, search, searchListStr string) string {
|
|
||||||
return fmt.Sprintf(`
|
|
||||||
{
|
|
||||||
"input": [
|
|
||||||
{
|
|
||||||
"type": "%s",
|
|
||||||
"action": "add",
|
|
||||||
"args": {
|
|
||||||
"name": "%s",
|
|
||||||
"uri": "%s",
|
|
||||||
"inputDir": "%s"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
],
|
|
||||||
"output": [
|
case strings.ToLower(mihomo.TypeMRSIn):
|
||||||
{
|
input = &mihomo.MRSIn{
|
||||||
"type": "lookup",
|
Type: mihomo.TypeMRSIn,
|
||||||
"action": "output",
|
Action: lib.ActionAdd,
|
||||||
"args": {
|
Description: mihomo.DescMRSIn,
|
||||||
"search": "%s",
|
Name: name,
|
||||||
"searchList": [%s]
|
URI: uri,
|
||||||
}
|
InputDir: dir,
|
||||||
}
|
}
|
||||||
]
|
|
||||||
|
case strings.ToLower(singbox.TypeSRSIn):
|
||||||
|
input = &singbox.SRSIn{
|
||||||
|
Type: singbox.TypeSRSIn,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
|
Description: singbox.DescSRSIn,
|
||||||
|
Name: name,
|
||||||
|
URI: uri,
|
||||||
|
InputDir: dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.ToLower(v2ray.TypeGeoIPdatIn):
|
||||||
|
input = &v2ray.GeoIPDatIn{
|
||||||
|
Type: v2ray.TypeGeoIPdatIn,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
|
Description: v2ray.DescGeoIPdatIn,
|
||||||
|
URI: uri,
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.ToLower(plaintext.TypeTextIn):
|
||||||
|
input = &plaintext.TextIn{
|
||||||
|
Type: plaintext.TypeTextIn,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
|
Description: plaintext.DescTextIn,
|
||||||
|
Name: name,
|
||||||
|
URI: uri,
|
||||||
|
InputDir: dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.ToLower(plaintext.TypeClashRuleSetIPCIDRIn):
|
||||||
|
input = &plaintext.TextIn{
|
||||||
|
Type: plaintext.TypeClashRuleSetIPCIDRIn,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
|
Description: plaintext.DescClashRuleSetIn,
|
||||||
|
Name: name,
|
||||||
|
URI: uri,
|
||||||
|
InputDir: dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.ToLower(plaintext.TypeClashRuleSetClassicalIn):
|
||||||
|
input = &plaintext.TextIn{
|
||||||
|
Type: plaintext.TypeClashRuleSetClassicalIn,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
|
Description: plaintext.DescClashClassicalIn,
|
||||||
|
Name: name,
|
||||||
|
URI: uri,
|
||||||
|
InputDir: dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
case strings.ToLower(plaintext.TypeSurgeRuleSetIn):
|
||||||
|
input = &plaintext.TextIn{
|
||||||
|
Type: plaintext.TypeSurgeRuleSetIn,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
|
Description: plaintext.DescSurgeRuleSetIn,
|
||||||
|
Name: name,
|
||||||
|
URI: uri,
|
||||||
|
InputDir: dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
log.Fatal("unsupported input format")
|
||||||
|
}
|
||||||
|
|
||||||
|
return input
|
||||||
}
|
}
|
||||||
`, format, name, uri, dir, search, searchListStr)
|
|
||||||
|
func getOutputForLookup(search string, searchList ...string) lib.OutputConverter {
|
||||||
|
return &special.Lookup{
|
||||||
|
Type: special.TypeLookup,
|
||||||
|
Action: lib.ActionOutput,
|
||||||
|
Description: special.DescLookup,
|
||||||
|
Search: search,
|
||||||
|
SearchList: searchList,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
119
geoip/merge.go
119
geoip/merge.go
@@ -5,75 +5,10 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/Loyalsoldier/geoip/lib"
|
"github.com/Loyalsoldier/geoip/lib"
|
||||||
|
"github.com/Loyalsoldier/geoip/plugin/special"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
const tempConfig = `
|
|
||||||
{
|
|
||||||
"input": [
|
|
||||||
{
|
|
||||||
"type": "stdin",
|
|
||||||
"action": "add",
|
|
||||||
"args": {
|
|
||||||
"name": "temp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"output": [
|
|
||||||
{
|
|
||||||
"type": "stdout",
|
|
||||||
"action": "output"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const tempConfigWithIPv4 = `
|
|
||||||
{
|
|
||||||
"input": [
|
|
||||||
{
|
|
||||||
"type": "stdin",
|
|
||||||
"action": "add",
|
|
||||||
"args": {
|
|
||||||
"name": "temp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"output": [
|
|
||||||
{
|
|
||||||
"type": "stdout",
|
|
||||||
"action": "output",
|
|
||||||
"args": {
|
|
||||||
"onlyIPType": "ipv4"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
const tempConfigWithIPv6 = `
|
|
||||||
{
|
|
||||||
"input": [
|
|
||||||
{
|
|
||||||
"type": "stdin",
|
|
||||||
"action": "add",
|
|
||||||
"args": {
|
|
||||||
"name": "temp"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"output": [
|
|
||||||
{
|
|
||||||
"type": "stdout",
|
|
||||||
"action": "output",
|
|
||||||
"args": {
|
|
||||||
"onlyIPType": "ipv6"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.AddCommand(mergeCmd)
|
rootCmd.AddCommand(mergeCmd)
|
||||||
mergeCmd.PersistentFlags().StringP("onlyiptype", "t", "", "The only IP type to output, available options: \"ipv4\", \"ipv6\"")
|
mergeCmd.PersistentFlags().StringP("onlyiptype", "t", "", "The only IP type to output, available options: \"ipv4\", \"ipv6\"")
|
||||||
@@ -91,27 +26,53 @@ var mergeCmd = &cobra.Command{
|
|||||||
log.Fatal("invalid argument onlyiptype: ", otype)
|
log.Fatal("invalid argument onlyiptype: ", otype)
|
||||||
}
|
}
|
||||||
|
|
||||||
var configBytes []byte
|
|
||||||
switch lib.IPType(otype) {
|
|
||||||
case lib.IPv4:
|
|
||||||
configBytes = []byte(tempConfigWithIPv4)
|
|
||||||
case lib.IPv6:
|
|
||||||
configBytes = []byte(tempConfigWithIPv6)
|
|
||||||
default:
|
|
||||||
configBytes = []byte(tempConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
instance, err := lib.NewInstance()
|
instance, err := lib.NewInstance()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := instance.InitFromBytes(configBytes); err != nil {
|
instance.AddInput(getInputForMerge())
|
||||||
log.Fatal(err)
|
instance.AddOutput(getOutputForMerge(otype))
|
||||||
}
|
|
||||||
|
|
||||||
if err := instance.Run(); err != nil {
|
if err := instance.Run(); err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getInputForMerge() lib.InputConverter {
|
||||||
|
return &special.Stdin{
|
||||||
|
Type: special.TypeStdin,
|
||||||
|
Action: lib.ActionAdd,
|
||||||
|
Description: special.DescStdin,
|
||||||
|
Name: "temp",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getOutputForMerge(otype string) lib.OutputConverter {
|
||||||
|
switch lib.IPType(otype) {
|
||||||
|
case lib.IPv4:
|
||||||
|
return &special.Stdout{
|
||||||
|
Type: special.TypeStdout,
|
||||||
|
Action: lib.ActionOutput,
|
||||||
|
Description: special.DescStdout,
|
||||||
|
OnlyIPType: lib.IPv4,
|
||||||
|
}
|
||||||
|
|
||||||
|
case lib.IPv6:
|
||||||
|
return &special.Stdout{
|
||||||
|
Type: special.TypeStdout,
|
||||||
|
Action: lib.ActionOutput,
|
||||||
|
Description: special.DescStdout,
|
||||||
|
OnlyIPType: lib.IPv6,
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return &special.Stdout{
|
||||||
|
Type: special.TypeStdout,
|
||||||
|
Action: lib.ActionOutput,
|
||||||
|
Description: special.DescStdout,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
@@ -13,8 +13,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeASNCSV = "maxmindGeoLite2ASNCSV"
|
TypeASNCSV = "maxmindGeoLite2ASNCSV"
|
||||||
descASNCSV = "Convert MaxMind GeoLite2 ASN CSV data to other formats"
|
DescASNCSV = "Convert MaxMind GeoLite2 ASN CSV data to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -23,11 +23,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeASNCSV, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeASNCSV, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newGeoLite2ASNCSV(action, data)
|
return newGeoLite2ASNCSV(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeASNCSV, &geoLite2ASNCSV{
|
lib.RegisterInputConverter(TypeASNCSV, &GeoLite2ASNCSV{
|
||||||
Description: descASNCSV,
|
Description: DescASNCSV,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,13 +77,13 @@ func newGeoLite2ASNCSV(action lib.Action, data json.RawMessage) (lib.InputConver
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(wantList) == 0 {
|
if len(wantList) == 0 {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] wantedList must be specified in config", typeASNCSV, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] wantedList must be specified in config", TypeASNCSV, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &geoLite2ASNCSV{
|
return &GeoLite2ASNCSV{
|
||||||
Type: typeASNCSV,
|
Type: TypeASNCSV,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descASNCSV,
|
Description: DescASNCSV,
|
||||||
IPv4File: tmp.IPv4File,
|
IPv4File: tmp.IPv4File,
|
||||||
IPv6File: tmp.IPv6File,
|
IPv6File: tmp.IPv6File,
|
||||||
Want: wantList,
|
Want: wantList,
|
||||||
@@ -91,7 +91,7 @@ func newGeoLite2ASNCSV(action lib.Action, data json.RawMessage) (lib.InputConver
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type geoLite2ASNCSV struct {
|
type GeoLite2ASNCSV struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -101,19 +101,19 @@ type geoLite2ASNCSV struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2ASNCSV) GetType() string {
|
func (g *GeoLite2ASNCSV) GetType() string {
|
||||||
return g.Type
|
return g.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2ASNCSV) GetAction() lib.Action {
|
func (g *GeoLite2ASNCSV) GetAction() lib.Action {
|
||||||
return g.Action
|
return g.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2ASNCSV) GetDescription() string {
|
func (g *GeoLite2ASNCSV) GetDescription() string {
|
||||||
return g.Description
|
return g.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2ASNCSV) Input(container lib.Container) (lib.Container, error) {
|
func (g *GeoLite2ASNCSV) Input(container lib.Container) (lib.Container, error) {
|
||||||
entries := make(map[string]*lib.Entry)
|
entries := make(map[string]*lib.Entry)
|
||||||
|
|
||||||
if g.IPv4File != "" {
|
if g.IPv4File != "" {
|
||||||
@@ -158,7 +158,7 @@ func (g *geoLite2ASNCSV) Input(container lib.Container) (lib.Container, error) {
|
|||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2ASNCSV) process(file string, entries map[string]*lib.Entry) error {
|
func (g *GeoLite2ASNCSV) process(file string, entries map[string]*lib.Entry) error {
|
||||||
if entries == nil {
|
if entries == nil {
|
||||||
entries = make(map[string]*lib.Entry)
|
entries = make(map[string]*lib.Entry)
|
||||||
}
|
}
|
||||||
|
@@ -13,8 +13,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeCountryCSV = "maxmindGeoLite2CountryCSV"
|
TypeCountryCSV = "maxmindGeoLite2CountryCSV"
|
||||||
descCountryCSV = "Convert MaxMind GeoLite2 country CSV data to other formats"
|
DescCountryCSV = "Convert MaxMind GeoLite2 country CSV data to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -24,11 +24,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeCountryCSV, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeCountryCSV, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newGeoLite2CountryCSV(action, data)
|
return newGeoLite2CountryCSV(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeCountryCSV, &geoLite2CountryCSV{
|
lib.RegisterInputConverter(TypeCountryCSV, &GeoLite2CountryCSV{
|
||||||
Description: descCountryCSV,
|
Description: DescCountryCSV,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,10 +67,10 @@ func newGeoLite2CountryCSV(action lib.Action, data json.RawMessage) (lib.InputCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &geoLite2CountryCSV{
|
return &GeoLite2CountryCSV{
|
||||||
Type: typeCountryCSV,
|
Type: TypeCountryCSV,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descCountryCSV,
|
Description: DescCountryCSV,
|
||||||
CountryCodeFile: tmp.CountryCodeFile,
|
CountryCodeFile: tmp.CountryCodeFile,
|
||||||
IPv4File: tmp.IPv4File,
|
IPv4File: tmp.IPv4File,
|
||||||
IPv6File: tmp.IPv6File,
|
IPv6File: tmp.IPv6File,
|
||||||
@@ -79,7 +79,7 @@ func newGeoLite2CountryCSV(action lib.Action, data json.RawMessage) (lib.InputCo
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type geoLite2CountryCSV struct {
|
type GeoLite2CountryCSV struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -90,19 +90,19 @@ type geoLite2CountryCSV struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2CountryCSV) GetType() string {
|
func (g *GeoLite2CountryCSV) GetType() string {
|
||||||
return g.Type
|
return g.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2CountryCSV) GetAction() lib.Action {
|
func (g *GeoLite2CountryCSV) GetAction() lib.Action {
|
||||||
return g.Action
|
return g.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2CountryCSV) GetDescription() string {
|
func (g *GeoLite2CountryCSV) GetDescription() string {
|
||||||
return g.Description
|
return g.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2CountryCSV) Input(container lib.Container) (lib.Container, error) {
|
func (g *GeoLite2CountryCSV) Input(container lib.Container) (lib.Container, error) {
|
||||||
ccMap, err := g.getCountryCode()
|
ccMap, err := g.getCountryCode()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@@ -152,7 +152,7 @@ func (g *geoLite2CountryCSV) Input(container lib.Container) (lib.Container, erro
|
|||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2CountryCSV) getCountryCode() (map[string]string, error) {
|
func (g *GeoLite2CountryCSV) getCountryCode() (map[string]string, error) {
|
||||||
var f io.ReadCloser
|
var f io.ReadCloser
|
||||||
var err error
|
var err error
|
||||||
switch {
|
switch {
|
||||||
@@ -199,7 +199,7 @@ func (g *geoLite2CountryCSV) getCountryCode() (map[string]string, error) {
|
|||||||
return ccMap, nil
|
return ccMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoLite2CountryCSV) process(file string, ccMap map[string]string, entries map[string]*lib.Entry) error {
|
func (g *GeoLite2CountryCSV) process(file string, ccMap map[string]string, entries map[string]*lib.Entry) error {
|
||||||
if len(ccMap) == 0 {
|
if len(ccMap) == 0 {
|
||||||
return fmt.Errorf("❌ [type %s | action %s] invalid country code data", g.Type, g.Action)
|
return fmt.Errorf("❌ [type %s | action %s] invalid country code data", g.Type, g.Action)
|
||||||
}
|
}
|
||||||
|
@@ -12,8 +12,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeMaxmindMMDBIn = "maxmindMMDB"
|
TypeMaxmindMMDBIn = "maxmindMMDB"
|
||||||
descMaxmindMMDBIn = "Convert MaxMind mmdb database to other formats"
|
DescMaxmindMMDBIn = "Convert MaxMind mmdb database to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -21,11 +21,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeMaxmindMMDBIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeMaxmindMMDBIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newMaxmindMMDBIn(action, data)
|
return newMaxmindMMDBIn(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeMaxmindMMDBIn, &maxmindMMDBIn{
|
lib.RegisterInputConverter(TypeMaxmindMMDBIn, &MaxmindMMDBIn{
|
||||||
Description: descMaxmindMMDBIn,
|
Description: DescMaxmindMMDBIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,17 +54,17 @@ func newMaxmindMMDBIn(action lib.Action, data json.RawMessage) (lib.InputConvert
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &maxmindMMDBIn{
|
return &MaxmindMMDBIn{
|
||||||
Type: typeMaxmindMMDBIn,
|
Type: TypeMaxmindMMDBIn,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descMaxmindMMDBIn,
|
Description: DescMaxmindMMDBIn,
|
||||||
URI: tmp.URI,
|
URI: tmp.URI,
|
||||||
Want: wantList,
|
Want: wantList,
|
||||||
OnlyIPType: tmp.OnlyIPType,
|
OnlyIPType: tmp.OnlyIPType,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type maxmindMMDBIn struct {
|
type MaxmindMMDBIn struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -73,19 +73,19 @@ type maxmindMMDBIn struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *maxmindMMDBIn) GetType() string {
|
func (m *MaxmindMMDBIn) GetType() string {
|
||||||
return m.Type
|
return m.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *maxmindMMDBIn) GetAction() lib.Action {
|
func (m *MaxmindMMDBIn) GetAction() lib.Action {
|
||||||
return m.Action
|
return m.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *maxmindMMDBIn) GetDescription() string {
|
func (m *MaxmindMMDBIn) GetDescription() string {
|
||||||
return m.Description
|
return m.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *maxmindMMDBIn) Input(container lib.Container) (lib.Container, error) {
|
func (m *MaxmindMMDBIn) Input(container lib.Container) (lib.Container, error) {
|
||||||
var content []byte
|
var content []byte
|
||||||
var err error
|
var err error
|
||||||
switch {
|
switch {
|
||||||
@@ -134,7 +134,7 @@ func (m *maxmindMMDBIn) Input(container lib.Container) (lib.Container, error) {
|
|||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *maxmindMMDBIn) generateEntries(content []byte, entries map[string]*lib.Entry) error {
|
func (m *MaxmindMMDBIn) generateEntries(content []byte, entries map[string]*lib.Entry) error {
|
||||||
db, err := maxminddb.FromBytes(content)
|
db, err := maxminddb.FromBytes(content)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -15,8 +15,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeMaxmindMMDBOut = "maxmindMMDB"
|
TypeMaxmindMMDBOut = "maxmindMMDB"
|
||||||
descMaxmindMMDBOut = "Convert data to MaxMind mmdb database format"
|
DescMaxmindMMDBOut = "Convert data to MaxMind mmdb database format"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -25,11 +25,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeMaxmindMMDBOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeMaxmindMMDBOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newMMDBOut(action, data)
|
return newMMDBOut(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeMaxmindMMDBOut, &mmdbOut{
|
lib.RegisterOutputConverter(TypeMaxmindMMDBOut, &MMDBOut{
|
||||||
Description: descMaxmindMMDBOut,
|
Description: DescMaxmindMMDBOut,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,10 +57,10 @@ func newMMDBOut(action lib.Action, data json.RawMessage) (lib.OutputConverter, e
|
|||||||
tmp.OutputDir = defaultOutputDir
|
tmp.OutputDir = defaultOutputDir
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mmdbOut{
|
return &MMDBOut{
|
||||||
Type: typeMaxmindMMDBOut,
|
Type: TypeMaxmindMMDBOut,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descMaxmindMMDBOut,
|
Description: DescMaxmindMMDBOut,
|
||||||
OutputName: tmp.OutputName,
|
OutputName: tmp.OutputName,
|
||||||
OutputDir: tmp.OutputDir,
|
OutputDir: tmp.OutputDir,
|
||||||
Want: tmp.Want,
|
Want: tmp.Want,
|
||||||
@@ -70,7 +70,7 @@ func newMMDBOut(action lib.Action, data json.RawMessage) (lib.OutputConverter, e
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type mmdbOut struct {
|
type MMDBOut struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -82,19 +82,19 @@ type mmdbOut struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mmdbOut) GetType() string {
|
func (m *MMDBOut) GetType() string {
|
||||||
return m.Type
|
return m.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mmdbOut) GetAction() lib.Action {
|
func (m *MMDBOut) GetAction() lib.Action {
|
||||||
return m.Action
|
return m.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mmdbOut) GetDescription() string {
|
func (m *MMDBOut) GetDescription() string {
|
||||||
return m.Description
|
return m.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mmdbOut) Output(container lib.Container) error {
|
func (m *MMDBOut) Output(container lib.Container) error {
|
||||||
writer, err := mmdbwriter.New(
|
writer, err := mmdbwriter.New(
|
||||||
mmdbwriter.Options{
|
mmdbwriter.Options{
|
||||||
DatabaseType: "GeoLite2-Country",
|
DatabaseType: "GeoLite2-Country",
|
||||||
@@ -129,7 +129,7 @@ func (m *mmdbOut) Output(container lib.Container) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mmdbOut) filterAndSortList(container lib.Container) []string {
|
func (m *MMDBOut) filterAndSortList(container lib.Container) []string {
|
||||||
/*
|
/*
|
||||||
Note: The IPs and/or CIDRs of the latter list will overwrite those of the former one
|
Note: The IPs and/or CIDRs of the latter list will overwrite those of the former one
|
||||||
when duplicated data found due to MaxMind mmdb file format constraint.
|
when duplicated data found due to MaxMind mmdb file format constraint.
|
||||||
@@ -185,7 +185,7 @@ func (m *mmdbOut) filterAndSortList(container lib.Container) []string {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mmdbOut) marshalData(writer *mmdbwriter.Tree, entry *lib.Entry) error {
|
func (m *MMDBOut) marshalData(writer *mmdbwriter.Tree, entry *lib.Entry) error {
|
||||||
var entryCidr []string
|
var entryCidr []string
|
||||||
var err error
|
var err error
|
||||||
switch m.OnlyIPType {
|
switch m.OnlyIPType {
|
||||||
@@ -219,7 +219,7 @@ func (m *mmdbOut) marshalData(writer *mmdbwriter.Tree, entry *lib.Entry) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mmdbOut) writeFile(filename string, writer *mmdbwriter.Tree) error {
|
func (m *MMDBOut) writeFile(filename string, writer *mmdbwriter.Tree) error {
|
||||||
if err := os.MkdirAll(m.OutputDir, 0755); err != nil {
|
if err := os.MkdirAll(m.OutputDir, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -21,16 +21,16 @@ import (
|
|||||||
var mrsMagicBytes = [4]byte{'M', 'R', 'S', 1} // MRSv1
|
var mrsMagicBytes = [4]byte{'M', 'R', 'S', 1} // MRSv1
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeMRSIn = "mihomoMRS"
|
TypeMRSIn = "mihomoMRS"
|
||||||
descMRSIn = "Convert mihomo MRS data to other formats"
|
DescMRSIn = "Convert mihomo MRS data to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeMRSIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeMRSIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newMRSIn(action, data)
|
return newMRSIn(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeMRSIn, &mrsIn{
|
lib.RegisterInputConverter(TypeMRSIn, &MRSIn{
|
||||||
Description: descMRSIn,
|
Description: DescMRSIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,11 +50,11 @@ func newMRSIn(action lib.Action, data json.RawMessage) (lib.InputConverter, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmp.Name == "" && tmp.URI == "" && tmp.InputDir == "" {
|
if tmp.Name == "" && tmp.URI == "" && tmp.InputDir == "" {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] missing inputDir or name or uri", typeMRSIn, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] missing inputDir or name or uri", TypeMRSIn, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp.Name != "" && tmp.URI == "") || (tmp.Name == "" && tmp.URI != "") {
|
if (tmp.Name != "" && tmp.URI == "") || (tmp.Name == "" && tmp.URI != "") {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] name & uri must be specified together", typeMRSIn, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] name & uri must be specified together", TypeMRSIn, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter want list
|
// Filter want list
|
||||||
@@ -65,10 +65,10 @@ func newMRSIn(action lib.Action, data json.RawMessage) (lib.InputConverter, erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mrsIn{
|
return &MRSIn{
|
||||||
Type: typeMRSIn,
|
Type: TypeMRSIn,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descMRSIn,
|
Description: DescMRSIn,
|
||||||
Name: tmp.Name,
|
Name: tmp.Name,
|
||||||
URI: tmp.URI,
|
URI: tmp.URI,
|
||||||
InputDir: tmp.InputDir,
|
InputDir: tmp.InputDir,
|
||||||
@@ -77,7 +77,7 @@ func newMRSIn(action lib.Action, data json.RawMessage) (lib.InputConverter, erro
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type mrsIn struct {
|
type MRSIn struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -88,19 +88,19 @@ type mrsIn struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) GetType() string {
|
func (m *MRSIn) GetType() string {
|
||||||
return m.Type
|
return m.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) GetAction() lib.Action {
|
func (m *MRSIn) GetAction() lib.Action {
|
||||||
return m.Action
|
return m.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) GetDescription() string {
|
func (m *MRSIn) GetDescription() string {
|
||||||
return m.Description
|
return m.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) Input(container lib.Container) (lib.Container, error) {
|
func (m *MRSIn) Input(container lib.Container) (lib.Container, error) {
|
||||||
entries := make(map[string]*lib.Entry)
|
entries := make(map[string]*lib.Entry)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -152,7 +152,7 @@ func (m *mrsIn) Input(container lib.Container) (lib.Container, error) {
|
|||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
func (m *MRSIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
||||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -171,7 +171,7 @@ func (m *mrsIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) walkLocalFile(path, name string, entries map[string]*lib.Entry) error {
|
func (m *MRSIn) walkLocalFile(path, name string, entries map[string]*lib.Entry) error {
|
||||||
entryName := ""
|
entryName := ""
|
||||||
name = strings.TrimSpace(name)
|
name = strings.TrimSpace(name)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
@@ -209,7 +209,7 @@ func (m *mrsIn) walkLocalFile(path, name string, entries map[string]*lib.Entry)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) error {
|
func (m *MRSIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) error {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -227,7 +227,7 @@ func (m *mrsIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) generateEntries(name string, reader io.Reader, entries map[string]*lib.Entry) error {
|
func (m *MRSIn) generateEntries(name string, reader io.Reader, entries map[string]*lib.Entry) error {
|
||||||
name = strings.ToUpper(name)
|
name = strings.ToUpper(name)
|
||||||
|
|
||||||
if len(m.Want) > 0 && !m.Want[name] {
|
if len(m.Want) > 0 && !m.Want[name] {
|
||||||
@@ -253,7 +253,7 @@ func (m *mrsIn) generateEntries(name string, reader io.Reader, entries map[strin
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsIn) parseMRS(data []byte, entry *lib.Entry) error {
|
func (m *MRSIn) parseMRS(data []byte, entry *lib.Entry) error {
|
||||||
reader, err := zstd.NewReader(bytes.NewReader(data))
|
reader, err := zstd.NewReader(bytes.NewReader(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -17,8 +17,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeMRSOut = "mihomoMRS"
|
TypeMRSOut = "mihomoMRS"
|
||||||
descMRSOut = "Convert data to mihomo MRS format"
|
DescMRSOut = "Convert data to mihomo MRS format"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -26,11 +26,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeMRSOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeMRSOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newMRSOut(action, data)
|
return newMRSOut(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeMRSOut, &mrsOut{
|
lib.RegisterOutputConverter(TypeMRSOut, &MRSOut{
|
||||||
Description: descMRSOut,
|
Description: DescMRSOut,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +52,10 @@ func newMRSOut(action lib.Action, data json.RawMessage) (lib.OutputConverter, er
|
|||||||
tmp.OutputDir = defaultOutputDir
|
tmp.OutputDir = defaultOutputDir
|
||||||
}
|
}
|
||||||
|
|
||||||
return &mrsOut{
|
return &MRSOut{
|
||||||
Type: typeMRSOut,
|
Type: TypeMRSOut,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descMRSOut,
|
Description: DescMRSOut,
|
||||||
OutputDir: tmp.OutputDir,
|
OutputDir: tmp.OutputDir,
|
||||||
Want: tmp.Want,
|
Want: tmp.Want,
|
||||||
Exclude: tmp.Exclude,
|
Exclude: tmp.Exclude,
|
||||||
@@ -63,7 +63,7 @@ func newMRSOut(action lib.Action, data json.RawMessage) (lib.OutputConverter, er
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type mrsOut struct {
|
type MRSOut struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -73,19 +73,19 @@ type mrsOut struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) GetType() string {
|
func (m *MRSOut) GetType() string {
|
||||||
return m.Type
|
return m.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) GetAction() lib.Action {
|
func (m *MRSOut) GetAction() lib.Action {
|
||||||
return m.Action
|
return m.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) GetDescription() string {
|
func (m *MRSOut) GetDescription() string {
|
||||||
return m.Description
|
return m.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) Output(container lib.Container) error {
|
func (m *MRSOut) Output(container lib.Container) error {
|
||||||
for _, name := range m.filterAndSortList(container) {
|
for _, name := range m.filterAndSortList(container) {
|
||||||
entry, found := container.GetEntry(name)
|
entry, found := container.GetEntry(name)
|
||||||
if !found {
|
if !found {
|
||||||
@@ -101,7 +101,7 @@ func (m *mrsOut) Output(container lib.Container) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) filterAndSortList(container lib.Container) []string {
|
func (m *MRSOut) filterAndSortList(container lib.Container) []string {
|
||||||
excludeMap := make(map[string]bool)
|
excludeMap := make(map[string]bool)
|
||||||
for _, exclude := range m.Exclude {
|
for _, exclude := range m.Exclude {
|
||||||
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
||||||
@@ -137,7 +137,7 @@ func (m *mrsOut) filterAndSortList(container lib.Container) []string {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) generate(entry *lib.Entry) error {
|
func (m *MRSOut) generate(entry *lib.Entry) error {
|
||||||
var ipRanges []netipx.IPRange
|
var ipRanges []netipx.IPRange
|
||||||
var err error
|
var err error
|
||||||
switch m.OnlyIPType {
|
switch m.OnlyIPType {
|
||||||
@@ -164,7 +164,7 @@ func (m *mrsOut) generate(entry *lib.Entry) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) writeFile(filename string, ipRanges []netipx.IPRange) error {
|
func (m *MRSOut) writeFile(filename string, ipRanges []netipx.IPRange) error {
|
||||||
if err := os.MkdirAll(m.OutputDir, 0755); err != nil {
|
if err := os.MkdirAll(m.OutputDir, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -185,7 +185,7 @@ func (m *mrsOut) writeFile(filename string, ipRanges []netipx.IPRange) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *mrsOut) convertToMrs(ipRanges []netipx.IPRange, w io.Writer) (err error) {
|
func (m *MRSOut) convertToMrs(ipRanges []netipx.IPRange, w io.Writer) (err error) {
|
||||||
encoder, err := zstd.NewWriter(w)
|
encoder, err := zstd.NewWriter(w)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -12,25 +12,25 @@ which make it possible to support more formats for the project.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeClashRuleSetClassicalIn = "clashRuleSetClassical"
|
TypeClashRuleSetClassicalIn = "clashRuleSetClassical"
|
||||||
descClashClassicalIn = "Convert classical type of Clash RuleSet to other formats (just processing IP & CIDR lines)"
|
DescClashClassicalIn = "Convert classical type of Clash RuleSet to other formats (just processing IP & CIDR lines)"
|
||||||
|
|
||||||
typeClashRuleSetIPCIDRIn = "clashRuleSet"
|
TypeClashRuleSetIPCIDRIn = "clashRuleSet"
|
||||||
descClashRuleSetIn = "Convert ipcidr type of Clash RuleSet to other formats"
|
DescClashRuleSetIn = "Convert ipcidr type of Clash RuleSet to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeClashRuleSetClassicalIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeClashRuleSetClassicalIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newTextIn(typeClashRuleSetClassicalIn, action, data)
|
return newTextIn(TypeClashRuleSetClassicalIn, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeClashRuleSetClassicalIn, &textIn{
|
lib.RegisterInputConverter(TypeClashRuleSetClassicalIn, &TextIn{
|
||||||
Description: descClashClassicalIn,
|
Description: DescClashClassicalIn,
|
||||||
})
|
})
|
||||||
|
|
||||||
lib.RegisterInputConfigCreator(typeClashRuleSetIPCIDRIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeClashRuleSetIPCIDRIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newTextIn(typeClashRuleSetIPCIDRIn, action, data)
|
return newTextIn(TypeClashRuleSetIPCIDRIn, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeClashRuleSetIPCIDRIn, &textIn{
|
lib.RegisterInputConverter(TypeClashRuleSetIPCIDRIn, &TextIn{
|
||||||
Description: descClashRuleSetIn,
|
Description: DescClashRuleSetIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -12,25 +12,25 @@ which make it possible to support more formats for the project.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeClashRuleSetClassicalOut = "clashRuleSetClassical"
|
TypeClashRuleSetClassicalOut = "clashRuleSetClassical"
|
||||||
descClashClassicalOut = "Convert data to classical type of Clash RuleSet"
|
DescClashClassicalOut = "Convert data to classical type of Clash RuleSet"
|
||||||
|
|
||||||
typeClashRuleSetIPCIDROut = "clashRuleSet"
|
TypeClashRuleSetIPCIDROut = "clashRuleSet"
|
||||||
descClashRuleSetOut = "Convert data to ipcidr type of Clash RuleSet"
|
DescClashRuleSetOut = "Convert data to ipcidr type of Clash RuleSet"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeClashRuleSetClassicalOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeClashRuleSetClassicalOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newTextOut(typeClashRuleSetClassicalOut, action, data)
|
return newTextOut(TypeClashRuleSetClassicalOut, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeClashRuleSetClassicalOut, &textOut{
|
lib.RegisterOutputConverter(TypeClashRuleSetClassicalOut, &TextOut{
|
||||||
Description: descClashClassicalOut,
|
Description: DescClashClassicalOut,
|
||||||
})
|
})
|
||||||
|
|
||||||
lib.RegisterOutputConfigCreator(typeClashRuleSetIPCIDROut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeClashRuleSetIPCIDROut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newTextOut(typeClashRuleSetIPCIDROut, action, data)
|
return newTextOut(TypeClashRuleSetIPCIDROut, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeClashRuleSetIPCIDROut, &textOut{
|
lib.RegisterOutputConverter(TypeClashRuleSetIPCIDROut, &TextOut{
|
||||||
Description: descClashRuleSetOut,
|
Description: DescClashRuleSetOut,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ import (
|
|||||||
"gopkg.in/yaml.v2"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type textIn struct {
|
type TextIn struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -27,18 +27,18 @@ type textIn struct {
|
|||||||
RemoveSuffixesInLine []string
|
RemoveSuffixesInLine []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) scanFile(reader io.Reader, entry *lib.Entry) error {
|
func (t *TextIn) scanFile(reader io.Reader, entry *lib.Entry) error {
|
||||||
var err error
|
var err error
|
||||||
switch t.Type {
|
switch t.Type {
|
||||||
case typeTextIn:
|
case TypeTextIn:
|
||||||
err = t.scanFileForTextIn(reader, entry)
|
err = t.scanFileForTextIn(reader, entry)
|
||||||
case typeJSONIn:
|
case TypeJSONIn:
|
||||||
err = t.scanFileForJSONIn(reader, entry)
|
err = t.scanFileForJSONIn(reader, entry)
|
||||||
case typeClashRuleSetClassicalIn:
|
case TypeClashRuleSetClassicalIn:
|
||||||
err = t.scanFileForClashClassicalRuleSetIn(reader, entry)
|
err = t.scanFileForClashClassicalRuleSetIn(reader, entry)
|
||||||
case typeClashRuleSetIPCIDRIn:
|
case TypeClashRuleSetIPCIDRIn:
|
||||||
err = t.scanFileForClashIPCIDRRuleSetIn(reader, entry)
|
err = t.scanFileForClashIPCIDRRuleSetIn(reader, entry)
|
||||||
case typeSurgeRuleSetIn:
|
case TypeSurgeRuleSetIn:
|
||||||
err = t.scanFileForSurgeRuleSetIn(reader, entry)
|
err = t.scanFileForSurgeRuleSetIn(reader, entry)
|
||||||
default:
|
default:
|
||||||
return lib.ErrNotSupportedFormat
|
return lib.ErrNotSupportedFormat
|
||||||
@@ -47,7 +47,7 @@ func (t *textIn) scanFile(reader io.Reader, entry *lib.Entry) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) scanFileForTextIn(reader io.Reader, entry *lib.Entry) error {
|
func (t *TextIn) scanFileForTextIn(reader io.Reader, entry *lib.Entry) error {
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
@@ -83,7 +83,7 @@ func (t *textIn) scanFileForTextIn(reader io.Reader, entry *lib.Entry) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) readClashRuleSetYAMLFile(reader io.Reader) ([]string, error) {
|
func (t *TextIn) readClashRuleSetYAMLFile(reader io.Reader) ([]string, error) {
|
||||||
var payload struct {
|
var payload struct {
|
||||||
Payload []string `yaml:"payload"`
|
Payload []string `yaml:"payload"`
|
||||||
}
|
}
|
||||||
@@ -100,7 +100,7 @@ func (t *textIn) readClashRuleSetYAMLFile(reader io.Reader) ([]string, error) {
|
|||||||
return payload.Payload, nil
|
return payload.Payload, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) scanFileForClashIPCIDRRuleSetIn(reader io.Reader, entry *lib.Entry) error {
|
func (t *TextIn) scanFileForClashIPCIDRRuleSetIn(reader io.Reader, entry *lib.Entry) error {
|
||||||
payload, err := t.readClashRuleSetYAMLFile(reader)
|
payload, err := t.readClashRuleSetYAMLFile(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -119,7 +119,7 @@ func (t *textIn) scanFileForClashIPCIDRRuleSetIn(reader io.Reader, entry *lib.En
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) scanFileForClashClassicalRuleSetIn(reader io.Reader, entry *lib.Entry) error {
|
func (t *TextIn) scanFileForClashClassicalRuleSetIn(reader io.Reader, entry *lib.Entry) error {
|
||||||
payload, err := t.readClashRuleSetYAMLFile(reader)
|
payload, err := t.readClashRuleSetYAMLFile(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -154,7 +154,7 @@ func (t *textIn) scanFileForClashClassicalRuleSetIn(reader io.Reader, entry *lib
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) scanFileForSurgeRuleSetIn(reader io.Reader, entry *lib.Entry) error {
|
func (t *TextIn) scanFileForSurgeRuleSetIn(reader io.Reader, entry *lib.Entry) error {
|
||||||
scanner := bufio.NewScanner(reader)
|
scanner := bufio.NewScanner(reader)
|
||||||
for scanner.Scan() {
|
for scanner.Scan() {
|
||||||
line := scanner.Text()
|
line := scanner.Text()
|
||||||
@@ -193,7 +193,7 @@ func (t *textIn) scanFileForSurgeRuleSetIn(reader io.Reader, entry *lib.Entry) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) scanFileForJSONIn(reader io.Reader, entry *lib.Entry) error {
|
func (t *TextIn) scanFileForJSONIn(reader io.Reader, entry *lib.Entry) error {
|
||||||
data, err := io.ReadAll(reader)
|
data, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -18,7 +18,7 @@ var (
|
|||||||
defaultOutputDirForSurgeRuleSetOut = filepath.Join("./", "output", "surge")
|
defaultOutputDirForSurgeRuleSetOut = filepath.Join("./", "output", "surge")
|
||||||
)
|
)
|
||||||
|
|
||||||
type textOut struct {
|
type TextOut struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -52,13 +52,13 @@ func newTextOut(iType string, action lib.Action, data json.RawMessage) (lib.Outp
|
|||||||
|
|
||||||
if tmp.OutputDir == "" {
|
if tmp.OutputDir == "" {
|
||||||
switch iType {
|
switch iType {
|
||||||
case typeTextOut:
|
case TypeTextOut:
|
||||||
tmp.OutputDir = defaultOutputDirForTextOut
|
tmp.OutputDir = defaultOutputDirForTextOut
|
||||||
case typeClashRuleSetClassicalOut:
|
case TypeClashRuleSetClassicalOut:
|
||||||
tmp.OutputDir = defaultOutputDirForClashRuleSetClassicalOut
|
tmp.OutputDir = defaultOutputDirForClashRuleSetClassicalOut
|
||||||
case typeClashRuleSetIPCIDROut:
|
case TypeClashRuleSetIPCIDROut:
|
||||||
tmp.OutputDir = defaultOutputDirForClashRuleSetIPCIDROut
|
tmp.OutputDir = defaultOutputDirForClashRuleSetIPCIDROut
|
||||||
case typeSurgeRuleSetOut:
|
case TypeSurgeRuleSetOut:
|
||||||
tmp.OutputDir = defaultOutputDirForSurgeRuleSetOut
|
tmp.OutputDir = defaultOutputDirForSurgeRuleSetOut
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -67,10 +67,10 @@ func newTextOut(iType string, action lib.Action, data json.RawMessage) (lib.Outp
|
|||||||
tmp.OutputExt = ".txt"
|
tmp.OutputExt = ".txt"
|
||||||
}
|
}
|
||||||
|
|
||||||
return &textOut{
|
return &TextOut{
|
||||||
Type: iType,
|
Type: iType,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descTextOut,
|
Description: DescTextOut,
|
||||||
OutputDir: tmp.OutputDir,
|
OutputDir: tmp.OutputDir,
|
||||||
OutputExt: tmp.OutputExt,
|
OutputExt: tmp.OutputExt,
|
||||||
Want: tmp.Want,
|
Want: tmp.Want,
|
||||||
@@ -82,7 +82,7 @@ func newTextOut(iType string, action lib.Action, data json.RawMessage) (lib.Outp
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) marshalBytes(entry *lib.Entry) ([]byte, error) {
|
func (t *TextOut) marshalBytes(entry *lib.Entry) ([]byte, error) {
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
var entryCidr []string
|
var entryCidr []string
|
||||||
@@ -100,13 +100,13 @@ func (t *textOut) marshalBytes(entry *lib.Entry) ([]byte, error) {
|
|||||||
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
switch t.Type {
|
switch t.Type {
|
||||||
case typeTextOut:
|
case TypeTextOut:
|
||||||
err = t.marshalBytesForTextOut(&buf, entryCidr)
|
err = t.marshalBytesForTextOut(&buf, entryCidr)
|
||||||
case typeClashRuleSetClassicalOut:
|
case TypeClashRuleSetClassicalOut:
|
||||||
err = t.marshalBytesForClashRuleSetClassicalOut(&buf, entryCidr)
|
err = t.marshalBytesForClashRuleSetClassicalOut(&buf, entryCidr)
|
||||||
case typeClashRuleSetIPCIDROut:
|
case TypeClashRuleSetIPCIDROut:
|
||||||
err = t.marshalBytesForClashRuleSetIPCIDROut(&buf, entryCidr)
|
err = t.marshalBytesForClashRuleSetIPCIDROut(&buf, entryCidr)
|
||||||
case typeSurgeRuleSetOut:
|
case TypeSurgeRuleSetOut:
|
||||||
err = t.marshalBytesForSurgeRuleSetOut(&buf, entryCidr)
|
err = t.marshalBytesForSurgeRuleSetOut(&buf, entryCidr)
|
||||||
default:
|
default:
|
||||||
return nil, lib.ErrNotSupportedFormat
|
return nil, lib.ErrNotSupportedFormat
|
||||||
@@ -118,7 +118,7 @@ func (t *textOut) marshalBytes(entry *lib.Entry) ([]byte, error) {
|
|||||||
return buf.Bytes(), nil
|
return buf.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) marshalBytesForTextOut(buf *bytes.Buffer, entryCidr []string) error {
|
func (t *TextOut) marshalBytesForTextOut(buf *bytes.Buffer, entryCidr []string) error {
|
||||||
for _, cidr := range entryCidr {
|
for _, cidr := range entryCidr {
|
||||||
if t.AddPrefixInLine != "" {
|
if t.AddPrefixInLine != "" {
|
||||||
buf.WriteString(t.AddPrefixInLine)
|
buf.WriteString(t.AddPrefixInLine)
|
||||||
@@ -132,7 +132,7 @@ func (t *textOut) marshalBytesForTextOut(buf *bytes.Buffer, entryCidr []string)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) marshalBytesForClashRuleSetClassicalOut(buf *bytes.Buffer, entryCidr []string) error {
|
func (t *TextOut) marshalBytesForClashRuleSetClassicalOut(buf *bytes.Buffer, entryCidr []string) error {
|
||||||
buf.WriteString("payload:\n")
|
buf.WriteString("payload:\n")
|
||||||
for _, cidr := range entryCidr {
|
for _, cidr := range entryCidr {
|
||||||
ip, _, err := net.ParseCIDR(cidr)
|
ip, _, err := net.ParseCIDR(cidr)
|
||||||
@@ -151,7 +151,7 @@ func (t *textOut) marshalBytesForClashRuleSetClassicalOut(buf *bytes.Buffer, ent
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) marshalBytesForClashRuleSetIPCIDROut(buf *bytes.Buffer, entryCidr []string) error {
|
func (t *TextOut) marshalBytesForClashRuleSetIPCIDROut(buf *bytes.Buffer, entryCidr []string) error {
|
||||||
buf.WriteString("payload:\n")
|
buf.WriteString("payload:\n")
|
||||||
for _, cidr := range entryCidr {
|
for _, cidr := range entryCidr {
|
||||||
buf.WriteString(" - '")
|
buf.WriteString(" - '")
|
||||||
@@ -162,7 +162,7 @@ func (t *textOut) marshalBytesForClashRuleSetIPCIDROut(buf *bytes.Buffer, entryC
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) marshalBytesForSurgeRuleSetOut(buf *bytes.Buffer, entryCidr []string) error {
|
func (t *TextOut) marshalBytesForSurgeRuleSetOut(buf *bytes.Buffer, entryCidr []string) error {
|
||||||
for _, cidr := range entryCidr {
|
for _, cidr := range entryCidr {
|
||||||
ip, _, err := net.ParseCIDR(cidr)
|
ip, _, err := net.ParseCIDR(cidr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -183,7 +183,7 @@ func (t *textOut) marshalBytesForSurgeRuleSetOut(buf *bytes.Buffer, entryCidr []
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) writeFile(filename string, data []byte) error {
|
func (t *TextOut) writeFile(filename string, data []byte) error {
|
||||||
if err := os.MkdirAll(t.OutputDir, 0755); err != nil {
|
if err := os.MkdirAll(t.OutputDir, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -7,16 +7,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeJSONIn = "json"
|
TypeJSONIn = "json"
|
||||||
descJSONIn = "Convert JSON data to other formats"
|
DescJSONIn = "Convert JSON data to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeJSONIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeJSONIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newTextIn(typeJSONIn, action, data)
|
return newTextIn(TypeJSONIn, action, data)
|
||||||
})
|
})
|
||||||
|
|
||||||
lib.RegisterInputConverter(typeJSONIn, &textIn{
|
lib.RegisterInputConverter(TypeJSONIn, &TextIn{
|
||||||
Description: descJSONIn,
|
Description: DescJSONIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -12,15 +12,15 @@ which make it possible to support more formats for the project.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeSurgeRuleSetIn = "surgeRuleSet"
|
TypeSurgeRuleSetIn = "surgeRuleSet"
|
||||||
descSurgeRuleSetIn = "Convert Surge RuleSet to other formats (just processing IP & CIDR lines)"
|
DescSurgeRuleSetIn = "Convert Surge RuleSet to other formats (just processing IP & CIDR lines)"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeSurgeRuleSetIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeSurgeRuleSetIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newTextIn(typeSurgeRuleSetIn, action, data)
|
return newTextIn(TypeSurgeRuleSetIn, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeSurgeRuleSetIn, &textIn{
|
lib.RegisterInputConverter(TypeSurgeRuleSetIn, &TextIn{
|
||||||
Description: descSurgeRuleSetIn,
|
Description: DescSurgeRuleSetIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -12,15 +12,15 @@ which make it possible to support more formats for the project.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeSurgeRuleSetOut = "surgeRuleSet"
|
TypeSurgeRuleSetOut = "surgeRuleSet"
|
||||||
descSurgeRuleSetOut = "Convert data to Surge RuleSet"
|
DescSurgeRuleSetOut = "Convert data to Surge RuleSet"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeSurgeRuleSetOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeSurgeRuleSetOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newTextOut(typeSurgeRuleSetOut, action, data)
|
return newTextOut(TypeSurgeRuleSetOut, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeSurgeRuleSetOut, &textOut{
|
lib.RegisterOutputConverter(TypeSurgeRuleSetOut, &TextOut{
|
||||||
Description: descSurgeRuleSetOut,
|
Description: DescSurgeRuleSetOut,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -13,16 +13,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeTextIn = "text"
|
TypeTextIn = "text"
|
||||||
descTextIn = "Convert plaintext IP & CIDR to other formats"
|
DescTextIn = "Convert plaintext IP & CIDR to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeTextIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeTextIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newTextIn(typeTextIn, action, data)
|
return newTextIn(TypeTextIn, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeTextIn, &textIn{
|
lib.RegisterInputConverter(TypeTextIn, &TextIn{
|
||||||
Description: descTextIn,
|
Description: DescTextIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,11 +50,11 @@ func newTextIn(iType string, action lib.Action, data json.RawMessage) (lib.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if iType != typeTextIn && len(tmp.IPOrCIDR) > 0 {
|
if iType != TypeTextIn && len(tmp.IPOrCIDR) > 0 {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] ipOrCIDR is invalid for this input format", iType, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] ipOrCIDR is invalid for this input format", iType, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
if iType == typeJSONIn && len(tmp.JSONPath) == 0 {
|
if iType == TypeJSONIn && len(tmp.JSONPath) == 0 {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] missing jsonPath", iType, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] missing jsonPath", iType, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,10 +77,10 @@ func newTextIn(iType string, action lib.Action, data json.RawMessage) (lib.Input
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &textIn{
|
return &TextIn{
|
||||||
Type: iType,
|
Type: iType,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descTextIn,
|
Description: DescTextIn,
|
||||||
Name: tmp.Name,
|
Name: tmp.Name,
|
||||||
URI: tmp.URI,
|
URI: tmp.URI,
|
||||||
IPOrCIDR: tmp.IPOrCIDR,
|
IPOrCIDR: tmp.IPOrCIDR,
|
||||||
@@ -94,19 +94,19 @@ func newTextIn(iType string, action lib.Action, data json.RawMessage) (lib.Input
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) GetType() string {
|
func (t *TextIn) GetType() string {
|
||||||
return t.Type
|
return t.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) GetAction() lib.Action {
|
func (t *TextIn) GetAction() lib.Action {
|
||||||
return t.Action
|
return t.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) GetDescription() string {
|
func (t *TextIn) GetDescription() string {
|
||||||
return t.Description
|
return t.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) Input(container lib.Container) (lib.Container, error) {
|
func (t *TextIn) Input(container lib.Container) (lib.Container, error) {
|
||||||
entries := make(map[string]*lib.Entry)
|
entries := make(map[string]*lib.Entry)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -168,7 +168,7 @@ func (t *textIn) Input(container lib.Container) (lib.Container, error) {
|
|||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
func (t *TextIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
||||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -187,7 +187,7 @@ func (t *textIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) walkLocalFile(path, name string, entries map[string]*lib.Entry) error {
|
func (t *TextIn) walkLocalFile(path, name string, entries map[string]*lib.Entry) error {
|
||||||
entryName := ""
|
entryName := ""
|
||||||
name = strings.TrimSpace(name)
|
name = strings.TrimSpace(name)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
@@ -231,7 +231,7 @@ func (t *textIn) walkLocalFile(path, name string, entries map[string]*lib.Entry)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) error {
|
func (t *TextIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) error {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -258,7 +258,7 @@ func (t *textIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textIn) appendIPOrCIDR(ipOrCIDR []string, name string, entries map[string]*lib.Entry) error {
|
func (t *TextIn) appendIPOrCIDR(ipOrCIDR []string, name string, entries map[string]*lib.Entry) error {
|
||||||
name = strings.ToUpper(name)
|
name = strings.ToUpper(name)
|
||||||
|
|
||||||
entry, found := entries[name]
|
entry, found := entries[name]
|
||||||
|
@@ -10,32 +10,32 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeTextOut = "text"
|
TypeTextOut = "text"
|
||||||
descTextOut = "Convert data to plaintext CIDR format"
|
DescTextOut = "Convert data to plaintext CIDR format"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeTextOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeTextOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newTextOut(typeTextOut, action, data)
|
return newTextOut(TypeTextOut, action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeTextOut, &textOut{
|
lib.RegisterOutputConverter(TypeTextOut, &TextOut{
|
||||||
Description: descTextOut,
|
Description: DescTextOut,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) GetType() string {
|
func (t *TextOut) GetType() string {
|
||||||
return t.Type
|
return t.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) GetAction() lib.Action {
|
func (t *TextOut) GetAction() lib.Action {
|
||||||
return t.Action
|
return t.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) GetDescription() string {
|
func (t *TextOut) GetDescription() string {
|
||||||
return t.Description
|
return t.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) Output(container lib.Container) error {
|
func (t *TextOut) Output(container lib.Container) error {
|
||||||
for _, name := range t.filterAndSortList(container) {
|
for _, name := range t.filterAndSortList(container) {
|
||||||
entry, found := container.GetEntry(name)
|
entry, found := container.GetEntry(name)
|
||||||
if !found {
|
if !found {
|
||||||
@@ -57,7 +57,7 @@ func (t *textOut) Output(container lib.Container) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *textOut) filterAndSortList(container lib.Container) []string {
|
func (t *TextOut) filterAndSortList(container lib.Container) []string {
|
||||||
excludeMap := make(map[string]bool)
|
excludeMap := make(map[string]bool)
|
||||||
for _, exclude := range t.Exclude {
|
for _, exclude := range t.Exclude {
|
||||||
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
||||||
|
@@ -15,16 +15,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeSRSIn = "singboxSRS"
|
TypeSRSIn = "singboxSRS"
|
||||||
descSRSIn = "Convert sing-box SRS data to other formats"
|
DescSRSIn = "Convert sing-box SRS data to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeSRSIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeSRSIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newSRSIn(action, data)
|
return newSRSIn(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeSRSIn, &srsIn{
|
lib.RegisterInputConverter(TypeSRSIn, &SRSIn{
|
||||||
Description: descSRSIn,
|
Description: DescSRSIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,11 +44,11 @@ func newSRSIn(action lib.Action, data json.RawMessage) (lib.InputConverter, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmp.Name == "" && tmp.URI == "" && tmp.InputDir == "" {
|
if tmp.Name == "" && tmp.URI == "" && tmp.InputDir == "" {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] missing inputdir or name or uri", typeSRSIn, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] missing inputdir or name or uri", TypeSRSIn, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmp.Name != "" && tmp.URI == "") || (tmp.Name == "" && tmp.URI != "") {
|
if (tmp.Name != "" && tmp.URI == "") || (tmp.Name == "" && tmp.URI != "") {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] name & uri must be specified together", typeSRSIn, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] name & uri must be specified together", TypeSRSIn, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter want list
|
// Filter want list
|
||||||
@@ -59,10 +59,10 @@ func newSRSIn(action lib.Action, data json.RawMessage) (lib.InputConverter, erro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &srsIn{
|
return &SRSIn{
|
||||||
Type: typeSRSIn,
|
Type: TypeSRSIn,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descSRSIn,
|
Description: DescSRSIn,
|
||||||
Name: tmp.Name,
|
Name: tmp.Name,
|
||||||
URI: tmp.URI,
|
URI: tmp.URI,
|
||||||
InputDir: tmp.InputDir,
|
InputDir: tmp.InputDir,
|
||||||
@@ -71,7 +71,7 @@ func newSRSIn(action lib.Action, data json.RawMessage) (lib.InputConverter, erro
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type srsIn struct {
|
type SRSIn struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -82,19 +82,19 @@ type srsIn struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) GetType() string {
|
func (s *SRSIn) GetType() string {
|
||||||
return s.Type
|
return s.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) GetAction() lib.Action {
|
func (s *SRSIn) GetAction() lib.Action {
|
||||||
return s.Action
|
return s.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) GetDescription() string {
|
func (s *SRSIn) GetDescription() string {
|
||||||
return s.Description
|
return s.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) Input(container lib.Container) (lib.Container, error) {
|
func (s *SRSIn) Input(container lib.Container) (lib.Container, error) {
|
||||||
entries := make(map[string]*lib.Entry)
|
entries := make(map[string]*lib.Entry)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -146,7 +146,7 @@ func (s *srsIn) Input(container lib.Container) (lib.Container, error) {
|
|||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
func (s *SRSIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
||||||
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -165,7 +165,7 @@ func (s *srsIn) walkDir(dir string, entries map[string]*lib.Entry) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) walkLocalFile(path, name string, entries map[string]*lib.Entry) error {
|
func (s *SRSIn) walkLocalFile(path, name string, entries map[string]*lib.Entry) error {
|
||||||
entryName := ""
|
entryName := ""
|
||||||
name = strings.TrimSpace(name)
|
name = strings.TrimSpace(name)
|
||||||
if name != "" {
|
if name != "" {
|
||||||
@@ -203,7 +203,7 @@ func (s *srsIn) walkLocalFile(path, name string, entries map[string]*lib.Entry)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) error {
|
func (s *SRSIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry) error {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -221,7 +221,7 @@ func (s *srsIn) walkRemoteFile(url, name string, entries map[string]*lib.Entry)
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsIn) generateEntries(name string, reader io.Reader, entries map[string]*lib.Entry) error {
|
func (s *SRSIn) generateEntries(name string, reader io.Reader, entries map[string]*lib.Entry) error {
|
||||||
name = strings.ToUpper(name)
|
name = strings.ToUpper(name)
|
||||||
|
|
||||||
if len(s.Want) > 0 && !s.Want[name] {
|
if len(s.Want) > 0 && !s.Want[name] {
|
||||||
|
@@ -16,8 +16,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeSRSOut = "singboxSRS"
|
TypeSRSOut = "singboxSRS"
|
||||||
descSRSOut = "Convert data to sing-box SRS format"
|
DescSRSOut = "Convert data to sing-box SRS format"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -25,11 +25,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeSRSOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeSRSOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newSRSOut(action, data)
|
return newSRSOut(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeSRSOut, &srsOut{
|
lib.RegisterOutputConverter(TypeSRSOut, &SRSOut{
|
||||||
Description: descSRSOut,
|
Description: DescSRSOut,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,10 +51,10 @@ func newSRSOut(action lib.Action, data json.RawMessage) (lib.OutputConverter, er
|
|||||||
tmp.OutputDir = defaultOutputDir
|
tmp.OutputDir = defaultOutputDir
|
||||||
}
|
}
|
||||||
|
|
||||||
return &srsOut{
|
return &SRSOut{
|
||||||
Type: typeSRSOut,
|
Type: TypeSRSOut,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descSRSOut,
|
Description: DescSRSOut,
|
||||||
OutputDir: tmp.OutputDir,
|
OutputDir: tmp.OutputDir,
|
||||||
Want: tmp.Want,
|
Want: tmp.Want,
|
||||||
Exclude: tmp.Exclude,
|
Exclude: tmp.Exclude,
|
||||||
@@ -62,7 +62,7 @@ func newSRSOut(action lib.Action, data json.RawMessage) (lib.OutputConverter, er
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type srsOut struct {
|
type SRSOut struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -72,19 +72,19 @@ type srsOut struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) GetType() string {
|
func (s *SRSOut) GetType() string {
|
||||||
return s.Type
|
return s.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) GetAction() lib.Action {
|
func (s *SRSOut) GetAction() lib.Action {
|
||||||
return s.Action
|
return s.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) GetDescription() string {
|
func (s *SRSOut) GetDescription() string {
|
||||||
return s.Description
|
return s.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) Output(container lib.Container) error {
|
func (s *SRSOut) Output(container lib.Container) error {
|
||||||
for _, name := range s.filterAndSortList(container) {
|
for _, name := range s.filterAndSortList(container) {
|
||||||
entry, found := container.GetEntry(name)
|
entry, found := container.GetEntry(name)
|
||||||
if !found {
|
if !found {
|
||||||
@@ -100,7 +100,7 @@ func (s *srsOut) Output(container lib.Container) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) filterAndSortList(container lib.Container) []string {
|
func (s *SRSOut) filterAndSortList(container lib.Container) []string {
|
||||||
excludeMap := make(map[string]bool)
|
excludeMap := make(map[string]bool)
|
||||||
for _, exclude := range s.Exclude {
|
for _, exclude := range s.Exclude {
|
||||||
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
||||||
@@ -136,7 +136,7 @@ func (s *srsOut) filterAndSortList(container lib.Container) []string {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) generate(entry *lib.Entry) error {
|
func (s *SRSOut) generate(entry *lib.Entry) error {
|
||||||
ruleset, err := s.marshalRuleSet(entry)
|
ruleset, err := s.marshalRuleSet(entry)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -150,7 +150,7 @@ func (s *srsOut) generate(entry *lib.Entry) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) marshalRuleSet(entry *lib.Entry) (*option.PlainRuleSet, error) {
|
func (s *SRSOut) marshalRuleSet(entry *lib.Entry) (*option.PlainRuleSet, error) {
|
||||||
var entryCidr []string
|
var entryCidr []string
|
||||||
var err error
|
var err error
|
||||||
switch s.OnlyIPType {
|
switch s.OnlyIPType {
|
||||||
@@ -183,7 +183,7 @@ func (s *srsOut) marshalRuleSet(entry *lib.Entry) (*option.PlainRuleSet, error)
|
|||||||
return nil, fmt.Errorf("❌ [type %s | action %s] entry %s has no CIDR", s.Type, s.Action, entry.GetName())
|
return nil, fmt.Errorf("❌ [type %s | action %s] entry %s has no CIDR", s.Type, s.Action, entry.GetName())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *srsOut) writeFile(filename string, ruleset *option.PlainRuleSet) error {
|
func (s *SRSOut) writeFile(filename string, ruleset *option.PlainRuleSet) error {
|
||||||
if err := os.MkdirAll(s.OutputDir, 0755); err != nil {
|
if err := os.MkdirAll(s.OutputDir, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -194,7 +194,7 @@ func (s *srsOut) writeFile(filename string, ruleset *option.PlainRuleSet) error
|
|||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
err = srs.Write(f, *ruleset)
|
err = srs.Write(f, *ruleset, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -9,16 +9,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeCutter = "cutter"
|
TypeCutter = "cutter"
|
||||||
descCutter = "Remove data from previous steps"
|
DescCutter = "Remove data from previous steps"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeCutter, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeCutter, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newCutter(action, data)
|
return newCutter(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeCutter, &cutter{
|
lib.RegisterInputConverter(TypeCutter, &Cutter{
|
||||||
Description: descCutter,
|
Description: DescCutter,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ func newCutter(action lib.Action, data json.RawMessage) (lib.InputConverter, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if action != lib.ActionRemove {
|
if action != lib.ActionRemove {
|
||||||
return nil, fmt.Errorf("❌ [type %s] only supports `remove` action", typeCutter)
|
return nil, fmt.Errorf("❌ [type %s] only supports `remove` action", TypeCutter)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter want list
|
// Filter want list
|
||||||
@@ -47,19 +47,19 @@ func newCutter(action lib.Action, data json.RawMessage) (lib.InputConverter, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(wantList) == 0 {
|
if len(wantList) == 0 {
|
||||||
return nil, fmt.Errorf("❌ [type %s] wantedList must be specified", typeCutter)
|
return nil, fmt.Errorf("❌ [type %s] wantedList must be specified", TypeCutter)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &cutter{
|
return &Cutter{
|
||||||
Type: typeCutter,
|
Type: TypeCutter,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descCutter,
|
Description: DescCutter,
|
||||||
Want: wantList,
|
Want: wantList,
|
||||||
OnlyIPType: tmp.OnlyIPType,
|
OnlyIPType: tmp.OnlyIPType,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type cutter struct {
|
type Cutter struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -67,19 +67,19 @@ type cutter struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cutter) GetType() string {
|
func (c *Cutter) GetType() string {
|
||||||
return c.Type
|
return c.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cutter) GetAction() lib.Action {
|
func (c *Cutter) GetAction() lib.Action {
|
||||||
return c.Action
|
return c.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cutter) GetDescription() string {
|
func (c *Cutter) GetDescription() string {
|
||||||
return c.Description
|
return c.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *cutter) Input(container lib.Container) (lib.Container, error) {
|
func (c *Cutter) Input(container lib.Container) (lib.Container, error) {
|
||||||
var ignoreIPType lib.IgnoreIPOption
|
var ignoreIPType lib.IgnoreIPOption
|
||||||
switch c.OnlyIPType {
|
switch c.OnlyIPType {
|
||||||
case lib.IPv4:
|
case lib.IPv4:
|
||||||
|
@@ -12,16 +12,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeLookup = "lookup"
|
TypeLookup = "lookup"
|
||||||
descLookup = "Lookup specified IP or CIDR from various formats of data"
|
DescLookup = "Lookup specified IP or CIDR from various formats of data"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeLookup, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeLookup, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newLookup(action, data)
|
return newLookup(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeLookup, &lookup{
|
lib.RegisterOutputConverter(TypeLookup, &Lookup{
|
||||||
Description: descLookup,
|
Description: DescLookup,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,19 +39,19 @@ func newLookup(action lib.Action, data json.RawMessage) (lib.OutputConverter, er
|
|||||||
|
|
||||||
tmp.Search = strings.TrimSpace(tmp.Search)
|
tmp.Search = strings.TrimSpace(tmp.Search)
|
||||||
if tmp.Search == "" {
|
if tmp.Search == "" {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] please specify an IP or a CIDR as search target", typeLookup, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] please specify an IP or a CIDR as search target", TypeLookup, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &lookup{
|
return &Lookup{
|
||||||
Type: typeLookup,
|
Type: TypeLookup,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descLookup,
|
Description: DescLookup,
|
||||||
Search: tmp.Search,
|
Search: tmp.Search,
|
||||||
SearchList: tmp.SearchList,
|
SearchList: tmp.SearchList,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type lookup struct {
|
type Lookup struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -59,19 +59,19 @@ type lookup struct {
|
|||||||
SearchList []string
|
SearchList []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lookup) GetType() string {
|
func (l *Lookup) GetType() string {
|
||||||
return l.Type
|
return l.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lookup) GetAction() lib.Action {
|
func (l *Lookup) GetAction() lib.Action {
|
||||||
return l.Action
|
return l.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lookup) GetDescription() string {
|
func (l *Lookup) GetDescription() string {
|
||||||
return l.Description
|
return l.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (l *lookup) Output(container lib.Container) error {
|
func (l *Lookup) Output(container lib.Container) error {
|
||||||
switch strings.Contains(l.Search, "/") {
|
switch strings.Contains(l.Search, "/") {
|
||||||
case true: // CIDR
|
case true: // CIDR
|
||||||
if _, err := netip.ParsePrefix(l.Search); err != nil {
|
if _, err := netip.ParsePrefix(l.Search); err != nil {
|
||||||
|
@@ -8,8 +8,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
entryNamePrivate = "private"
|
entryNamePrivate = "private"
|
||||||
typePrivate = "private"
|
TypePrivate = "private"
|
||||||
descPrivate = "Convert LAN and private network CIDR to other formats"
|
DescPrivate = "Convert LAN and private network CIDR to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
var privateCIDRs = []string{
|
var privateCIDRs = []string{
|
||||||
@@ -37,11 +37,11 @@ var privateCIDRs = []string{
|
|||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typePrivate, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypePrivate, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newPrivate(action, data)
|
return newPrivate(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typePrivate, &private{
|
lib.RegisterInputConverter(TypePrivate, &Private{
|
||||||
Description: descPrivate,
|
Description: DescPrivate,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,34 +56,34 @@ func newPrivate(action lib.Action, data json.RawMessage) (lib.InputConverter, er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &private{
|
return &Private{
|
||||||
Type: typePrivate,
|
Type: TypePrivate,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descPrivate,
|
Description: DescPrivate,
|
||||||
OnlyIPType: tmp.OnlyIPType,
|
OnlyIPType: tmp.OnlyIPType,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type private struct {
|
type Private struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *private) GetType() string {
|
func (p *Private) GetType() string {
|
||||||
return p.Type
|
return p.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *private) GetAction() lib.Action {
|
func (p *Private) GetAction() lib.Action {
|
||||||
return p.Action
|
return p.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *private) GetDescription() string {
|
func (p *Private) GetDescription() string {
|
||||||
return p.Description
|
return p.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *private) Input(container lib.Container) (lib.Container, error) {
|
func (p *Private) Input(container lib.Container) (lib.Container, error) {
|
||||||
entry, found := container.GetEntry(entryNamePrivate)
|
entry, found := container.GetEntry(entryNamePrivate)
|
||||||
if !found {
|
if !found {
|
||||||
entry = lib.NewEntry(entryNamePrivate)
|
entry = lib.NewEntry(entryNamePrivate)
|
||||||
|
@@ -11,16 +11,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeStdin = "stdin"
|
TypeStdin = "stdin"
|
||||||
descStdin = "Accept plaintext IP & CIDR from standard input, separated by newline"
|
DescStdin = "Accept plaintext IP & CIDR from standard input, separated by newline"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeStdin, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeStdin, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newStdin(action, data)
|
return newStdin(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeStdin, &stdin{
|
lib.RegisterInputConverter(TypeStdin, &Stdin{
|
||||||
Description: descStdin,
|
Description: DescStdin,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -37,19 +37,19 @@ func newStdin(action lib.Action, data json.RawMessage) (lib.InputConverter, erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmp.Name == "" {
|
if tmp.Name == "" {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] missing name", typeStdin, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] missing name", TypeStdin, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &stdin{
|
return &Stdin{
|
||||||
Type: typeStdin,
|
Type: TypeStdin,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descStdin,
|
Description: DescStdin,
|
||||||
Name: tmp.Name,
|
Name: tmp.Name,
|
||||||
OnlyIPType: tmp.OnlyIPType,
|
OnlyIPType: tmp.OnlyIPType,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type stdin struct {
|
type Stdin struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -57,19 +57,19 @@ type stdin struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdin) GetType() string {
|
func (s *Stdin) GetType() string {
|
||||||
return s.Type
|
return s.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdin) GetAction() lib.Action {
|
func (s *Stdin) GetAction() lib.Action {
|
||||||
return s.Action
|
return s.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdin) GetDescription() string {
|
func (s *Stdin) GetDescription() string {
|
||||||
return s.Description
|
return s.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdin) Input(container lib.Container) (lib.Container, error) {
|
func (s *Stdin) Input(container lib.Container) (lib.Container, error) {
|
||||||
entry := lib.NewEntry(s.Name)
|
entry := lib.NewEntry(s.Name)
|
||||||
|
|
||||||
scanner := bufio.NewScanner(os.Stdin)
|
scanner := bufio.NewScanner(os.Stdin)
|
||||||
|
@@ -12,16 +12,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeStdout = "stdout"
|
TypeStdout = "stdout"
|
||||||
descStdout = "Convert data to plaintext CIDR format and output to standard output"
|
DescStdout = "Convert data to plaintext CIDR format and output to standard output"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeStdout, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeStdout, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newStdout(action, data)
|
return newStdout(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeStdout, &stdout{
|
lib.RegisterOutputConverter(TypeStdout, &Stdout{
|
||||||
Description: descStdout,
|
Description: DescStdout,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,17 +38,17 @@ func newStdout(action lib.Action, data json.RawMessage) (lib.OutputConverter, er
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &stdout{
|
return &Stdout{
|
||||||
Type: typeStdout,
|
Type: TypeStdout,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descStdout,
|
Description: DescStdout,
|
||||||
Want: tmp.Want,
|
Want: tmp.Want,
|
||||||
Exclude: tmp.Exclude,
|
Exclude: tmp.Exclude,
|
||||||
OnlyIPType: tmp.OnlyIPType,
|
OnlyIPType: tmp.OnlyIPType,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type stdout struct {
|
type Stdout struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -57,19 +57,19 @@ type stdout struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdout) GetType() string {
|
func (s *Stdout) GetType() string {
|
||||||
return s.Type
|
return s.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdout) GetAction() lib.Action {
|
func (s *Stdout) GetAction() lib.Action {
|
||||||
return s.Action
|
return s.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdout) GetDescription() string {
|
func (s *Stdout) GetDescription() string {
|
||||||
return s.Description
|
return s.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdout) Output(container lib.Container) error {
|
func (s *Stdout) Output(container lib.Container) error {
|
||||||
for _, name := range s.filterAndSortList(container) {
|
for _, name := range s.filterAndSortList(container) {
|
||||||
entry, found := container.GetEntry(name)
|
entry, found := container.GetEntry(name)
|
||||||
if !found {
|
if !found {
|
||||||
@@ -89,7 +89,7 @@ func (s *stdout) Output(container lib.Container) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdout) filterAndSortList(container lib.Container) []string {
|
func (s *Stdout) filterAndSortList(container lib.Container) []string {
|
||||||
excludeMap := make(map[string]bool)
|
excludeMap := make(map[string]bool)
|
||||||
for _, exclude := range s.Exclude {
|
for _, exclude := range s.Exclude {
|
||||||
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
||||||
@@ -125,7 +125,7 @@ func (s *stdout) filterAndSortList(container lib.Container) []string {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *stdout) generateCIDRList(entry *lib.Entry) ([]string, error) {
|
func (s *Stdout) generateCIDRList(entry *lib.Entry) ([]string, error) {
|
||||||
var entryList []string
|
var entryList []string
|
||||||
var err error
|
var err error
|
||||||
switch s.OnlyIPType {
|
switch s.OnlyIPType {
|
||||||
|
@@ -14,16 +14,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeGeoIPdatIn = "v2rayGeoIPDat"
|
TypeGeoIPdatIn = "v2rayGeoIPDat"
|
||||||
descGeoIPdatIn = "Convert V2Ray GeoIP dat to other formats"
|
DescGeoIPdatIn = "Convert V2Ray GeoIP dat to other formats"
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterInputConfigCreator(typeGeoIPdatIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
lib.RegisterInputConfigCreator(TypeGeoIPdatIn, func(action lib.Action, data json.RawMessage) (lib.InputConverter, error) {
|
||||||
return newGeoIPDatIn(action, data)
|
return newGeoIPDatIn(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterInputConverter(typeGeoIPdatIn, &geoIPDatIn{
|
lib.RegisterInputConverter(TypeGeoIPdatIn, &GeoIPDatIn{
|
||||||
Description: descGeoIPdatIn,
|
Description: DescGeoIPdatIn,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,7 +41,7 @@ func newGeoIPDatIn(action lib.Action, data json.RawMessage) (lib.InputConverter,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if tmp.URI == "" {
|
if tmp.URI == "" {
|
||||||
return nil, fmt.Errorf("❌ [type %s | action %s] uri must be specified in config", typeGeoIPdatIn, action)
|
return nil, fmt.Errorf("❌ [type %s | action %s] uri must be specified in config", TypeGeoIPdatIn, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter want list
|
// Filter want list
|
||||||
@@ -52,17 +52,17 @@ func newGeoIPDatIn(action lib.Action, data json.RawMessage) (lib.InputConverter,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return &geoIPDatIn{
|
return &GeoIPDatIn{
|
||||||
Type: typeGeoIPdatIn,
|
Type: TypeGeoIPdatIn,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descGeoIPdatIn,
|
Description: DescGeoIPdatIn,
|
||||||
URI: tmp.URI,
|
URI: tmp.URI,
|
||||||
Want: wantList,
|
Want: wantList,
|
||||||
OnlyIPType: tmp.OnlyIPType,
|
OnlyIPType: tmp.OnlyIPType,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type geoIPDatIn struct {
|
type GeoIPDatIn struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -71,19 +71,19 @@ type geoIPDatIn struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatIn) GetType() string {
|
func (g *GeoIPDatIn) GetType() string {
|
||||||
return g.Type
|
return g.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatIn) GetAction() lib.Action {
|
func (g *GeoIPDatIn) GetAction() lib.Action {
|
||||||
return g.Action
|
return g.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatIn) GetDescription() string {
|
func (g *GeoIPDatIn) GetDescription() string {
|
||||||
return g.Description
|
return g.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatIn) Input(container lib.Container) (lib.Container, error) {
|
func (g *GeoIPDatIn) Input(container lib.Container) (lib.Container, error) {
|
||||||
entries := make(map[string]*lib.Entry)
|
entries := make(map[string]*lib.Entry)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ func (g *geoIPDatIn) Input(container lib.Container) (lib.Container, error) {
|
|||||||
return container, nil
|
return container, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatIn) walkLocalFile(path string, entries map[string]*lib.Entry) error {
|
func (g *GeoIPDatIn) walkLocalFile(path string, entries map[string]*lib.Entry) error {
|
||||||
file, err := os.Open(path)
|
file, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -142,7 +142,7 @@ func (g *geoIPDatIn) walkLocalFile(path string, entries map[string]*lib.Entry) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatIn) walkRemoteFile(url string, entries map[string]*lib.Entry) error {
|
func (g *GeoIPDatIn) walkRemoteFile(url string, entries map[string]*lib.Entry) error {
|
||||||
resp, err := http.Get(url)
|
resp, err := http.Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -160,7 +160,7 @@ func (g *geoIPDatIn) walkRemoteFile(url string, entries map[string]*lib.Entry) e
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatIn) generateEntries(reader io.Reader, entries map[string]*lib.Entry) error {
|
func (g *GeoIPDatIn) generateEntries(reader io.Reader, entries map[string]*lib.Entry) error {
|
||||||
geoipBytes, err := io.ReadAll(reader)
|
geoipBytes, err := io.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -16,8 +16,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
typeGeoIPdatOut = "v2rayGeoIPDat"
|
TypeGeoIPdatOut = "v2rayGeoIPDat"
|
||||||
descGeoIPdatOut = "Convert data to V2Ray GeoIP dat format"
|
DescGeoIPdatOut = "Convert data to V2Ray GeoIP dat format"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -26,11 +26,11 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
lib.RegisterOutputConfigCreator(typeGeoIPdatOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
lib.RegisterOutputConfigCreator(TypeGeoIPdatOut, func(action lib.Action, data json.RawMessage) (lib.OutputConverter, error) {
|
||||||
return newGeoIPDat(action, data)
|
return newGeoIPDat(action, data)
|
||||||
})
|
})
|
||||||
lib.RegisterOutputConverter(typeGeoIPdatOut, &geoIPDatOut{
|
lib.RegisterOutputConverter(TypeGeoIPdatOut, &GeoIPDatOut{
|
||||||
Description: descGeoIPdatOut,
|
Description: DescGeoIPdatOut,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,10 +58,10 @@ func newGeoIPDat(action lib.Action, data json.RawMessage) (lib.OutputConverter,
|
|||||||
tmp.OutputDir = defaultOutputDir
|
tmp.OutputDir = defaultOutputDir
|
||||||
}
|
}
|
||||||
|
|
||||||
return &geoIPDatOut{
|
return &GeoIPDatOut{
|
||||||
Type: typeGeoIPdatOut,
|
Type: TypeGeoIPdatOut,
|
||||||
Action: action,
|
Action: action,
|
||||||
Description: descGeoIPdatOut,
|
Description: DescGeoIPdatOut,
|
||||||
OutputName: tmp.OutputName,
|
OutputName: tmp.OutputName,
|
||||||
OutputDir: tmp.OutputDir,
|
OutputDir: tmp.OutputDir,
|
||||||
Want: tmp.Want,
|
Want: tmp.Want,
|
||||||
@@ -71,7 +71,7 @@ func newGeoIPDat(action lib.Action, data json.RawMessage) (lib.OutputConverter,
|
|||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type geoIPDatOut struct {
|
type GeoIPDatOut struct {
|
||||||
Type string
|
Type string
|
||||||
Action lib.Action
|
Action lib.Action
|
||||||
Description string
|
Description string
|
||||||
@@ -83,19 +83,19 @@ type geoIPDatOut struct {
|
|||||||
OnlyIPType lib.IPType
|
OnlyIPType lib.IPType
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatOut) GetType() string {
|
func (g *GeoIPDatOut) GetType() string {
|
||||||
return g.Type
|
return g.Type
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatOut) GetAction() lib.Action {
|
func (g *GeoIPDatOut) GetAction() lib.Action {
|
||||||
return g.Action
|
return g.Action
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatOut) GetDescription() string {
|
func (g *GeoIPDatOut) GetDescription() string {
|
||||||
return g.Description
|
return g.Description
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatOut) Output(container lib.Container) error {
|
func (g *GeoIPDatOut) Output(container lib.Container) error {
|
||||||
geoIPList := new(GeoIPList)
|
geoIPList := new(GeoIPList)
|
||||||
geoIPList.Entry = make([]*GeoIP, 0, 300)
|
geoIPList.Entry = make([]*GeoIP, 0, 300)
|
||||||
updated := false
|
updated := false
|
||||||
@@ -145,7 +145,7 @@ func (g *geoIPDatOut) Output(container lib.Container) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatOut) filterAndSortList(container lib.Container) []string {
|
func (g *GeoIPDatOut) filterAndSortList(container lib.Container) []string {
|
||||||
excludeMap := make(map[string]bool)
|
excludeMap := make(map[string]bool)
|
||||||
for _, exclude := range g.Exclude {
|
for _, exclude := range g.Exclude {
|
||||||
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
if exclude = strings.ToUpper(strings.TrimSpace(exclude)); exclude != "" {
|
||||||
@@ -181,7 +181,7 @@ func (g *geoIPDatOut) filterAndSortList(container lib.Container) []string {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatOut) generateGeoIP(entry *lib.Entry) (*GeoIP, error) {
|
func (g *GeoIPDatOut) generateGeoIP(entry *lib.Entry) (*GeoIP, error) {
|
||||||
var entryCidr []netip.Prefix
|
var entryCidr []netip.Prefix
|
||||||
var err error
|
var err error
|
||||||
switch g.OnlyIPType {
|
switch g.OnlyIPType {
|
||||||
@@ -215,13 +215,13 @@ func (g *geoIPDatOut) generateGeoIP(entry *lib.Entry) (*GeoIP, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort by country code to make reproducible builds
|
// Sort by country code to make reproducible builds
|
||||||
func (g *geoIPDatOut) sort(list *GeoIPList) {
|
func (g *GeoIPDatOut) sort(list *GeoIPList) {
|
||||||
sort.SliceStable(list.Entry, func(i, j int) bool {
|
sort.SliceStable(list.Entry, func(i, j int) bool {
|
||||||
return list.Entry[i].CountryCode < list.Entry[j].CountryCode
|
return list.Entry[i].CountryCode < list.Entry[j].CountryCode
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *geoIPDatOut) writeFile(filename string, geoIPBytes []byte) error {
|
func (g *GeoIPDatOut) writeFile(filename string, geoIPBytes []byte) error {
|
||||||
if err := os.MkdirAll(g.OutputDir, 0755); err != nil {
|
if err := os.MkdirAll(g.OutputDir, 0755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@@ -656,6 +656,22 @@ endef
|
|||||||
$(eval $(call KernelPackage,usb-serial-ch341))
|
$(eval $(call KernelPackage,usb-serial-ch341))
|
||||||
|
|
||||||
|
|
||||||
|
define KernelPackage/usb-serial-ch348
|
||||||
|
TITLE:=Support for CH348 devices
|
||||||
|
KCONFIG:=CONFIG_USB_SERIAL_CH348
|
||||||
|
FILES:=$(LINUX_DIR)/drivers/usb/serial/ch348.ko
|
||||||
|
AUTOLOAD:=$(call AutoProbe,ch348)
|
||||||
|
DEPENDS:=@(LINUX_6_1||LINUX_6_6)
|
||||||
|
$(call AddDepends/usb-serial)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define KernelPackage/usb-serial-ch348/description
|
||||||
|
Kernel support for Winchiphead CH348 USB-to-8x-Serial converters
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call KernelPackage,usb-serial-ch348))
|
||||||
|
|
||||||
|
|
||||||
define KernelPackage/usb-serial-edgeport
|
define KernelPackage/usb-serial-edgeport
|
||||||
TITLE:=Support for Digi Edgeport devices
|
TITLE:=Support for Digi Edgeport devices
|
||||||
KCONFIG:=CONFIG_USB_SERIAL_EDGEPORT
|
KCONFIG:=CONFIG_USB_SERIAL_EDGEPORT
|
||||||
|
@@ -0,0 +1,783 @@
|
|||||||
|
From df1357358eec062241bddd2995e7ef0ce86cf45a Mon Sep 17 00:00:00 2001
|
||||||
|
X-Patchwork-Submitter: Corentin Labbe <clabbe@baylibre.com>
|
||||||
|
X-Patchwork-Id: 13656881
|
||||||
|
Message-Id: <20240507131522.3546113-2-clabbe@baylibre.com>
|
||||||
|
X-Mailer: git-send-email 2.25.1
|
||||||
|
In-Reply-To: <20240507131522.3546113-1-clabbe@baylibre.com>
|
||||||
|
References: <20240507131522.3546113-1-clabbe@baylibre.com>
|
||||||
|
Precedence: bulk
|
||||||
|
X-Mailing-List: linux-usb@vger.kernel.org
|
||||||
|
List-Id: <linux-usb.vger.kernel.org>
|
||||||
|
From: Corentin Labbe <clabbe@baylibre.com>
|
||||||
|
Date: Tue, 7 May 2024 13:15:22 +0000
|
||||||
|
Subject: [PATCH v7] usb: serial: add support for CH348
|
||||||
|
|
||||||
|
The CH348 is an USB octo port serial adapter.
|
||||||
|
The device multiplexes all 8 ports in the same pair of Bulk endpoints.
|
||||||
|
Since there is no public datasheet, unfortunately it remains some magic values
|
||||||
|
|
||||||
|
Signed-off-by: Corentin Labbe <clabbe@baylibre.com>
|
||||||
|
Tested-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||||
|
---
|
||||||
|
drivers/usb/serial/Kconfig | 9 +
|
||||||
|
drivers/usb/serial/Makefile | 1 +
|
||||||
|
drivers/usb/serial/ch348.c | 725 ++++++++++++++++++++++++++++++++++++
|
||||||
|
3 files changed, 735 insertions(+)
|
||||||
|
create mode 100644 drivers/usb/serial/ch348.c
|
||||||
|
|
||||||
|
--- a/drivers/usb/serial/Kconfig
|
||||||
|
+++ b/drivers/usb/serial/Kconfig
|
||||||
|
@@ -112,6 +112,15 @@ config USB_SERIAL_CH341
|
||||||
|
To compile this driver as a module, choose M here: the
|
||||||
|
module will be called ch341.
|
||||||
|
|
||||||
|
+config USB_SERIAL_CH348
|
||||||
|
+ tristate "USB Winchiphead CH348 Octo Port Serial Driver"
|
||||||
|
+ help
|
||||||
|
+ Say Y here if you want to use a Winchiphead CH348 octo port
|
||||||
|
+ USB to serial adapter.
|
||||||
|
+
|
||||||
|
+ To compile this driver as a module, choose M here: the
|
||||||
|
+ module will be called ch348.
|
||||||
|
+
|
||||||
|
config USB_SERIAL_WHITEHEAT
|
||||||
|
tristate "USB ConnectTech WhiteHEAT Serial Driver"
|
||||||
|
select USB_EZUSB_FX2
|
||||||
|
--- a/drivers/usb/serial/Makefile
|
||||||
|
+++ b/drivers/usb/serial/Makefile
|
||||||
|
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_SERIAL_AIRCABLE) += ai
|
||||||
|
obj-$(CONFIG_USB_SERIAL_ARK3116) += ark3116.o
|
||||||
|
obj-$(CONFIG_USB_SERIAL_BELKIN) += belkin_sa.o
|
||||||
|
obj-$(CONFIG_USB_SERIAL_CH341) += ch341.o
|
||||||
|
+obj-$(CONFIG_USB_SERIAL_CH348) += ch348.o
|
||||||
|
obj-$(CONFIG_USB_SERIAL_CP210X) += cp210x.o
|
||||||
|
obj-$(CONFIG_USB_SERIAL_CYBERJACK) += cyberjack.o
|
||||||
|
obj-$(CONFIG_USB_SERIAL_CYPRESS_M8) += cypress_m8.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/usb/serial/ch348.c
|
||||||
|
@@ -0,0 +1,725 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+/*
|
||||||
|
+ * USB serial driver for USB to Octal UARTs chip ch348.
|
||||||
|
+ *
|
||||||
|
+ * Copyright (C) 2022 Corentin Labbe <clabbe@baylibre.com>
|
||||||
|
+ * With the help of Neil Armstrong <neil.armstrong@linaro.org>
|
||||||
|
+ * and the help of Martin Blumenstingl <martin.blumenstingl@googlemail.com>
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <linux/completion.h>
|
||||||
|
+#include <linux/errno.h>
|
||||||
|
+#include <linux/init.h>
|
||||||
|
+#include <linux/kernel.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/mutex.h>
|
||||||
|
+#include <linux/overflow.h>
|
||||||
|
+#include <linux/serial.h>
|
||||||
|
+#include <linux/slab.h>
|
||||||
|
+#include <linux/tty.h>
|
||||||
|
+#include <linux/tty_driver.h>
|
||||||
|
+#include <linux/tty_flip.h>
|
||||||
|
+#include <linux/usb.h>
|
||||||
|
+#include <linux/usb/serial.h>
|
||||||
|
+
|
||||||
|
+#define CH348_CMD_TIMEOUT 2000
|
||||||
|
+
|
||||||
|
+#define CH348_CTO_D 0x01
|
||||||
|
+#define CH348_CTO_R 0x02
|
||||||
|
+
|
||||||
|
+#define CH348_CTI_C 0x10
|
||||||
|
+#define CH348_CTI_DSR 0x20
|
||||||
|
+#define CH348_CTI_R 0x40
|
||||||
|
+#define CH348_CTI_DCD 0x80
|
||||||
|
+
|
||||||
|
+#define CH348_LO 0x02
|
||||||
|
+#define CH348_LP 0x04
|
||||||
|
+#define CH348_LF 0x08
|
||||||
|
+#define CH348_LB 0x10
|
||||||
|
+
|
||||||
|
+#define CMD_W_R 0xC0
|
||||||
|
+#define CMD_W_BR 0x80
|
||||||
|
+
|
||||||
|
+#define CMD_WB_E 0x90
|
||||||
|
+#define CMD_RB_E 0xC0
|
||||||
|
+
|
||||||
|
+#define M_NOR 0x00
|
||||||
|
+#define M_HF 0x03
|
||||||
|
+
|
||||||
|
+#define R_MOD 0x97
|
||||||
|
+#define R_IO_D 0x98
|
||||||
|
+#define R_IO_O 0x99
|
||||||
|
+#define R_IO_I 0x9b
|
||||||
|
+#define R_TM_O 0x9c
|
||||||
|
+#define R_INIT 0xa1
|
||||||
|
+
|
||||||
|
+#define R_C1 0x01
|
||||||
|
+#define R_C2 0x02
|
||||||
|
+#define R_C4 0x04
|
||||||
|
+#define R_C5 0x06
|
||||||
|
+
|
||||||
|
+#define R_II_B1 0x06
|
||||||
|
+#define R_II_B2 0x02
|
||||||
|
+#define R_II_B3 0x00
|
||||||
|
+
|
||||||
|
+#define CMD_VER 0x96
|
||||||
|
+
|
||||||
|
+#define CH348_RX_PORT_CHUNK_LENGTH 32
|
||||||
|
+#define CH348_RX_PORT_MAX_LENGTH 30
|
||||||
|
+
|
||||||
|
+struct ch348_rxbuf {
|
||||||
|
+ u8 port;
|
||||||
|
+ u8 length;
|
||||||
|
+ u8 data[CH348_RX_PORT_MAX_LENGTH];
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
+struct ch348_txbuf {
|
||||||
|
+ u8 port;
|
||||||
|
+ __le16 length;
|
||||||
|
+ u8 data[];
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
+#define CH348_TX_HDRSIZE offsetof(struct ch348_txbuf, data)
|
||||||
|
+
|
||||||
|
+struct ch348_initbuf {
|
||||||
|
+ u8 cmd;
|
||||||
|
+ u8 reg;
|
||||||
|
+ u8 port;
|
||||||
|
+ __be32 baudrate;
|
||||||
|
+ u8 format;
|
||||||
|
+ u8 paritytype;
|
||||||
|
+ u8 databits;
|
||||||
|
+ u8 rate;
|
||||||
|
+ u8 unknown;
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
+#define CH348_MAXPORT 8
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * The CH348 multiplexes rx & tx into a pair of Bulk USB endpoints for
|
||||||
|
+ * the 8 serial ports, and another pair of Bulk USB endpoints to
|
||||||
|
+ * set port settings and receive port status events.
|
||||||
|
+ *
|
||||||
|
+ * The USB serial cores ties every Bulk endpoints pairs to each ports,
|
||||||
|
+ * but in our case it will set port 0 with the rx/tx endpoints
|
||||||
|
+ * and port 1 with the setup/status endpoints.
|
||||||
|
+ *
|
||||||
|
+ * To still take advantage of the generic code, we (re-)initialize
|
||||||
|
+ * the USB serial port structure with the correct USB endpoint
|
||||||
|
+ * for read and write, and write proper process_read_urb()
|
||||||
|
+ * and prepare_write_buffer() to correctly (de-)multiplex data.
|
||||||
|
+ * Also we use a custom write() implementation to wait until the buffer
|
||||||
|
+ * has been fully transmitted to prevent TX buffer overruns.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * struct ch348_port - per-port information
|
||||||
|
+ * @uartmode: UART port current mode
|
||||||
|
+ * @write_completion: completion event when the TX buffer has been written out
|
||||||
|
+ */
|
||||||
|
+struct ch348_port {
|
||||||
|
+ u8 uartmode;
|
||||||
|
+ struct completion write_completion;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * struct ch348 - main container for all this driver information
|
||||||
|
+ * @udev: pointer to the CH348 USB device
|
||||||
|
+ * @ports: List of per-port information
|
||||||
|
+ * @serial: pointer to the serial structure
|
||||||
|
+ * @write_lock: protect against concurrent writes so we don't lose data
|
||||||
|
+ * @cmd_ep: endpoint number for configure operations
|
||||||
|
+ * @status_urb: URB for status
|
||||||
|
+ * @status_buffer: buffer used by status_urb
|
||||||
|
+ */
|
||||||
|
+struct ch348 {
|
||||||
|
+ struct usb_device *udev;
|
||||||
|
+ struct ch348_port ports[CH348_MAXPORT];
|
||||||
|
+ struct usb_serial *serial;
|
||||||
|
+
|
||||||
|
+ struct mutex write_lock;
|
||||||
|
+
|
||||||
|
+ int cmd_ep;
|
||||||
|
+
|
||||||
|
+ struct urb *status_urb;
|
||||||
|
+ u8 status_buffer[];
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+struct ch348_magic {
|
||||||
|
+ u8 action;
|
||||||
|
+ u8 reg;
|
||||||
|
+ u8 control;
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
+struct ch348_status_entry {
|
||||||
|
+ u8 portnum:4;
|
||||||
|
+ u8 unused:4;
|
||||||
|
+ u8 reg_iir;
|
||||||
|
+ union {
|
||||||
|
+ u8 lsr_signal;
|
||||||
|
+ u8 modem_signal;
|
||||||
|
+ u8 init_data[10];
|
||||||
|
+ };
|
||||||
|
+} __packed;
|
||||||
|
+
|
||||||
|
+static void ch348_process_status_urb(struct urb *urb)
|
||||||
|
+{
|
||||||
|
+ struct ch348_status_entry *status_entry;
|
||||||
|
+ struct ch348 *ch348 = urb->context;
|
||||||
|
+ int ret, status = urb->status;
|
||||||
|
+ struct usb_serial_port *port;
|
||||||
|
+ unsigned int i, status_len;
|
||||||
|
+
|
||||||
|
+ switch (status) {
|
||||||
|
+ case 0:
|
||||||
|
+ /* success */
|
||||||
|
+ break;
|
||||||
|
+ case -ECONNRESET:
|
||||||
|
+ case -ENOENT:
|
||||||
|
+ case -ESHUTDOWN:
|
||||||
|
+ /* this urb is terminated, clean up */
|
||||||
|
+ dev_dbg(&urb->dev->dev, "%s - urb shutting down with status: %d\n",
|
||||||
|
+ __func__, status);
|
||||||
|
+ return;
|
||||||
|
+ default:
|
||||||
|
+ dev_err(&urb->dev->dev, "%s - nonzero urb status received: %d\n",
|
||||||
|
+ __func__, status);
|
||||||
|
+ goto exit;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (urb->actual_length < 3) {
|
||||||
|
+ dev_warn(&ch348->udev->dev,
|
||||||
|
+ "Received too short status buffer with %u bytes\n",
|
||||||
|
+ urb->actual_length);
|
||||||
|
+ goto exit;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < urb->actual_length;) {
|
||||||
|
+ status_entry = urb->transfer_buffer + i;
|
||||||
|
+
|
||||||
|
+ if (status_entry->portnum >= CH348_MAXPORT) {
|
||||||
|
+ dev_warn(&ch348->udev->dev,
|
||||||
|
+ "Invalid port %d in status entry\n",
|
||||||
|
+ status_entry->portnum);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ port = ch348->serial->port[status_entry->portnum];
|
||||||
|
+ status_len = 3;
|
||||||
|
+
|
||||||
|
+ if (!status_entry->reg_iir) {
|
||||||
|
+ dev_dbg(&port->dev, "Ignoring status with zero reg_iir\n");
|
||||||
|
+ } else if (status_entry->reg_iir == R_INIT) {
|
||||||
|
+ status_len = 12;
|
||||||
|
+ } else if ((status_entry->reg_iir & 0x0f) == R_II_B1) {
|
||||||
|
+ if (status_entry->lsr_signal & CH348_LO)
|
||||||
|
+ port->icount.overrun++;
|
||||||
|
+ if (status_entry->lsr_signal & CH348_LP)
|
||||||
|
+ port->icount.parity++;
|
||||||
|
+ if (status_entry->lsr_signal & CH348_LF)
|
||||||
|
+ port->icount.frame++;
|
||||||
|
+ if (status_entry->lsr_signal & CH348_LF)
|
||||||
|
+ port->icount.brk++;
|
||||||
|
+ } else if ((status_entry->reg_iir & 0x0f) == R_II_B2) {
|
||||||
|
+ complete_all(&ch348->ports[status_entry->portnum].write_completion);
|
||||||
|
+ } else {
|
||||||
|
+ dev_warn(&port->dev,
|
||||||
|
+ "Unsupported status with reg_iir 0x%02x\n",
|
||||||
|
+ status_entry->reg_iir);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ usb_serial_debug_data(&port->dev, __func__, status_len,
|
||||||
|
+ urb->transfer_buffer + i);
|
||||||
|
+
|
||||||
|
+ i += status_len;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+exit:
|
||||||
|
+ ret = usb_submit_urb(urb, GFP_ATOMIC);
|
||||||
|
+ if (ret)
|
||||||
|
+ dev_err(&urb->dev->dev, "%s - usb_submit_urb failed; %d\n",
|
||||||
|
+ __func__, ret);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/*
|
||||||
|
+ * Some values came from vendor tree, and we have no meaning for them, this
|
||||||
|
+ * function simply use them.
|
||||||
|
+ */
|
||||||
|
+static int ch348_do_magic(struct ch348 *ch348, int portnum, u8 action, u8 reg, u8 control)
|
||||||
|
+{
|
||||||
|
+ struct ch348_magic *buffer;
|
||||||
|
+ int ret, len;
|
||||||
|
+
|
||||||
|
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||||
|
+ if (!buffer)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ if (portnum < 4)
|
||||||
|
+ reg += 0x10 * portnum;
|
||||||
|
+ else
|
||||||
|
+ reg += 0x10 * (portnum - 4) + 0x08;
|
||||||
|
+
|
||||||
|
+ buffer->action = action;
|
||||||
|
+ buffer->reg = reg;
|
||||||
|
+ buffer->control = control;
|
||||||
|
+
|
||||||
|
+ ret = usb_bulk_msg(ch348->udev, ch348->cmd_ep, buffer, 3, &len,
|
||||||
|
+ CH348_CMD_TIMEOUT);
|
||||||
|
+ if (ret)
|
||||||
|
+ dev_err(&ch348->udev->dev, "Failed to write magic err=%d\n", ret);
|
||||||
|
+
|
||||||
|
+ kfree(buffer);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_configure(struct ch348 *ch348, int portnum)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = ch348_do_magic(ch348, portnum, CMD_W_R, R_C2, 0x87);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return ch348_do_magic(ch348, portnum, CMD_W_R, R_C4, 0x08);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ch348_process_read_urb(struct urb *urb)
|
||||||
|
+{
|
||||||
|
+ struct usb_serial_port *port = urb->context;
|
||||||
|
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||||
|
+ unsigned int portnum, usblen, i;
|
||||||
|
+ struct ch348_rxbuf *rxb;
|
||||||
|
+
|
||||||
|
+ if (urb->actual_length < 2) {
|
||||||
|
+ dev_dbg(&ch348->udev->dev, "Empty rx buffer\n");
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < urb->actual_length; i += CH348_RX_PORT_CHUNK_LENGTH) {
|
||||||
|
+ rxb = urb->transfer_buffer + i;
|
||||||
|
+ portnum = rxb->port;
|
||||||
|
+ if (portnum >= CH348_MAXPORT) {
|
||||||
|
+ dev_dbg(&ch348->udev->dev, "Invalid port %d\n", portnum);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ port = ch348->serial->port[portnum];
|
||||||
|
+
|
||||||
|
+ usblen = rxb->length;
|
||||||
|
+ if (usblen > CH348_RX_PORT_MAX_LENGTH) {
|
||||||
|
+ dev_dbg(&port->dev, "Invalid length %d for port %d\n",
|
||||||
|
+ usblen, portnum);
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ tty_insert_flip_string(&port->port, rxb->data, usblen);
|
||||||
|
+ tty_flip_buffer_push(&port->port);
|
||||||
|
+ port->icount.rx += usblen;
|
||||||
|
+ usb_serial_debug_data(&port->dev, __func__, usblen, rxb->data);
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_prepare_write_buffer(struct usb_serial_port *port, void *dest, size_t size)
|
||||||
|
+{
|
||||||
|
+ struct ch348_txbuf *rxt = dest;
|
||||||
|
+ int count;
|
||||||
|
+
|
||||||
|
+ count = kfifo_out_locked(&port->write_fifo, rxt->data,
|
||||||
|
+ size - CH348_TX_HDRSIZE, &port->lock);
|
||||||
|
+
|
||||||
|
+ rxt->port = port->port_number;
|
||||||
|
+ rxt->length = cpu_to_le16(count);
|
||||||
|
+
|
||||||
|
+ return count + CH348_TX_HDRSIZE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_write(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
|
+ const unsigned char *buf, int count)
|
||||||
|
+{
|
||||||
|
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||||
|
+ struct ch348_port *ch348_port = &ch348->ports[port->port_number];
|
||||||
|
+ int ret, max_tx_size;
|
||||||
|
+
|
||||||
|
+ if (tty_get_baud_rate(tty) < 9600 && count >= 128)
|
||||||
|
+ /*
|
||||||
|
+ * Writing larger buffers can take longer than the hardware
|
||||||
|
+ * allows before discarding the write buffer. Limit the
|
||||||
|
+ * transfer size in such cases.
|
||||||
|
+ * These values have been found by empirical testing.
|
||||||
|
+ */
|
||||||
|
+ max_tx_size = 128;
|
||||||
|
+ else
|
||||||
|
+ /*
|
||||||
|
+ * Only ingest as many bytes as we can transfer with one URB at
|
||||||
|
+ * a time. Once an URB has been written we need to wait for the
|
||||||
|
+ * R_II_B2 status event before we are allowed to send more data.
|
||||||
|
+ * If we ingest more data then usb_serial_generic_write() will
|
||||||
|
+ * internally try to process as much data as possible with any
|
||||||
|
+ * number of URBs without giving us the chance to wait in
|
||||||
|
+ * between transfers.
|
||||||
|
+ */
|
||||||
|
+ max_tx_size = port->bulk_out_size - CH348_TX_HDRSIZE;
|
||||||
|
+
|
||||||
|
+ reinit_completion(&ch348_port->write_completion);
|
||||||
|
+
|
||||||
|
+ mutex_lock(&ch348->write_lock);
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * For any (remaining) bytes that we did not transfer TTY core will
|
||||||
|
+ * call us again, with the buffer and count adjusted to the remaining
|
||||||
|
+ * data.
|
||||||
|
+ */
|
||||||
|
+ ret = usb_serial_generic_write(tty, port, buf, min(count, max_tx_size));
|
||||||
|
+
|
||||||
|
+ mutex_unlock(&ch348->write_lock);
|
||||||
|
+
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (!wait_for_completion_interruptible_timeout(&ch348_port->write_completion,
|
||||||
|
+ msecs_to_jiffies(CH348_CMD_TIMEOUT))) {
|
||||||
|
+ dev_err_console(port, "Failed to wait for TX buffer flush\n");
|
||||||
|
+ return -ETIMEDOUT;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_set_uartmode(struct ch348 *ch348, int portnum, u8 mode)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (ch348->ports[portnum].uartmode == M_NOR && mode == M_HF) {
|
||||||
|
+ ret = ch348_do_magic(ch348, portnum, CMD_W_BR, R_C4, 0x51);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ ch348->ports[portnum].uartmode = M_HF;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (ch348->ports[portnum].uartmode == M_HF && mode == M_NOR) {
|
||||||
|
+ ret = ch348_do_magic(ch348, portnum, CMD_W_BR, R_C4, 0x50);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+ ch348->ports[portnum].uartmode = M_NOR;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ch348_set_termios(struct tty_struct *tty, struct usb_serial_port *port,
|
||||||
|
+ const struct ktermios *termios_old)
|
||||||
|
+{
|
||||||
|
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||||
|
+ struct ktermios *termios = &tty->termios;
|
||||||
|
+ int ret, portnum = port->port_number;
|
||||||
|
+ struct ch348_initbuf *buffer;
|
||||||
|
+ speed_t baudrate;
|
||||||
|
+ u8 format;
|
||||||
|
+
|
||||||
|
+ if (termios_old && !tty_termios_hw_change(&tty->termios, termios_old))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ buffer = kzalloc(sizeof(*buffer), GFP_KERNEL);
|
||||||
|
+ if (!buffer) {
|
||||||
|
+ if (termios_old)
|
||||||
|
+ tty->termios = *termios_old;
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ /*
|
||||||
|
+ * The datasheet states that only baud rates in range of 1200..6000000
|
||||||
|
+ * are supported. Tests however show that even baud rates as low as 50
|
||||||
|
+ * and as high as 12000000 are working in practice.
|
||||||
|
+ */
|
||||||
|
+ baudrate = clamp(tty_get_baud_rate(tty), 50, 12000000);
|
||||||
|
+
|
||||||
|
+ format = termios->c_cflag & CSTOPB ? 2 : 1;
|
||||||
|
+
|
||||||
|
+ buffer->paritytype = 0;
|
||||||
|
+ if (termios->c_cflag & PARENB) {
|
||||||
|
+ if (termios->c_cflag & PARODD)
|
||||||
|
+ buffer->paritytype += 1;
|
||||||
|
+ else
|
||||||
|
+ buffer->paritytype += 2;
|
||||||
|
+ if (termios->c_cflag & CMSPAR)
|
||||||
|
+ buffer->paritytype += 2;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ switch (C_CSIZE(tty)) {
|
||||||
|
+ case CS5:
|
||||||
|
+ buffer->databits = 5;
|
||||||
|
+ break;
|
||||||
|
+ case CS6:
|
||||||
|
+ buffer->databits = 6;
|
||||||
|
+ break;
|
||||||
|
+ case CS7:
|
||||||
|
+ buffer->databits = 7;
|
||||||
|
+ break;
|
||||||
|
+ case CS8:
|
||||||
|
+ default:
|
||||||
|
+ buffer->databits = 8;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+ buffer->cmd = CMD_WB_E | (portnum & 0x0F);
|
||||||
|
+ buffer->reg = R_INIT;
|
||||||
|
+ buffer->port = portnum;
|
||||||
|
+ buffer->baudrate = cpu_to_be32(baudrate);
|
||||||
|
+
|
||||||
|
+ if (format == 2)
|
||||||
|
+ buffer->format = 0x02;
|
||||||
|
+ else if (format == 1)
|
||||||
|
+ buffer->format = 0x00;
|
||||||
|
+
|
||||||
|
+ buffer->rate = max_t(speed_t, 5, (10000 * 15 / baudrate) + 1);
|
||||||
|
+
|
||||||
|
+ ret = usb_bulk_msg(ch348->udev, ch348->cmd_ep, buffer,
|
||||||
|
+ sizeof(*buffer), NULL, CH348_CMD_TIMEOUT);
|
||||||
|
+ if (ret < 0) {
|
||||||
|
+ dev_err(&ch348->udev->dev, "Failed to change line settings: err=%d\n",
|
||||||
|
+ ret);
|
||||||
|
+ goto out;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = ch348_do_magic(ch348, portnum, CMD_W_R, R_C1, 0x0F);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ goto out;
|
||||||
|
+
|
||||||
|
+ if (C_CRTSCTS(tty))
|
||||||
|
+ ret = ch348_set_uartmode(ch348, portnum, M_HF);
|
||||||
|
+ else
|
||||||
|
+ ret = ch348_set_uartmode(ch348, portnum, M_NOR);
|
||||||
|
+
|
||||||
|
+out:
|
||||||
|
+ kfree(buffer);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_open(struct tty_struct *tty, struct usb_serial_port *port)
|
||||||
|
+{
|
||||||
|
+ struct ch348 *ch348 = usb_get_serial_data(port->serial);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (tty)
|
||||||
|
+ ch348_set_termios(tty, port, NULL);
|
||||||
|
+
|
||||||
|
+ ret = ch348_configure(ch348, port->port_number);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&ch348->udev->dev, "Fail to configure err=%d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return usb_serial_generic_open(tty, port);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_attach(struct usb_serial *serial)
|
||||||
|
+{
|
||||||
|
+ struct usb_endpoint_descriptor *epcmd, *epstatus;
|
||||||
|
+ struct usb_serial_port *port0 = serial->port[1];
|
||||||
|
+ struct usb_device *usb_dev = serial->dev;
|
||||||
|
+ int status_buffer_size, i, ret;
|
||||||
|
+ struct usb_interface *intf;
|
||||||
|
+ struct ch348 *ch348;
|
||||||
|
+
|
||||||
|
+ intf = usb_ifnum_to_if(usb_dev, 0);
|
||||||
|
+ epstatus = &intf->cur_altsetting->endpoint[2].desc;
|
||||||
|
+ epcmd = &intf->cur_altsetting->endpoint[3].desc;
|
||||||
|
+
|
||||||
|
+ status_buffer_size = usb_endpoint_maxp(epstatus);
|
||||||
|
+
|
||||||
|
+ ch348 = kzalloc(struct_size(ch348, status_buffer, status_buffer_size),
|
||||||
|
+ GFP_KERNEL);
|
||||||
|
+ if (!ch348)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ usb_set_serial_data(serial, ch348);
|
||||||
|
+
|
||||||
|
+ ch348->udev = serial->dev;
|
||||||
|
+ ch348->serial = serial;
|
||||||
|
+ mutex_init(&ch348->write_lock);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < CH348_MAXPORT; i++)
|
||||||
|
+ init_completion(&ch348->ports[i].write_completion);
|
||||||
|
+
|
||||||
|
+ ch348->status_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
|
+ if (!ch348->status_urb) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto err_free_ch348;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ usb_fill_bulk_urb(ch348->status_urb, ch348->udev,
|
||||||
|
+ usb_rcvbulkpipe(ch348->udev, epstatus->bEndpointAddress),
|
||||||
|
+ ch348->status_buffer, status_buffer_size,
|
||||||
|
+ ch348_process_status_urb, ch348);
|
||||||
|
+
|
||||||
|
+ ret = usb_submit_urb(ch348->status_urb, GFP_KERNEL);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&ch348->udev->dev,
|
||||||
|
+ "%s - failed to submit status/interrupt urb %i\n",
|
||||||
|
+ __func__, ret);
|
||||||
|
+ goto err_free_status_urb;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = usb_serial_generic_submit_read_urbs(port0, GFP_KERNEL);
|
||||||
|
+ if (ret)
|
||||||
|
+ goto err_kill_status_urb;
|
||||||
|
+
|
||||||
|
+ ch348->cmd_ep = usb_sndbulkpipe(usb_dev, epcmd->bEndpointAddress);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+err_kill_status_urb:
|
||||||
|
+ usb_kill_urb(ch348->status_urb);
|
||||||
|
+err_free_status_urb:
|
||||||
|
+ usb_free_urb(ch348->status_urb);
|
||||||
|
+err_free_ch348:
|
||||||
|
+ kfree(ch348);
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ch348_release(struct usb_serial *serial)
|
||||||
|
+{
|
||||||
|
+ struct ch348 *ch348 = usb_get_serial_data(serial);
|
||||||
|
+
|
||||||
|
+ usb_kill_urb(ch348->status_urb);
|
||||||
|
+ usb_free_urb(ch348->status_urb);
|
||||||
|
+
|
||||||
|
+ kfree(ch348);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void ch348_print_version(struct usb_serial *serial)
|
||||||
|
+{
|
||||||
|
+ u8 *version_buf;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ version_buf = kzalloc(4, GFP_KERNEL);
|
||||||
|
+ if (!version_buf)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ ret = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0),
|
||||||
|
+ CMD_VER,
|
||||||
|
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE | USB_DIR_IN,
|
||||||
|
+ 0, 0, version_buf, 4, CH348_CMD_TIMEOUT);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ dev_dbg(&serial->dev->dev, "Failed to read CMD_VER: %d\n", ret);
|
||||||
|
+ else
|
||||||
|
+ dev_info(&serial->dev->dev, "Found WCH CH348%s\n",
|
||||||
|
+ (version_buf[1] & 0x80) ? "Q" : "L");
|
||||||
|
+
|
||||||
|
+ kfree(version_buf);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_probe(struct usb_serial *serial, const struct usb_device_id *id)
|
||||||
|
+{
|
||||||
|
+ struct usb_endpoint_descriptor *epread, *epwrite, *epstatus, *epcmd;
|
||||||
|
+ struct usb_device *usb_dev = serial->dev;
|
||||||
|
+ struct usb_interface *intf;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ intf = usb_ifnum_to_if(usb_dev, 0);
|
||||||
|
+
|
||||||
|
+ ret = usb_find_common_endpoints(intf->cur_altsetting, &epread, &epwrite,
|
||||||
|
+ NULL, NULL);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&serial->dev->dev, "Failed to find basic endpoints ret=%d\n", ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ epstatus = &intf->cur_altsetting->endpoint[2].desc;
|
||||||
|
+ if (!usb_endpoint_is_bulk_in(epstatus)) {
|
||||||
|
+ dev_err(&serial->dev->dev, "Missing second bulk in (STATUS/INT)\n");
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ epcmd = &intf->cur_altsetting->endpoint[3].desc;
|
||||||
|
+ if (!usb_endpoint_is_bulk_out(epcmd)) {
|
||||||
|
+ dev_err(&serial->dev->dev, "Missing second bulk out (CMD)\n");
|
||||||
|
+ return -ENODEV;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ch348_print_version(serial);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_calc_num_ports(struct usb_serial *serial,
|
||||||
|
+ struct usb_serial_endpoints *epds)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 1; i < CH348_MAXPORT; ++i) {
|
||||||
|
+ epds->bulk_out[i] = epds->bulk_out[0];
|
||||||
|
+ epds->bulk_in[i] = epds->bulk_in[0];
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ epds->num_bulk_out = CH348_MAXPORT;
|
||||||
|
+ epds->num_bulk_in = CH348_MAXPORT;
|
||||||
|
+
|
||||||
|
+ return CH348_MAXPORT;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_suspend(struct usb_serial *serial, pm_message_t message)
|
||||||
|
+{
|
||||||
|
+ struct ch348 *ch348 = usb_get_serial_data(serial);
|
||||||
|
+
|
||||||
|
+ usb_kill_urb(ch348->status_urb);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int ch348_resume(struct usb_serial *serial)
|
||||||
|
+{
|
||||||
|
+ struct ch348 *ch348 = usb_get_serial_data(serial);
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = usb_submit_urb(ch348->status_urb, GFP_KERNEL);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(&ch348->udev->dev,
|
||||||
|
+ "%s - failed to submit status/interrupt urb %i\n",
|
||||||
|
+ __func__, ret);
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = usb_serial_generic_resume(serial);
|
||||||
|
+ if (ret)
|
||||||
|
+ usb_kill_urb(ch348->status_urb);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const struct usb_device_id ch348_ids[] = {
|
||||||
|
+ { USB_DEVICE(0x1a86, 0x55d9), },
|
||||||
|
+ { /* sentinel */ }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+MODULE_DEVICE_TABLE(usb, ch348_ids);
|
||||||
|
+
|
||||||
|
+static struct usb_serial_driver ch348_device = {
|
||||||
|
+ .driver = {
|
||||||
|
+ .owner = THIS_MODULE,
|
||||||
|
+ .name = "ch348",
|
||||||
|
+ },
|
||||||
|
+ .id_table = ch348_ids,
|
||||||
|
+ .num_ports = CH348_MAXPORT,
|
||||||
|
+ .num_bulk_in = 1,
|
||||||
|
+ .num_bulk_out = 1,
|
||||||
|
+ .open = ch348_open,
|
||||||
|
+ .set_termios = ch348_set_termios,
|
||||||
|
+ .process_read_urb = ch348_process_read_urb,
|
||||||
|
+ .prepare_write_buffer = ch348_prepare_write_buffer,
|
||||||
|
+ .write = ch348_write,
|
||||||
|
+ .probe = ch348_probe,
|
||||||
|
+ .calc_num_ports = ch348_calc_num_ports,
|
||||||
|
+ .attach = ch348_attach,
|
||||||
|
+ .release = ch348_release,
|
||||||
|
+ .suspend = ch348_suspend,
|
||||||
|
+ .resume = ch348_resume,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static struct usb_serial_driver * const serial_drivers[] = {
|
||||||
|
+ &ch348_device, NULL
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+module_usb_serial_driver(serial_drivers, ch348_ids);
|
||||||
|
+
|
||||||
|
+MODULE_AUTHOR("Corentin Labbe <clabbe@baylibre.com>");
|
||||||
|
+MODULE_DESCRIPTION("USB CH348 Octo port serial converter driver");
|
||||||
|
+MODULE_LICENSE("GPL");
|
@@ -1559,6 +1559,23 @@
|
|||||||
compatible = "ethernet-phy-ieee802.3-c45";
|
compatible = "ethernet-phy-ieee802.3-c45";
|
||||||
reg = <15>;
|
reg = <15>;
|
||||||
phy-mode = "internal";
|
phy-mode = "internal";
|
||||||
|
|
||||||
|
leds {
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <0>;
|
||||||
|
|
||||||
|
i2p5gbe_led0: i2p5gbe-led0@0 {
|
||||||
|
reg = <0>;
|
||||||
|
function = LED_FUNCTION_LAN;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
|
||||||
|
i2p5gbe_led1: i2p5gbe-led1@1 {
|
||||||
|
reg = <1>;
|
||||||
|
function = LED_FUNCTION_LAN;
|
||||||
|
status = "disabled";
|
||||||
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@@ -1,321 +0,0 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0+
|
|
||||||
#include <linux/bitfield.h>
|
|
||||||
#include <linux/firmware.h>
|
|
||||||
#include <linux/module.h>
|
|
||||||
#include <linux/nvmem-consumer.h>
|
|
||||||
#include <linux/of_address.h>
|
|
||||||
#include <linux/of_platform.h>
|
|
||||||
#include <linux/pinctrl/consumer.h>
|
|
||||||
#include <linux/phy.h>
|
|
||||||
#include <linux/pm_domain.h>
|
|
||||||
#include <linux/pm_runtime.h>
|
|
||||||
|
|
||||||
#define MT7988_2P5GE_PMB "mediatek/mt7988/i2p5ge-phy-pmb.bin"
|
|
||||||
|
|
||||||
#define MD32_EN BIT(0)
|
|
||||||
#define PMEM_PRIORITY BIT(8)
|
|
||||||
#define DMEM_PRIORITY BIT(16)
|
|
||||||
|
|
||||||
#define BASE100T_STATUS_EXTEND 0x10
|
|
||||||
#define BASE1000T_STATUS_EXTEND 0x11
|
|
||||||
#define EXTEND_CTRL_AND_STATUS 0x16
|
|
||||||
|
|
||||||
#define PHY_AUX_CTRL_STATUS 0x1d
|
|
||||||
#define PHY_AUX_DPX_MASK GENMASK(5, 5)
|
|
||||||
#define PHY_AUX_SPEED_MASK GENMASK(4, 2)
|
|
||||||
|
|
||||||
/* Registers on MDIO_MMD_VEND1 */
|
|
||||||
#define MTK_PHY_LINK_STATUS_MISC 0xa2
|
|
||||||
#define MTK_PHY_FDX_ENABLE BIT(5)
|
|
||||||
|
|
||||||
#define MTK_PHY_LPI_PCS_DSP_CTRL 0x121
|
|
||||||
#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8)
|
|
||||||
|
|
||||||
/* Registers on MDIO_MMD_VEND2 */
|
|
||||||
#define MTK_PHY_LED0_ON_CTRL 0x24
|
|
||||||
#define MTK_PHY_LED0_ON_LINK1000 BIT(0)
|
|
||||||
#define MTK_PHY_LED0_ON_LINK100 BIT(1)
|
|
||||||
#define MTK_PHY_LED0_ON_LINK10 BIT(2)
|
|
||||||
#define MTK_PHY_LED0_ON_LINK2500 BIT(7)
|
|
||||||
#define MTK_PHY_LED0_POLARITY BIT(14)
|
|
||||||
|
|
||||||
#define MTK_PHY_LED1_ON_CTRL 0x26
|
|
||||||
#define MTK_PHY_LED1_ON_FDX BIT(4)
|
|
||||||
#define MTK_PHY_LED1_ON_HDX BIT(5)
|
|
||||||
#define MTK_PHY_LED1_POLARITY BIT(14)
|
|
||||||
|
|
||||||
#define MTK_EXT_PAGE_ACCESS 0x1f
|
|
||||||
#define MTK_PHY_PAGE_STANDARD 0x0000
|
|
||||||
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
|
||||||
|
|
||||||
struct mtk_i2p5ge_phy_priv {
|
|
||||||
bool fw_loaded;
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
PHY_AUX_SPD_10 = 0,
|
|
||||||
PHY_AUX_SPD_100,
|
|
||||||
PHY_AUX_SPD_1000,
|
|
||||||
PHY_AUX_SPD_2500,
|
|
||||||
};
|
|
||||||
|
|
||||||
static int mtk_2p5ge_phy_read_page(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mtk_2p5ge_phy_write_page(struct phy_device *phydev, int page)
|
|
||||||
{
|
|
||||||
return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mt7988_2p5ge_phy_probe(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
struct mtk_i2p5ge_phy_priv *phy_priv;
|
|
||||||
|
|
||||||
phy_priv = devm_kzalloc(&phydev->mdio.dev,
|
|
||||||
sizeof(struct mtk_i2p5ge_phy_priv), GFP_KERNEL);
|
|
||||||
if (!phy_priv)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
phydev->priv = phy_priv;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mt7988_2p5ge_phy_config_init(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
int ret, i;
|
|
||||||
const struct firmware *fw;
|
|
||||||
struct device *dev = &phydev->mdio.dev;
|
|
||||||
struct device_node *np;
|
|
||||||
void __iomem *pmb_addr;
|
|
||||||
void __iomem *md32_en_cfg_base;
|
|
||||||
struct mtk_i2p5ge_phy_priv *phy_priv = phydev->priv;
|
|
||||||
u16 reg;
|
|
||||||
struct pinctrl *pinctrl;
|
|
||||||
|
|
||||||
if (!phy_priv->fw_loaded) {
|
|
||||||
np = of_find_compatible_node(NULL, NULL, "mediatek,2p5gphy-fw");
|
|
||||||
if (!np)
|
|
||||||
return -ENOENT;
|
|
||||||
pmb_addr = of_iomap(np, 0);
|
|
||||||
if (!pmb_addr)
|
|
||||||
return -ENOMEM;
|
|
||||||
md32_en_cfg_base = of_iomap(np, 1);
|
|
||||||
if (!md32_en_cfg_base)
|
|
||||||
return -ENOMEM;
|
|
||||||
|
|
||||||
ret = request_firmware(&fw, MT7988_2P5GE_PMB, dev);
|
|
||||||
if (ret) {
|
|
||||||
dev_err(dev, "failed to load firmware: %s, ret: %d\n",
|
|
||||||
MT7988_2P5GE_PMB, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
reg = readw(md32_en_cfg_base);
|
|
||||||
if (reg & MD32_EN) {
|
|
||||||
phy_set_bits(phydev, 0, BIT(15));
|
|
||||||
usleep_range(10000, 11000);
|
|
||||||
}
|
|
||||||
phy_set_bits(phydev, 0, BIT(11));
|
|
||||||
|
|
||||||
/* Write magic number to safely stall MCU */
|
|
||||||
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800e, 0x1100);
|
|
||||||
phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800f, 0x00df);
|
|
||||||
|
|
||||||
for (i = 0; i < fw->size - 1; i += 4)
|
|
||||||
writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
|
|
||||||
release_firmware(fw);
|
|
||||||
|
|
||||||
writew(reg & ~MD32_EN, md32_en_cfg_base);
|
|
||||||
writew(reg | MD32_EN, md32_en_cfg_base);
|
|
||||||
phy_set_bits(phydev, 0, BIT(15));
|
|
||||||
dev_info(dev, "Firmware loading/trigger ok.\n");
|
|
||||||
|
|
||||||
phy_priv->fw_loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup LED */
|
|
||||||
|
|
||||||
/* Set polarity of led0 to active-high for BPI-R4 */
|
|
||||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
|
|
||||||
MTK_PHY_LED0_POLARITY);
|
|
||||||
|
|
||||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
|
|
||||||
MTK_PHY_LED0_ON_LINK10 |
|
|
||||||
MTK_PHY_LED0_ON_LINK100 |
|
|
||||||
MTK_PHY_LED0_ON_LINK1000 |
|
|
||||||
MTK_PHY_LED0_ON_LINK2500);
|
|
||||||
phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
|
|
||||||
MTK_PHY_LED1_ON_FDX | MTK_PHY_LED1_ON_HDX);
|
|
||||||
|
|
||||||
pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
|
|
||||||
if (IS_ERR(pinctrl)) {
|
|
||||||
dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
|
|
||||||
return PTR_ERR(pinctrl);
|
|
||||||
}
|
|
||||||
|
|
||||||
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL,
|
|
||||||
MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0);
|
|
||||||
|
|
||||||
/* Enable 16-bit next page exchange bit if 1000-BT isn't advertizing */
|
|
||||||
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
|
||||||
__phy_write(phydev, 0x11, 0xfbfa);
|
|
||||||
__phy_write(phydev, 0x12, 0xc3);
|
|
||||||
__phy_write(phydev, 0x10, 0x87f8);
|
|
||||||
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mt7988_2p5ge_phy_config_aneg(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
bool changed = false;
|
|
||||||
u32 adv;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (phydev->autoneg == AUTONEG_DISABLE) {
|
|
||||||
/* Configure half duplex with genphy_setup_forced,
|
|
||||||
* because genphy_c45_pma_setup_forced does not support.
|
|
||||||
*/
|
|
||||||
return phydev->duplex != DUPLEX_FULL
|
|
||||||
? genphy_setup_forced(phydev)
|
|
||||||
: genphy_c45_pma_setup_forced(phydev);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = genphy_c45_an_config_aneg(phydev);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
if (ret > 0)
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
|
|
||||||
ret = phy_modify_changed(phydev, MII_CTRL1000,
|
|
||||||
ADVERTISE_1000FULL | ADVERTISE_1000HALF,
|
|
||||||
adv);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
if (ret > 0)
|
|
||||||
changed = true;
|
|
||||||
|
|
||||||
return genphy_c45_check_and_restart_aneg(phydev, changed);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mt7988_2p5ge_phy_get_features(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = genphy_read_abilities(phydev);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* We don't support HDX at MAC layer on mt7988.
|
|
||||||
* So mask phy's HDX capabilities, too.
|
|
||||||
*/
|
|
||||||
linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT,
|
|
||||||
phydev->supported);
|
|
||||||
linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
|
|
||||||
phydev->supported);
|
|
||||||
linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
|
|
||||||
phydev->supported);
|
|
||||||
linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT,
|
|
||||||
phydev->supported);
|
|
||||||
linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, phydev->supported);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mt7988_2p5ge_phy_read_status(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = genphy_update_link(phydev);
|
|
||||||
if (ret)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
phydev->speed = SPEED_UNKNOWN;
|
|
||||||
phydev->duplex = DUPLEX_UNKNOWN;
|
|
||||||
phydev->pause = 0;
|
|
||||||
phydev->asym_pause = 0;
|
|
||||||
|
|
||||||
if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
|
|
||||||
ret = genphy_c45_read_lpa(phydev);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
/* Read the link partner's 1G advertisement */
|
|
||||||
ret = phy_read(phydev, MII_STAT1000);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
|
|
||||||
} else if (phydev->autoneg == AUTONEG_DISABLE) {
|
|
||||||
linkmode_zero(phydev->lp_advertising);
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
|
|
||||||
case PHY_AUX_SPD_10:
|
|
||||||
phydev->speed = SPEED_10;
|
|
||||||
break;
|
|
||||||
case PHY_AUX_SPD_100:
|
|
||||||
phydev->speed = SPEED_100;
|
|
||||||
break;
|
|
||||||
case PHY_AUX_SPD_1000:
|
|
||||||
phydev->speed = SPEED_1000;
|
|
||||||
break;
|
|
||||||
case PHY_AUX_SPD_2500:
|
|
||||||
phydev->speed = SPEED_2500;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC);
|
|
||||||
if (ret < 0)
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
phydev->duplex = (ret & MTK_PHY_FDX_ENABLE) ? DUPLEX_FULL : DUPLEX_HALF;
|
|
||||||
/* FIXME: The current firmware always enables rate adaptation mode. */
|
|
||||||
phydev->rate_matching = RATE_MATCH_PAUSE;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int mt7988_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
|
|
||||||
phy_interface_t iface)
|
|
||||||
{
|
|
||||||
return RATE_MATCH_PAUSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct phy_driver mtk_gephy_driver[] = {
|
|
||||||
{
|
|
||||||
PHY_ID_MATCH_MODEL(0x00339c11),
|
|
||||||
.name = "MediaTek MT798x 2.5GbE PHY",
|
|
||||||
.probe = mt7988_2p5ge_phy_probe,
|
|
||||||
.config_init = mt7988_2p5ge_phy_config_init,
|
|
||||||
.config_aneg = mt7988_2p5ge_phy_config_aneg,
|
|
||||||
.get_features = mt7988_2p5ge_phy_get_features,
|
|
||||||
.read_status = mt7988_2p5ge_phy_read_status,
|
|
||||||
.get_rate_matching = mt7988_2p5ge_phy_get_rate_matching,
|
|
||||||
.suspend = genphy_suspend,
|
|
||||||
.resume = genphy_resume,
|
|
||||||
.read_page = mtk_2p5ge_phy_read_page,
|
|
||||||
.write_page = mtk_2p5ge_phy_write_page,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
module_phy_driver(mtk_gephy_driver);
|
|
||||||
|
|
||||||
static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = {
|
|
||||||
{ PHY_ID_MATCH_VENDOR(0x00339c00) },
|
|
||||||
{ }
|
|
||||||
};
|
|
||||||
|
|
||||||
MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver");
|
|
||||||
MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
|
|
||||||
MODULE_LICENSE("GPL");
|
|
||||||
|
|
||||||
MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl);
|
|
||||||
MODULE_FIRMWARE(MT7988_2P5GE_PMB);
|
|
@@ -240,7 +240,7 @@ CONFIG_MAXLINEAR_GPHY=y
|
|||||||
CONFIG_MDIO_BUS=y
|
CONFIG_MDIO_BUS=y
|
||||||
CONFIG_MDIO_DEVICE=y
|
CONFIG_MDIO_DEVICE=y
|
||||||
CONFIG_MDIO_DEVRES=y
|
CONFIG_MDIO_DEVRES=y
|
||||||
CONFIG_MEDIATEK_2P5G_PHY=y
|
CONFIG_MEDIATEK_2P5GE_PHY=y
|
||||||
CONFIG_MEDIATEK_GE_PHY=y
|
CONFIG_MEDIATEK_GE_PHY=y
|
||||||
CONFIG_MEDIATEK_GE_SOC_PHY=y
|
CONFIG_MEDIATEK_GE_SOC_PHY=y
|
||||||
CONFIG_MEDIATEK_WATCHDOG=y
|
CONFIG_MEDIATEK_WATCHDOG=y
|
||||||
|
@@ -242,7 +242,7 @@ CONFIG_MAXLINEAR_GPHY=y
|
|||||||
CONFIG_MDIO_BUS=y
|
CONFIG_MDIO_BUS=y
|
||||||
CONFIG_MDIO_DEVICE=y
|
CONFIG_MDIO_DEVICE=y
|
||||||
CONFIG_MDIO_DEVRES=y
|
CONFIG_MDIO_DEVRES=y
|
||||||
# CONFIG_MEDIATEK_2P5G_PHY is not set
|
# CONFIG_MEDIATEK_2P5GE_PHY is not set
|
||||||
CONFIG_MEDIATEK_GE_PHY=y
|
CONFIG_MEDIATEK_GE_PHY=y
|
||||||
# CONFIG_MEDIATEK_GE_SOC_PHY is not set
|
# CONFIG_MEDIATEK_GE_SOC_PHY is not set
|
||||||
CONFIG_MEDIATEK_WATCHDOG=y
|
CONFIG_MEDIATEK_WATCHDOG=y
|
||||||
|
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
|||||||
|
From 12054d38fc55adbfa2b40299ad8af3449d882ee2 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:06 +0800
|
||||||
|
Subject: [PATCH 02/13] net: phy: mediatek: Fix spelling errors and rearrange
|
||||||
|
variables
|
||||||
|
|
||||||
|
This patch fixes spelling errors which comes from mediatek-ge-soc.c and
|
||||||
|
rearrange variables with reverse Xmas tree order.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 19 ++++++++++---------
|
||||||
|
1 file changed, 10 insertions(+), 9 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -408,16 +408,17 @@ static int tx_offset_cal_efuse(struct ph
|
||||||
|
|
||||||
|
static int tx_amp_fill_result(struct phy_device *phydev, u16 *buf)
|
||||||
|
{
|
||||||
|
- int i;
|
||||||
|
- int bias[16] = {};
|
||||||
|
- const int vals_9461[16] = { 7, 1, 4, 7,
|
||||||
|
- 7, 1, 4, 7,
|
||||||
|
- 7, 1, 4, 7,
|
||||||
|
- 7, 1, 4, 7 };
|
||||||
|
const int vals_9481[16] = { 10, 6, 6, 10,
|
||||||
|
10, 6, 6, 10,
|
||||||
|
10, 6, 6, 10,
|
||||||
|
10, 6, 6, 10 };
|
||||||
|
+ const int vals_9461[16] = { 7, 1, 4, 7,
|
||||||
|
+ 7, 1, 4, 7,
|
||||||
|
+ 7, 1, 4, 7,
|
||||||
|
+ 7, 1, 4, 7 };
|
||||||
|
+ int bias[16] = {};
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
switch (phydev->drv->phy_id) {
|
||||||
|
case MTK_GPHY_ID_MT7981:
|
||||||
|
/* We add some calibration to efuse values
|
||||||
|
@@ -1069,10 +1070,10 @@ static int start_cal(struct phy_device *
|
||||||
|
|
||||||
|
static int mt798x_phy_calibration(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
+ struct nvmem_cell *cell;
|
||||||
|
int ret = 0;
|
||||||
|
- u32 *buf;
|
||||||
|
size_t len;
|
||||||
|
- struct nvmem_cell *cell;
|
||||||
|
+ u32 *buf;
|
||||||
|
|
||||||
|
cell = nvmem_cell_get(&phydev->mdio.dev, "phy-cal-data");
|
||||||
|
if (IS_ERR(cell)) {
|
||||||
|
@@ -1415,7 +1416,7 @@ static int mt7988_phy_probe_shared(struc
|
||||||
|
* LED_C and LED_D respectively. At the same time those pins are used to
|
||||||
|
* bootstrap configuration of the reference clock source (LED_A),
|
||||||
|
* DRAM DDRx16b x2/x1 (LED_B) and boot device (LED_C, LED_D).
|
||||||
|
- * In practise this is done using a LED and a resistor pulling the pin
|
||||||
|
+ * In practice this is done using a LED and a resistor pulling the pin
|
||||||
|
* either to GND or to VIO.
|
||||||
|
* The detected value at boot time is accessible at run-time using the
|
||||||
|
* TPBANK0 register located in the gpio base of the pinctrl, in order
|
@@ -0,0 +1,742 @@
|
|||||||
|
From 434e41555c45ec10b19320024163bb009da168bc Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:07 +0800
|
||||||
|
Subject: [PATCH 03/13] net: phy: mediatek: Move LED helper functions into mtk
|
||||||
|
phy lib
|
||||||
|
|
||||||
|
This patch creates mtk-phy-lib.c & mtk-phy.h and integrates mtk-ge-soc.c's
|
||||||
|
LED helper functions so that we can use those helper functions in other
|
||||||
|
MTK's ethernet phy driver.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/Kconfig | 5 +
|
||||||
|
drivers/net/phy/mediatek/Makefile | 1 +
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 262 +++----------------------
|
||||||
|
drivers/net/phy/mediatek/mtk-phy-lib.c | 251 +++++++++++++++++++++++
|
||||||
|
drivers/net/phy/mediatek/mtk.h | 82 ++++++++
|
||||||
|
6 files changed, 368 insertions(+), 235 deletions(-)
|
||||||
|
create mode 100644 drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
create mode 100644 drivers/net/phy/mediatek/mtk.h
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/Kconfig
|
||||||
|
+++ b/drivers/net/phy/mediatek/Kconfig
|
||||||
|
@@ -1,6 +1,10 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
+config MTK_NET_PHYLIB
|
||||||
|
+ tristate
|
||||||
|
+
|
||||||
|
config MEDIATEK_GE_PHY
|
||||||
|
tristate "MediaTek Gigabit Ethernet PHYs"
|
||||||
|
+ select MTK_NET_PHYLIB
|
||||||
|
help
|
||||||
|
Supports the MediaTek non-built-in Gigabit Ethernet PHYs.
|
||||||
|
|
||||||
|
@@ -13,6 +17,7 @@ config MEDIATEK_GE_SOC_PHY
|
||||||
|
tristate "MediaTek SoC Ethernet PHYs"
|
||||||
|
depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
|
||||||
|
select NVMEM_MTK_EFUSE
|
||||||
|
+ select MTK_NET_PHYLIB
|
||||||
|
help
|
||||||
|
Supports MediaTek SoC built-in Gigabit Ethernet PHYs.
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/Makefile
|
||||||
|
+++ b/drivers/net/phy/mediatek/Makefile
|
||||||
|
@@ -1,3 +1,4 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
+obj-$(CONFIG_MTK_NET_PHYLIB) += mtk-phy-lib.o
|
||||||
|
obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o
|
||||||
|
obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -8,6 +8,8 @@
|
||||||
|
#include <linux/phy.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
|
+#include "mtk.h"
|
||||||
|
+
|
||||||
|
#define MTK_GPHY_ID_MT7981 0x03a29461
|
||||||
|
#define MTK_GPHY_ID_MT7988 0x03a29481
|
||||||
|
|
||||||
|
@@ -210,41 +212,6 @@
|
||||||
|
#define MTK_PHY_DA_TX_R50_PAIR_D 0x540
|
||||||
|
|
||||||
|
/* Registers on MDIO_MMD_VEND2 */
|
||||||
|
-#define MTK_PHY_LED0_ON_CTRL 0x24
|
||||||
|
-#define MTK_PHY_LED1_ON_CTRL 0x26
|
||||||
|
-#define MTK_PHY_LED_ON_MASK GENMASK(6, 0)
|
||||||
|
-#define MTK_PHY_LED_ON_LINK1000 BIT(0)
|
||||||
|
-#define MTK_PHY_LED_ON_LINK100 BIT(1)
|
||||||
|
-#define MTK_PHY_LED_ON_LINK10 BIT(2)
|
||||||
|
-#define MTK_PHY_LED_ON_LINK (MTK_PHY_LED_ON_LINK10 |\
|
||||||
|
- MTK_PHY_LED_ON_LINK100 |\
|
||||||
|
- MTK_PHY_LED_ON_LINK1000)
|
||||||
|
-#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
|
||||||
|
-#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
|
||||||
|
-#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
|
||||||
|
-#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
|
||||||
|
-#define MTK_PHY_LED_ON_POLARITY BIT(14)
|
||||||
|
-#define MTK_PHY_LED_ON_ENABLE BIT(15)
|
||||||
|
-
|
||||||
|
-#define MTK_PHY_LED0_BLINK_CTRL 0x25
|
||||||
|
-#define MTK_PHY_LED1_BLINK_CTRL 0x27
|
||||||
|
-#define MTK_PHY_LED_BLINK_1000TX BIT(0)
|
||||||
|
-#define MTK_PHY_LED_BLINK_1000RX BIT(1)
|
||||||
|
-#define MTK_PHY_LED_BLINK_100TX BIT(2)
|
||||||
|
-#define MTK_PHY_LED_BLINK_100RX BIT(3)
|
||||||
|
-#define MTK_PHY_LED_BLINK_10TX BIT(4)
|
||||||
|
-#define MTK_PHY_LED_BLINK_10RX BIT(5)
|
||||||
|
-#define MTK_PHY_LED_BLINK_RX (MTK_PHY_LED_BLINK_10RX |\
|
||||||
|
- MTK_PHY_LED_BLINK_100RX |\
|
||||||
|
- MTK_PHY_LED_BLINK_1000RX)
|
||||||
|
-#define MTK_PHY_LED_BLINK_TX (MTK_PHY_LED_BLINK_10TX |\
|
||||||
|
- MTK_PHY_LED_BLINK_100TX |\
|
||||||
|
- MTK_PHY_LED_BLINK_1000TX)
|
||||||
|
-#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
|
||||||
|
-#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
|
||||||
|
-#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
|
||||||
|
-#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
|
||||||
|
-
|
||||||
|
#define MTK_PHY_LED1_DEFAULT_POLARITIES BIT(1)
|
||||||
|
|
||||||
|
#define MTK_PHY_RG_BG_RASEL 0x115
|
||||||
|
@@ -299,10 +266,6 @@ enum CAL_MODE {
|
||||||
|
SW_M
|
||||||
|
};
|
||||||
|
|
||||||
|
-#define MTK_PHY_LED_STATE_FORCE_ON 0
|
||||||
|
-#define MTK_PHY_LED_STATE_FORCE_BLINK 1
|
||||||
|
-#define MTK_PHY_LED_STATE_NETDEV 2
|
||||||
|
-
|
||||||
|
struct mtk_socphy_priv {
|
||||||
|
unsigned long led_state;
|
||||||
|
};
|
||||||
|
@@ -1131,84 +1094,39 @@ static int mt798x_phy_config_init(struct
|
||||||
|
return mt798x_phy_calibration(phydev);
|
||||||
|
}
|
||||||
|
|
||||||
|
-static int mt798x_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
|
||||||
|
- bool on)
|
||||||
|
-{
|
||||||
|
- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
||||||
|
- struct mtk_socphy_priv *priv = phydev->priv;
|
||||||
|
- bool changed;
|
||||||
|
-
|
||||||
|
- if (on)
|
||||||
|
- changed = !test_and_set_bit(bit_on, &priv->led_state);
|
||||||
|
- else
|
||||||
|
- changed = !!test_and_clear_bit(bit_on, &priv->led_state);
|
||||||
|
-
|
||||||
|
- changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
|
||||||
|
- (index ? 16 : 0), &priv->led_state);
|
||||||
|
- if (changed)
|
||||||
|
- return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
- MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
|
||||||
|
- MTK_PHY_LED_ON_MASK,
|
||||||
|
- on ? MTK_PHY_LED_ON_FORCE_ON : 0);
|
||||||
|
- else
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int mt798x_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
|
||||||
|
- bool blinking)
|
||||||
|
-{
|
||||||
|
- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
|
||||||
|
- struct mtk_socphy_priv *priv = phydev->priv;
|
||||||
|
- bool changed;
|
||||||
|
-
|
||||||
|
- if (blinking)
|
||||||
|
- changed = !test_and_set_bit(bit_blink, &priv->led_state);
|
||||||
|
- else
|
||||||
|
- changed = !!test_and_clear_bit(bit_blink, &priv->led_state);
|
||||||
|
-
|
||||||
|
- changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
|
||||||
|
- (index ? 16 : 0), &priv->led_state);
|
||||||
|
- if (changed)
|
||||||
|
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
- MTK_PHY_LED1_BLINK_CTRL : MTK_PHY_LED0_BLINK_CTRL,
|
||||||
|
- blinking ? MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
|
||||||
|
- else
|
||||||
|
- return 0;
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int mt798x_phy_led_blink_set(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long *delay_on,
|
||||||
|
unsigned long *delay_off)
|
||||||
|
{
|
||||||
|
+ struct mtk_socphy_priv *priv = phydev->priv;
|
||||||
|
bool blinking = false;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
- if (index > 1)
|
||||||
|
- return -EINVAL;
|
||||||
|
-
|
||||||
|
- if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
|
||||||
|
- blinking = true;
|
||||||
|
- *delay_on = 50;
|
||||||
|
- *delay_off = 50;
|
||||||
|
- }
|
||||||
|
+ err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
|
||||||
|
+ if (err < 0)
|
||||||
|
+ return err;
|
||||||
|
|
||||||
|
- err = mt798x_phy_hw_led_blink_set(phydev, index, blinking);
|
||||||
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state,
|
||||||
|
+ blinking);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
- return mt798x_phy_hw_led_on_set(phydev, index, false);
|
||||||
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_MASK, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mt798x_phy_led_brightness_set(struct phy_device *phydev,
|
||||||
|
u8 index, enum led_brightness value)
|
||||||
|
{
|
||||||
|
+ struct mtk_socphy_priv *priv = phydev->priv;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
- err = mt798x_phy_hw_led_blink_set(phydev, index, false);
|
||||||
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state, false);
|
||||||
|
if (err)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
- return mt798x_phy_hw_led_on_set(phydev, index, (value != LED_OFF));
|
||||||
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_MASK, (value != LED_OFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
@@ -1223,148 +1141,30 @@ static const unsigned long supported_tri
|
||||||
|
static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules)
|
||||||
|
{
|
||||||
|
- if (index > 1)
|
||||||
|
- return -EINVAL;
|
||||||
|
-
|
||||||
|
- /* All combinations of the supported triggers are allowed */
|
||||||
|
- if (rules & ~supported_triggers)
|
||||||
|
- return -EOPNOTSUPP;
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
-};
|
||||||
|
+ return mtk_phy_led_hw_is_supported(phydev, index, rules,
|
||||||
|
+ supported_triggers);
|
||||||
|
+}
|
||||||
|
|
||||||
|
static int mt798x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long *rules)
|
||||||
|
{
|
||||||
|
- unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK + (index ? 16 : 0);
|
||||||
|
- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
||||||
|
- unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
||||||
|
struct mtk_socphy_priv *priv = phydev->priv;
|
||||||
|
- int on, blink;
|
||||||
|
-
|
||||||
|
- if (index > 1)
|
||||||
|
- return -EINVAL;
|
||||||
|
-
|
||||||
|
- on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||||
|
- index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
|
||||||
|
-
|
||||||
|
- if (on < 0)
|
||||||
|
- return -EIO;
|
||||||
|
-
|
||||||
|
- blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||||
|
- index ? MTK_PHY_LED1_BLINK_CTRL :
|
||||||
|
- MTK_PHY_LED0_BLINK_CTRL);
|
||||||
|
- if (blink < 0)
|
||||||
|
- return -EIO;
|
||||||
|
-
|
||||||
|
- if ((on & (MTK_PHY_LED_ON_LINK | MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX |
|
||||||
|
- MTK_PHY_LED_ON_LINKDOWN)) ||
|
||||||
|
- (blink & (MTK_PHY_LED_BLINK_RX | MTK_PHY_LED_BLINK_TX)))
|
||||||
|
- set_bit(bit_netdev, &priv->led_state);
|
||||||
|
- else
|
||||||
|
- clear_bit(bit_netdev, &priv->led_state);
|
||||||
|
-
|
||||||
|
- if (on & MTK_PHY_LED_ON_FORCE_ON)
|
||||||
|
- set_bit(bit_on, &priv->led_state);
|
||||||
|
- else
|
||||||
|
- clear_bit(bit_on, &priv->led_state);
|
||||||
|
-
|
||||||
|
- if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
|
||||||
|
- set_bit(bit_blink, &priv->led_state);
|
||||||
|
- else
|
||||||
|
- clear_bit(bit_blink, &priv->led_state);
|
||||||
|
-
|
||||||
|
- if (!rules)
|
||||||
|
- return 0;
|
||||||
|
-
|
||||||
|
- if (on & MTK_PHY_LED_ON_LINK)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_LINK);
|
||||||
|
|
||||||
|
- if (on & MTK_PHY_LED_ON_LINK10)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_LINK_10);
|
||||||
|
-
|
||||||
|
- if (on & MTK_PHY_LED_ON_LINK100)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_LINK_100);
|
||||||
|
-
|
||||||
|
- if (on & MTK_PHY_LED_ON_LINK1000)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
|
||||||
|
-
|
||||||
|
- if (on & MTK_PHY_LED_ON_FDX)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
|
||||||
|
-
|
||||||
|
- if (on & MTK_PHY_LED_ON_HDX)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
|
||||||
|
-
|
||||||
|
- if (blink & MTK_PHY_LED_BLINK_RX)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_RX);
|
||||||
|
-
|
||||||
|
- if (blink & MTK_PHY_LED_BLINK_TX)
|
||||||
|
- *rules |= BIT(TRIGGER_NETDEV_TX);
|
||||||
|
-
|
||||||
|
- return 0;
|
||||||
|
+ return mtk_phy_led_hw_ctrl_get(phydev, index, rules, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_SET,
|
||||||
|
+ MTK_GPHY_LED_RX_BLINK_SET,
|
||||||
|
+ MTK_GPHY_LED_TX_BLINK_SET);
|
||||||
|
};
|
||||||
|
|
||||||
|
static int mt798x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules)
|
||||||
|
{
|
||||||
|
- unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
||||||
|
struct mtk_socphy_priv *priv = phydev->priv;
|
||||||
|
- u16 on = 0, blink = 0;
|
||||||
|
- int ret;
|
||||||
|
|
||||||
|
- if (index > 1)
|
||||||
|
- return -EINVAL;
|
||||||
|
-
|
||||||
|
- if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
|
||||||
|
- on |= MTK_PHY_LED_ON_FDX;
|
||||||
|
-
|
||||||
|
- if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
|
||||||
|
- on |= MTK_PHY_LED_ON_HDX;
|
||||||
|
-
|
||||||
|
- if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
|
||||||
|
- on |= MTK_PHY_LED_ON_LINK10;
|
||||||
|
-
|
||||||
|
- if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
|
||||||
|
- on |= MTK_PHY_LED_ON_LINK100;
|
||||||
|
-
|
||||||
|
- if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
|
||||||
|
- on |= MTK_PHY_LED_ON_LINK1000;
|
||||||
|
-
|
||||||
|
- if (rules & BIT(TRIGGER_NETDEV_RX)) {
|
||||||
|
- blink |= (on & MTK_PHY_LED_ON_LINK) ?
|
||||||
|
- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10RX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100RX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000RX : 0)) :
|
||||||
|
- MTK_PHY_LED_BLINK_RX;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (rules & BIT(TRIGGER_NETDEV_TX)) {
|
||||||
|
- blink |= (on & MTK_PHY_LED_ON_LINK) ?
|
||||||
|
- (((on & MTK_PHY_LED_ON_LINK10) ? MTK_PHY_LED_BLINK_10TX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK100) ? MTK_PHY_LED_BLINK_100TX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK1000) ? MTK_PHY_LED_BLINK_1000TX : 0)) :
|
||||||
|
- MTK_PHY_LED_BLINK_TX;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- if (blink || on)
|
||||||
|
- set_bit(bit_netdev, &priv->led_state);
|
||||||
|
- else
|
||||||
|
- clear_bit(bit_netdev, &priv->led_state);
|
||||||
|
-
|
||||||
|
- ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
- MTK_PHY_LED1_ON_CTRL :
|
||||||
|
- MTK_PHY_LED0_ON_CTRL,
|
||||||
|
- MTK_PHY_LED_ON_FDX |
|
||||||
|
- MTK_PHY_LED_ON_HDX |
|
||||||
|
- MTK_PHY_LED_ON_LINK,
|
||||||
|
- on);
|
||||||
|
-
|
||||||
|
- if (ret)
|
||||||
|
- return ret;
|
||||||
|
-
|
||||||
|
- return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
- MTK_PHY_LED1_BLINK_CTRL :
|
||||||
|
- MTK_PHY_LED0_BLINK_CTRL, blink);
|
||||||
|
+ return mtk_phy_led_hw_ctrl_set(phydev, index, rules, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_SET,
|
||||||
|
+ MTK_GPHY_LED_RX_BLINK_SET,
|
||||||
|
+ MTK_GPHY_LED_TX_BLINK_SET);
|
||||||
|
};
|
||||||
|
|
||||||
|
static bool mt7988_phy_led_get_polarity(struct phy_device *phydev, int led_num)
|
||||||
|
@@ -1438,14 +1238,6 @@ static int mt7988_phy_probe_shared(struc
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
-static void mt798x_phy_leds_state_init(struct phy_device *phydev)
|
||||||
|
-{
|
||||||
|
- int i;
|
||||||
|
-
|
||||||
|
- for (i = 0; i < 2; ++i)
|
||||||
|
- mt798x_phy_led_hw_control_get(phydev, i, NULL);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static int mt7988_phy_probe(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
struct mtk_socphy_shared *shared;
|
||||||
|
@@ -1471,7 +1263,7 @@ static int mt7988_phy_probe(struct phy_d
|
||||||
|
|
||||||
|
phydev->priv = priv;
|
||||||
|
|
||||||
|
- mt798x_phy_leds_state_init(phydev);
|
||||||
|
+ mtk_phy_leds_state_init(phydev);
|
||||||
|
|
||||||
|
err = mt7988_phy_fix_leds_polarities(phydev);
|
||||||
|
if (err)
|
||||||
|
@@ -1498,7 +1290,7 @@ static int mt7981_phy_probe(struct phy_d
|
||||||
|
|
||||||
|
phydev->priv = priv;
|
||||||
|
|
||||||
|
- mt798x_phy_leds_state_init(phydev);
|
||||||
|
+ mtk_phy_leds_state_init(phydev);
|
||||||
|
|
||||||
|
return mt798x_phy_calibration(phydev);
|
||||||
|
}
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
@@ -0,0 +1,251 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0
|
||||||
|
+#include <linux/phy.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+
|
||||||
|
+#include <linux/netdevice.h>
|
||||||
|
+
|
||||||
|
+#include "mtk.h"
|
||||||
|
+
|
||||||
|
+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long rules,
|
||||||
|
+ unsigned long supported_triggers)
|
||||||
|
+{
|
||||||
|
+ if (index > 1)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ /* All combinations of the supported triggers are allowed */
|
||||||
|
+ if (rules & ~supported_triggers)
|
||||||
|
+ return -EOPNOTSUPP;
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_is_supported);
|
||||||
|
+
|
||||||
|
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *rules, unsigned long *led_state,
|
||||||
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
|
||||||
|
+{
|
||||||
|
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
|
||||||
|
+ (index ? 16 : 0);
|
||||||
|
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
||||||
|
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
||||||
|
+ int on, blink;
|
||||||
|
+
|
||||||
|
+ if (index > 1)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ on = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||||
|
+ index ? MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL);
|
||||||
|
+
|
||||||
|
+ if (on < 0)
|
||||||
|
+ return -EIO;
|
||||||
|
+
|
||||||
|
+ blink = phy_read_mmd(phydev, MDIO_MMD_VEND2,
|
||||||
|
+ index ? MTK_PHY_LED1_BLINK_CTRL :
|
||||||
|
+ MTK_PHY_LED0_BLINK_CTRL);
|
||||||
|
+ if (blink < 0)
|
||||||
|
+ return -EIO;
|
||||||
|
+
|
||||||
|
+ if ((on & (on_set | MTK_PHY_LED_ON_FDX |
|
||||||
|
+ MTK_PHY_LED_ON_HDX | MTK_PHY_LED_ON_LINKDOWN)) ||
|
||||||
|
+ (blink & (rx_blink_set | tx_blink_set)))
|
||||||
|
+ set_bit(bit_netdev, led_state);
|
||||||
|
+ else
|
||||||
|
+ clear_bit(bit_netdev, led_state);
|
||||||
|
+
|
||||||
|
+ if (on & MTK_PHY_LED_ON_FORCE_ON)
|
||||||
|
+ set_bit(bit_on, led_state);
|
||||||
|
+ else
|
||||||
|
+ clear_bit(bit_on, led_state);
|
||||||
|
+
|
||||||
|
+ if (blink & MTK_PHY_LED_BLINK_FORCE_BLINK)
|
||||||
|
+ set_bit(bit_blink, led_state);
|
||||||
|
+ else
|
||||||
|
+ clear_bit(bit_blink, led_state);
|
||||||
|
+
|
||||||
|
+ if (!rules)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ if (on & on_set)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK);
|
||||||
|
+
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK10)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_10);
|
||||||
|
+
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK100)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_100);
|
||||||
|
+
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK1000)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_1000);
|
||||||
|
+
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK2500)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_LINK_2500);
|
||||||
|
+
|
||||||
|
+ if (on & MTK_PHY_LED_ON_FDX)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_FULL_DUPLEX);
|
||||||
|
+
|
||||||
|
+ if (on & MTK_PHY_LED_ON_HDX)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_HALF_DUPLEX);
|
||||||
|
+
|
||||||
|
+ if (blink & rx_blink_set)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_RX);
|
||||||
|
+
|
||||||
|
+ if (blink & tx_blink_set)
|
||||||
|
+ *rules |= BIT(TRIGGER_NETDEV_TX);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_get);
|
||||||
|
+
|
||||||
|
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long rules, unsigned long *led_state,
|
||||||
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set)
|
||||||
|
+{
|
||||||
|
+ unsigned int bit_netdev = MTK_PHY_LED_STATE_NETDEV + (index ? 16 : 0);
|
||||||
|
+ u16 on = 0, blink = 0;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ if (index > 1)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ if (rules & BIT(TRIGGER_NETDEV_FULL_DUPLEX))
|
||||||
|
+ on |= MTK_PHY_LED_ON_FDX;
|
||||||
|
+
|
||||||
|
+ if (rules & BIT(TRIGGER_NETDEV_HALF_DUPLEX))
|
||||||
|
+ on |= MTK_PHY_LED_ON_HDX;
|
||||||
|
+
|
||||||
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_10) | BIT(TRIGGER_NETDEV_LINK)))
|
||||||
|
+ on |= MTK_PHY_LED_ON_LINK10;
|
||||||
|
+
|
||||||
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_100) | BIT(TRIGGER_NETDEV_LINK)))
|
||||||
|
+ on |= MTK_PHY_LED_ON_LINK100;
|
||||||
|
+
|
||||||
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_1000) | BIT(TRIGGER_NETDEV_LINK)))
|
||||||
|
+ on |= MTK_PHY_LED_ON_LINK1000;
|
||||||
|
+
|
||||||
|
+ if (rules & (BIT(TRIGGER_NETDEV_LINK_2500) | BIT(TRIGGER_NETDEV_LINK)))
|
||||||
|
+ on |= MTK_PHY_LED_ON_LINK2500;
|
||||||
|
+
|
||||||
|
+ if (rules & BIT(TRIGGER_NETDEV_RX)) {
|
||||||
|
+ blink |= (on & on_set) ?
|
||||||
|
+ (((on & MTK_PHY_LED_ON_LINK10) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_10RX : 0) |
|
||||||
|
+ ((on & MTK_PHY_LED_ON_LINK100) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_100RX : 0) |
|
||||||
|
+ ((on & MTK_PHY_LED_ON_LINK1000) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_1000RX : 0) |
|
||||||
|
+ ((on & MTK_PHY_LED_ON_LINK2500) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_2500RX : 0)) :
|
||||||
|
+ rx_blink_set;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (rules & BIT(TRIGGER_NETDEV_TX)) {
|
||||||
|
+ blink |= (on & on_set) ?
|
||||||
|
+ (((on & MTK_PHY_LED_ON_LINK10) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_10TX : 0) |
|
||||||
|
+ ((on & MTK_PHY_LED_ON_LINK100) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_100TX : 0) |
|
||||||
|
+ ((on & MTK_PHY_LED_ON_LINK1000) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_1000TX : 0) |
|
||||||
|
+ ((on & MTK_PHY_LED_ON_LINK2500) ?
|
||||||
|
+ MTK_PHY_LED_BLINK_2500TX : 0)) :
|
||||||
|
+ tx_blink_set;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (blink || on)
|
||||||
|
+ set_bit(bit_netdev, led_state);
|
||||||
|
+ else
|
||||||
|
+ clear_bit(bit_netdev, led_state);
|
||||||
|
+
|
||||||
|
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
+ MTK_PHY_LED1_ON_CTRL : MTK_PHY_LED0_ON_CTRL,
|
||||||
|
+ MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX | on_set,
|
||||||
|
+ on);
|
||||||
|
+
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
+ MTK_PHY_LED1_BLINK_CTRL :
|
||||||
|
+ MTK_PHY_LED0_BLINK_CTRL, blink);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_hw_ctrl_set);
|
||||||
|
+
|
||||||
|
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
|
||||||
|
+ unsigned long *delay_off, bool *blinking)
|
||||||
|
+{
|
||||||
|
+ if (index > 1)
|
||||||
|
+ return -EINVAL;
|
||||||
|
+
|
||||||
|
+ if (delay_on && delay_off && (*delay_on > 0) && (*delay_off > 0)) {
|
||||||
|
+ *blinking = true;
|
||||||
|
+ *delay_on = 50;
|
||||||
|
+ *delay_off = 50;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_led_num_dly_cfg);
|
||||||
|
+
|
||||||
|
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *led_state, u16 led_on_mask, bool on)
|
||||||
|
+{
|
||||||
|
+ unsigned int bit_on = MTK_PHY_LED_STATE_FORCE_ON + (index ? 16 : 0);
|
||||||
|
+ bool changed;
|
||||||
|
+
|
||||||
|
+ if (on)
|
||||||
|
+ changed = !test_and_set_bit(bit_on, led_state);
|
||||||
|
+ else
|
||||||
|
+ changed = !!test_and_clear_bit(bit_on, led_state);
|
||||||
|
+
|
||||||
|
+ changed |= !!test_and_clear_bit(MTK_PHY_LED_STATE_NETDEV +
|
||||||
|
+ (index ? 16 : 0), led_state);
|
||||||
|
+ if (changed)
|
||||||
|
+ return phy_modify_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
+ MTK_PHY_LED1_ON_CTRL :
|
||||||
|
+ MTK_PHY_LED0_ON_CTRL,
|
||||||
|
+ led_on_mask,
|
||||||
|
+ on ? MTK_PHY_LED_ON_FORCE_ON : 0);
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_on_set);
|
||||||
|
+
|
||||||
|
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *led_state, bool blinking)
|
||||||
|
+{
|
||||||
|
+ unsigned int bit_blink = MTK_PHY_LED_STATE_FORCE_BLINK +
|
||||||
|
+ (index ? 16 : 0);
|
||||||
|
+ bool changed;
|
||||||
|
+
|
||||||
|
+ if (blinking)
|
||||||
|
+ changed = !test_and_set_bit(bit_blink, led_state);
|
||||||
|
+ else
|
||||||
|
+ changed = !!test_and_clear_bit(bit_blink, led_state);
|
||||||
|
+
|
||||||
|
+ changed |= !!test_bit(MTK_PHY_LED_STATE_NETDEV +
|
||||||
|
+ (index ? 16 : 0), led_state);
|
||||||
|
+ if (changed)
|
||||||
|
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2, index ?
|
||||||
|
+ MTK_PHY_LED1_BLINK_CTRL :
|
||||||
|
+ MTK_PHY_LED0_BLINK_CTRL,
|
||||||
|
+ blinking ?
|
||||||
|
+ MTK_PHY_LED_BLINK_FORCE_BLINK : 0);
|
||||||
|
+ else
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_hw_led_blink_set);
|
||||||
|
+
|
||||||
|
+void mtk_phy_leds_state_init(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ int i;
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < 2; ++i)
|
||||||
|
+ phydev->drv->led_hw_control_get(phydev, i, NULL);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_leds_state_init);
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("MediaTek Ethernet PHY driver common");
|
||||||
|
+MODULE_AUTHOR("Sky Huang <SkyLake.Huang@mediatek.com>");
|
||||||
|
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk.h
|
||||||
|
@@ -0,0 +1,82 @@
|
||||||
|
+/* SPDX-License-Identifier: GPL-2.0
|
||||||
|
+ *
|
||||||
|
+ * Common definition for Mediatek Ethernet PHYs
|
||||||
|
+ * Author: SkyLake Huang <SkyLake.Huang@mediatek.com>
|
||||||
|
+ * Copyright (c) 2024 MediaTek Inc.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#ifndef _MTK_EPHY_H_
|
||||||
|
+#define _MTK_EPHY_H_
|
||||||
|
+
|
||||||
|
+#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||||
|
+
|
||||||
|
+/* Registers on MDIO_MMD_VEND2 */
|
||||||
|
+#define MTK_PHY_LED0_ON_CTRL 0x24
|
||||||
|
+#define MTK_PHY_LED1_ON_CTRL 0x26
|
||||||
|
+#define MTK_GPHY_LED_ON_MASK GENMASK(6, 0)
|
||||||
|
+#define MTK_2P5GPHY_LED_ON_MASK GENMASK(7, 0)
|
||||||
|
+#define MTK_PHY_LED_ON_LINK1000 BIT(0)
|
||||||
|
+#define MTK_PHY_LED_ON_LINK100 BIT(1)
|
||||||
|
+#define MTK_PHY_LED_ON_LINK10 BIT(2)
|
||||||
|
+#define MTK_PHY_LED_ON_LINKDOWN BIT(3)
|
||||||
|
+#define MTK_PHY_LED_ON_FDX BIT(4) /* Full duplex */
|
||||||
|
+#define MTK_PHY_LED_ON_HDX BIT(5) /* Half duplex */
|
||||||
|
+#define MTK_PHY_LED_ON_FORCE_ON BIT(6)
|
||||||
|
+#define MTK_PHY_LED_ON_LINK2500 BIT(7)
|
||||||
|
+#define MTK_PHY_LED_ON_POLARITY BIT(14)
|
||||||
|
+#define MTK_PHY_LED_ON_ENABLE BIT(15)
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_LED0_BLINK_CTRL 0x25
|
||||||
|
+#define MTK_PHY_LED1_BLINK_CTRL 0x27
|
||||||
|
+#define MTK_PHY_LED_BLINK_1000TX BIT(0)
|
||||||
|
+#define MTK_PHY_LED_BLINK_1000RX BIT(1)
|
||||||
|
+#define MTK_PHY_LED_BLINK_100TX BIT(2)
|
||||||
|
+#define MTK_PHY_LED_BLINK_100RX BIT(3)
|
||||||
|
+#define MTK_PHY_LED_BLINK_10TX BIT(4)
|
||||||
|
+#define MTK_PHY_LED_BLINK_10RX BIT(5)
|
||||||
|
+#define MTK_PHY_LED_BLINK_COLLISION BIT(6)
|
||||||
|
+#define MTK_PHY_LED_BLINK_RX_CRC_ERR BIT(7)
|
||||||
|
+#define MTK_PHY_LED_BLINK_RX_IDLE_ERR BIT(8)
|
||||||
|
+#define MTK_PHY_LED_BLINK_FORCE_BLINK BIT(9)
|
||||||
|
+#define MTK_PHY_LED_BLINK_2500TX BIT(10)
|
||||||
|
+#define MTK_PHY_LED_BLINK_2500RX BIT(11)
|
||||||
|
+
|
||||||
|
+#define MTK_GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK1000 | \
|
||||||
|
+ MTK_PHY_LED_ON_LINK100 | \
|
||||||
|
+ MTK_PHY_LED_ON_LINK10)
|
||||||
|
+#define MTK_GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
|
||||||
|
+ MTK_PHY_LED_BLINK_100RX | \
|
||||||
|
+ MTK_PHY_LED_BLINK_10RX)
|
||||||
|
+#define MTK_GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_1000RX | \
|
||||||
|
+ MTK_PHY_LED_BLINK_100RX | \
|
||||||
|
+ MTK_PHY_LED_BLINK_10RX)
|
||||||
|
+
|
||||||
|
+#define MTK_2P5GPHY_LED_ON_SET (MTK_PHY_LED_ON_LINK2500 | \
|
||||||
|
+ MTK_GPHY_LED_ON_SET)
|
||||||
|
+#define MTK_2P5GPHY_LED_RX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
|
||||||
|
+ MTK_GPHY_LED_RX_BLINK_SET)
|
||||||
|
+#define MTK_2P5GPHY_LED_TX_BLINK_SET (MTK_PHY_LED_BLINK_2500RX | \
|
||||||
|
+ MTK_GPHY_LED_TX_BLINK_SET)
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_LED_STATE_FORCE_ON 0
|
||||||
|
+#define MTK_PHY_LED_STATE_FORCE_BLINK 1
|
||||||
|
+#define MTK_PHY_LED_STATE_NETDEV 2
|
||||||
|
+
|
||||||
|
+int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long rules,
|
||||||
|
+ unsigned long supported_triggers);
|
||||||
|
+int mtk_phy_led_hw_ctrl_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long rules, unsigned long *led_state,
|
||||||
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
|
||||||
|
+int mtk_phy_led_hw_ctrl_get(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *rules, unsigned long *led_state,
|
||||||
|
+ u16 on_set, u16 rx_blink_set, u16 tx_blink_set);
|
||||||
|
+int mtk_phy_led_num_dly_cfg(u8 index, unsigned long *delay_on,
|
||||||
|
+ unsigned long *delay_off, bool *blinking);
|
||||||
|
+int mtk_phy_hw_led_on_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *led_state, u16 led_on_mask, bool on);
|
||||||
|
+int mtk_phy_hw_led_blink_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *led_state, bool blinking);
|
||||||
|
+void mtk_phy_leds_state_init(struct phy_device *phydev);
|
||||||
|
+
|
||||||
|
+#endif /* _MTK_EPHY_H_ */
|
@@ -0,0 +1,70 @@
|
|||||||
|
From 2783929879854d5750ba82e2e203663313362abb Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:08 +0800
|
||||||
|
Subject: [PATCH 04/13] net: phy: mediatek: Improve readability of
|
||||||
|
mtk-phy-lib.c's mtk_phy_led_hw_ctrl_set()
|
||||||
|
|
||||||
|
This patch removes parens around TRIGGER_NETDEV_RX/TRIGGER_NETDEV_TX in
|
||||||
|
mtk_phy_led_hw_ctrl_set(), which improves readability.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-phy-lib.c | 44 ++++++++++++++------------
|
||||||
|
1 file changed, 24 insertions(+), 20 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
@@ -127,29 +127,33 @@ int mtk_phy_led_hw_ctrl_set(struct phy_d
|
||||||
|
on |= MTK_PHY_LED_ON_LINK2500;
|
||||||
|
|
||||||
|
if (rules & BIT(TRIGGER_NETDEV_RX)) {
|
||||||
|
- blink |= (on & on_set) ?
|
||||||
|
- (((on & MTK_PHY_LED_ON_LINK10) ?
|
||||||
|
- MTK_PHY_LED_BLINK_10RX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK100) ?
|
||||||
|
- MTK_PHY_LED_BLINK_100RX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK1000) ?
|
||||||
|
- MTK_PHY_LED_BLINK_1000RX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK2500) ?
|
||||||
|
- MTK_PHY_LED_BLINK_2500RX : 0)) :
|
||||||
|
- rx_blink_set;
|
||||||
|
+ if (on & on_set) {
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK10)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_10RX;
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK100)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_100RX;
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK1000)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_1000RX;
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK2500)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_2500RX;
|
||||||
|
+ } else {
|
||||||
|
+ blink |= rx_blink_set;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rules & BIT(TRIGGER_NETDEV_TX)) {
|
||||||
|
- blink |= (on & on_set) ?
|
||||||
|
- (((on & MTK_PHY_LED_ON_LINK10) ?
|
||||||
|
- MTK_PHY_LED_BLINK_10TX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK100) ?
|
||||||
|
- MTK_PHY_LED_BLINK_100TX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK1000) ?
|
||||||
|
- MTK_PHY_LED_BLINK_1000TX : 0) |
|
||||||
|
- ((on & MTK_PHY_LED_ON_LINK2500) ?
|
||||||
|
- MTK_PHY_LED_BLINK_2500TX : 0)) :
|
||||||
|
- tx_blink_set;
|
||||||
|
+ if (on & on_set) {
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK10)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_10TX;
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK100)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_100TX;
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK1000)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_1000TX;
|
||||||
|
+ if (on & MTK_PHY_LED_ON_LINK2500)
|
||||||
|
+ blink |= MTK_PHY_LED_BLINK_2500TX;
|
||||||
|
+ } else {
|
||||||
|
+ blink |= tx_blink_set;
|
||||||
|
+ }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blink || on)
|
@@ -0,0 +1,141 @@
|
|||||||
|
From 58c1270423ab48464cdc31ef71ffe7f5b2441961 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:09 +0800
|
||||||
|
Subject: [PATCH 05/13] net: phy: mediatek: Integrate read/write page helper
|
||||||
|
functions
|
||||||
|
|
||||||
|
This patch integrates read/write page helper functions as MTK phy lib.
|
||||||
|
They are basically the same in mtk-ge.c & mtk-ge-soc.c.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 18 ++++--------------
|
||||||
|
drivers/net/phy/mediatek/mtk-ge.c | 20 ++++++--------------
|
||||||
|
drivers/net/phy/mediatek/mtk-phy-lib.c | 12 ++++++++++++
|
||||||
|
drivers/net/phy/mediatek/mtk.h | 3 +++
|
||||||
|
4 files changed, 25 insertions(+), 28 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -275,16 +275,6 @@ struct mtk_socphy_shared {
|
||||||
|
struct mtk_socphy_priv priv[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
-static int mtk_socphy_read_page(struct phy_device *phydev)
|
||||||
|
-{
|
||||||
|
- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int mtk_socphy_write_page(struct phy_device *phydev, int page)
|
||||||
|
-{
|
||||||
|
- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
/* One calibration cycle consists of:
|
||||||
|
* 1.Set DA_CALIN_FLAG high to start calibration. Keep it high
|
||||||
|
* until AD_CAL_COMP is ready to output calibration result.
|
||||||
|
@@ -1305,8 +1295,8 @@ static struct phy_driver mtk_socphy_driv
|
||||||
|
.probe = mt7981_phy_probe,
|
||||||
|
.suspend = genphy_suspend,
|
||||||
|
.resume = genphy_resume,
|
||||||
|
- .read_page = mtk_socphy_read_page,
|
||||||
|
- .write_page = mtk_socphy_write_page,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
.led_blink_set = mt798x_phy_led_blink_set,
|
||||||
|
.led_brightness_set = mt798x_phy_led_brightness_set,
|
||||||
|
.led_hw_is_supported = mt798x_phy_led_hw_is_supported,
|
||||||
|
@@ -1322,8 +1312,8 @@ static struct phy_driver mtk_socphy_driv
|
||||||
|
.probe = mt7988_phy_probe,
|
||||||
|
.suspend = genphy_suspend,
|
||||||
|
.resume = genphy_resume,
|
||||||
|
- .read_page = mtk_socphy_read_page,
|
||||||
|
- .write_page = mtk_socphy_write_page,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
.led_blink_set = mt798x_phy_led_blink_set,
|
||||||
|
.led_brightness_set = mt798x_phy_led_brightness_set,
|
||||||
|
.led_hw_is_supported = mt798x_phy_led_hw_is_supported,
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
@@ -4,6 +4,8 @@
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/phy.h>
|
||||||
|
|
||||||
|
+#include "mtk.h"
|
||||||
|
+
|
||||||
|
#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||||
|
#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED 0x0001
|
||||||
|
@@ -12,16 +14,6 @@
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
||||||
|
|
||||||
|
-static int mtk_gephy_read_page(struct phy_device *phydev)
|
||||||
|
-{
|
||||||
|
- return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
-static int mtk_gephy_write_page(struct phy_device *phydev, int page)
|
||||||
|
-{
|
||||||
|
- return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
|
||||||
|
-}
|
||||||
|
-
|
||||||
|
static void mtk_gephy_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
/* Disable EEE */
|
||||||
|
@@ -114,8 +106,8 @@ static struct phy_driver mtk_gephy_drive
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
.suspend = genphy_suspend,
|
||||||
|
.resume = genphy_resume,
|
||||||
|
- .read_page = mtk_gephy_read_page,
|
||||||
|
- .write_page = mtk_gephy_write_page,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(0x03a29441),
|
||||||
|
@@ -128,8 +120,8 @@ static struct phy_driver mtk_gephy_drive
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
.suspend = genphy_suspend,
|
||||||
|
.resume = genphy_resume,
|
||||||
|
- .read_page = mtk_gephy_read_page,
|
||||||
|
- .write_page = mtk_gephy_write_page,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
@@ -6,6 +6,18 @@
|
||||||
|
|
||||||
|
#include "mtk.h"
|
||||||
|
|
||||||
|
+int mtk_phy_read_page(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_read_page);
|
||||||
|
+
|
||||||
|
+int mtk_phy_write_page(struct phy_device *phydev, int page)
|
||||||
|
+{
|
||||||
|
+ return __phy_write(phydev, MTK_EXT_PAGE_ACCESS, page);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_phy_write_page);
|
||||||
|
+
|
||||||
|
int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules,
|
||||||
|
unsigned long supported_triggers)
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk.h
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk.h
|
||||||
|
@@ -62,6 +62,9 @@
|
||||||
|
#define MTK_PHY_LED_STATE_FORCE_BLINK 1
|
||||||
|
#define MTK_PHY_LED_STATE_NETDEV 2
|
||||||
|
|
||||||
|
+int mtk_phy_read_page(struct phy_device *phydev);
|
||||||
|
+int mtk_phy_write_page(struct phy_device *phydev, int page);
|
||||||
|
+
|
||||||
|
int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules,
|
||||||
|
unsigned long supported_triggers);
|
@@ -0,0 +1,146 @@
|
|||||||
|
From 9403f1d54598ae56386a8bf47a5b6b34c884e4f5 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:10 +0800
|
||||||
|
Subject: [PATCH 06/13] net: phy: mediatek: Hook LED helper functions in
|
||||||
|
mtk-ge.c
|
||||||
|
|
||||||
|
We have mtk-phy-lib.c now so that we can use LED helper functions in
|
||||||
|
mtk-ge.c(mt7531 part). It also means that mt7531/mt7981/mt7988's
|
||||||
|
Giga ethernet phys share almost the same HW LED controller design.
|
||||||
|
Also, add probe function for mt7531 so that it can initialize LED state.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge.c | 100 ++++++++++++++++++++++++++++++
|
||||||
|
1 file changed, 100 insertions(+)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
@@ -14,6 +14,10 @@
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
||||||
|
|
||||||
|
+struct mtk_gephy_priv {
|
||||||
|
+ unsigned long led_state;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static void mtk_gephy_config_init(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
/* Disable EEE */
|
||||||
|
@@ -94,6 +98,96 @@ static int mt7531_phy_config_init(struct
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+static int mt7531_phy_probe(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ struct mtk_gephy_priv *priv;
|
||||||
|
+
|
||||||
|
+ priv = devm_kzalloc(&phydev->mdio.dev, sizeof(struct mtk_gephy_priv),
|
||||||
|
+ GFP_KERNEL);
|
||||||
|
+ if (!priv)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ phydev->priv = priv;
|
||||||
|
+
|
||||||
|
+ mtk_phy_leds_state_init(phydev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt753x_phy_led_blink_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *delay_on,
|
||||||
|
+ unsigned long *delay_off)
|
||||||
|
+{
|
||||||
|
+ struct mtk_gephy_priv *priv = phydev->priv;
|
||||||
|
+ bool blinking = false;
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
|
||||||
|
+ if (err < 0)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state,
|
||||||
|
+ blinking);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_MASK, false);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt753x_phy_led_brightness_set(struct phy_device *phydev,
|
||||||
|
+ u8 index, enum led_brightness value)
|
||||||
|
+{
|
||||||
|
+ struct mtk_gephy_priv *priv = phydev->priv;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state, false);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_MASK, (value != LED_OFF));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const unsigned long supported_triggers =
|
||||||
|
+ (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_TX));
|
||||||
|
+
|
||||||
|
+static int mt753x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long rules)
|
||||||
|
+{
|
||||||
|
+ return mtk_phy_led_hw_is_supported(phydev, index, rules,
|
||||||
|
+ supported_triggers);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt753x_phy_led_hw_control_get(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *rules)
|
||||||
|
+{
|
||||||
|
+ struct mtk_gephy_priv *priv = phydev->priv;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_led_hw_ctrl_get(phydev, index, rules, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_SET,
|
||||||
|
+ MTK_GPHY_LED_RX_BLINK_SET,
|
||||||
|
+ MTK_GPHY_LED_TX_BLINK_SET);
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int mt753x_phy_led_hw_control_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long rules)
|
||||||
|
+{
|
||||||
|
+ struct mtk_gephy_priv *priv = phydev->priv;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_led_hw_ctrl_set(phydev, index, rules, &priv->led_state,
|
||||||
|
+ MTK_GPHY_LED_ON_SET,
|
||||||
|
+ MTK_GPHY_LED_RX_BLINK_SET,
|
||||||
|
+ MTK_GPHY_LED_TX_BLINK_SET);
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
static struct phy_driver mtk_gephy_driver[] = {
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(0x03a29412),
|
||||||
|
@@ -112,6 +206,7 @@ static struct phy_driver mtk_gephy_drive
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(0x03a29441),
|
||||||
|
.name = "MediaTek MT7531 PHY",
|
||||||
|
+ .probe = mt7531_phy_probe,
|
||||||
|
.config_init = mt7531_phy_config_init,
|
||||||
|
/* Interrupts are handled by the switch, not the PHY
|
||||||
|
* itself.
|
||||||
|
@@ -122,6 +217,11 @@ static struct phy_driver mtk_gephy_drive
|
||||||
|
.resume = genphy_resume,
|
||||||
|
.read_page = mtk_phy_read_page,
|
||||||
|
.write_page = mtk_phy_write_page,
|
||||||
|
+ .led_blink_set = mt753x_phy_led_blink_set,
|
||||||
|
+ .led_brightness_set = mt753x_phy_led_brightness_set,
|
||||||
|
+ .led_hw_is_supported = mt753x_phy_led_hw_is_supported,
|
||||||
|
+ .led_hw_control_set = mt753x_phy_led_hw_control_set,
|
||||||
|
+ .led_hw_control_get = mt753x_phy_led_hw_control_get,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
@@ -0,0 +1,54 @@
|
|||||||
|
From 51ee83602dbb84716180d9b6e43f6bebb0c2d7bd Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:11 +0800
|
||||||
|
Subject: [PATCH 07/13] net: phy: mediatek: add MT7530 & MT7531's PHY ID macros
|
||||||
|
|
||||||
|
This patch adds MT7530 & MT7531's PHY ID macros in mtk-ge.c so that
|
||||||
|
it follows the same rule of mtk-ge-soc.c.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge.c | 11 +++++++----
|
||||||
|
1 file changed, 7 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
@@ -6,6 +6,9 @@
|
||||||
|
|
||||||
|
#include "mtk.h"
|
||||||
|
|
||||||
|
+#define MTK_GPHY_ID_MT7530 0x03a29412
|
||||||
|
+#define MTK_GPHY_ID_MT7531 0x03a29441
|
||||||
|
+
|
||||||
|
#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||||
|
#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED 0x0001
|
||||||
|
@@ -190,7 +193,7 @@ static int mt753x_phy_led_hw_control_set
|
||||||
|
|
||||||
|
static struct phy_driver mtk_gephy_driver[] = {
|
||||||
|
{
|
||||||
|
- PHY_ID_MATCH_EXACT(0x03a29412),
|
||||||
|
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
|
||||||
|
.name = "MediaTek MT7530 PHY",
|
||||||
|
.config_init = mt7530_phy_config_init,
|
||||||
|
/* Interrupts are handled by the switch, not the PHY
|
||||||
|
@@ -204,7 +207,7 @@ static struct phy_driver mtk_gephy_drive
|
||||||
|
.write_page = mtk_phy_write_page,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
- PHY_ID_MATCH_EXACT(0x03a29441),
|
||||||
|
+ PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
|
||||||
|
.name = "MediaTek MT7531 PHY",
|
||||||
|
.probe = mt7531_phy_probe,
|
||||||
|
.config_init = mt7531_phy_config_init,
|
||||||
|
@@ -228,8 +231,8 @@ static struct phy_driver mtk_gephy_drive
|
||||||
|
module_phy_driver(mtk_gephy_driver);
|
||||||
|
|
||||||
|
static struct mdio_device_id __maybe_unused mtk_gephy_tbl[] = {
|
||||||
|
- { PHY_ID_MATCH_EXACT(0x03a29441) },
|
||||||
|
- { PHY_ID_MATCH_EXACT(0x03a29412) },
|
||||||
|
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530) },
|
||||||
|
+ { PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531) },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
@@ -0,0 +1,182 @@
|
|||||||
|
From e73df692396b0d6bdcb2317299fa1e8e547f3446 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:12 +0800
|
||||||
|
Subject: [PATCH 08/13] net: phy: mediatek: Change mtk-ge-soc.c line wrapping
|
||||||
|
|
||||||
|
This patch shrinks mtk-ge-soc.c line wrapping to 80 characters.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 67 +++++++++++++++++----------
|
||||||
|
1 file changed, 42 insertions(+), 25 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -295,7 +295,8 @@ static int cal_cycle(struct phy_device *
|
||||||
|
ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND1,
|
||||||
|
MTK_PHY_RG_AD_CAL_CLK, reg_val,
|
||||||
|
reg_val & MTK_PHY_DA_CAL_CLK, 500,
|
||||||
|
- ANALOG_INTERNAL_OPERATION_MAX_US, false);
|
||||||
|
+ ANALOG_INTERNAL_OPERATION_MAX_US,
|
||||||
|
+ false);
|
||||||
|
if (ret) {
|
||||||
|
phydev_err(phydev, "Calibration cycle timeout\n");
|
||||||
|
return ret;
|
||||||
|
@@ -304,7 +305,7 @@ static int cal_cycle(struct phy_device *
|
||||||
|
phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CALIN,
|
||||||
|
MTK_PHY_DA_CALIN_FLAG);
|
||||||
|
ret = phy_read_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_AD_CAL_COMP) >>
|
||||||
|
- MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
|
||||||
|
+ MTK_PHY_AD_CAL_COMP_OUT_SHIFT;
|
||||||
|
phydev_dbg(phydev, "cal_val: 0x%x, ret: %d\n", cal_val, ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
@@ -394,38 +395,46 @@ static int tx_amp_fill_result(struct phy
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_A_GBE_MASK, (buf[0] + bias[0]) << 10);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_A_GBE_MASK,
|
||||||
|
+ (buf[0] + bias[0]) << 10);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TXVLD_DA_RG,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_A_TBT_MASK, buf[0] + bias[1]);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_A_HBT_MASK, (buf[0] + bias[2]) << 10);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_A_HBT_MASK,
|
||||||
|
+ (buf[0] + bias[2]) << 10);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_A2,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_A_TST_MASK, buf[0] + bias[3]);
|
||||||
|
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_B_GBE_MASK, (buf[1] + bias[4]) << 8);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_B_GBE_MASK,
|
||||||
|
+ (buf[1] + bias[4]) << 8);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B1,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_B_TBT_MASK, buf[1] + bias[5]);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_B_HBT_MASK, (buf[1] + bias[6]) << 8);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_B_HBT_MASK,
|
||||||
|
+ (buf[1] + bias[6]) << 8);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_B2,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_B_TST_MASK, buf[1] + bias[7]);
|
||||||
|
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_C_GBE_MASK, (buf[2] + bias[8]) << 8);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_C_GBE_MASK,
|
||||||
|
+ (buf[2] + bias[8]) << 8);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C1,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_C_TBT_MASK, buf[2] + bias[9]);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_C_HBT_MASK, (buf[2] + bias[10]) << 8);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_C_HBT_MASK,
|
||||||
|
+ (buf[2] + bias[10]) << 8);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_C2,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_C_TST_MASK, buf[2] + bias[11]);
|
||||||
|
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_D_GBE_MASK, (buf[3] + bias[12]) << 8);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_D_GBE_MASK,
|
||||||
|
+ (buf[3] + bias[12]) << 8);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D1,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_D_TBT_MASK, buf[3] + bias[13]);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
|
||||||
|
- MTK_PHY_DA_TX_I2MPB_D_HBT_MASK, (buf[3] + bias[14]) << 8);
|
||||||
|
+ MTK_PHY_DA_TX_I2MPB_D_HBT_MASK,
|
||||||
|
+ (buf[3] + bias[14]) << 8);
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TX_I2MPB_TEST_MODE_D2,
|
||||||
|
MTK_PHY_DA_TX_I2MPB_D_TST_MASK, buf[3] + bias[15]);
|
||||||
|
|
||||||
|
@@ -616,7 +625,8 @@ static int tx_vcm_cal_sw(struct phy_devi
|
||||||
|
goto restore;
|
||||||
|
|
||||||
|
/* We calibrate TX-VCM in different logic. Check upper index and then
|
||||||
|
- * lower index. If this calibration is valid, apply lower index's result.
|
||||||
|
+ * lower index. If this calibration is valid, apply lower index's
|
||||||
|
+ * result.
|
||||||
|
*/
|
||||||
|
ret = upper_ret - lower_ret;
|
||||||
|
if (ret == 1) {
|
||||||
|
@@ -645,7 +655,8 @@ static int tx_vcm_cal_sw(struct phy_devi
|
||||||
|
} else if (upper_idx == TXRESERVE_MAX && upper_ret == 0 &&
|
||||||
|
lower_ret == 0) {
|
||||||
|
ret = 0;
|
||||||
|
- phydev_warn(phydev, "TX-VCM SW cal result at high margin 0x%x\n",
|
||||||
|
+ phydev_warn(phydev,
|
||||||
|
+ "TX-VCM SW cal result at high margin 0x%x\n",
|
||||||
|
upper_idx);
|
||||||
|
} else {
|
||||||
|
ret = -EINVAL;
|
||||||
|
@@ -749,7 +760,8 @@ static void mt7981_phy_finetune(struct p
|
||||||
|
|
||||||
|
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
|
||||||
|
- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
|
||||||
|
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK |
|
||||||
|
+ MTK_PHY_LPF_X_AVERAGE_MASK,
|
||||||
|
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0x9));
|
||||||
|
|
||||||
|
/* rg_tr_lpf_cnt_val = 512 */
|
||||||
|
@@ -818,7 +830,8 @@ static void mt7988_phy_finetune(struct p
|
||||||
|
|
||||||
|
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_DEV1E_REG234,
|
||||||
|
- MTK_PHY_TR_OPEN_LOOP_EN_MASK | MTK_PHY_LPF_X_AVERAGE_MASK,
|
||||||
|
+ MTK_PHY_TR_OPEN_LOOP_EN_MASK |
|
||||||
|
+ MTK_PHY_LPF_X_AVERAGE_MASK,
|
||||||
|
BIT(0) | FIELD_PREP(MTK_PHY_LPF_X_AVERAGE_MASK, 0xa));
|
||||||
|
|
||||||
|
/* rg_tr_lpf_cnt_val = 1023 */
|
||||||
|
@@ -930,7 +943,8 @@ static void mt798x_phy_eee(struct phy_de
|
||||||
|
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
|
||||||
|
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
|
||||||
|
- __phy_modify(phydev, MTK_PHY_LPI_REG_14, MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
|
||||||
|
+ __phy_modify(phydev, MTK_PHY_LPI_REG_14,
|
||||||
|
+ MTK_PHY_LPI_WAKE_TIMER_1000_MASK,
|
||||||
|
FIELD_PREP(MTK_PHY_LPI_WAKE_TIMER_1000_MASK, 0x19c));
|
||||||
|
|
||||||
|
__phy_modify(phydev, MTK_PHY_LPI_REG_1c, MTK_PHY_SMI_DET_ON_THRESH_MASK,
|
||||||
|
@@ -940,7 +954,8 @@ static void mt798x_phy_eee(struct phy_de
|
||||||
|
phy_modify_mmd(phydev, MDIO_MMD_VEND1,
|
||||||
|
MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG122,
|
||||||
|
MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
|
||||||
|
- FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK, 0xff));
|
||||||
|
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH1000_MASK,
|
||||||
|
+ 0xff));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cal_sw(struct phy_device *phydev, enum CAL_ITEM cal_item,
|
||||||
|
@@ -1119,14 +1134,15 @@ static int mt798x_phy_led_brightness_set
|
||||||
|
MTK_GPHY_LED_ON_MASK, (value != LED_OFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
-static const unsigned long supported_triggers = (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
- BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_TX));
|
||||||
|
+static const unsigned long supported_triggers =
|
||||||
|
+ (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_TX));
|
||||||
|
|
||||||
|
static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules)
|
||||||
|
@@ -1189,7 +1205,8 @@ static int mt7988_phy_fix_leds_polaritie
|
||||||
|
/* Only now setup pinctrl to avoid bogus blinking */
|
||||||
|
pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "gbe-led");
|
||||||
|
if (IS_ERR(pinctrl))
|
||||||
|
- dev_err(&phydev->mdio.bus->dev, "Failed to setup PHY LED pinctrl\n");
|
||||||
|
+ dev_err(&phydev->mdio.bus->dev,
|
||||||
|
+ "Failed to setup PHY LED pinctrl\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -0,0 +1,614 @@
|
|||||||
|
From 60228de48d8bfde62b4db5945314e6a62079f091 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:13 +0800
|
||||||
|
Subject: [PATCH 09/13] net: phy: mediatek: Add token ring access helper
|
||||||
|
functions in mtk-phy-lib
|
||||||
|
|
||||||
|
This patch adds TR(token ring) manipulations and adds correct
|
||||||
|
macro names for those magic numbers. TR is a way to access
|
||||||
|
proprietary registers on page 52b5. Use these helper functions
|
||||||
|
so we can see which fields we're going to modify/set/clear.
|
||||||
|
|
||||||
|
This patch doesn't really change registers' settings but just
|
||||||
|
enhances readability and maintainability.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 297 ++++++++++++++++---------
|
||||||
|
drivers/net/phy/mediatek/mtk-ge.c | 82 +++++--
|
||||||
|
drivers/net/phy/mediatek/mtk-phy-lib.c | 91 ++++++++
|
||||||
|
drivers/net/phy/mediatek/mtk.h | 13 ++
|
||||||
|
4 files changed, 358 insertions(+), 125 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -24,7 +24,108 @@
|
||||||
|
#define MTK_PHY_SMI_DET_ON_THRESH_MASK GENMASK(13, 8)
|
||||||
|
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
|
||||||
|
-#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
||||||
|
+
|
||||||
|
+/* Registers on Token Ring debug nodes */
|
||||||
|
+/* ch_addr = 0x0, node_addr = 0x7, data_addr = 0x15 */
|
||||||
|
+/* NormMseLoThresh */
|
||||||
|
+#define NORMAL_MSE_LO_THRESH_MASK GENMASK(15, 8)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
|
||||||
|
+/* RemAckCntLimitCtrl */
|
||||||
|
+#define REMOTE_ACK_COUNT_LIMIT_CTRL_MASK GENMASK(2, 1)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xd, data_addr = 0x20 */
|
||||||
|
+/* VcoSlicerThreshBitsHigh */
|
||||||
|
+#define VCO_SLICER_THRESH_HIGH_MASK GENMASK(23, 0)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x0 */
|
||||||
|
+/* DfeTailEnableVgaThresh1000 */
|
||||||
|
+#define DFE_TAIL_EANBLE_VGA_TRHESH_1000 GENMASK(5, 1)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x1 */
|
||||||
|
+/* MrvlTrFix100Kp */
|
||||||
|
+#define MRVL_TR_FIX_100KP_MASK GENMASK(22, 20)
|
||||||
|
+/* MrvlTrFix100Kf */
|
||||||
|
+#define MRVL_TR_FIX_100KF_MASK GENMASK(19, 17)
|
||||||
|
+/* MrvlTrFix1000Kp */
|
||||||
|
+#define MRVL_TR_FIX_1000KP_MASK GENMASK(16, 14)
|
||||||
|
+/* MrvlTrFix1000Kf */
|
||||||
|
+#define MRVL_TR_FIX_1000KF_MASK GENMASK(13, 11)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x12 */
|
||||||
|
+/* VgaDecRate */
|
||||||
|
+#define VGA_DECIMATION_RATE_MASK GENMASK(8, 5)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
|
||||||
|
+/* SlvDSPreadyTime */
|
||||||
|
+#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15)
|
||||||
|
+/* MasDSPreadyTime */
|
||||||
|
+#define MASTER_DSP_READY_TIME_MASK GENMASK(14, 7)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x18 */
|
||||||
|
+/* EnabRandUpdTrig */
|
||||||
|
+#define ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER BIT(8)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x20 */
|
||||||
|
+/* ResetSyncOffset */
|
||||||
|
+#define RESET_SYNC_OFFSET_MASK GENMASK(11, 8)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x0 */
|
||||||
|
+/* FfeUpdGainForceVal */
|
||||||
|
+#define FFE_UPDATE_GAIN_FORCE_VAL_MASK GENMASK(9, 7)
|
||||||
|
+/* FfeUpdGainForce */
|
||||||
|
+#define FFE_UPDATE_GAIN_FORCE BIT(6)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x3 */
|
||||||
|
+/* TrFreeze */
|
||||||
|
+#define TR_FREEZE_MASK GENMASK(11, 0)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x6 */
|
||||||
|
+/* SS: Steady-state, KP: Proportional Gain */
|
||||||
|
+/* SSTrKp100 */
|
||||||
|
+#define SS_TR_KP100_MASK GENMASK(21, 19)
|
||||||
|
+/* SSTrKf100 */
|
||||||
|
+#define SS_TR_KF100_MASK GENMASK(18, 16)
|
||||||
|
+/* SSTrKp1000Mas */
|
||||||
|
+#define SS_TR_KP1000_MASTER_MASK GENMASK(15, 13)
|
||||||
|
+/* SSTrKf1000Mas */
|
||||||
|
+#define SS_TR_KF1000_MASTER_MASK GENMASK(12, 10)
|
||||||
|
+/* SSTrKp1000Slv */
|
||||||
|
+#define SS_TR_KP1000_SLAVE_MASK GENMASK(9, 7)
|
||||||
|
+/* SSTrKf1000Slv */
|
||||||
|
+#define SS_TR_KF1000_SLAVE_MASK GENMASK(6, 4)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x8 */
|
||||||
|
+/* clear this bit if wanna select from AFE */
|
||||||
|
+/* Regsigdet_sel_1000 */
|
||||||
|
+#define EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE BIT(4)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xd */
|
||||||
|
+/* RegEEE_st2TrKf1000 */
|
||||||
|
+#define EEE1000_STAGE2_TR_KF_MASK GENMASK(13, 11)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0xf */
|
||||||
|
+/* RegEEE_slv_waketr_timer_tar */
|
||||||
|
+#define SLAVE_WAKETR_TIMER_MASK GENMASK(20, 11)
|
||||||
|
+/* RegEEE_slv_remtx_timer_tar */
|
||||||
|
+#define SLAVE_REMTX_TIMER_MASK GENMASK(10, 1)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x10 */
|
||||||
|
+/* RegEEE_slv_wake_int_timer_tar */
|
||||||
|
+#define SLAVE_WAKEINT_TIMER_MASK GENMASK(10, 1)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x14 */
|
||||||
|
+/* RegEEE_trfreeze_timer2 */
|
||||||
|
+#define TR_FREEZE_TIMER2_MASK GENMASK(9, 0)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x1c */
|
||||||
|
+/* RegEEE100Stg1_tar */
|
||||||
|
+#define EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK GENMASK(8, 0)
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x2, node_addr = 0xd, data_addr = 0x25 */
|
||||||
|
+/* REGEEE_wake_slv_tr_wait_dfesigdet_en */
|
||||||
|
+#define WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN BIT(11)
|
||||||
|
+
|
||||||
|
|
||||||
|
#define ANALOG_INTERNAL_OPERATION_MAX_US 20
|
||||||
|
#define TXRESERVE_MIN 0
|
||||||
|
@@ -679,40 +780,36 @@ restore:
|
||||||
|
static void mt798x_phy_common_finetune(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||||
|
- /* SlvDSPreadyTime = 24, MasDSPreadyTime = 24 */
|
||||||
|
- __phy_write(phydev, 0x11, 0xc71);
|
||||||
|
- __phy_write(phydev, 0x12, 0xc);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8fae);
|
||||||
|
-
|
||||||
|
- /* EnabRandUpdTrig = 1 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x2f00);
|
||||||
|
- __phy_write(phydev, 0x12, 0xe);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8fb0);
|
||||||
|
-
|
||||||
|
- /* NormMseLoThresh = 85 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x55a0);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x83aa);
|
||||||
|
-
|
||||||
|
- /* FfeUpdGainForce = 1(Enable), FfeUpdGainForceVal = 4 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x240);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x9680);
|
||||||
|
-
|
||||||
|
- /* TrFreeze = 0 (mt7988 default) */
|
||||||
|
- __phy_write(phydev, 0x11, 0x0);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x9686);
|
||||||
|
-
|
||||||
|
- /* SSTrKp100 = 5 */
|
||||||
|
- /* SSTrKf100 = 6 */
|
||||||
|
- /* SSTrKp1000Mas = 5 */
|
||||||
|
- /* SSTrKf1000Mas = 6 */
|
||||||
|
- /* SSTrKp1000Slv = 5 */
|
||||||
|
- /* SSTrKf1000Slv = 6 */
|
||||||
|
- __phy_write(phydev, 0x11, 0xbaef);
|
||||||
|
- __phy_write(phydev, 0x12, 0x2e);
|
||||||
|
- __phy_write(phydev, 0x10, 0x968c);
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x17,
|
||||||
|
+ SLAVE_DSP_READY_TIME_MASK | MASTER_DSP_READY_TIME_MASK,
|
||||||
|
+ FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x18) |
|
||||||
|
+ FIELD_PREP(MASTER_DSP_READY_TIME_MASK, 0x18));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_set_bits(phydev, 0x1, 0xf, 0x18,
|
||||||
|
+ ENABLE_RANDOM_UPDOWN_COUNTER_TRIGGER);
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x0, 0x7, 0x15,
|
||||||
|
+ NORMAL_MSE_LO_THRESH_MASK,
|
||||||
|
+ FIELD_PREP(NORMAL_MSE_LO_THRESH_MASK, 0x55));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x0,
|
||||||
|
+ FFE_UPDATE_GAIN_FORCE_VAL_MASK,
|
||||||
|
+ FIELD_PREP(FFE_UPDATE_GAIN_FORCE_VAL_MASK, 0x4) |
|
||||||
|
+ FFE_UPDATE_GAIN_FORCE);
|
||||||
|
+
|
||||||
|
+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x3, TR_FREEZE_MASK);
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x6,
|
||||||
|
+ SS_TR_KP100_MASK | SS_TR_KF100_MASK |
|
||||||
|
+ SS_TR_KP1000_MASTER_MASK | SS_TR_KF1000_MASTER_MASK |
|
||||||
|
+ SS_TR_KP1000_SLAVE_MASK | SS_TR_KF1000_SLAVE_MASK,
|
||||||
|
+ FIELD_PREP(SS_TR_KP100_MASK, 0x5) |
|
||||||
|
+ FIELD_PREP(SS_TR_KF100_MASK, 0x6) |
|
||||||
|
+ FIELD_PREP(SS_TR_KP1000_MASTER_MASK, 0x5) |
|
||||||
|
+ FIELD_PREP(SS_TR_KF1000_MASTER_MASK, 0x6) |
|
||||||
|
+ FIELD_PREP(SS_TR_KP1000_SLAVE_MASK, 0x5) |
|
||||||
|
+ FIELD_PREP(SS_TR_KF1000_SLAVE_MASK, 0x6));
|
||||||
|
+
|
||||||
|
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -735,27 +832,29 @@ static void mt7981_phy_finetune(struct p
|
||||||
|
}
|
||||||
|
|
||||||
|
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||||
|
- /* ResetSyncOffset = 6 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x600);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8fc0);
|
||||||
|
-
|
||||||
|
- /* VgaDecRate = 1 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x4c2a);
|
||||||
|
- __phy_write(phydev, 0x12, 0x3e);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8fa4);
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x20,
|
||||||
|
+ RESET_SYNC_OFFSET_MASK,
|
||||||
|
+ FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x6));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x12,
|
||||||
|
+ VGA_DECIMATION_RATE_MASK,
|
||||||
|
+ FIELD_PREP(VGA_DECIMATION_RATE_MASK, 0x1));
|
||||||
|
|
||||||
|
/* MrvlTrFix100Kp = 3, MrvlTrFix100Kf = 2,
|
||||||
|
* MrvlTrFix1000Kp = 3, MrvlTrFix1000Kf = 2
|
||||||
|
*/
|
||||||
|
- __phy_write(phydev, 0x11, 0xd10a);
|
||||||
|
- __phy_write(phydev, 0x12, 0x34);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8f82);
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x1,
|
||||||
|
+ MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK |
|
||||||
|
+ MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK,
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x3) |
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x2) |
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x3) |
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x2));
|
||||||
|
|
||||||
|
/* VcoSlicerThreshBitsHigh */
|
||||||
|
- __phy_write(phydev, 0x11, 0x5555);
|
||||||
|
- __phy_write(phydev, 0x12, 0x55);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8ec0);
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xd, 0x20,
|
||||||
|
+ VCO_SLICER_THRESH_HIGH_MASK,
|
||||||
|
+ FIELD_PREP(VCO_SLICER_THRESH_HIGH_MASK, 0x555555));
|
||||||
|
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
|
||||||
|
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 9 */
|
||||||
|
@@ -807,25 +906,23 @@ static void mt7988_phy_finetune(struct p
|
||||||
|
phy_write_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RG_TX_FILTER, 0x5);
|
||||||
|
|
||||||
|
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||||
|
- /* ResetSyncOffset = 5 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x500);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8fc0);
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x20,
|
||||||
|
+ RESET_SYNC_OFFSET_MASK,
|
||||||
|
+ FIELD_PREP(RESET_SYNC_OFFSET_MASK, 0x5));
|
||||||
|
|
||||||
|
/* VgaDecRate is 1 at default on mt7988 */
|
||||||
|
|
||||||
|
- /* MrvlTrFix100Kp = 6, MrvlTrFix100Kf = 7,
|
||||||
|
- * MrvlTrFix1000Kp = 6, MrvlTrFix1000Kf = 7
|
||||||
|
- */
|
||||||
|
- __phy_write(phydev, 0x11, 0xb90a);
|
||||||
|
- __phy_write(phydev, 0x12, 0x6f);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8f82);
|
||||||
|
-
|
||||||
|
- /* RemAckCntLimitCtrl = 1 */
|
||||||
|
- __phy_write(phydev, 0x11, 0xfbba);
|
||||||
|
- __phy_write(phydev, 0x12, 0xc3);
|
||||||
|
- __phy_write(phydev, 0x10, 0x87f8);
|
||||||
|
-
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x1,
|
||||||
|
+ MRVL_TR_FIX_100KP_MASK | MRVL_TR_FIX_100KF_MASK |
|
||||||
|
+ MRVL_TR_FIX_1000KP_MASK | MRVL_TR_FIX_1000KF_MASK,
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_100KP_MASK, 0x6) |
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_100KF_MASK, 0x7) |
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_1000KP_MASK, 0x6) |
|
||||||
|
+ FIELD_PREP(MRVL_TR_FIX_1000KF_MASK, 0x7));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
|
||||||
|
+ REMOTE_ACK_COUNT_LIMIT_CTRL_MASK,
|
||||||
|
+ FIELD_PREP(REMOTE_ACK_COUNT_LIMIT_CTRL_MASK, 0x1));
|
||||||
|
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
|
||||||
|
/* TR_OPEN_LOOP_EN = 1, lpf_x_average = 10 */
|
||||||
|
@@ -901,45 +998,37 @@ static void mt798x_phy_eee(struct phy_de
|
||||||
|
MTK_PHY_TR_READY_SKIP_AFE_WAKEUP);
|
||||||
|
|
||||||
|
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||||
|
- /* Regsigdet_sel_1000 = 0 */
|
||||||
|
- __phy_write(phydev, 0x11, 0xb);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x9690);
|
||||||
|
-
|
||||||
|
- /* REG_EEE_st2TrKf1000 = 2 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x114f);
|
||||||
|
- __phy_write(phydev, 0x12, 0x2);
|
||||||
|
- __phy_write(phydev, 0x10, 0x969a);
|
||||||
|
-
|
||||||
|
- /* RegEEE_slv_wake_tr_timer_tar = 6, RegEEE_slv_remtx_timer_tar = 20 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x3028);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x969e);
|
||||||
|
-
|
||||||
|
- /* RegEEE_slv_wake_int_timer_tar = 8 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x5010);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x96a0);
|
||||||
|
-
|
||||||
|
- /* RegEEE_trfreeze_timer2 = 586 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x24a);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x96a8);
|
||||||
|
-
|
||||||
|
- /* RegEEE100Stg1_tar = 16 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x3210);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x96b8);
|
||||||
|
-
|
||||||
|
- /* REGEEE_wake_slv_tr_wait_dfesigdet_en = 0 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x1463);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x96ca);
|
||||||
|
-
|
||||||
|
- /* DfeTailEnableVgaThresh1000 = 27 */
|
||||||
|
- __phy_write(phydev, 0x11, 0x36);
|
||||||
|
- __phy_write(phydev, 0x12, 0x0);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8f80);
|
||||||
|
+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x8,
|
||||||
|
+ EEE1000_SELECT_SIGNAL_DETECTION_FROM_DFE);
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0xd,
|
||||||
|
+ EEE1000_STAGE2_TR_KF_MASK,
|
||||||
|
+ FIELD_PREP(EEE1000_STAGE2_TR_KF_MASK, 0x2));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0xf,
|
||||||
|
+ SLAVE_WAKETR_TIMER_MASK | SLAVE_REMTX_TIMER_MASK,
|
||||||
|
+ FIELD_PREP(SLAVE_WAKETR_TIMER_MASK, 0x6) |
|
||||||
|
+ FIELD_PREP(SLAVE_REMTX_TIMER_MASK, 0x14));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x10,
|
||||||
|
+ SLAVE_WAKEINT_TIMER_MASK,
|
||||||
|
+ FIELD_PREP(SLAVE_WAKEINT_TIMER_MASK, 0x8));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x14,
|
||||||
|
+ TR_FREEZE_TIMER2_MASK,
|
||||||
|
+ FIELD_PREP(TR_FREEZE_TIMER2_MASK, 0x24a));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x2, 0xd, 0x1c,
|
||||||
|
+ EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK,
|
||||||
|
+ FIELD_PREP(EEE100_LPSYNC_STAGE1_UPDATE_TIMER_MASK,
|
||||||
|
+ 0x10));
|
||||||
|
+
|
||||||
|
+ __mtk_tr_clr_bits(phydev, 0x2, 0xd, 0x25,
|
||||||
|
+ WAKE_SLAVE_TR_WAIT_DFE_DETECTION_EN);
|
||||||
|
+
|
||||||
|
+ __mtk_tr_modify(phydev, 0x1, 0xf, 0x0,
|
||||||
|
+ DFE_TAIL_EANBLE_VGA_TRHESH_1000,
|
||||||
|
+ FIELD_PREP(DFE_TAIL_EANBLE_VGA_TRHESH_1000, 0x1b));
|
||||||
|
phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
|
||||||
|
phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_3);
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
@@ -9,13 +9,35 @@
|
||||||
|
#define MTK_GPHY_ID_MT7530 0x03a29412
|
||||||
|
#define MTK_GPHY_ID_MT7531 0x03a29441
|
||||||
|
|
||||||
|
-#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||||
|
-#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||||
|
-#define MTK_PHY_PAGE_EXTENDED 0x0001
|
||||||
|
-#define MTK_PHY_PAGE_EXTENDED_2 0x0002
|
||||||
|
-#define MTK_PHY_PAGE_EXTENDED_3 0x0003
|
||||||
|
-#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
|
||||||
|
-#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
||||||
|
+#define MTK_PHY_PAGE_EXTENDED_1 0x0001
|
||||||
|
+#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14
|
||||||
|
+#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4)
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_PAGE_EXTENDED_2 0x0002
|
||||||
|
+#define MTK_PHY_PAGE_EXTENDED_3 0x0003
|
||||||
|
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11 0x11
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_PAGE_EXTENDED_2A30 0x2a30
|
||||||
|
+
|
||||||
|
+/* Registers on Token Ring debug nodes */
|
||||||
|
+/* ch_addr = 0x1, node_addr = 0xf, data_addr = 0x17 */
|
||||||
|
+#define SLAVE_DSP_READY_TIME_MASK GENMASK(22, 15)
|
||||||
|
+
|
||||||
|
+/* Registers on MDIO_MMD_VEND1 */
|
||||||
|
+#define MTK_PHY_GBE_MODE_TX_DELAY_SEL 0x13
|
||||||
|
+#define MTK_PHY_TEST_MODE_TX_DELAY_SEL 0x14
|
||||||
|
+#define MTK_TX_DELAY_PAIR_B_MASK GENMASK(10, 8)
|
||||||
|
+#define MTK_TX_DELAY_PAIR_D_MASK GENMASK(2, 0)
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL 0xa6
|
||||||
|
+#define MTK_MCC_NEARECHO_OFFSET_MASK GENMASK(15, 8)
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_RXADC_CTRL_RG7 0xc6
|
||||||
|
+#define MTK_PHY_DA_AD_BUF_BIAS_LP_MASK GENMASK(9, 8)
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123 0x123
|
||||||
|
+#define MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK GENMASK(15, 8)
|
||||||
|
+#define MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK GENMASK(7, 0)
|
||||||
|
|
||||||
|
struct mtk_gephy_priv {
|
||||||
|
unsigned long led_state;
|
||||||
|
@@ -27,20 +49,29 @@ static void mtk_gephy_config_init(struct
|
||||||
|
phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, 0);
|
||||||
|
|
||||||
|
/* Enable HW auto downshift */
|
||||||
|
- phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED, 0x14, 0, BIT(4));
|
||||||
|
+ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
|
||||||
|
+ MTK_PHY_AUX_CTRL_AND_STATUS,
|
||||||
|
+ 0, MTK_PHY_ENABLE_DOWNSHIFT);
|
||||||
|
|
||||||
|
/* Increase SlvDPSready time */
|
||||||
|
- phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||||
|
- __phy_write(phydev, 0x10, 0xafae);
|
||||||
|
- __phy_write(phydev, 0x12, 0x2f);
|
||||||
|
- __phy_write(phydev, 0x10, 0x8fae);
|
||||||
|
- phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
+ mtk_tr_modify(phydev, 0x1, 0xf, 0x17, SLAVE_DSP_READY_TIME_MASK,
|
||||||
|
+ FIELD_PREP(SLAVE_DSP_READY_TIME_MASK, 0x5e));
|
||||||
|
|
||||||
|
/* Adjust 100_mse_threshold */
|
||||||
|
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x123, 0xffff);
|
||||||
|
-
|
||||||
|
- /* Disable mcc */
|
||||||
|
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0xa6, 0x300);
|
||||||
|
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
|
||||||
|
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG123,
|
||||||
|
+ MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK |
|
||||||
|
+ MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
|
||||||
|
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_LO_THRESH100_MASK,
|
||||||
|
+ 0xff) |
|
||||||
|
+ FIELD_PREP(MTK_PHY_LPI_NORM_MSE_HI_THRESH100_MASK,
|
||||||
|
+ 0xff));
|
||||||
|
+
|
||||||
|
+ /* If echo time is narrower than 0x3, it will be regarded as noise */
|
||||||
|
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1,
|
||||||
|
+ MTK_PHY_MCC_CTRL_AND_TX_POWER_CTRL,
|
||||||
|
+ MTK_MCC_NEARECHO_OFFSET_MASK,
|
||||||
|
+ FIELD_PREP(MTK_MCC_NEARECHO_OFFSET_MASK, 0x3));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int mt7530_phy_config_init(struct phy_device *phydev)
|
||||||
|
@@ -48,7 +79,8 @@ static int mt7530_phy_config_init(struct
|
||||||
|
mtk_gephy_config_init(phydev);
|
||||||
|
|
||||||
|
/* Increase post_update_timer */
|
||||||
|
- phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3, 0x11, 0x4b);
|
||||||
|
+ phy_write_paged(phydev, MTK_PHY_PAGE_EXTENDED_3,
|
||||||
|
+ MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11, 0x4b);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
@@ -89,11 +121,19 @@ static int mt7531_phy_config_init(struct
|
||||||
|
|
||||||
|
/* PHY link down power saving enable */
|
||||||
|
phy_set_bits(phydev, 0x17, BIT(4));
|
||||||
|
- phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1, 0xc6, 0x300);
|
||||||
|
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_RXADC_CTRL_RG7,
|
||||||
|
+ MTK_PHY_DA_AD_BUF_BIAS_LP_MASK,
|
||||||
|
+ FIELD_PREP(MTK_PHY_DA_AD_BUF_BIAS_LP_MASK, 0x3));
|
||||||
|
|
||||||
|
/* Set TX Pair delay selection */
|
||||||
|
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x13, 0x404);
|
||||||
|
- phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x14, 0x404);
|
||||||
|
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_GBE_MODE_TX_DELAY_SEL,
|
||||||
|
+ MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
|
||||||
|
+ FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
|
||||||
|
+ FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
|
||||||
|
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_TEST_MODE_TX_DELAY_SEL,
|
||||||
|
+ MTK_TX_DELAY_PAIR_B_MASK | MTK_TX_DELAY_PAIR_D_MASK,
|
||||||
|
+ FIELD_PREP(MTK_TX_DELAY_PAIR_B_MASK, 0x4) |
|
||||||
|
+ FIELD_PREP(MTK_TX_DELAY_PAIR_D_MASK, 0x4));
|
||||||
|
|
||||||
|
/* LED Config*/
|
||||||
|
mt7530_led_config_of(phydev);
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
@@ -6,6 +6,97 @@
|
||||||
|
|
||||||
|
#include "mtk.h"
|
||||||
|
|
||||||
|
+/* Difference between functions with mtk_tr* and __mtk_tr* prefixes is
|
||||||
|
+ * mtk_tr* functions: wrapped by page switching operations
|
||||||
|
+ * __mtk_tr* functions: no page switching operations
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+static void __mtk_tr_access(struct phy_device *phydev, bool read, u8 ch_addr,
|
||||||
|
+ u8 node_addr, u8 data_addr)
|
||||||
|
+{
|
||||||
|
+ u16 tr_cmd = BIT(15); /* bit 14 & 0 are reserved */
|
||||||
|
+
|
||||||
|
+ if (read)
|
||||||
|
+ tr_cmd |= BIT(13);
|
||||||
|
+
|
||||||
|
+ tr_cmd |= (((ch_addr & 0x3) << 11) |
|
||||||
|
+ ((node_addr & 0xf) << 7) |
|
||||||
|
+ ((data_addr & 0x3f) << 1));
|
||||||
|
+ dev_dbg(&phydev->mdio.dev, "tr_cmd: 0x%x\n", tr_cmd);
|
||||||
|
+ __phy_write(phydev, 0x10, tr_cmd);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u16 *tr_high, u16 *tr_low)
|
||||||
|
+{
|
||||||
|
+ __mtk_tr_access(phydev, true, ch_addr, node_addr, data_addr);
|
||||||
|
+ *tr_low = __phy_read(phydev, 0x11);
|
||||||
|
+ *tr_high = __phy_read(phydev, 0x12);
|
||||||
|
+ dev_dbg(&phydev->mdio.dev, "tr_high read: 0x%x, tr_low read: 0x%x\n",
|
||||||
|
+ *tr_high, *tr_low);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr)
|
||||||
|
+{
|
||||||
|
+ u16 tr_high;
|
||||||
|
+ u16 tr_low;
|
||||||
|
+
|
||||||
|
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||||
|
+ __mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
|
||||||
|
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
+
|
||||||
|
+ return (tr_high << 16) | tr_low;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_tr_read);
|
||||||
|
+
|
||||||
|
+static void __mtk_tr_write(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 tr_data)
|
||||||
|
+{
|
||||||
|
+ __phy_write(phydev, 0x11, tr_data & 0xffff);
|
||||||
|
+ __phy_write(phydev, 0x12, tr_data >> 16);
|
||||||
|
+ dev_dbg(&phydev->mdio.dev, "tr_high write: 0x%x, tr_low write: 0x%x\n",
|
||||||
|
+ tr_data >> 16, tr_data & 0xffff);
|
||||||
|
+ __mtk_tr_access(phydev, false, ch_addr, node_addr, data_addr);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 mask, u32 set)
|
||||||
|
+{
|
||||||
|
+ u32 tr_data;
|
||||||
|
+ u16 tr_high;
|
||||||
|
+ u16 tr_low;
|
||||||
|
+
|
||||||
|
+ __mtk_tr_read(phydev, ch_addr, node_addr, data_addr, &tr_high, &tr_low);
|
||||||
|
+ tr_data = (tr_high << 16) | tr_low;
|
||||||
|
+ tr_data = (tr_data & ~mask) | set;
|
||||||
|
+ __mtk_tr_write(phydev, ch_addr, node_addr, data_addr, tr_data);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(__mtk_tr_modify);
|
||||||
|
+
|
||||||
|
+void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 mask, u32 set)
|
||||||
|
+{
|
||||||
|
+ phy_select_page(phydev, MTK_PHY_PAGE_EXTENDED_52B5);
|
||||||
|
+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, mask, set);
|
||||||
|
+ phy_restore_page(phydev, MTK_PHY_PAGE_STANDARD, 0);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_tr_modify);
|
||||||
|
+
|
||||||
|
+void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 set)
|
||||||
|
+{
|
||||||
|
+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, 0, set);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(__mtk_tr_set_bits);
|
||||||
|
+
|
||||||
|
+void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 clr)
|
||||||
|
+{
|
||||||
|
+ __mtk_tr_modify(phydev, ch_addr, node_addr, data_addr, clr, 0);
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(__mtk_tr_clr_bits);
|
||||||
|
+
|
||||||
|
int mtk_phy_read_page(struct phy_device *phydev)
|
||||||
|
{
|
||||||
|
return __phy_read(phydev, MTK_EXT_PAGE_ACCESS);
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk.h
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk.h
|
||||||
|
@@ -9,6 +9,8 @@
|
||||||
|
#define _MTK_EPHY_H_
|
||||||
|
|
||||||
|
#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||||
|
+#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||||
|
+#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
||||||
|
|
||||||
|
/* Registers on MDIO_MMD_VEND2 */
|
||||||
|
#define MTK_PHY_LED0_ON_CTRL 0x24
|
||||||
|
@@ -62,6 +64,17 @@
|
||||||
|
#define MTK_PHY_LED_STATE_FORCE_BLINK 1
|
||||||
|
#define MTK_PHY_LED_STATE_NETDEV 2
|
||||||
|
|
||||||
|
+u32 mtk_tr_read(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr);
|
||||||
|
+void __mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 mask, u32 set);
|
||||||
|
+void mtk_tr_modify(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 mask, u32 set);
|
||||||
|
+void __mtk_tr_set_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 set);
|
||||||
|
+void __mtk_tr_clr_bits(struct phy_device *phydev, u8 ch_addr, u8 node_addr,
|
||||||
|
+ u8 data_addr, u32 clr);
|
||||||
|
+
|
||||||
|
int mtk_phy_read_page(struct phy_device *phydev);
|
||||||
|
int mtk_phy_write_page(struct phy_device *phydev, int page);
|
||||||
|
|
@@ -0,0 +1,209 @@
|
|||||||
|
From 3c05195fc2c232cd853fc8cebf55310c4605111d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:14 +0800
|
||||||
|
Subject: [PATCH 10/13] net: phy: mediatek: Extend 1G TX/RX link pulse time
|
||||||
|
|
||||||
|
We observe that some 10G devices' (mostly Marvell's chips inside) 1G
|
||||||
|
training time violates specification, which may last 2230ms and affect
|
||||||
|
later TX/RX link pulse time. This will invalidate MediaTek series
|
||||||
|
gigabit Ethernet PHYs' hardware auto downshift mechanism.
|
||||||
|
|
||||||
|
Without this patch, if someone is trying to use "4-wire" cable to
|
||||||
|
connect above devices, MediaTek' gigabit Ethernet PHYs may fail
|
||||||
|
to downshift to 100Mbps. (If partner 10G devices' downshift mechanism
|
||||||
|
stops at 1G)
|
||||||
|
|
||||||
|
This patch extends our 1G TX/RX link pulse time so that we can still
|
||||||
|
link up with those 10G devices.
|
||||||
|
|
||||||
|
Tested device:
|
||||||
|
- Netgear GS110EMX's 10G port (Marvell 88X3340P)
|
||||||
|
- QNAP QSW-M408-4C
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 2 +
|
||||||
|
drivers/net/phy/mediatek/mtk-ge.c | 5 +-
|
||||||
|
drivers/net/phy/mediatek/mtk-phy-lib.c | 92 ++++++++++++++++++++++++++
|
||||||
|
drivers/net/phy/mediatek/mtk.h | 21 ++++++
|
||||||
|
4 files changed, 116 insertions(+), 4 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -1396,6 +1396,7 @@ static struct phy_driver mtk_socphy_driv
|
||||||
|
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
|
||||||
|
.name = "MediaTek MT7981 PHY",
|
||||||
|
.config_init = mt798x_phy_config_init,
|
||||||
|
+ .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
.config_intr = genphy_no_config_intr,
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
.probe = mt7981_phy_probe,
|
||||||
|
@@ -1413,6 +1414,7 @@ static struct phy_driver mtk_socphy_driv
|
||||||
|
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
|
||||||
|
.name = "MediaTek MT7988 PHY",
|
||||||
|
.config_init = mt798x_phy_config_init,
|
||||||
|
+ .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
.config_intr = genphy_no_config_intr,
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
.probe = mt7988_phy_probe,
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
@@ -9,10 +9,6 @@
|
||||||
|
#define MTK_GPHY_ID_MT7530 0x03a29412
|
||||||
|
#define MTK_GPHY_ID_MT7531 0x03a29441
|
||||||
|
|
||||||
|
-#define MTK_PHY_PAGE_EXTENDED_1 0x0001
|
||||||
|
-#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14
|
||||||
|
-#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4)
|
||||||
|
-
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_2 0x0002
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_3 0x0003
|
||||||
|
#define MTK_PHY_RG_LPI_PCS_DSP_CTRL_REG11 0x11
|
||||||
|
@@ -251,6 +247,7 @@ static struct phy_driver mtk_gephy_drive
|
||||||
|
.name = "MediaTek MT7531 PHY",
|
||||||
|
.probe = mt7531_phy_probe,
|
||||||
|
.config_init = mt7531_phy_config_init,
|
||||||
|
+ .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
/* Interrupts are handled by the switch, not the PHY
|
||||||
|
* itself.
|
||||||
|
*/
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-phy-lib.c
|
||||||
|
@@ -109,6 +109,98 @@ int mtk_phy_write_page(struct phy_device
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtk_phy_write_page);
|
||||||
|
|
||||||
|
+/* This function deals with the case that 1G AN starts but isn't completed. We
|
||||||
|
+ * set AN_NEW_LP_CNT_LIMIT with different values time after time to let our
|
||||||
|
+ * 1G->100Mbps hardware automatic downshift to fit more partner devices.
|
||||||
|
+ */
|
||||||
|
+static int extend_an_new_lp_cnt_limit(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ int mmd_read_ret;
|
||||||
|
+ u32 reg_val;
|
||||||
|
+ int timeout;
|
||||||
|
+
|
||||||
|
+ /* According to table 28-9 & Figure 28-18 in IEEE 802.3,
|
||||||
|
+ * link_fail_inhibit_timer of 10/100/1000 Mbps devices ranges from 750
|
||||||
|
+ * to "1000ms". Once MTK_PHY_FINAL_SPEED_1000 is set, it means that we
|
||||||
|
+ * enter "FLP LINK GOOD CHECK" state, link_fail_inhibit_timer starts and
|
||||||
|
+ * this PHY's 1G training starts. If 1G training never starts, we do
|
||||||
|
+ * nothing but leave.
|
||||||
|
+ */
|
||||||
|
+ timeout = read_poll_timeout(mmd_read_ret = phy_read_mmd, reg_val,
|
||||||
|
+ (mmd_read_ret < 0) ||
|
||||||
|
+ reg_val & MTK_PHY_FINAL_SPEED_1000,
|
||||||
|
+ 10000, 1000000, false, phydev,
|
||||||
|
+ MDIO_MMD_VEND1, MTK_PHY_LINK_STATUS_MISC);
|
||||||
|
+ if (mmd_read_ret < 0)
|
||||||
|
+ return mmd_read_ret;
|
||||||
|
+
|
||||||
|
+ if (!timeout) {
|
||||||
|
+ /* Once we found MTK_PHY_FINAL_SPEED_1000 is set, no matter 1G
|
||||||
|
+ * AN is completed or not, we'll set AN_NEW_LP_CNT_LIMIT again
|
||||||
|
+ * and again.
|
||||||
|
+ */
|
||||||
|
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, AN_NEW_LP_CNT_LIMIT_MASK,
|
||||||
|
+ FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK, 0xf));
|
||||||
|
+ mdelay(1500);
|
||||||
|
+
|
||||||
|
+ timeout = read_poll_timeout(mtk_tr_read, reg_val,
|
||||||
|
+ (reg_val & AN_STATE_MASK) !=
|
||||||
|
+ (AN_STATE_TX_DISABLE <<
|
||||||
|
+ AN_STATE_SHIFT),
|
||||||
|
+ 10000, 1000000, false, phydev,
|
||||||
|
+ 0x0, 0xf, 0x2);
|
||||||
|
+ if (!timeout) {
|
||||||
|
+ mdelay(625);
|
||||||
|
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
|
||||||
|
+ AN_NEW_LP_CNT_LIMIT_MASK,
|
||||||
|
+ FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK,
|
||||||
|
+ 0x8));
|
||||||
|
+ mdelay(500);
|
||||||
|
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c,
|
||||||
|
+ AN_NEW_LP_CNT_LIMIT_MASK,
|
||||||
|
+ FIELD_PREP(AN_NEW_LP_CNT_LIMIT_MASK,
|
||||||
|
+ 0xf));
|
||||||
|
+ } else {
|
||||||
|
+ return -ETIMEDOUT;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int mtk_gphy_cl22_read_status(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = genphy_read_status(phydev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ if (phydev->autoneg == AUTONEG_ENABLE && !phydev->autoneg_complete) {
|
||||||
|
+ ret = phy_read_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
|
||||||
|
+ MTK_PHY_AUX_CTRL_AND_STATUS);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Once LP_DETECTED is set, it means that"ability_match" in
|
||||||
|
+ * IEEE 802.3 Figure 28-18 is set. This happens after we plug in
|
||||||
|
+ * cable. Also, LP_DETECTED will be cleared after AN complete.
|
||||||
|
+ */
|
||||||
|
+ if (!FIELD_GET(MTK_PHY_LP_DETECTED_MASK, ret))
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ ret = phy_read(phydev, MII_CTRL1000);
|
||||||
|
+ if (ret & (ADVERTISE_1000FULL | ADVERTISE_1000HALF)) {
|
||||||
|
+ ret = extend_an_new_lp_cnt_limit(phydev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+EXPORT_SYMBOL_GPL(mtk_gphy_cl22_read_status);
|
||||||
|
+
|
||||||
|
int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules,
|
||||||
|
unsigned long supported_triggers)
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk.h
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk.h
|
||||||
|
@@ -10,8 +10,28 @@
|
||||||
|
|
||||||
|
#define MTK_EXT_PAGE_ACCESS 0x1f
|
||||||
|
#define MTK_PHY_PAGE_STANDARD 0x0000
|
||||||
|
+#define MTK_PHY_PAGE_EXTENDED_1 0x0001
|
||||||
|
+#define MTK_PHY_AUX_CTRL_AND_STATUS 0x14
|
||||||
|
+/* suprv_media_select_RefClk */
|
||||||
|
+#define MTK_PHY_LP_DETECTED_MASK GENMASK(7, 6)
|
||||||
|
+#define MTK_PHY_ENABLE_DOWNSHIFT BIT(4)
|
||||||
|
+
|
||||||
|
#define MTK_PHY_PAGE_EXTENDED_52B5 0x52b5
|
||||||
|
|
||||||
|
+/* Registers on Token Ring debug nodes */
|
||||||
|
+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x2 */
|
||||||
|
+#define AN_STATE_MASK GENMASK(22, 19)
|
||||||
|
+#define AN_STATE_SHIFT 19
|
||||||
|
+#define AN_STATE_TX_DISABLE 1
|
||||||
|
+
|
||||||
|
+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
|
||||||
|
+#define AN_NEW_LP_CNT_LIMIT_MASK GENMASK(23, 20)
|
||||||
|
+#define AUTO_NP_10XEN BIT(6)
|
||||||
|
+
|
||||||
|
+/* Registers on MDIO_MMD_VEND1 */
|
||||||
|
+#define MTK_PHY_LINK_STATUS_MISC (0xa2)
|
||||||
|
+#define MTK_PHY_FINAL_SPEED_1000 BIT(3)
|
||||||
|
+
|
||||||
|
/* Registers on MDIO_MMD_VEND2 */
|
||||||
|
#define MTK_PHY_LED0_ON_CTRL 0x24
|
||||||
|
#define MTK_PHY_LED1_ON_CTRL 0x26
|
||||||
|
@@ -78,6 +98,7 @@ void __mtk_tr_clr_bits(struct phy_device
|
||||||
|
int mtk_phy_read_page(struct phy_device *phydev);
|
||||||
|
int mtk_phy_write_page(struct phy_device *phydev, int page);
|
||||||
|
|
||||||
|
+int mtk_gphy_cl22_read_status(struct phy_device *phydev);
|
||||||
|
int mtk_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules,
|
||||||
|
unsigned long supported_triggers);
|
@@ -0,0 +1,477 @@
|
|||||||
|
From 69ca89165e39e6b6f4c79e6b4c03559e0fac7051 Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:15 +0800
|
||||||
|
Subject: [PATCH 11/13] net: phy: add driver for built-in 2.5G ethernet PHY on
|
||||||
|
MT7988
|
||||||
|
|
||||||
|
Add support for internal 2.5Gphy on MT7988. This driver will load
|
||||||
|
necessary firmware, add appropriate time delay and figure out LED.
|
||||||
|
Also, certain control registers will be set to fix link-up issues.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/Kconfig | 11 +
|
||||||
|
drivers/net/phy/mediatek/Makefile | 1 +
|
||||||
|
drivers/net/phy/mediatek/mtk-2p5ge.c | 432 +++++++++++++++++++++++++++
|
||||||
|
4 files changed, 445 insertions(+)
|
||||||
|
create mode 100644 drivers/net/phy/mediatek/mtk-2p5ge.c
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/Kconfig
|
||||||
|
+++ b/drivers/net/phy/mediatek/Kconfig
|
||||||
|
@@ -25,3 +25,14 @@ config MEDIATEK_GE_SOC_PHY
|
||||||
|
the MT7981 and MT7988 SoCs. These PHYs need calibration data
|
||||||
|
present in the SoCs efuse and will dynamically calibrate VCM
|
||||||
|
(common-mode voltage) during startup.
|
||||||
|
+
|
||||||
|
+config MEDIATEK_2P5GE_PHY
|
||||||
|
+ tristate "MediaTek 2.5Gb Ethernet PHYs"
|
||||||
|
+ depends on (ARM64 && ARCH_MEDIATEK) || COMPILE_TEST
|
||||||
|
+ select MTK_NET_PHYLIB
|
||||||
|
+ help
|
||||||
|
+ Supports MediaTek SoC built-in 2.5Gb Ethernet PHYs.
|
||||||
|
+
|
||||||
|
+ This will load necessary firmware and add appropriate time delay.
|
||||||
|
+ Accelerate this procedure through internal pbus instead of MDIO
|
||||||
|
+ bus. Certain link-up issues will also be fixed here.
|
||||||
|
--- a/drivers/net/phy/mediatek/Makefile
|
||||||
|
+++ b/drivers/net/phy/mediatek/Makefile
|
||||||
|
@@ -2,3 +2,4 @@
|
||||||
|
obj-$(CONFIG_MTK_NET_PHYLIB) += mtk-phy-lib.o
|
||||||
|
obj-$(CONFIG_MEDIATEK_GE_PHY) += mtk-ge.o
|
||||||
|
obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mtk-ge-soc.o
|
||||||
|
+obj-$(CONFIG_MEDIATEK_2P5GE_PHY) += mtk-2p5ge.o
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-2p5ge.c
|
||||||
|
@@ -0,0 +1,432 @@
|
||||||
|
+// SPDX-License-Identifier: GPL-2.0+
|
||||||
|
+#include <linux/bitfield.h>
|
||||||
|
+#include <linux/firmware.h>
|
||||||
|
+#include <linux/module.h>
|
||||||
|
+#include <linux/nvmem-consumer.h>
|
||||||
|
+#include <linux/of_address.h>
|
||||||
|
+#include <linux/of_platform.h>
|
||||||
|
+#include <linux/pinctrl/consumer.h>
|
||||||
|
+#include <linux/phy.h>
|
||||||
|
+#include <linux/pm_domain.h>
|
||||||
|
+#include <linux/pm_runtime.h>
|
||||||
|
+
|
||||||
|
+#include "mtk.h"
|
||||||
|
+
|
||||||
|
+#define MTK_2P5GPHY_ID_MT7988 (0x00339c11)
|
||||||
|
+
|
||||||
|
+#define MT7988_2P5GE_PMB_FW "mediatek/mt7988/i2p5ge-phy-pmb.bin"
|
||||||
|
+#define MT7988_2P5GE_PMB_FW_SIZE (0x20000)
|
||||||
|
+#define MT7988_2P5GE_PMB_FW_BASE (0x0f100000)
|
||||||
|
+#define MT7988_2P5GE_PMB_FW_LEN (0x20000)
|
||||||
|
+#define MT7988_2P5GE_MD32_EN_CFG_BASE (0x0f0f0018)
|
||||||
|
+#define MT7988_2P5GE_MD32_EN_CFG_LEN (0x20)
|
||||||
|
+#define MD32_EN BIT(0)
|
||||||
|
+
|
||||||
|
+#define BASE100T_STATUS_EXTEND (0x10)
|
||||||
|
+#define BASE1000T_STATUS_EXTEND (0x11)
|
||||||
|
+#define EXTEND_CTRL_AND_STATUS (0x16)
|
||||||
|
+
|
||||||
|
+#define PHY_AUX_CTRL_STATUS (0x1d)
|
||||||
|
+#define PHY_AUX_DPX_MASK GENMASK(5, 5)
|
||||||
|
+#define PHY_AUX_SPEED_MASK GENMASK(4, 2)
|
||||||
|
+
|
||||||
|
+#define MTK_PHY_LPI_PCS_DSP_CTRL (0x121)
|
||||||
|
+#define MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK GENMASK(12, 8)
|
||||||
|
+
|
||||||
|
+/* Registers on Token Ring debug nodes */
|
||||||
|
+/* ch_addr = 0x0, node_addr = 0xf, data_addr = 0x3c */
|
||||||
|
+#define AUTO_NP_10XEN BIT(6)
|
||||||
|
+
|
||||||
|
+struct mtk_i2p5ge_phy_priv {
|
||||||
|
+ bool fw_loaded;
|
||||||
|
+ unsigned long led_state;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+enum {
|
||||||
|
+ PHY_AUX_SPD_10 = 0,
|
||||||
|
+ PHY_AUX_SPD_100,
|
||||||
|
+ PHY_AUX_SPD_1000,
|
||||||
|
+ PHY_AUX_SPD_2500,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_load_fw(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
|
||||||
|
+ void __iomem *md32_en_cfg_base, *pmb_addr;
|
||||||
|
+ struct device *dev = &phydev->mdio.dev;
|
||||||
|
+ const struct firmware *fw;
|
||||||
|
+ int ret, i;
|
||||||
|
+ u16 reg;
|
||||||
|
+
|
||||||
|
+ if (priv->fw_loaded)
|
||||||
|
+ return 0;
|
||||||
|
+
|
||||||
|
+ pmb_addr = ioremap(MT7988_2P5GE_PMB_FW_BASE, MT7988_2P5GE_PMB_FW_LEN);
|
||||||
|
+ if (!pmb_addr)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+ md32_en_cfg_base = ioremap(MT7988_2P5GE_MD32_EN_CFG_BASE,
|
||||||
|
+ MT7988_2P5GE_MD32_EN_CFG_LEN);
|
||||||
|
+ if (!md32_en_cfg_base) {
|
||||||
|
+ ret = -ENOMEM;
|
||||||
|
+ goto free_pmb;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ret = request_firmware(&fw, MT7988_2P5GE_PMB_FW, dev);
|
||||||
|
+ if (ret) {
|
||||||
|
+ dev_err(dev, "failed to load firmware: %s, ret: %d\n",
|
||||||
|
+ MT7988_2P5GE_PMB_FW, ret);
|
||||||
|
+ goto free;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (fw->size != MT7988_2P5GE_PMB_FW_SIZE) {
|
||||||
|
+ dev_err(dev, "Firmware size 0x%zx != 0x%x\n",
|
||||||
|
+ fw->size, MT7988_2P5GE_PMB_FW_SIZE);
|
||||||
|
+ ret = -EINVAL;
|
||||||
|
+ goto release_fw;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ reg = readw(md32_en_cfg_base);
|
||||||
|
+ if (reg & MD32_EN) {
|
||||||
|
+ phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
|
||||||
|
+ usleep_range(10000, 11000);
|
||||||
|
+ }
|
||||||
|
+ phy_set_bits(phydev, MII_BMCR, BMCR_PDOWN);
|
||||||
|
+
|
||||||
|
+ /* Write magic number to safely stall MCU */
|
||||||
|
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800e, 0x1100);
|
||||||
|
+ phy_write_mmd(phydev, MDIO_MMD_VEND1, 0x800f, 0x00df);
|
||||||
|
+
|
||||||
|
+ for (i = 0; i < MT7988_2P5GE_PMB_FW_SIZE - 1; i += 4)
|
||||||
|
+ writel(*((uint32_t *)(fw->data + i)), pmb_addr + i);
|
||||||
|
+ dev_info(dev, "Firmware date code: %x/%x/%x, version: %x.%x\n",
|
||||||
|
+ be16_to_cpu(*((__be16 *)(fw->data +
|
||||||
|
+ MT7988_2P5GE_PMB_FW_SIZE - 8))),
|
||||||
|
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 6),
|
||||||
|
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 5),
|
||||||
|
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 2),
|
||||||
|
+ *(fw->data + MT7988_2P5GE_PMB_FW_SIZE - 1));
|
||||||
|
+
|
||||||
|
+ writew(reg & ~MD32_EN, md32_en_cfg_base);
|
||||||
|
+ writew(reg | MD32_EN, md32_en_cfg_base);
|
||||||
|
+ phy_set_bits(phydev, MII_BMCR, BMCR_RESET);
|
||||||
|
+ /* We need a delay here to stabilize initialization of MCU */
|
||||||
|
+ usleep_range(7000, 8000);
|
||||||
|
+ dev_info(dev, "Firmware loading/trigger ok.\n");
|
||||||
|
+
|
||||||
|
+ priv->fw_loaded = true;
|
||||||
|
+
|
||||||
|
+release_fw:
|
||||||
|
+ release_firmware(fw);
|
||||||
|
+free:
|
||||||
|
+ iounmap(md32_en_cfg_base);
|
||||||
|
+free_pmb:
|
||||||
|
+ iounmap(pmb_addr);
|
||||||
|
+
|
||||||
|
+ return ret;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_config_init(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ struct pinctrl *pinctrl;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /* Check if PHY interface type is compatible */
|
||||||
|
+ if (phydev->interface != PHY_INTERFACE_MODE_INTERNAL)
|
||||||
|
+ return -ENODEV;
|
||||||
|
+
|
||||||
|
+ ret = mt798x_2p5ge_phy_load_fw(phydev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Setup LED */
|
||||||
|
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED0_ON_CTRL,
|
||||||
|
+ MTK_PHY_LED_ON_POLARITY | MTK_PHY_LED_ON_LINK10 |
|
||||||
|
+ MTK_PHY_LED_ON_LINK100 | MTK_PHY_LED_ON_LINK1000 |
|
||||||
|
+ MTK_PHY_LED_ON_LINK2500);
|
||||||
|
+ phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MTK_PHY_LED1_ON_CTRL,
|
||||||
|
+ MTK_PHY_LED_ON_FDX | MTK_PHY_LED_ON_HDX);
|
||||||
|
+
|
||||||
|
+ /* Switch pinctrl after setting polarity to avoid bogus blinking */
|
||||||
|
+ pinctrl = devm_pinctrl_get_select(&phydev->mdio.dev, "i2p5gbe-led");
|
||||||
|
+ if (IS_ERR(pinctrl))
|
||||||
|
+ dev_err(&phydev->mdio.dev, "Fail to set LED pins!\n");
|
||||||
|
+
|
||||||
|
+ phy_modify_mmd(phydev, MDIO_MMD_VEND1, MTK_PHY_LPI_PCS_DSP_CTRL,
|
||||||
|
+ MTK_PHY_LPI_SIG_EN_LO_THRESH100_MASK, 0);
|
||||||
|
+
|
||||||
|
+ /* Enable 16-bit next page exchange bit if 1000-BT isn't advertising */
|
||||||
|
+ mtk_tr_modify(phydev, 0x0, 0xf, 0x3c, AUTO_NP_10XEN,
|
||||||
|
+ FIELD_PREP(AUTO_NP_10XEN, 0x1));
|
||||||
|
+
|
||||||
|
+ /* Enable HW auto downshift */
|
||||||
|
+ phy_modify_paged(phydev, MTK_PHY_PAGE_EXTENDED_1,
|
||||||
|
+ MTK_PHY_AUX_CTRL_AND_STATUS,
|
||||||
|
+ 0, MTK_PHY_ENABLE_DOWNSHIFT);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_config_aneg(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ bool changed = false;
|
||||||
|
+ u32 adv;
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /* In fact, if we disable autoneg, we can't link up correctly:
|
||||||
|
+ * 2.5G/1G: Need AN to exchange master/slave information.
|
||||||
|
+ * 100M/10M: Without AN, link starts at half duplex (According to
|
||||||
|
+ * IEEE 802.3-2018), which this phy doesn't support.
|
||||||
|
+ */
|
||||||
|
+ if (phydev->autoneg == AUTONEG_DISABLE)
|
||||||
|
+ return -EOPNOTSUPP;
|
||||||
|
+
|
||||||
|
+ ret = genphy_c45_an_config_aneg(phydev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+ if (ret > 0)
|
||||||
|
+ changed = true;
|
||||||
|
+
|
||||||
|
+ /* Clause 45 doesn't define 1000BaseT support. Use Clause 22 instead in
|
||||||
|
+ * our design.
|
||||||
|
+ */
|
||||||
|
+ adv = linkmode_adv_to_mii_ctrl1000_t(phydev->advertising);
|
||||||
|
+ ret = phy_modify_changed(phydev, MII_CTRL1000, ADVERTISE_1000FULL, adv);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+ if (ret > 0)
|
||||||
|
+ changed = true;
|
||||||
|
+
|
||||||
|
+ return genphy_c45_check_and_restart_aneg(phydev, changed);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_get_features(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ ret = genphy_c45_pma_read_abilities(phydev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* This phy can't handle collision, and neither can (XFI)MAC it's
|
||||||
|
+ * connected to. Although it can do HDX handshake, it doesn't support
|
||||||
|
+ * CSMA/CD that HDX requires.
|
||||||
|
+ */
|
||||||
|
+ linkmode_clear_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT,
|
||||||
|
+ phydev->supported);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_read_status(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ int ret;
|
||||||
|
+
|
||||||
|
+ /* When MDIO_STAT1_LSTATUS is raised genphy_c45_read_link(), this phy
|
||||||
|
+ * actually hasn't finished AN. So use CL22's link update function
|
||||||
|
+ * instead.
|
||||||
|
+ */
|
||||||
|
+ ret = genphy_update_link(phydev);
|
||||||
|
+ if (ret)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ phydev->speed = SPEED_UNKNOWN;
|
||||||
|
+ phydev->duplex = DUPLEX_UNKNOWN;
|
||||||
|
+ phydev->pause = 0;
|
||||||
|
+ phydev->asym_pause = 0;
|
||||||
|
+
|
||||||
|
+ /* We'll read link speed through vendor specific registers down below.
|
||||||
|
+ * So remove phy_resolve_aneg_linkmode (AN on) & genphy_c45_read_pma
|
||||||
|
+ * (AN off).
|
||||||
|
+ */
|
||||||
|
+ if (phydev->autoneg == AUTONEG_ENABLE && phydev->autoneg_complete) {
|
||||||
|
+ ret = genphy_c45_read_lpa(phydev);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ /* Clause 45 doesn't define 1000BaseT support. Read the link
|
||||||
|
+ * partner's 1G advertisement via Clause 22.
|
||||||
|
+ */
|
||||||
|
+ ret = phy_read(phydev, MII_STAT1000);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, ret);
|
||||||
|
+ } else if (phydev->autoneg == AUTONEG_DISABLE) {
|
||||||
|
+ linkmode_zero(phydev->lp_advertising);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ if (phydev->link) {
|
||||||
|
+ ret = phy_read(phydev, PHY_AUX_CTRL_STATUS);
|
||||||
|
+ if (ret < 0)
|
||||||
|
+ return ret;
|
||||||
|
+
|
||||||
|
+ switch (FIELD_GET(PHY_AUX_SPEED_MASK, ret)) {
|
||||||
|
+ case PHY_AUX_SPD_10:
|
||||||
|
+ phydev->speed = SPEED_10;
|
||||||
|
+ break;
|
||||||
|
+ case PHY_AUX_SPD_100:
|
||||||
|
+ phydev->speed = SPEED_100;
|
||||||
|
+ break;
|
||||||
|
+ case PHY_AUX_SPD_1000:
|
||||||
|
+ phydev->speed = SPEED_1000;
|
||||||
|
+ break;
|
||||||
|
+ case PHY_AUX_SPD_2500:
|
||||||
|
+ phydev->speed = SPEED_2500;
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ phydev->duplex = DUPLEX_FULL;
|
||||||
|
+ /* FIXME:
|
||||||
|
+ * The current firmware always enables rate adaptation mode.
|
||||||
|
+ */
|
||||||
|
+ phydev->rate_matching = RATE_MATCH_PAUSE;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_get_rate_matching(struct phy_device *phydev,
|
||||||
|
+ phy_interface_t iface)
|
||||||
|
+{
|
||||||
|
+ return RATE_MATCH_PAUSE;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const unsigned long supported_triggers =
|
||||||
|
+ BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_2500) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_TX);
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_led_blink_set(struct phy_device *phydev, u8 index,
|
||||||
|
+ unsigned long *delay_on,
|
||||||
|
+ unsigned long *delay_off)
|
||||||
|
+{
|
||||||
|
+ struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
|
||||||
|
+ bool blinking = false;
|
||||||
|
+ int err = 0;
|
||||||
|
+
|
||||||
|
+ err = mtk_phy_led_num_dly_cfg(index, delay_on, delay_off, &blinking);
|
||||||
|
+ if (err < 0)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state,
|
||||||
|
+ blinking);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
||||||
|
+ MTK_2P5GPHY_LED_ON_MASK, false);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_led_brightness_set(struct phy_device *phydev,
|
||||||
|
+ u8 index,
|
||||||
|
+ enum led_brightness value)
|
||||||
|
+{
|
||||||
|
+ struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
|
||||||
|
+ int err;
|
||||||
|
+
|
||||||
|
+ err = mtk_phy_hw_led_blink_set(phydev, index, &priv->led_state, false);
|
||||||
|
+ if (err)
|
||||||
|
+ return err;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_hw_led_on_set(phydev, index, &priv->led_state,
|
||||||
|
+ MTK_2P5GPHY_LED_ON_MASK,
|
||||||
|
+ (value != LED_OFF));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_led_hw_is_supported(struct phy_device *phydev,
|
||||||
|
+ u8 index, unsigned long rules)
|
||||||
|
+{
|
||||||
|
+ return mtk_phy_led_hw_is_supported(phydev, index, rules,
|
||||||
|
+ supported_triggers);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_led_hw_control_get(struct phy_device *phydev,
|
||||||
|
+ u8 index, unsigned long *rules)
|
||||||
|
+{
|
||||||
|
+ struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_led_hw_ctrl_get(phydev, index, rules, &priv->led_state,
|
||||||
|
+ MTK_2P5GPHY_LED_ON_SET,
|
||||||
|
+ MTK_2P5GPHY_LED_RX_BLINK_SET,
|
||||||
|
+ MTK_2P5GPHY_LED_TX_BLINK_SET);
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_led_hw_control_set(struct phy_device *phydev,
|
||||||
|
+ u8 index, unsigned long rules)
|
||||||
|
+{
|
||||||
|
+ struct mtk_i2p5ge_phy_priv *priv = phydev->priv;
|
||||||
|
+
|
||||||
|
+ return mtk_phy_led_hw_ctrl_set(phydev, index, rules, &priv->led_state,
|
||||||
|
+ MTK_2P5GPHY_LED_ON_SET,
|
||||||
|
+ MTK_2P5GPHY_LED_RX_BLINK_SET,
|
||||||
|
+ MTK_2P5GPHY_LED_TX_BLINK_SET);
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int mt798x_2p5ge_phy_probe(struct phy_device *phydev)
|
||||||
|
+{
|
||||||
|
+ struct mtk_i2p5ge_phy_priv *priv;
|
||||||
|
+
|
||||||
|
+ priv = devm_kzalloc(&phydev->mdio.dev,
|
||||||
|
+ sizeof(struct mtk_i2p5ge_phy_priv), GFP_KERNEL);
|
||||||
|
+ if (!priv)
|
||||||
|
+ return -ENOMEM;
|
||||||
|
+
|
||||||
|
+ switch (phydev->drv->phy_id) {
|
||||||
|
+ case MTK_2P5GPHY_ID_MT7988:
|
||||||
|
+ /* The original hardware only sets MDIO_DEVS_PMAPMD */
|
||||||
|
+ phydev->c45_ids.mmds_present |= MDIO_DEVS_PCS |
|
||||||
|
+ MDIO_DEVS_AN |
|
||||||
|
+ MDIO_DEVS_VEND1 |
|
||||||
|
+ MDIO_DEVS_VEND2;
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return -EINVAL;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ priv->fw_loaded = false;
|
||||||
|
+ phydev->priv = priv;
|
||||||
|
+
|
||||||
|
+ mtk_phy_leds_state_init(phydev);
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static struct phy_driver mtk_2p5gephy_driver[] = {
|
||||||
|
+ {
|
||||||
|
+ PHY_ID_MATCH_MODEL(MTK_2P5GPHY_ID_MT7988),
|
||||||
|
+ .name = "MediaTek MT7988 2.5GbE PHY",
|
||||||
|
+ .probe = mt798x_2p5ge_phy_probe,
|
||||||
|
+ .config_init = mt798x_2p5ge_phy_config_init,
|
||||||
|
+ .config_aneg = mt798x_2p5ge_phy_config_aneg,
|
||||||
|
+ .get_features = mt798x_2p5ge_phy_get_features,
|
||||||
|
+ .read_status = mt798x_2p5ge_phy_read_status,
|
||||||
|
+ .get_rate_matching = mt798x_2p5ge_phy_get_rate_matching,
|
||||||
|
+ .suspend = genphy_suspend,
|
||||||
|
+ .resume = genphy_resume,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
+ .led_blink_set = mt798x_2p5ge_phy_led_blink_set,
|
||||||
|
+ .led_brightness_set = mt798x_2p5ge_phy_led_brightness_set,
|
||||||
|
+ .led_hw_is_supported = mt798x_2p5ge_phy_led_hw_is_supported,
|
||||||
|
+ .led_hw_control_get = mt798x_2p5ge_phy_led_hw_control_get,
|
||||||
|
+ .led_hw_control_set = mt798x_2p5ge_phy_led_hw_control_set,
|
||||||
|
+ },
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+module_phy_driver(mtk_2p5gephy_driver);
|
||||||
|
+
|
||||||
|
+static struct mdio_device_id __maybe_unused mtk_2p5ge_phy_tbl[] = {
|
||||||
|
+ { PHY_ID_MATCH_VENDOR(0x00339c00) },
|
||||||
|
+ { }
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+MODULE_DESCRIPTION("MediaTek 2.5Gb Ethernet PHY driver");
|
||||||
|
+MODULE_AUTHOR("SkyLake Huang <SkyLake.Huang@mediatek.com>");
|
||||||
|
+MODULE_LICENSE("GPL");
|
||||||
|
+
|
||||||
|
+MODULE_DEVICE_TABLE(mdio, mtk_2p5ge_phy_tbl);
|
||||||
|
+MODULE_FIRMWARE(MT7988_2P5GE_PMB_FW);
|
@@ -0,0 +1,130 @@
|
|||||||
|
From 07e90eb1819319a0c34b0cf3a57a4a3878e96e4d Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:16 +0800
|
||||||
|
Subject: [PATCH 12/13] net: phy: mediatek: Fix alignment in callback
|
||||||
|
functions' hook
|
||||||
|
|
||||||
|
Align declarations in mtk_gephy_driver(mtk-ge.c) and
|
||||||
|
mtk_socphy_driver(mtk-ge-soc.c). At first, some of them are
|
||||||
|
".foo<tab>= method_foo", and others are ".bar<space>= method_bar".
|
||||||
|
Use space instead for all of them here in case line is longer than
|
||||||
|
80 chars.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 40 +++++++++++++--------------
|
||||||
|
drivers/net/phy/mediatek/mtk-ge.c | 34 +++++++++++------------
|
||||||
|
2 files changed, 37 insertions(+), 37 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -1394,17 +1394,17 @@ static int mt7981_phy_probe(struct phy_d
|
||||||
|
static struct phy_driver mtk_socphy_driver[] = {
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7981),
|
||||||
|
- .name = "MediaTek MT7981 PHY",
|
||||||
|
- .config_init = mt798x_phy_config_init,
|
||||||
|
- .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
- .config_intr = genphy_no_config_intr,
|
||||||
|
+ .name = "MediaTek MT7981 PHY",
|
||||||
|
+ .config_init = mt798x_phy_config_init,
|
||||||
|
+ .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
+ .config_intr = genphy_no_config_intr,
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
- .probe = mt7981_phy_probe,
|
||||||
|
- .suspend = genphy_suspend,
|
||||||
|
- .resume = genphy_resume,
|
||||||
|
- .read_page = mtk_phy_read_page,
|
||||||
|
- .write_page = mtk_phy_write_page,
|
||||||
|
- .led_blink_set = mt798x_phy_led_blink_set,
|
||||||
|
+ .probe = mt7981_phy_probe,
|
||||||
|
+ .suspend = genphy_suspend,
|
||||||
|
+ .resume = genphy_resume,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
+ .led_blink_set = mt798x_phy_led_blink_set,
|
||||||
|
.led_brightness_set = mt798x_phy_led_brightness_set,
|
||||||
|
.led_hw_is_supported = mt798x_phy_led_hw_is_supported,
|
||||||
|
.led_hw_control_set = mt798x_phy_led_hw_control_set,
|
||||||
|
@@ -1412,17 +1412,17 @@ static struct phy_driver mtk_socphy_driv
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7988),
|
||||||
|
- .name = "MediaTek MT7988 PHY",
|
||||||
|
- .config_init = mt798x_phy_config_init,
|
||||||
|
- .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
- .config_intr = genphy_no_config_intr,
|
||||||
|
+ .name = "MediaTek MT7988 PHY",
|
||||||
|
+ .config_init = mt798x_phy_config_init,
|
||||||
|
+ .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
+ .config_intr = genphy_no_config_intr,
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
- .probe = mt7988_phy_probe,
|
||||||
|
- .suspend = genphy_suspend,
|
||||||
|
- .resume = genphy_resume,
|
||||||
|
- .read_page = mtk_phy_read_page,
|
||||||
|
- .write_page = mtk_phy_write_page,
|
||||||
|
- .led_blink_set = mt798x_phy_led_blink_set,
|
||||||
|
+ .probe = mt7988_phy_probe,
|
||||||
|
+ .suspend = genphy_suspend,
|
||||||
|
+ .resume = genphy_resume,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
+ .led_blink_set = mt798x_phy_led_blink_set,
|
||||||
|
.led_brightness_set = mt798x_phy_led_brightness_set,
|
||||||
|
.led_hw_is_supported = mt798x_phy_led_hw_is_supported,
|
||||||
|
.led_hw_control_set = mt798x_phy_led_hw_control_set,
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
@@ -230,34 +230,34 @@ static int mt753x_phy_led_hw_control_set
|
||||||
|
static struct phy_driver mtk_gephy_driver[] = {
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7530),
|
||||||
|
- .name = "MediaTek MT7530 PHY",
|
||||||
|
- .config_init = mt7530_phy_config_init,
|
||||||
|
+ .name = "MediaTek MT7530 PHY",
|
||||||
|
+ .config_init = mt7530_phy_config_init,
|
||||||
|
/* Interrupts are handled by the switch, not the PHY
|
||||||
|
* itself.
|
||||||
|
*/
|
||||||
|
- .config_intr = genphy_no_config_intr,
|
||||||
|
+ .config_intr = genphy_no_config_intr,
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
- .suspend = genphy_suspend,
|
||||||
|
- .resume = genphy_resume,
|
||||||
|
- .read_page = mtk_phy_read_page,
|
||||||
|
- .write_page = mtk_phy_write_page,
|
||||||
|
+ .suspend = genphy_suspend,
|
||||||
|
+ .resume = genphy_resume,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
PHY_ID_MATCH_EXACT(MTK_GPHY_ID_MT7531),
|
||||||
|
- .name = "MediaTek MT7531 PHY",
|
||||||
|
- .probe = mt7531_phy_probe,
|
||||||
|
- .config_init = mt7531_phy_config_init,
|
||||||
|
- .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
+ .name = "MediaTek MT7531 PHY",
|
||||||
|
+ .probe = mt7531_phy_probe,
|
||||||
|
+ .config_init = mt7531_phy_config_init,
|
||||||
|
+ .read_status = mtk_gphy_cl22_read_status,
|
||||||
|
/* Interrupts are handled by the switch, not the PHY
|
||||||
|
* itself.
|
||||||
|
*/
|
||||||
|
- .config_intr = genphy_no_config_intr,
|
||||||
|
+ .config_intr = genphy_no_config_intr,
|
||||||
|
.handle_interrupt = genphy_handle_interrupt_no_ack,
|
||||||
|
- .suspend = genphy_suspend,
|
||||||
|
- .resume = genphy_resume,
|
||||||
|
- .read_page = mtk_phy_read_page,
|
||||||
|
- .write_page = mtk_phy_write_page,
|
||||||
|
- .led_blink_set = mt753x_phy_led_blink_set,
|
||||||
|
+ .suspend = genphy_suspend,
|
||||||
|
+ .resume = genphy_resume,
|
||||||
|
+ .read_page = mtk_phy_read_page,
|
||||||
|
+ .write_page = mtk_phy_write_page,
|
||||||
|
+ .led_blink_set = mt753x_phy_led_blink_set,
|
||||||
|
.led_brightness_set = mt753x_phy_led_brightness_set,
|
||||||
|
.led_hw_is_supported = mt753x_phy_led_hw_is_supported,
|
||||||
|
.led_hw_control_set = mt753x_phy_led_hw_control_set,
|
@@ -0,0 +1,65 @@
|
|||||||
|
From e59883b637ae317c2ac275b542e8a50670d76e7c Mon Sep 17 00:00:00 2001
|
||||||
|
From: "SkyLake.Huang" <skylake.huang@mediatek.com>
|
||||||
|
Date: Mon, 1 Jul 2024 18:54:17 +0800
|
||||||
|
Subject: [PATCH 13/13] net: phy: mediatek: Remove unnecessary outer parens of
|
||||||
|
"supported_triggers" var
|
||||||
|
|
||||||
|
This patch removes unnecessary outer parens of "supported_triggers" vars
|
||||||
|
in mtk-ge.c & mtk-ge-soc.c to improve readability.
|
||||||
|
|
||||||
|
Signed-off-by: SkyLake.Huang <skylake.huang@mediatek.com>
|
||||||
|
---
|
||||||
|
drivers/net/phy/mediatek/mtk-ge-soc.c | 16 ++++++++--------
|
||||||
|
drivers/net/phy/mediatek/mtk-ge.c | 16 ++++++++--------
|
||||||
|
2 files changed, 16 insertions(+), 16 deletions(-)
|
||||||
|
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge-soc.c
|
||||||
|
@@ -1224,14 +1224,14 @@ static int mt798x_phy_led_brightness_set
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned long supported_triggers =
|
||||||
|
- (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
- BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_TX));
|
||||||
|
+ BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_TX);
|
||||||
|
|
||||||
|
static int mt798x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules)
|
||||||
|
--- a/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
+++ b/drivers/net/phy/mediatek/mtk-ge.c
|
||||||
|
@@ -189,14 +189,14 @@ static int mt753x_phy_led_brightness_set
|
||||||
|
}
|
||||||
|
|
||||||
|
static const unsigned long supported_triggers =
|
||||||
|
- (BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
- BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
- BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
- BIT(TRIGGER_NETDEV_TX));
|
||||||
|
+ BIT(TRIGGER_NETDEV_FULL_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_HALF_DUPLEX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_10) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_100) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_LINK_1000) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_RX) |
|
||||||
|
+ BIT(TRIGGER_NETDEV_TX);
|
||||||
|
|
||||||
|
static int mt753x_phy_led_hw_is_supported(struct phy_device *phydev, u8 index,
|
||||||
|
unsigned long rules)
|
@@ -1,39 +0,0 @@
|
|||||||
From 128dc09b0af36772062142ce9e85b19c84ac789a Mon Sep 17 00:00:00 2001
|
|
||||||
From: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
Date: Tue, 28 Feb 2023 17:53:37 +0000
|
|
||||||
Subject: [PATCH] net: phy: add driver for MediaTek 2.5G PHY
|
|
||||||
|
|
||||||
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
|
|
||||||
---
|
|
||||||
drivers/net/phy/Kconfig | 7 ++
|
|
||||||
drivers/net/phy/Makefile | 1 +
|
|
||||||
drivers/net/phy/mediatek-2p5ge.c | 220 +++++++++++++++++++++++++++++++
|
|
||||||
3 files changed, 226 insertions(+)
|
|
||||||
create mode 100644 drivers/net/phy/mediatek-2p5ge.c
|
|
||||||
|
|
||||||
--- a/drivers/net/phy/Kconfig
|
|
||||||
+++ b/drivers/net/phy/Kconfig
|
|
||||||
@@ -330,6 +330,13 @@ config MEDIATEK_GE_SOC_PHY
|
|
||||||
present in the SoCs efuse and will dynamically calibrate VCM
|
|
||||||
(common-mode voltage) during startup.
|
|
||||||
|
|
||||||
+config MEDIATEK_2P5G_PHY
|
|
||||||
+ tristate "MediaTek 2.5G Ethernet PHY"
|
|
||||||
+ depends on (ARCH_MEDIATEK && ARM64) || COMPILE_TEST
|
|
||||||
+ default NET_MEDIATEK_SOC
|
|
||||||
+ help
|
|
||||||
+ Supports the MediaTek 2.5G Ethernet PHY.
|
|
||||||
+
|
|
||||||
config MICREL_PHY
|
|
||||||
tristate "Micrel PHYs"
|
|
||||||
depends on PTP_1588_CLOCK_OPTIONAL
|
|
||||||
--- a/drivers/net/phy/Makefile
|
|
||||||
+++ b/drivers/net/phy/Makefile
|
|
||||||
@@ -82,6 +82,7 @@ obj-$(CONFIG_MARVELL_PHY) += marvell.o
|
|
||||||
obj-$(CONFIG_MARVELL_88Q2XXX_PHY) += marvell-88q2xxx.o
|
|
||||||
obj-$(CONFIG_MARVELL_88X2222_PHY) += marvell-88x2222.o
|
|
||||||
obj-$(CONFIG_MAXLINEAR_GPHY) += mxl-gpy.o
|
|
||||||
+obj-$(CONFIG_MEDIATEK_2P5G_PHY) += mediatek-2p5ge.o
|
|
||||||
obj-$(CONFIG_MEDIATEK_GE_PHY) += mediatek-ge.o
|
|
||||||
obj-$(CONFIG_MEDIATEK_GE_SOC_PHY) += mediatek-ge-soc.o
|
|
||||||
obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
|
|
@@ -8,12 +8,12 @@
|
|||||||
include $(TOPDIR)/rules.mk
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
PKG_NAME:=ddns-go
|
PKG_NAME:=ddns-go
|
||||||
PKG_VERSION:=6.7.3
|
PKG_VERSION:=6.7.5
|
||||||
PKG_RELEASE:=1
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
|
||||||
PKG_SOURCE_URL:=https://codeload.github.com/jeessy2/ddns-go/tar.gz/v$(PKG_VERSION)?
|
PKG_SOURCE_URL:=https://codeload.github.com/jeessy2/ddns-go/tar.gz/v$(PKG_VERSION)?
|
||||||
PKG_HASH:=3edaf68505df7188e57ad89c1fc66fd7c2918e36017f357953fce4101e493424
|
PKG_HASH:=b6f5f74c544c4765ac5499c3f47ec3c07e6f6a55c1ff4e510433334786cf8aaa
|
||||||
|
|
||||||
PKG_LICENSE:=MIT
|
PKG_LICENSE:=MIT
|
||||||
PKG_LICENSE_FILES:=LICENSE
|
PKG_LICENSE_FILES:=LICENSE
|
||||||
|
@@ -1079,3 +1079,24 @@ function luci_types(id, m, s, type_name, option_prefix)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_std_domain(domain)
|
||||||
|
domain = trim(domain)
|
||||||
|
if domain == "" or domain:find("#") then return "" end
|
||||||
|
-- 删除首尾所有的 .
|
||||||
|
domain = domain:gsub("^[%.]+", ""):gsub("[%.]+$", "")
|
||||||
|
-- 如果 domain 包含 '*',则分割并删除包含 '*' 的部分及其前面的部分
|
||||||
|
if domain:find("%*") then
|
||||||
|
local parts = {}
|
||||||
|
for part in domain:gmatch("[^%.]+") do
|
||||||
|
table.insert(parts, part)
|
||||||
|
end
|
||||||
|
for i = #parts, 1, -1 do
|
||||||
|
if parts[i]:find("%*") then
|
||||||
|
-- 删除包含 '*' 的部分及其前面的部分
|
||||||
|
return parts[i + 1] and parts[i + 1] .. "." .. table.concat(parts, ".", i + 2) or ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return domain
|
||||||
|
end
|
||||||
|
@@ -546,6 +546,8 @@ run_chinadns_ng() {
|
|||||||
local _flag _listen_port _dns_local _dns_trust _no_ipv6_trust _use_direct_list _use_proxy_list _gfwlist _chnlist _default_mode _default_tag
|
local _flag _listen_port _dns_local _dns_trust _no_ipv6_trust _use_direct_list _use_proxy_list _gfwlist _chnlist _default_mode _default_tag
|
||||||
eval_set_val $@
|
eval_set_val $@
|
||||||
|
|
||||||
|
lua $APP_PATH/helper_chinadns_add.lua -FLAG $_flag -USE_DIRECT_LIST $_use_direct_list -USE_PROXY_LIST $_use_proxy_list
|
||||||
|
|
||||||
local _CONF_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.conf
|
local _CONF_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.conf
|
||||||
local _LOG_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.log
|
local _LOG_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.log
|
||||||
_LOG_FILE="/dev/null"
|
_LOG_FILE="/dev/null"
|
||||||
@@ -579,7 +581,7 @@ run_chinadns_ng() {
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
[ "${_use_direct_list}" = "1" ] && [ -s "${RULES_PATH}/direct_host" ] && {
|
[ "${_use_direct_list}" = "1" ] && [ -s "${TMP_PATH}/direct_host" ] && {
|
||||||
local whitelist4_set="passwall_whitelist"
|
local whitelist4_set="passwall_whitelist"
|
||||||
local whitelist6_set="passwall_whitelist6"
|
local whitelist6_set="passwall_whitelist6"
|
||||||
[ "$nftflag" = "1" ] && {
|
[ "$nftflag" = "1" ] && {
|
||||||
@@ -588,13 +590,13 @@ run_chinadns_ng() {
|
|||||||
}
|
}
|
||||||
cat <<-EOF >> ${_CONF_FILE}
|
cat <<-EOF >> ${_CONF_FILE}
|
||||||
group directlist
|
group directlist
|
||||||
group-dnl ${RULES_PATH}/direct_host
|
group-dnl ${TMP_PATH}/direct_host
|
||||||
group-upstream ${_dns_local}
|
group-upstream ${_dns_local}
|
||||||
group-ipset ${whitelist4_set},${whitelist6_set}
|
group-ipset ${whitelist4_set},${whitelist6_set}
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
[ "${_use_proxy_list}" = "1" ] && [ -s "${RULES_PATH}/proxy_host" ] && {
|
[ "${_use_proxy_list}" = "1" ] && [ -s "${TMP_PATH}/proxy_host" ] && {
|
||||||
local blacklist4_set="passwall_blacklist"
|
local blacklist4_set="passwall_blacklist"
|
||||||
local blacklist6_set="passwall_blacklist6"
|
local blacklist6_set="passwall_blacklist6"
|
||||||
[ "$nftflag" = "1" ] && {
|
[ "$nftflag" = "1" ] && {
|
||||||
@@ -603,7 +605,7 @@ run_chinadns_ng() {
|
|||||||
}
|
}
|
||||||
cat <<-EOF >> ${_CONF_FILE}
|
cat <<-EOF >> ${_CONF_FILE}
|
||||||
group proxylist
|
group proxylist
|
||||||
group-dnl ${RULES_PATH}/proxy_host
|
group-dnl ${TMP_PATH}/proxy_host
|
||||||
group-upstream ${_dns_trust}
|
group-upstream ${_dns_trust}
|
||||||
group-ipset ${blacklist4_set},${blacklist6_set}
|
group-ipset ${blacklist4_set},${blacklist6_set}
|
||||||
EOF
|
EOF
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
require 'nixio'
|
||||||
|
local api = require "luci.passwall.api"
|
||||||
|
local appname = "passwall"
|
||||||
|
|
||||||
|
local var = api.get_args(arg)
|
||||||
|
local FLAG = var["-FLAG"]
|
||||||
|
local USE_DIRECT_LIST = var["-USE_DIRECT_LIST"]
|
||||||
|
local USE_PROXY_LIST = var["-USE_PROXY_LIST"]
|
||||||
|
|
||||||
|
local TMP_PATH = "/tmp/etc/" .. appname
|
||||||
|
|
||||||
|
if not nixio.fs.access(TMP_PATH) then
|
||||||
|
nixio.fs.mkdir(TMP_PATH, 493)
|
||||||
|
end
|
||||||
|
|
||||||
|
local tmp_direct_host = TMP_PATH .. "/direct_host"
|
||||||
|
if USE_DIRECT_LIST == "1" and not nixio.fs.access(tmp_direct_host) then
|
||||||
|
local direct_domain = {}
|
||||||
|
for line in io.lines("/usr/share/passwall/rules/direct_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
|
if line ~= "" and not line:find("#") then
|
||||||
|
table.insert(direct_domain, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #direct_domain > 0 then
|
||||||
|
local direct_out = io.open(tmp_direct_host, "a")
|
||||||
|
for i = 1, #direct_domain do
|
||||||
|
direct_out:write(direct_domain[i] .. "\n")
|
||||||
|
end
|
||||||
|
direct_out:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tmp_proxy_host = TMP_PATH .. "/proxy_host"
|
||||||
|
if USE_PROXY_LIST == "1" and not nixio.fs.access(tmp_proxy_host) then
|
||||||
|
local proxy_domain = {}
|
||||||
|
for line in io.lines("/usr/share/passwall/rules/proxy_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
|
if line ~= "" and not line:find("#") then
|
||||||
|
table.insert(proxy_domain, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #proxy_domain > 0 then
|
||||||
|
local proxy_out = io.open(tmp_proxy_host, "a")
|
||||||
|
for i = 1, #proxy_domain do
|
||||||
|
proxy_out:write(proxy_domain[i] .. "\n")
|
||||||
|
end
|
||||||
|
proxy_out:close()
|
||||||
|
end
|
||||||
|
end
|
@@ -196,6 +196,7 @@ if not fs.access(CACHE_DNS_PATH) then
|
|||||||
--屏蔽列表
|
--屏蔽列表
|
||||||
if USE_BLOCK_LIST == "1" then
|
if USE_BLOCK_LIST == "1" then
|
||||||
for line in io.lines("/usr/share/passwall/rules/block_host") do
|
for line in io.lines("/usr/share/passwall/rules/block_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
if line ~= "" and not line:find("#") then
|
if line ~= "" and not line:find("#") then
|
||||||
set_domain_address(line, "")
|
set_domain_address(line, "")
|
||||||
end
|
end
|
||||||
@@ -234,6 +235,7 @@ if not fs.access(CACHE_DNS_PATH) then
|
|||||||
if fwd_dns then
|
if fwd_dns then
|
||||||
--始终用国内DNS解析直连(白名单)列表
|
--始终用国内DNS解析直连(白名单)列表
|
||||||
for line in io.lines("/usr/share/passwall/rules/direct_host") do
|
for line in io.lines("/usr/share/passwall/rules/direct_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
if line ~= "" and not line:find("#") then
|
if line ~= "" and not line:find("#") then
|
||||||
add_excluded_domain(line)
|
add_excluded_domain(line)
|
||||||
set_domain_dns(line, fwd_dns)
|
set_domain_dns(line, fwd_dns)
|
||||||
@@ -255,6 +257,7 @@ if not fs.access(CACHE_DNS_PATH) then
|
|||||||
if fwd_dns then
|
if fwd_dns then
|
||||||
--始终使用远程DNS解析代理(黑名单)列表
|
--始终使用远程DNS解析代理(黑名单)列表
|
||||||
for line in io.lines("/usr/share/passwall/rules/proxy_host") do
|
for line in io.lines("/usr/share/passwall/rules/proxy_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
if line ~= "" and not line:find("#") then
|
if line ~= "" and not line:find("#") then
|
||||||
add_excluded_domain(line)
|
add_excluded_domain(line)
|
||||||
local ipset_flag = setflag_4 .. "passwall_blacklist," .. setflag_6 .. "passwall_blacklist6"
|
local ipset_flag = setflag_4 .. "passwall_blacklist," .. setflag_6 .. "passwall_blacklist6"
|
||||||
|
19
shadowsocks-rust/.github/workflows/deny-check.yml
vendored
Normal file
19
shadowsocks-rust/.github/workflows/deny-check.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
name: Cargo Deny Check
|
||||||
|
on: [push, pull_request]
|
||||||
|
jobs:
|
||||||
|
cargo-deny:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
checks:
|
||||||
|
- advisories
|
||||||
|
- bans licenses sources
|
||||||
|
|
||||||
|
# Prevent sudden announcement of a new advisory from failing ci:
|
||||||
|
continue-on-error: ${{ matrix.checks == 'advisories' }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: EmbarkStudios/cargo-deny-action@v2
|
||||||
|
with:
|
||||||
|
command: check ${{ matrix.checks }}
|
53
shadowsocks-rust/Cargo.lock
generated
53
shadowsocks-rust/Cargo.lock
generated
@@ -136,9 +136,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle"
|
name = "anstyle"
|
||||||
version = "1.0.9"
|
version = "1.0.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56"
|
checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstyle-parse"
|
name = "anstyle-parse"
|
||||||
@@ -170,9 +170,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.91"
|
version = "1.0.92"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8"
|
checksum = "74f37166d7d48a0284b99dd824694c26119c700b53bf0d1540cdb147dbdaaf13"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
@@ -465,9 +465,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.1.31"
|
version = "1.1.32"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f"
|
checksum = "538b056773ee67775e422d15c33169f5415706855814b96505c84ee942f2bae2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jobserver",
|
"jobserver",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -1097,9 +1097,9 @@ checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures-lite"
|
name = "futures-lite"
|
||||||
version = "2.3.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5"
|
checksum = "3f1fa2f9765705486b33fd2acf1577f8ec449c2ba1f318ae5447697b7c08d210"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@@ -1503,7 +1503,7 @@ dependencies = [
|
|||||||
"http 1.1.0",
|
"http 1.1.0",
|
||||||
"hyper",
|
"hyper",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"rustls 0.23.15",
|
"rustls 0.23.16",
|
||||||
"rustls-native-certs 0.8.0",
|
"rustls-native-certs 0.8.0",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -1530,9 +1530,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.9"
|
version = "0.1.10"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b"
|
checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-channel",
|
"futures-channel",
|
||||||
@@ -2569,9 +2569,9 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn-proto 0.11.8",
|
"quinn-proto 0.11.8",
|
||||||
"quinn-udp 0.5.5",
|
"quinn-udp 0.5.6",
|
||||||
"rustc-hash 2.0.0",
|
"rustc-hash 2.0.0",
|
||||||
"rustls 0.23.15",
|
"rustls 0.23.16",
|
||||||
"socket2",
|
"socket2",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
@@ -2605,7 +2605,7 @@ dependencies = [
|
|||||||
"rand",
|
"rand",
|
||||||
"ring 0.17.8",
|
"ring 0.17.8",
|
||||||
"rustc-hash 2.0.0",
|
"rustc-hash 2.0.0",
|
||||||
"rustls 0.23.15",
|
"rustls 0.23.16",
|
||||||
"slab",
|
"slab",
|
||||||
"thiserror",
|
"thiserror",
|
||||||
"tinyvec",
|
"tinyvec",
|
||||||
@@ -2627,10 +2627,11 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quinn-udp"
|
name = "quinn-udp"
|
||||||
version = "0.5.5"
|
version = "0.5.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4fe68c2e9e1a1234e218683dbdf9f9dfcb094113c5ac2b938dfcb9bab4c4140b"
|
checksum = "e346e016eacfff12233c243718197ca12f148c84e1e84268a896699b41c71780"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"cfg_aliases",
|
||||||
"libc",
|
"libc",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"socket2",
|
"socket2",
|
||||||
@@ -2785,7 +2786,7 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
"quinn 0.11.5",
|
"quinn 0.11.5",
|
||||||
"rustls 0.23.15",
|
"rustls 0.23.16",
|
||||||
"rustls-native-certs 0.8.0",
|
"rustls-native-certs 0.8.0",
|
||||||
"rustls-pemfile 2.2.0",
|
"rustls-pemfile 2.2.0",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
@@ -2926,9 +2927,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.37"
|
version = "0.38.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811"
|
checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.6.0",
|
"bitflags 2.6.0",
|
||||||
"errno",
|
"errno",
|
||||||
@@ -2951,9 +2952,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls"
|
name = "rustls"
|
||||||
version = "0.23.15"
|
version = "0.23.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993"
|
checksum = "eee87ff5d9b36712a58574e12e9f0ea80f915a5b0ac518d322b24a465617925e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
@@ -3259,9 +3260,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shadowsocks-crypto"
|
name = "shadowsocks-crypto"
|
||||||
version = "0.5.5"
|
version = "0.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a9e49ecfad8b27f3df28848af11f08aa10df0c6b74b45748131753913be23373"
|
checksum = "bc77ecb3a97509d22751b76665894fcffad2d10df8758f4e3f20c92ccde6bf4f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"aead",
|
"aead",
|
||||||
"aes",
|
"aes",
|
||||||
@@ -3287,7 +3288,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shadowsocks-rust"
|
name = "shadowsocks-rust"
|
||||||
version = "1.21.2"
|
version = "1.21.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"build-time",
|
"build-time",
|
||||||
@@ -3328,7 +3329,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "shadowsocks-service"
|
name = "shadowsocks-service"
|
||||||
version = "1.21.2"
|
version = "1.21.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arc-swap",
|
"arc-swap",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@@ -3809,7 +3810,7 @@ version = "0.26.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"rustls 0.23.15",
|
"rustls 0.23.16",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"tokio",
|
"tokio",
|
||||||
]
|
]
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "shadowsocks-rust"
|
name = "shadowsocks-rust"
|
||||||
version = "1.21.2"
|
version = "1.21.3"
|
||||||
authors = ["Shadowsocks Contributors"]
|
authors = ["Shadowsocks Contributors"]
|
||||||
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
|
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
|
||||||
repository = "https://github.com/shadowsocks/shadowsocks-rust"
|
repository = "https://github.com/shadowsocks/shadowsocks-rust"
|
||||||
@@ -67,11 +67,19 @@ default = [
|
|||||||
"local-tunnel",
|
"local-tunnel",
|
||||||
"local-socks4",
|
"local-socks4",
|
||||||
"multi-threaded",
|
"multi-threaded",
|
||||||
|
"aead-cipher",
|
||||||
"aead-cipher-2022",
|
"aead-cipher-2022",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Basic Features
|
# Basic Features
|
||||||
basic = ["logging", "hickory-dns", "local", "server", "multi-threaded"]
|
basic = [
|
||||||
|
"logging",
|
||||||
|
"hickory-dns",
|
||||||
|
"local",
|
||||||
|
"server",
|
||||||
|
"multi-threaded",
|
||||||
|
"aead-cipher",
|
||||||
|
]
|
||||||
|
|
||||||
# All Suggested Features
|
# All Suggested Features
|
||||||
full = [
|
full = [
|
||||||
@@ -95,6 +103,7 @@ full = [
|
|||||||
"local-online-config",
|
"local-online-config",
|
||||||
"multi-threaded",
|
"multi-threaded",
|
||||||
"stream-cipher",
|
"stream-cipher",
|
||||||
|
"aead-cipher",
|
||||||
"aead-cipher-2022",
|
"aead-cipher-2022",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -190,9 +199,12 @@ multi-threaded = ["tokio/rt-multi-thread"]
|
|||||||
# Users should always avoid using these ciphers in practice
|
# Users should always avoid using these ciphers in practice
|
||||||
stream-cipher = ["shadowsocks-service/stream-cipher"]
|
stream-cipher = ["shadowsocks-service/stream-cipher"]
|
||||||
|
|
||||||
|
# Enable AEAD ciphers
|
||||||
|
aead-cipher = ["shadowsocks-service/aead-cipher"]
|
||||||
|
|
||||||
# Enable extra AEAD ciphers
|
# Enable extra AEAD ciphers
|
||||||
# WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community
|
# WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community
|
||||||
aead-cipher-extra = ["shadowsocks-service/aead-cipher-extra"]
|
aead-cipher-extra = ["aead-cipher", "shadowsocks-service/aead-cipher-extra"]
|
||||||
|
|
||||||
# Enable AEAD 2022
|
# Enable AEAD 2022
|
||||||
aead-cipher-2022 = ["shadowsocks-service/aead-cipher-2022"]
|
aead-cipher-2022 = ["shadowsocks-service/aead-cipher-2022"]
|
||||||
@@ -248,7 +260,7 @@ jemallocator = { version = "0.5", optional = true }
|
|||||||
snmalloc-rs = { version = "0.3", optional = true }
|
snmalloc-rs = { version = "0.3", optional = true }
|
||||||
rpmalloc = { version = "0.2", optional = true }
|
rpmalloc = { version = "0.2", optional = true }
|
||||||
|
|
||||||
shadowsocks-service = { version = "1.21.2", path = "./crates/shadowsocks-service" }
|
shadowsocks-service = { version = "1.21.3", path = "./crates/shadowsocks-service" }
|
||||||
|
|
||||||
windows-service = { version = "0.7", optional = true }
|
windows-service = { version = "0.7", optional = true }
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "shadowsocks-service"
|
name = "shadowsocks-service"
|
||||||
version = "1.21.2"
|
version = "1.21.3"
|
||||||
authors = ["Shadowsocks Contributors"]
|
authors = ["Shadowsocks Contributors"]
|
||||||
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
|
description = "shadowsocks is a fast tunnel proxy that helps you bypass firewalls."
|
||||||
repository = "https://github.com/shadowsocks/shadowsocks-rust"
|
repository = "https://github.com/shadowsocks/shadowsocks-rust"
|
||||||
@@ -15,6 +15,9 @@ rust-version = "1.74"
|
|||||||
maintenance = { status = "passively-maintained" }
|
maintenance = { status = "passively-maintained" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
# WARN: Just for compatible. May be removed in the future releases.
|
||||||
|
default = ["aead-cipher"]
|
||||||
|
|
||||||
full = [
|
full = [
|
||||||
"local",
|
"local",
|
||||||
"server",
|
"server",
|
||||||
@@ -24,6 +27,7 @@ full = [
|
|||||||
"local-redir",
|
"local-redir",
|
||||||
"local-tunnel",
|
"local-tunnel",
|
||||||
"local-socks4",
|
"local-socks4",
|
||||||
|
"aead-cipher",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Enable local server
|
# Enable local server
|
||||||
@@ -114,14 +118,20 @@ local-online-config = [
|
|||||||
# Users should always avoid using these ciphers in practice
|
# Users should always avoid using these ciphers in practice
|
||||||
stream-cipher = ["shadowsocks/stream-cipher"]
|
stream-cipher = ["shadowsocks/stream-cipher"]
|
||||||
|
|
||||||
|
# Enable AEAD ciphers
|
||||||
|
aead-cipher = ["shadowsocks/aead-cipher"]
|
||||||
|
|
||||||
# Enable extra AEAD ciphers
|
# Enable extra AEAD ciphers
|
||||||
# WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community
|
# WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community
|
||||||
aead-cipher-extra = ["shadowsocks/aead-cipher-extra"]
|
aead-cipher-extra = ["aead-cipher", "shadowsocks/aead-cipher-extra"]
|
||||||
|
|
||||||
# Enable AEAD 2022
|
# Enable AEAD 2022
|
||||||
aead-cipher-2022 = ["shadowsocks/aead-cipher-2022"]
|
aead-cipher-2022 = ["shadowsocks/aead-cipher-2022"]
|
||||||
# Enable AEAD 2022 with extra ciphers
|
# Enable AEAD 2022 with extra ciphers
|
||||||
aead-cipher-2022-extra = ["shadowsocks/aead-cipher-2022-extra"]
|
aead-cipher-2022-extra = [
|
||||||
|
"aead-cipher-2022",
|
||||||
|
"shadowsocks/aead-cipher-2022-extra",
|
||||||
|
]
|
||||||
|
|
||||||
# Enable detection against replay attack
|
# Enable detection against replay attack
|
||||||
security-replay-attack-detect = ["shadowsocks/security-replay-attack-detect"]
|
security-replay-attack-detect = ["shadowsocks/security-replay-attack-detect"]
|
||||||
@@ -205,7 +215,7 @@ serde = { version = "1.0", features = ["derive"] }
|
|||||||
json5 = "0.4"
|
json5 = "0.4"
|
||||||
bson = { version = "2.13.0", optional = true }
|
bson = { version = "2.13.0", optional = true }
|
||||||
|
|
||||||
shadowsocks = { version = "1.21.0", path = "../shadowsocks", default-features = false }
|
shadowsocks = { version = "1.21.1", path = "../shadowsocks", default-features = false }
|
||||||
|
|
||||||
# Just for the ioctl call macro
|
# Just for the ioctl call macro
|
||||||
[target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))'.dependencies]
|
[target.'cfg(any(target_os = "macos", target_os = "ios", target_os = "freebsd", target_os = "openbsd"))'.dependencies]
|
||||||
|
@@ -473,7 +473,10 @@ impl Manager {
|
|||||||
return Ok(AddResponse(err));
|
return Ok(AddResponse(err));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
None => self.svr_cfg.method.unwrap_or(CipherKind::CHACHA20_POLY1305),
|
None => self.svr_cfg.method.unwrap_or(CipherKind::CHACHA20_POLY1305),
|
||||||
|
#[cfg(not(feature = "aead-cipher"))]
|
||||||
|
None => return Ok(AddResponse("method is required")),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut svr_cfg = ServerConfig::new(addr, req.password.clone(), method);
|
let mut svr_cfg = ServerConfig::new(addr, req.password.clone(), method);
|
||||||
|
@@ -113,9 +113,9 @@ impl UdpServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let assoc_map = match svr_cfg.method().category() {
|
let assoc_map = match svr_cfg.method().category() {
|
||||||
CipherCategory::None | CipherCategory::Aead => {
|
CipherCategory::None => NatMap::Association(create_assoc_map(time_to_live, capacity)),
|
||||||
NatMap::Association(create_assoc_map(time_to_live, capacity))
|
#[cfg(feature = "aead-cipher")]
|
||||||
}
|
CipherCategory::Aead => NatMap::Association(create_assoc_map(time_to_live, capacity)),
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
CipherCategory::Stream => NatMap::Association(create_assoc_map(time_to_live, capacity)),
|
CipherCategory::Stream => NatMap::Association(create_assoc_map(time_to_live, capacity)),
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
|
@@ -15,7 +15,7 @@ rust-version = "1.74"
|
|||||||
maintenance = { status = "passively-maintained" }
|
maintenance = { status = "passively-maintained" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["hickory-dns"]
|
default = ["hickory-dns", "aead-cipher"]
|
||||||
|
|
||||||
# Uses Hickory-DNS instead of tokio's builtin DNS resolver
|
# Uses Hickory-DNS instead of tokio's builtin DNS resolver
|
||||||
hickory-dns = ["hickory-resolver", "arc-swap", "notify"]
|
hickory-dns = ["hickory-resolver", "arc-swap", "notify"]
|
||||||
@@ -26,19 +26,22 @@ trust-dns = ["hickory-dns"]
|
|||||||
# WARN: Stream Cipher Protocol is proved to be insecure
|
# WARN: Stream Cipher Protocol is proved to be insecure
|
||||||
# https://github.com/shadowsocks/shadowsocks-rust/issues/373
|
# https://github.com/shadowsocks/shadowsocks-rust/issues/373
|
||||||
# Users should always avoid using these ciphers in practice
|
# Users should always avoid using these ciphers in practice
|
||||||
stream-cipher = ["shadowsocks-crypto/v1-stream"]
|
stream-cipher = ["shadowsocks-crypto/v1-stream", "shadowsocks-crypto/ring"]
|
||||||
|
|
||||||
|
# Enable AEAD ciphers
|
||||||
|
aead-cipher = ["shadowsocks-crypto/v1-aead", "shadowsocks-crypto/ring"]
|
||||||
|
|
||||||
# Enable extra AEAD ciphers
|
# Enable extra AEAD ciphers
|
||||||
# WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community
|
# WARN: These non-standard AEAD ciphers are not officially supported by shadowsocks community
|
||||||
aead-cipher-extra = ["shadowsocks-crypto/v1-aead-extra"]
|
aead-cipher-extra = ["aead-cipher", "shadowsocks-crypto/v1-aead-extra"]
|
||||||
|
|
||||||
# Enable AEAD 2022
|
|
||||||
aead-cipher-2022 = [
|
aead-cipher-2022 = [
|
||||||
"shadowsocks-crypto/v2",
|
"shadowsocks-crypto/v2",
|
||||||
|
"shadowsocks-crypto/ring",
|
||||||
"rand/small_rng",
|
"rand/small_rng",
|
||||||
"aes",
|
"aes",
|
||||||
"lru_time_cache",
|
"lru_time_cache",
|
||||||
]
|
] # Enable AEAD 2022
|
||||||
# Enable AEAD 2022 with extra ciphers
|
# Enable AEAD 2022 with extra ciphers
|
||||||
aead-cipher-2022-extra = ["aead-cipher-2022", "shadowsocks-crypto/v2-extra"]
|
aead-cipher-2022-extra = ["aead-cipher-2022", "shadowsocks-crypto/v2-extra"]
|
||||||
|
|
||||||
@@ -88,12 +91,7 @@ notify = { version = "7.0", optional = true }
|
|||||||
|
|
||||||
aes = { version = "0.8", optional = true }
|
aes = { version = "0.8", optional = true }
|
||||||
blake3 = "1.5"
|
blake3 = "1.5"
|
||||||
|
shadowsocks-crypto = { version = "0.5.8", default-features = false }
|
||||||
[target.'cfg(any(target_arch = "x86_64", target_arch = "aarch64"))'.dependencies]
|
|
||||||
shadowsocks-crypto = { version = "0.5.4", features = ["ring"] }
|
|
||||||
|
|
||||||
[target.'cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))'.dependencies]
|
|
||||||
shadowsocks-crypto = { version = "0.5.4", features = [] }
|
|
||||||
|
|
||||||
[target.'cfg(any(windows, target_os = "linux", target_os = "android", target_os = "freebsd", target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))'.dependencies]
|
[target.'cfg(any(windows, target_os = "linux", target_os = "android", target_os = "freebsd", target_os = "macos", target_os = "ios", target_os = "watchos", target_os = "tvos"))'.dependencies]
|
||||||
tokio-tfo = "0.3"
|
tokio-tfo = "0.3"
|
||||||
|
@@ -16,15 +16,13 @@ use base64::Engine as _;
|
|||||||
use byte_string::ByteStr;
|
use byte_string::ByteStr;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use cfg_if::cfg_if;
|
use cfg_if::cfg_if;
|
||||||
use log::error;
|
use log::{error, warn};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
use url::{self, Url};
|
use url::{self, Url};
|
||||||
|
|
||||||
use crate::{
|
#[cfg(any(feature = "stream-cipher", feature = "aead-cipher"))]
|
||||||
crypto::{v1::openssl_bytes_to_key, CipherKind},
|
use crate::crypto::v1::openssl_bytes_to_key;
|
||||||
plugin::PluginConfig,
|
use crate::{crypto::CipherKind, plugin::PluginConfig, relay::socks5::Address};
|
||||||
relay::socks5::Address,
|
|
||||||
};
|
|
||||||
|
|
||||||
const USER_KEY_BASE64_ENGINE: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new(
|
const USER_KEY_BASE64_ENGINE: base64::engine::GeneralPurpose = base64::engine::GeneralPurpose::new(
|
||||||
&base64::alphabet::STANDARD,
|
&base64::alphabet::STANDARD,
|
||||||
@@ -427,9 +425,9 @@ pub struct ServerConfig {
|
|||||||
source: ServerSource,
|
source: ServerSource,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn make_derived_key(method: CipherKind, password: &str, enc_key: &mut [u8]) {
|
fn make_derived_key(method: CipherKind, password: &str, enc_key: &mut [u8]) {
|
||||||
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
if method.is_aead_2022() {
|
if method.is_aead_2022() {
|
||||||
// AEAD 2022 password is a base64 form of enc_key
|
// AEAD 2022 password is a base64 form of enc_key
|
||||||
match AEAD2022_PASSWORD_BASE64_ENGINE.decode(password) {
|
match AEAD2022_PASSWORD_BASE64_ENGINE.decode(password) {
|
||||||
@@ -449,15 +447,21 @@ fn make_derived_key(method: CipherKind, password: &str, enc_key: &mut [u8]) {
|
|||||||
panic!("{method} password {password} is not base64 encoded, error: {err}");
|
panic!("{method} password {password} is not base64 encoded, error: {err}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
openssl_bytes_to_key(password.as_bytes(), enc_key);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(feature = "aead-cipher-2022"))]
|
return;
|
||||||
#[inline]
|
}
|
||||||
fn make_derived_key(_method: CipherKind, password: &str, enc_key: &mut [u8]) {
|
|
||||||
openssl_bytes_to_key(password.as_bytes(), enc_key);
|
cfg_if! {
|
||||||
|
if #[cfg(any(feature = "stream-cipher", feature = "aead-cipher"))] {
|
||||||
|
let _ = method;
|
||||||
|
openssl_bytes_to_key(password.as_bytes(), enc_key);
|
||||||
|
} else {
|
||||||
|
// No default implementation.
|
||||||
|
let _ = password;
|
||||||
|
let _ = enc_key;
|
||||||
|
unreachable!("{method} don't know how to make a derived key");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if method supports Extended Identity Header
|
/// Check if method supports Extended Identity Header
|
||||||
@@ -478,12 +482,28 @@ where
|
|||||||
{
|
{
|
||||||
let password = password.into();
|
let password = password.into();
|
||||||
|
|
||||||
#[cfg(feature = "stream-cipher")]
|
match method {
|
||||||
if method == CipherKind::SS_TABLE {
|
CipherKind::NONE => {
|
||||||
// TABLE cipher doesn't need key derivation.
|
// NONE method's key length is 0
|
||||||
// Reference implemenation: shadowsocks-libev, shadowsocks (Python)
|
debug_assert_eq!(method.key_len(), 0);
|
||||||
let enc_key = password.clone().into_bytes().into_boxed_slice();
|
|
||||||
return (password, enc_key, Vec::new());
|
if !password.is_empty() {
|
||||||
|
warn!("method \"none\" doesn't need a password, which should be set as an empty String, but password.len() = {}", password.len());
|
||||||
|
}
|
||||||
|
|
||||||
|
return (password, Vec::new().into_boxed_slice(), Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "stream-cipher")]
|
||||||
|
CipherKind::SS_TABLE => {
|
||||||
|
// TABLE cipher doesn't need key derivation.
|
||||||
|
// Reference implemenation: shadowsocks-libev, shadowsocks (Python)
|
||||||
|
let enc_key = password.clone().into_bytes().into_boxed_slice();
|
||||||
|
return (password, enc_key, Vec::new());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
|
@@ -7,7 +7,7 @@ use log::warn;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
config::{ReplayAttackPolicy, ServerType},
|
config::{ReplayAttackPolicy, ServerType},
|
||||||
crypto::{v1::random_iv_or_salt, CipherKind},
|
crypto::CipherKind,
|
||||||
dns_resolver::DnsResolver,
|
dns_resolver::DnsResolver,
|
||||||
security::replay::ReplayProtector,
|
security::replay::ReplayProtector,
|
||||||
};
|
};
|
||||||
@@ -50,6 +50,7 @@ impl Context {
|
|||||||
/// Check if nonce exist or not
|
/// Check if nonce exist or not
|
||||||
///
|
///
|
||||||
/// If not, set into the current bloom filter
|
/// If not, set into the current bloom filter
|
||||||
|
#[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))]
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn check_nonce_and_set(&self, method: CipherKind, nonce: &[u8]) -> bool {
|
fn check_nonce_and_set(&self, method: CipherKind, nonce: &[u8]) -> bool {
|
||||||
match self.replay_policy {
|
match self.replay_policy {
|
||||||
@@ -64,7 +65,10 @@ impl Context {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))]
|
||||||
loop {
|
loop {
|
||||||
|
use crate::crypto::utils::random_iv_or_salt;
|
||||||
|
|
||||||
random_iv_or_salt(nonce);
|
random_iv_or_salt(nonce);
|
||||||
|
|
||||||
// Salt already exists, generate a new one.
|
// Salt already exists, generate a new one.
|
||||||
@@ -74,6 +78,12 @@ impl Context {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(not(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022")))]
|
||||||
|
if !nonce.is_empty() {
|
||||||
|
let _ = unique;
|
||||||
|
panic!("{method} don't know how to generate nonce");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check nonce replay
|
/// Check nonce replay
|
||||||
|
@@ -8,9 +8,11 @@ use std::{
|
|||||||
task::{self, Poll},
|
task::{self, Poll},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))]
|
||||||
use byte_string::ByteStr;
|
use byte_string::ByteStr;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures::ready;
|
use futures::ready;
|
||||||
|
#[cfg(any(feature = "stream-cipher", feature = "aead-cipher", feature = "aead-cipher-2022"))]
|
||||||
use log::trace;
|
use log::trace;
|
||||||
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
|
|
||||||
@@ -20,6 +22,7 @@ use crate::{
|
|||||||
crypto::{CipherCategory, CipherKind},
|
crypto::{CipherCategory, CipherKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
use super::aead::{DecryptedReader as AeadDecryptedReader, EncryptedWriter as AeadEncryptedWriter};
|
use super::aead::{DecryptedReader as AeadDecryptedReader, EncryptedWriter as AeadEncryptedWriter};
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
use super::aead_2022::{DecryptedReader as Aead2022DecryptedReader, EncryptedWriter as Aead2022EncryptedWriter};
|
use super::aead_2022::{DecryptedReader as Aead2022DecryptedReader, EncryptedWriter as Aead2022EncryptedWriter};
|
||||||
@@ -34,6 +37,7 @@ pub enum ProtocolError {
|
|||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
StreamError(#[from] super::stream::ProtocolError),
|
StreamError(#[from] super::stream::ProtocolError),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
AeadError(#[from] super::aead::ProtocolError),
|
AeadError(#[from] super::aead::ProtocolError),
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -50,6 +54,7 @@ impl From<ProtocolError> for io::Error {
|
|||||||
ProtocolError::IoError(err) => err,
|
ProtocolError::IoError(err) => err,
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
ProtocolError::StreamError(err) => err.into(),
|
ProtocolError::StreamError(err) => err.into(),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
ProtocolError::AeadError(err) => err.into(),
|
ProtocolError::AeadError(err) => err.into(),
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
ProtocolError::Aead2022Error(err) => err.into(),
|
ProtocolError::Aead2022Error(err) => err.into(),
|
||||||
@@ -70,6 +75,7 @@ pub enum StreamType {
|
|||||||
#[allow(clippy::large_enum_variant)]
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum DecryptedReader {
|
pub enum DecryptedReader {
|
||||||
None,
|
None,
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
Aead(AeadDecryptedReader),
|
Aead(AeadDecryptedReader),
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
Stream(StreamDecryptedReader),
|
Stream(StreamDecryptedReader),
|
||||||
@@ -98,8 +104,13 @@ impl DecryptedReader {
|
|||||||
match method.category() {
|
match method.category() {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
CipherCategory::Stream => DecryptedReader::Stream(StreamDecryptedReader::new(method, key)),
|
CipherCategory::Stream => DecryptedReader::Stream(StreamDecryptedReader::new(method, key)),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => DecryptedReader::Aead(AeadDecryptedReader::new(method, key)),
|
CipherCategory::Aead => DecryptedReader::Aead(AeadDecryptedReader::new(method, key)),
|
||||||
CipherCategory::None => DecryptedReader::None,
|
CipherCategory::None => {
|
||||||
|
let _ = method;
|
||||||
|
let _ = key;
|
||||||
|
DecryptedReader::None
|
||||||
|
}
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
CipherCategory::Aead2022 => DecryptedReader::Aead2022(Aead2022DecryptedReader::with_user_manager(
|
CipherCategory::Aead2022 => DecryptedReader::Aead2022(Aead2022DecryptedReader::with_user_manager(
|
||||||
stream_ty,
|
stream_ty,
|
||||||
@@ -127,10 +138,14 @@ impl DecryptedReader {
|
|||||||
DecryptedReader::Stream(ref mut reader) => {
|
DecryptedReader::Stream(ref mut reader) => {
|
||||||
reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into)
|
reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
DecryptedReader::Aead(ref mut reader) => {
|
DecryptedReader::Aead(ref mut reader) => {
|
||||||
reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into)
|
reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into)
|
||||||
}
|
}
|
||||||
DecryptedReader::None => Pin::new(stream).poll_read(cx, buf).map_err(Into::into),
|
DecryptedReader::None => {
|
||||||
|
let _ = context;
|
||||||
|
Pin::new(stream).poll_read(cx, buf).map_err(Into::into)
|
||||||
|
}
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
DecryptedReader::Aead2022(ref mut reader) => {
|
DecryptedReader::Aead2022(ref mut reader) => {
|
||||||
reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into)
|
reader.poll_read_decrypted(cx, context, stream, buf).map_err(Into::into)
|
||||||
@@ -143,6 +158,7 @@ impl DecryptedReader {
|
|||||||
match *self {
|
match *self {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
DecryptedReader::Stream(ref reader) => reader.iv(),
|
DecryptedReader::Stream(ref reader) => reader.iv(),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
DecryptedReader::Aead(ref reader) => reader.salt(),
|
DecryptedReader::Aead(ref reader) => reader.salt(),
|
||||||
DecryptedReader::None => None,
|
DecryptedReader::None => None,
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -155,6 +171,7 @@ impl DecryptedReader {
|
|||||||
match *self {
|
match *self {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
DecryptedReader::Stream(..) => None,
|
DecryptedReader::Stream(..) => None,
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
DecryptedReader::Aead(..) => None,
|
DecryptedReader::Aead(..) => None,
|
||||||
DecryptedReader::None => None,
|
DecryptedReader::None => None,
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -167,6 +184,7 @@ impl DecryptedReader {
|
|||||||
match *self {
|
match *self {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
DecryptedReader::Stream(..) => None,
|
DecryptedReader::Stream(..) => None,
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
DecryptedReader::Aead(..) => None,
|
DecryptedReader::Aead(..) => None,
|
||||||
DecryptedReader::None => None,
|
DecryptedReader::None => None,
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -178,6 +196,7 @@ impl DecryptedReader {
|
|||||||
match *self {
|
match *self {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
DecryptedReader::Stream(ref reader) => reader.handshaked(),
|
DecryptedReader::Stream(ref reader) => reader.handshaked(),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
DecryptedReader::Aead(ref reader) => reader.handshaked(),
|
DecryptedReader::Aead(ref reader) => reader.handshaked(),
|
||||||
DecryptedReader::None => true,
|
DecryptedReader::None => true,
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -189,6 +208,7 @@ impl DecryptedReader {
|
|||||||
/// Writer for writing encrypted data stream into shadowsocks' tunnel
|
/// Writer for writing encrypted data stream into shadowsocks' tunnel
|
||||||
pub enum EncryptedWriter {
|
pub enum EncryptedWriter {
|
||||||
None,
|
None,
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
Aead(AeadEncryptedWriter),
|
Aead(AeadEncryptedWriter),
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
Stream(StreamEncryptedWriter),
|
Stream(StreamEncryptedWriter),
|
||||||
@@ -206,8 +226,13 @@ impl EncryptedWriter {
|
|||||||
match method.category() {
|
match method.category() {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
CipherCategory::Stream => EncryptedWriter::Stream(StreamEncryptedWriter::new(method, key, nonce)),
|
CipherCategory::Stream => EncryptedWriter::Stream(StreamEncryptedWriter::new(method, key, nonce)),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => EncryptedWriter::Aead(AeadEncryptedWriter::new(method, key, nonce)),
|
CipherCategory::Aead => EncryptedWriter::Aead(AeadEncryptedWriter::new(method, key, nonce)),
|
||||||
CipherCategory::None => EncryptedWriter::None,
|
CipherCategory::None => {
|
||||||
|
let _ = key;
|
||||||
|
let _ = nonce;
|
||||||
|
EncryptedWriter::None
|
||||||
|
}
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
CipherCategory::Aead2022 => {
|
CipherCategory::Aead2022 => {
|
||||||
EncryptedWriter::Aead2022(Aead2022EncryptedWriter::new(stream_ty, method, key, nonce))
|
EncryptedWriter::Aead2022(Aead2022EncryptedWriter::new(stream_ty, method, key, nonce))
|
||||||
@@ -231,8 +256,13 @@ impl EncryptedWriter {
|
|||||||
match method.category() {
|
match method.category() {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
CipherCategory::Stream => EncryptedWriter::Stream(StreamEncryptedWriter::new(method, key, nonce)),
|
CipherCategory::Stream => EncryptedWriter::Stream(StreamEncryptedWriter::new(method, key, nonce)),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => EncryptedWriter::Aead(AeadEncryptedWriter::new(method, key, nonce)),
|
CipherCategory::Aead => EncryptedWriter::Aead(AeadEncryptedWriter::new(method, key, nonce)),
|
||||||
CipherCategory::None => EncryptedWriter::None,
|
CipherCategory::None => {
|
||||||
|
let _ = key;
|
||||||
|
let _ = nonce;
|
||||||
|
EncryptedWriter::None
|
||||||
|
}
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
CipherCategory::Aead2022 => EncryptedWriter::Aead2022(Aead2022EncryptedWriter::with_identity(
|
CipherCategory::Aead2022 => EncryptedWriter::Aead2022(Aead2022EncryptedWriter::with_identity(
|
||||||
stream_ty,
|
stream_ty,
|
||||||
@@ -258,6 +288,7 @@ impl EncryptedWriter {
|
|||||||
match *self {
|
match *self {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
EncryptedWriter::Stream(ref mut writer) => writer.poll_write_encrypted(cx, stream, buf).map_err(Into::into),
|
EncryptedWriter::Stream(ref mut writer) => writer.poll_write_encrypted(cx, stream, buf).map_err(Into::into),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
EncryptedWriter::Aead(ref mut writer) => writer.poll_write_encrypted(cx, stream, buf).map_err(Into::into),
|
EncryptedWriter::Aead(ref mut writer) => writer.poll_write_encrypted(cx, stream, buf).map_err(Into::into),
|
||||||
EncryptedWriter::None => Pin::new(stream).poll_write(cx, buf).map_err(Into::into),
|
EncryptedWriter::None => Pin::new(stream).poll_write(cx, buf).map_err(Into::into),
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -272,6 +303,7 @@ impl EncryptedWriter {
|
|||||||
match *self {
|
match *self {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
EncryptedWriter::Stream(ref writer) => writer.iv(),
|
EncryptedWriter::Stream(ref writer) => writer.iv(),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
EncryptedWriter::Aead(ref writer) => writer.salt(),
|
EncryptedWriter::Aead(ref writer) => writer.salt(),
|
||||||
EncryptedWriter::None => &[],
|
EncryptedWriter::None => &[],
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -355,6 +387,7 @@ impl<S> CryptoStream<S> {
|
|||||||
let prev_len = match category {
|
let prev_len = match category {
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
CipherCategory::Stream => method.iv_len(),
|
CipherCategory::Stream => method.iv_len(),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => method.salt_len(),
|
CipherCategory::Aead => method.salt_len(),
|
||||||
CipherCategory::None => 0,
|
CipherCategory::None => 0,
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -369,13 +402,18 @@ impl<S> CryptoStream<S> {
|
|||||||
trace!("generated Stream cipher IV {:?}", ByteStr::new(&local_iv));
|
trace!("generated Stream cipher IV {:?}", ByteStr::new(&local_iv));
|
||||||
local_iv
|
local_iv
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => {
|
CipherCategory::Aead => {
|
||||||
let mut local_salt = vec![0u8; prev_len];
|
let mut local_salt = vec![0u8; prev_len];
|
||||||
context.generate_nonce(method, &mut local_salt, true);
|
context.generate_nonce(method, &mut local_salt, true);
|
||||||
trace!("generated AEAD cipher salt {:?}", ByteStr::new(&local_salt));
|
trace!("generated AEAD cipher salt {:?}", ByteStr::new(&local_salt));
|
||||||
local_salt
|
local_salt
|
||||||
}
|
}
|
||||||
CipherCategory::None => Vec::new(),
|
CipherCategory::None => {
|
||||||
|
debug_assert_eq!(prev_len, 0);
|
||||||
|
let _ = context;
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
CipherCategory::Aead2022 => {
|
CipherCategory::Aead2022 => {
|
||||||
// AEAD-2022 has a request-salt in respond header, so the generated salt doesn't need to be remembered.
|
// AEAD-2022 has a request-salt in respond header, so the generated salt doesn't need to be remembered.
|
||||||
|
@@ -5,6 +5,7 @@ pub use self::{
|
|||||||
proxy_stream::{ProxyClientStream, ProxyServerStream},
|
proxy_stream::{ProxyClientStream, ProxyServerStream},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
mod aead;
|
mod aead;
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
mod aead_2022;
|
mod aead_2022;
|
||||||
|
@@ -28,7 +28,11 @@ pub enum TcpRequestHeader {
|
|||||||
impl TcpRequestHeader {
|
impl TcpRequestHeader {
|
||||||
pub async fn read_from<R: AsyncRead + Unpin>(method: CipherKind, reader: &mut R) -> io::Result<TcpRequestHeader> {
|
pub async fn read_from<R: AsyncRead + Unpin>(method: CipherKind, reader: &mut R) -> io::Result<TcpRequestHeader> {
|
||||||
match method.category() {
|
match method.category() {
|
||||||
CipherCategory::None | CipherCategory::Aead => Ok(TcpRequestHeader::Stream(
|
CipherCategory::None => Ok(TcpRequestHeader::Stream(
|
||||||
|
StreamTcpRequestHeader::read_from(reader).await?,
|
||||||
|
)),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
|
CipherCategory::Aead => Ok(TcpRequestHeader::Stream(
|
||||||
StreamTcpRequestHeader::read_from(reader).await?,
|
StreamTcpRequestHeader::read_from(reader).await?,
|
||||||
)),
|
)),
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
|
@@ -155,6 +155,7 @@ where
|
|||||||
|
|
||||||
fn plain_read_buffer_size(method: CipherKind) -> usize {
|
fn plain_read_buffer_size(method: CipherKind) -> usize {
|
||||||
match method.category() {
|
match method.category() {
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => super::aead::MAX_PACKET_SIZE,
|
CipherCategory::Aead => super::aead::MAX_PACKET_SIZE,
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
CipherCategory::Stream => 1 << 14,
|
CipherCategory::Stream => 1 << 14,
|
||||||
|
@@ -30,17 +30,16 @@ use crate::{
|
|||||||
relay::socks5::{Address, Error as Socks5Error},
|
relay::socks5::{Address, Error as Socks5Error},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
|
use super::aead::{decrypt_payload_aead, encrypt_payload_aead};
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
use super::aead_2022::{
|
use super::aead_2022::{
|
||||||
decrypt_client_payload_aead_2022, decrypt_server_payload_aead_2022, encrypt_client_payload_aead_2022,
|
decrypt_client_payload_aead_2022, decrypt_server_payload_aead_2022, encrypt_client_payload_aead_2022,
|
||||||
encrypt_server_payload_aead_2022,
|
encrypt_server_payload_aead_2022,
|
||||||
};
|
};
|
||||||
|
use super::options::UdpSocketControlData;
|
||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
use super::stream::{decrypt_payload_stream, encrypt_payload_stream};
|
use super::stream::{decrypt_payload_stream, encrypt_payload_stream};
|
||||||
use super::{
|
|
||||||
aead::{decrypt_payload_aead, encrypt_payload_aead},
|
|
||||||
options::UdpSocketControlData,
|
|
||||||
};
|
|
||||||
|
|
||||||
/// UDP shadowsocks protocol errors
|
/// UDP shadowsocks protocol errors
|
||||||
#[derive(thiserror::Error, Debug)]
|
#[derive(thiserror::Error, Debug)]
|
||||||
@@ -50,6 +49,7 @@ pub enum ProtocolError {
|
|||||||
#[cfg(feature = "stream-cipher")]
|
#[cfg(feature = "stream-cipher")]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
StreamError(#[from] super::stream::ProtocolError),
|
StreamError(#[from] super::stream::ProtocolError),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
AeadError(#[from] super::aead::ProtocolError),
|
AeadError(#[from] super::aead::ProtocolError),
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
@@ -74,6 +74,8 @@ pub fn encrypt_client_payload(
|
|||||||
) {
|
) {
|
||||||
match method.category() {
|
match method.category() {
|
||||||
CipherCategory::None => {
|
CipherCategory::None => {
|
||||||
|
let _ = context;
|
||||||
|
let _ = key;
|
||||||
let _ = control;
|
let _ = control;
|
||||||
let _ = identity_keys;
|
let _ = identity_keys;
|
||||||
dst.reserve(addr.serialized_len() + payload.len());
|
dst.reserve(addr.serialized_len() + payload.len());
|
||||||
@@ -86,6 +88,7 @@ pub fn encrypt_client_payload(
|
|||||||
let _ = identity_keys;
|
let _ = identity_keys;
|
||||||
encrypt_payload_stream(context, method, key, addr, payload, dst)
|
encrypt_payload_stream(context, method, key, addr, payload, dst)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => {
|
CipherCategory::Aead => {
|
||||||
let _ = control;
|
let _ = control;
|
||||||
let _ = identity_keys;
|
let _ = identity_keys;
|
||||||
@@ -110,6 +113,8 @@ pub fn encrypt_server_payload(
|
|||||||
) {
|
) {
|
||||||
match method.category() {
|
match method.category() {
|
||||||
CipherCategory::None => {
|
CipherCategory::None => {
|
||||||
|
let _ = context;
|
||||||
|
let _ = key;
|
||||||
let _ = control;
|
let _ = control;
|
||||||
dst.reserve(addr.serialized_len() + payload.len());
|
dst.reserve(addr.serialized_len() + payload.len());
|
||||||
addr.write_to_buf(dst);
|
addr.write_to_buf(dst);
|
||||||
@@ -120,6 +125,7 @@ pub fn encrypt_server_payload(
|
|||||||
let _ = control;
|
let _ = control;
|
||||||
encrypt_payload_stream(context, method, key, addr, payload, dst)
|
encrypt_payload_stream(context, method, key, addr, payload, dst)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => {
|
CipherCategory::Aead => {
|
||||||
let _ = control;
|
let _ = control;
|
||||||
encrypt_payload_aead(context, method, key, addr, payload, dst)
|
encrypt_payload_aead(context, method, key, addr, payload, dst)
|
||||||
@@ -139,6 +145,8 @@ pub fn decrypt_client_payload(
|
|||||||
) -> ProtocolResult<(usize, Address, Option<UdpSocketControlData>)> {
|
) -> ProtocolResult<(usize, Address, Option<UdpSocketControlData>)> {
|
||||||
match method.category() {
|
match method.category() {
|
||||||
CipherCategory::None => {
|
CipherCategory::None => {
|
||||||
|
let _ = context;
|
||||||
|
let _ = key;
|
||||||
let _ = user_manager;
|
let _ = user_manager;
|
||||||
let mut cur = Cursor::new(payload);
|
let mut cur = Cursor::new(payload);
|
||||||
match Address::read_cursor(&mut cur) {
|
match Address::read_cursor(&mut cur) {
|
||||||
@@ -158,6 +166,7 @@ pub fn decrypt_client_payload(
|
|||||||
.map(|(n, a)| (n, a, None))
|
.map(|(n, a)| (n, a, None))
|
||||||
.map_err(Into::into)
|
.map_err(Into::into)
|
||||||
}
|
}
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => {
|
CipherCategory::Aead => {
|
||||||
let _ = user_manager;
|
let _ = user_manager;
|
||||||
decrypt_payload_aead(context, method, key, payload)
|
decrypt_payload_aead(context, method, key, payload)
|
||||||
@@ -180,6 +189,9 @@ pub fn decrypt_server_payload(
|
|||||||
) -> ProtocolResult<(usize, Address, Option<UdpSocketControlData>)> {
|
) -> ProtocolResult<(usize, Address, Option<UdpSocketControlData>)> {
|
||||||
match method.category() {
|
match method.category() {
|
||||||
CipherCategory::None => {
|
CipherCategory::None => {
|
||||||
|
let _ = context;
|
||||||
|
let _ = key;
|
||||||
|
|
||||||
let mut cur = Cursor::new(payload);
|
let mut cur = Cursor::new(payload);
|
||||||
match Address::read_cursor(&mut cur) {
|
match Address::read_cursor(&mut cur) {
|
||||||
Ok(address) => {
|
Ok(address) => {
|
||||||
@@ -195,6 +207,7 @@ pub fn decrypt_server_payload(
|
|||||||
CipherCategory::Stream => decrypt_payload_stream(context, method, key, payload)
|
CipherCategory::Stream => decrypt_payload_stream(context, method, key, payload)
|
||||||
.map(|(n, a)| (n, a, None))
|
.map(|(n, a)| (n, a, None))
|
||||||
.map_err(Into::into),
|
.map_err(Into::into),
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
CipherCategory::Aead => decrypt_payload_aead(context, method, key, payload)
|
CipherCategory::Aead => decrypt_payload_aead(context, method, key, payload)
|
||||||
.map(|(n, a)| (n, a, None))
|
.map(|(n, a)| (n, a, None))
|
||||||
.map_err(Into::into),
|
.map_err(Into::into),
|
||||||
|
@@ -52,6 +52,7 @@ use std::time::Duration;
|
|||||||
pub use self::proxy_socket::ProxySocket;
|
pub use self::proxy_socket::ProxySocket;
|
||||||
pub use compat::{DatagramReceive, DatagramReceiveExt, DatagramSend, DatagramSendExt, DatagramSocket};
|
pub use compat::{DatagramReceive, DatagramReceiveExt, DatagramSend, DatagramSendExt, DatagramSocket};
|
||||||
|
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
mod aead;
|
mod aead;
|
||||||
#[cfg(feature = "aead-cipher-2022")]
|
#[cfg(feature = "aead-cipher-2022")]
|
||||||
mod aead_2022;
|
mod aead_2022;
|
||||||
|
@@ -151,6 +151,7 @@ async fn tcp_tunnel_example(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn tcp_tunnel_aead() {
|
async fn tcp_tunnel_aead() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
@@ -180,7 +181,7 @@ async fn tcp_tunnel_none() {
|
|||||||
|
|
||||||
let server_addr = "127.0.0.1:33001".parse::<SocketAddr>().unwrap();
|
let server_addr = "127.0.0.1:33001".parse::<SocketAddr>().unwrap();
|
||||||
let local_addr = "127.0.0.1:33101".parse::<SocketAddr>().unwrap();
|
let local_addr = "127.0.0.1:33101".parse::<SocketAddr>().unwrap();
|
||||||
tcp_tunnel_example(server_addr, local_addr, "p$p", CipherKind::NONE)
|
tcp_tunnel_example(server_addr, local_addr, "", CipherKind::NONE)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@@ -32,7 +32,7 @@ use tokio::{
|
|||||||
async fn tcp_tunnel_tfo() {
|
async fn tcp_tunnel_tfo() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
|
||||||
let svr_cfg = ServerConfig::new(("127.0.0.1", 41000), "?", CipherKind::NONE);
|
let svr_cfg = ServerConfig::new(("127.0.0.1", 41000), "", CipherKind::NONE);
|
||||||
let svr_cfg_client = svr_cfg.clone();
|
let svr_cfg_client = svr_cfg.clone();
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
|
@@ -136,6 +136,7 @@ async fn udp_tunnel_echo(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "aead-cipher")]
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn udp_tunnel_aead() {
|
async fn udp_tunnel_aead() {
|
||||||
let _ = env_logger::try_init();
|
let _ = env_logger::try_init();
|
||||||
|
250
shadowsocks-rust/deny.toml
Normal file
250
shadowsocks-rust/deny.toml
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
# This template contains all of the possible sections and their default values
|
||||||
|
|
||||||
|
# Note that all fields that take a lint level have these possible values:
|
||||||
|
# * deny - An error will be produced and the check will fail
|
||||||
|
# * warn - A warning will be produced, but the check will not fail
|
||||||
|
# * allow - No warning or error will be produced, though in some cases a note
|
||||||
|
# will be
|
||||||
|
|
||||||
|
# The values provided in this template are the default values that will be used
|
||||||
|
# when any section or field is not specified in your own configuration
|
||||||
|
|
||||||
|
# Root options
|
||||||
|
|
||||||
|
# The graph table configures how the dependency graph is constructed and thus
|
||||||
|
# which crates the checks are performed against
|
||||||
|
[graph]
|
||||||
|
# If 1 or more target triples (and optionally, target_features) are specified,
|
||||||
|
# only the specified targets will be checked when running `cargo deny check`.
|
||||||
|
# This means, if a particular package is only ever used as a target specific
|
||||||
|
# dependency, such as, for example, the `nix` crate only being used via the
|
||||||
|
# `target_family = "unix"` configuration, that only having windows targets in
|
||||||
|
# this list would mean the nix crate, as well as any of its exclusive
|
||||||
|
# dependencies not shared by any other crates, would be ignored, as the target
|
||||||
|
# list here is effectively saying which targets you are building for.
|
||||||
|
targets = [
|
||||||
|
# The triple can be any string, but only the target triples built in to
|
||||||
|
# rustc (as of 1.40) can be checked against actual config expressions
|
||||||
|
#"x86_64-unknown-linux-musl",
|
||||||
|
# You can also specify which target_features you promise are enabled for a
|
||||||
|
# particular target. target_features are currently not validated against
|
||||||
|
# the actual valid features supported by the target architecture.
|
||||||
|
#{ triple = "wasm32-unknown-unknown", features = ["atomics"] },
|
||||||
|
]
|
||||||
|
# When creating the dependency graph used as the source of truth when checks are
|
||||||
|
# executed, this field can be used to prune crates from the graph, removing them
|
||||||
|
# from the view of cargo-deny. This is an extremely heavy hammer, as if a crate
|
||||||
|
# is pruned from the graph, all of its dependencies will also be pruned unless
|
||||||
|
# they are connected to another crate in the graph that hasn't been pruned,
|
||||||
|
# so it should be used with care. The identifiers are [Package ID Specifications]
|
||||||
|
# (https://doc.rust-lang.org/cargo/reference/pkgid-spec.html)
|
||||||
|
#exclude = []
|
||||||
|
# If true, metadata will be collected with `--all-features`. Note that this can't
|
||||||
|
# be toggled off if true, if you want to conditionally enable `--all-features` it
|
||||||
|
# is recommended to pass `--all-features` on the cmd line instead
|
||||||
|
all-features = false
|
||||||
|
# If true, metadata will be collected with `--no-default-features`. The same
|
||||||
|
# caveat with `all-features` applies
|
||||||
|
no-default-features = false
|
||||||
|
# If set, these feature will be enabled when collecting metadata. If `--features`
|
||||||
|
# is specified on the cmd line they will take precedence over this option.
|
||||||
|
features = ["full-extra"]
|
||||||
|
|
||||||
|
# The output table provides options for how/if diagnostics are outputted
|
||||||
|
[output]
|
||||||
|
# When outputting inclusion graphs in diagnostics that include features, this
|
||||||
|
# option can be used to specify the depth at which feature edges will be added.
|
||||||
|
# This option is included since the graphs can be quite large and the addition
|
||||||
|
# of features from the crate(s) to all of the graph roots can be far too verbose.
|
||||||
|
# This option can be overridden via `--feature-depth` on the cmd line
|
||||||
|
feature-depth = 1
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check advisories`
|
||||||
|
# More documentation for the advisories section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/advisories/cfg.html
|
||||||
|
[advisories]
|
||||||
|
# The path where the advisory databases are cloned/fetched into
|
||||||
|
#db-path = "$CARGO_HOME/advisory-dbs"
|
||||||
|
# The url(s) of the advisory databases to use
|
||||||
|
#db-urls = ["https://github.com/rustsec/advisory-db"]
|
||||||
|
# A list of advisory IDs to ignore. Note that ignored advisories will still
|
||||||
|
# output a note when they are encountered.
|
||||||
|
ignore = [
|
||||||
|
#"RUSTSEC-0000-0000",
|
||||||
|
#{ id = "RUSTSEC-0000-0000", reason = "you can specify a reason the advisory is ignored" },
|
||||||
|
#"a-crate-that-is-yanked@0.1.1", # you can also ignore yanked crate versions if you wish
|
||||||
|
#{ crate = "a-crate-that-is-yanked@0.1.1", reason = "you can specify why you are ignoring the yanked crate" },
|
||||||
|
]
|
||||||
|
# If this is true, then cargo deny will use the git executable to fetch advisory database.
|
||||||
|
# If this is false, then it uses a built-in git library.
|
||||||
|
# Setting this to true can be helpful if you have special authentication requirements that cargo-deny does not support.
|
||||||
|
# See Git Authentication for more information about setting up git authentication.
|
||||||
|
#git-fetch-with-cli = true
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check licenses`
|
||||||
|
# More documentation for the licenses section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/licenses/cfg.html
|
||||||
|
[licenses]
|
||||||
|
# List of explicitly allowed licenses
|
||||||
|
# See https://spdx.org/licenses/ for list of possible licenses
|
||||||
|
# [possible values: any SPDX 3.11 short identifier (+ optional exception)].
|
||||||
|
allow = [
|
||||||
|
"MIT",
|
||||||
|
"Apache-2.0",
|
||||||
|
"Apache-2.0 WITH LLVM-exception",
|
||||||
|
"ISC",
|
||||||
|
"BSD-2-Clause",
|
||||||
|
"BSD-3-Clause",
|
||||||
|
"Unicode-3.0",
|
||||||
|
"Unicode-DFS-2016",
|
||||||
|
"MPL-2.0",
|
||||||
|
"CC0-1.0",
|
||||||
|
"0BSD",
|
||||||
|
]
|
||||||
|
# The confidence threshold for detecting a license from license text.
|
||||||
|
# The higher the value, the more closely the license text must be to the
|
||||||
|
# canonical license text of a valid SPDX license file.
|
||||||
|
# [possible values: any between 0.0 and 1.0].
|
||||||
|
confidence-threshold = 0.8
|
||||||
|
# Allow 1 or more licenses on a per-crate basis, so that particular licenses
|
||||||
|
# aren't accepted for every possible crate as with the normal allow list
|
||||||
|
exceptions = [
|
||||||
|
# Each entry is the crate and version constraint, and its specific allow
|
||||||
|
# list
|
||||||
|
#{ allow = ["Zlib"], crate = "adler32" },
|
||||||
|
{ allow = ["WTFPL"], crate = "tun2" },
|
||||||
|
{ allow = ["LicenseRef-ring"], crate = "ring" },
|
||||||
|
]
|
||||||
|
|
||||||
|
# Some crates don't have (easily) machine readable licensing information,
|
||||||
|
# adding a clarification entry for it allows you to manually specify the
|
||||||
|
# licensing information
|
||||||
|
#[[licenses.clarify]]
|
||||||
|
# The package spec the clarification applies to
|
||||||
|
#crate = "ring"
|
||||||
|
# The SPDX expression for the license requirements of the crate
|
||||||
|
#expression = "MIT AND ISC AND OpenSSL"
|
||||||
|
# One or more files in the crate's source used as the "source of truth" for
|
||||||
|
# the license expression. If the contents match, the clarification will be used
|
||||||
|
# when running the license check, otherwise the clarification will be ignored
|
||||||
|
# and the crate will be checked normally, which may produce warnings or errors
|
||||||
|
# depending on the rest of your configuration
|
||||||
|
#license-files = [
|
||||||
|
# Each entry is a crate relative path, and the (opaque) hash of its contents
|
||||||
|
#{ path = "LICENSE", hash = 0xbd0eed23 }
|
||||||
|
#]
|
||||||
|
|
||||||
|
[[licenses.clarify]]
|
||||||
|
name = "ring"
|
||||||
|
expression = "LicenseRef-ring"
|
||||||
|
license-files = [{ path = "LICENSE", hash = 0xbd0eed23 }]
|
||||||
|
|
||||||
|
[licenses.private]
|
||||||
|
# If true, ignores workspace crates that aren't published, or are only
|
||||||
|
# published to private registries.
|
||||||
|
# To see how to mark a crate as unpublished (to the official registry),
|
||||||
|
# visit https://doc.rust-lang.org/cargo/reference/manifest.html#the-publish-field.
|
||||||
|
ignore = false
|
||||||
|
# One or more private registries that you might publish crates to, if a crate
|
||||||
|
# is only published to private registries, and ignore is true, the crate will
|
||||||
|
# not have its license(s) checked
|
||||||
|
registries = [
|
||||||
|
#"https://sekretz.com/registry
|
||||||
|
]
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check bans`.
|
||||||
|
# More documentation about the 'bans' section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/bans/cfg.html
|
||||||
|
[bans]
|
||||||
|
# Lint level for when multiple versions of the same crate are detected
|
||||||
|
multiple-versions = "warn"
|
||||||
|
# Lint level for when a crate version requirement is `*`
|
||||||
|
wildcards = "deny"
|
||||||
|
# The graph highlighting used when creating dotgraphs for crates
|
||||||
|
# with multiple versions
|
||||||
|
# * lowest-version - The path to the lowest versioned duplicate is highlighted
|
||||||
|
# * simplest-path - The path to the version with the fewest edges is highlighted
|
||||||
|
# * all - Both lowest-version and simplest-path are used
|
||||||
|
highlight = "all"
|
||||||
|
# The default lint level for `default` features for crates that are members of
|
||||||
|
# the workspace that is being checked. This can be overridden by allowing/denying
|
||||||
|
# `default` on a crate-by-crate basis if desired.
|
||||||
|
workspace-default-features = "allow"
|
||||||
|
# The default lint level for `default` features for external crates that are not
|
||||||
|
# members of the workspace. This can be overridden by allowing/denying `default`
|
||||||
|
# on a crate-by-crate basis if desired.
|
||||||
|
external-default-features = "allow"
|
||||||
|
# List of crates that are allowed. Use with care!
|
||||||
|
allow = [
|
||||||
|
#"ansi_term@0.11.0",
|
||||||
|
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is allowed" },
|
||||||
|
]
|
||||||
|
# List of crates to deny
|
||||||
|
deny = [
|
||||||
|
#"ansi_term@0.11.0",
|
||||||
|
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason it is banned" },
|
||||||
|
# Wrapper crates can optionally be specified to allow the crate when it
|
||||||
|
# is a direct dependency of the otherwise banned crate
|
||||||
|
#{ crate = "ansi_term@0.11.0", wrappers = ["this-crate-directly-depends-on-ansi_term"] },
|
||||||
|
]
|
||||||
|
|
||||||
|
# List of features to allow/deny
|
||||||
|
# Each entry the name of a crate and a version range. If version is
|
||||||
|
# not specified, all versions will be matched.
|
||||||
|
#[[bans.features]]
|
||||||
|
#crate = "reqwest"
|
||||||
|
# Features to not allow
|
||||||
|
#deny = ["json"]
|
||||||
|
# Features to allow
|
||||||
|
#allow = [
|
||||||
|
# "rustls",
|
||||||
|
# "__rustls",
|
||||||
|
# "__tls",
|
||||||
|
# "hyper-rustls",
|
||||||
|
# "rustls",
|
||||||
|
# "rustls-pemfile",
|
||||||
|
# "rustls-tls-webpki-roots",
|
||||||
|
# "tokio-rustls",
|
||||||
|
# "webpki-roots",
|
||||||
|
#]
|
||||||
|
# If true, the allowed features must exactly match the enabled feature set. If
|
||||||
|
# this is set there is no point setting `deny`
|
||||||
|
#exact = true
|
||||||
|
|
||||||
|
# Certain crates/versions that will be skipped when doing duplicate detection.
|
||||||
|
skip = [
|
||||||
|
#"ansi_term@0.11.0",
|
||||||
|
#{ crate = "ansi_term@0.11.0", reason = "you can specify a reason why it can't be updated/removed" },
|
||||||
|
]
|
||||||
|
# Similarly to `skip` allows you to skip certain crates during duplicate
|
||||||
|
# detection. Unlike skip, it also includes the entire tree of transitive
|
||||||
|
# dependencies starting at the specified crate, up to a certain depth, which is
|
||||||
|
# by default infinite.
|
||||||
|
skip-tree = [
|
||||||
|
#"ansi_term@0.11.0", # will be skipped along with _all_ of its direct and transitive dependencies
|
||||||
|
#{ crate = "ansi_term@0.11.0", depth = 20 },
|
||||||
|
]
|
||||||
|
|
||||||
|
# This section is considered when running `cargo deny check sources`.
|
||||||
|
# More documentation about the 'sources' section can be found here:
|
||||||
|
# https://embarkstudios.github.io/cargo-deny/checks/sources/cfg.html
|
||||||
|
[sources]
|
||||||
|
# Lint level for what to happen when a crate from a crate registry that is not
|
||||||
|
# in the allow list is encountered
|
||||||
|
unknown-registry = "warn"
|
||||||
|
# Lint level for what to happen when a crate from a git repository that is not
|
||||||
|
# in the allow list is encountered
|
||||||
|
unknown-git = "warn"
|
||||||
|
# List of URLs for allowed crate registries. Defaults to the crates.io index
|
||||||
|
# if not specified. If it is specified but empty, no registries are allowed.
|
||||||
|
allow-registry = ["https://github.com/rust-lang/crates.io-index"]
|
||||||
|
# List of URLs for allowed Git repositories
|
||||||
|
allow-git = []
|
||||||
|
|
||||||
|
[sources.allow-org]
|
||||||
|
# github.com organizations to allow git sources for
|
||||||
|
github = []
|
||||||
|
# gitlab.com organizations to allow git sources for
|
||||||
|
gitlab = []
|
||||||
|
# bitbucket.org organizations to allow git sources for
|
||||||
|
bitbucket = []
|
@@ -155,7 +155,16 @@ upload_macos_dmg:
|
|||||||
cp SFM.dmg "SFM-${VERSION}-universal.dmg" && \
|
cp SFM.dmg "SFM-${VERSION}-universal.dmg" && \
|
||||||
ghr --replace --draft --prerelease "v${VERSION}" "SFM-${VERSION}-universal.dmg"
|
ghr --replace --draft --prerelease "v${VERSION}" "SFM-${VERSION}-universal.dmg"
|
||||||
|
|
||||||
release_macos_standalone: build_macos_standalone build_macos_dmg upload_macos_dmg
|
upload_macos_dsyms:
|
||||||
|
pushd ../sing-box-for-apple/build/SFM.System.xcarchive && \
|
||||||
|
zip -r SFM.dSYMs.zip dSYMs && \
|
||||||
|
mv SFM.dSYMs.zip ../../../sing-box/dist/SFM && \
|
||||||
|
popd && \
|
||||||
|
cd dist/SFM && \
|
||||||
|
cp SFM.dSYMs.zip "SFM-${VERSION}-universal.dSYMs.zip" && \
|
||||||
|
ghr --replace --draft --prerelease "v${VERSION}" "SFM-${VERSION}-universal.dSYMs.zip"
|
||||||
|
|
||||||
|
release_macos_standalone: build_macos_standalone build_macos_dmg upload_macos_dmg upload_macos_dsyms
|
||||||
|
|
||||||
build_tvos:
|
build_tvos:
|
||||||
cd ../sing-box-for-apple && \
|
cd ../sing-box-for-apple && \
|
||||||
|
@@ -81,7 +81,7 @@ func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDi
|
|||||||
if options.ConnectTimeout != 0 {
|
if options.ConnectTimeout != 0 {
|
||||||
dialer.Timeout = time.Duration(options.ConnectTimeout)
|
dialer.Timeout = time.Duration(options.ConnectTimeout)
|
||||||
} else {
|
} else {
|
||||||
dialer.Timeout = C.TCPTimeout
|
dialer.Timeout = C.TCPConnectTimeout
|
||||||
}
|
}
|
||||||
// TODO: Add an option to customize the keep alive period
|
// TODO: Add an option to customize the keep alive period
|
||||||
dialer.KeepAlive = C.TCPKeepAliveInitial
|
dialer.KeepAlive = C.TCPKeepAliveInitial
|
||||||
|
@@ -8,6 +8,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
@@ -113,6 +114,7 @@ func URLTest(ctx context.Context, link string, detour N.Dialer) (t uint16, err e
|
|||||||
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
CheckRedirect: func(req *http.Request, via []*http.Request) error {
|
||||||
return http.ErrUseLastResponse
|
return http.ErrUseLastResponse
|
||||||
},
|
},
|
||||||
|
Timeout: C.TCPTimeout,
|
||||||
}
|
}
|
||||||
defer client.CloseIdleConnections()
|
defer client.CloseIdleConnections()
|
||||||
resp, err := client.Do(req.WithContext(ctx))
|
resp, err := client.Do(req.WithContext(ctx))
|
||||||
|
@@ -5,7 +5,8 @@ import "time"
|
|||||||
const (
|
const (
|
||||||
TCPKeepAliveInitial = 10 * time.Minute
|
TCPKeepAliveInitial = 10 * time.Minute
|
||||||
TCPKeepAliveInterval = 75 * time.Second
|
TCPKeepAliveInterval = 75 * time.Second
|
||||||
TCPTimeout = 5 * time.Second
|
TCPConnectTimeout = 5 * time.Second
|
||||||
|
TCPTimeout = 15 * time.Second
|
||||||
ReadPayloadTimeout = 300 * time.Millisecond
|
ReadPayloadTimeout = 300 * time.Millisecond
|
||||||
DNSTimeout = 10 * time.Second
|
DNSTimeout = 10 * time.Second
|
||||||
QUICTimeout = 30 * time.Second
|
QUICTimeout = 30 * time.Second
|
||||||
|
@@ -2,6 +2,10 @@
|
|||||||
icon: material/alert-decagram
|
icon: material/alert-decagram
|
||||||
---
|
---
|
||||||
|
|
||||||
|
#### 1.11.0-alpha.5
|
||||||
|
|
||||||
|
* Fixes and improvements
|
||||||
|
|
||||||
#### 1.11.0-alpha.2
|
#### 1.11.0-alpha.2
|
||||||
|
|
||||||
* Add warnings for usage of deprecated features
|
* Add warnings for usage of deprecated features
|
||||||
|
@@ -9,9 +9,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
@@ -60,7 +60,7 @@ func (s *Server) downloadExternalUI() error {
|
|||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
TLSHandshakeTimeout: 5 * time.Second,
|
TLSHandshakeTimeout: C.TCPTimeout,
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
},
|
},
|
||||||
|
@@ -20,6 +20,7 @@ type CommandClient struct {
|
|||||||
type CommandClientOptions struct {
|
type CommandClientOptions struct {
|
||||||
Command int32
|
Command int32
|
||||||
StatusInterval int64
|
StatusInterval int64
|
||||||
|
IsMainClient bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommandClientHandler interface {
|
type CommandClientHandler interface {
|
||||||
@@ -28,6 +29,7 @@ type CommandClientHandler interface {
|
|||||||
ClearLogs()
|
ClearLogs()
|
||||||
WriteLogs(messageList StringIterator)
|
WriteLogs(messageList StringIterator)
|
||||||
WriteStatus(message *StatusMessage)
|
WriteStatus(message *StatusMessage)
|
||||||
|
OpenURL(url string)
|
||||||
WriteGroups(message OutboundGroupIterator)
|
WriteGroups(message OutboundGroupIterator)
|
||||||
InitializeClashMode(modeList StringIterator, currentMode string)
|
InitializeClashMode(modeList StringIterator, currentMode string)
|
||||||
UpdateClashMode(newMode string)
|
UpdateClashMode(newMode string)
|
||||||
@@ -91,9 +93,13 @@ func (c *CommandClient) Connect() error {
|
|||||||
c.handler.Connected()
|
c.handler.Connected()
|
||||||
go c.handleLogConn(conn)
|
go c.handleLogConn(conn)
|
||||||
case CommandStatus:
|
case CommandStatus:
|
||||||
|
err = binary.Write(conn, binary.BigEndian, c.options.IsMainClient)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "write is main client")
|
||||||
|
}
|
||||||
err = binary.Write(conn, binary.BigEndian, c.options.StatusInterval)
|
err = binary.Write(conn, binary.BigEndian, c.options.StatusInterval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "write interval")
|
return E.Cause(err, "write header")
|
||||||
}
|
}
|
||||||
c.handler.Connected()
|
c.handler.Connected()
|
||||||
go c.handleStatusConn(conn)
|
go c.handleStatusConn(conn)
|
||||||
|
40
sing-box/experimental/libbox/command_event.go
Normal file
40
sing-box/experimental/libbox/command_event.go
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
package libbox
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/binary"
|
||||||
|
|
||||||
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
"github.com/sagernet/sing/common/varbin"
|
||||||
|
)
|
||||||
|
|
||||||
|
type myEvent interface {
|
||||||
|
writeTo(writer varbin.Writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
func readEvent(reader varbin.Reader) (myEvent, error) {
|
||||||
|
eventType, err := reader.ReadByte()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch eventType {
|
||||||
|
case eventTypeEmpty:
|
||||||
|
return nil, nil
|
||||||
|
case eventTypeOpenURL:
|
||||||
|
url, err := varbin.ReadValue[string](reader, binary.BigEndian)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &eventOpenURL{URL: url}, nil
|
||||||
|
default:
|
||||||
|
return nil, E.New("unknown event type: ", eventType)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type eventOpenURL struct {
|
||||||
|
URL string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *eventOpenURL) writeTo(writer varbin.Writer) {
|
||||||
|
writer.WriteByte(eventTypeOpenURL)
|
||||||
|
varbin.Write(writer, binary.BigEndian, e.URL)
|
||||||
|
}
|
@@ -33,6 +33,7 @@ type CommandServer struct {
|
|||||||
urlTestUpdate chan struct{}
|
urlTestUpdate chan struct{}
|
||||||
modeUpdate chan struct{}
|
modeUpdate chan struct{}
|
||||||
logReset chan struct{}
|
logReset chan struct{}
|
||||||
|
events chan myEvent
|
||||||
|
|
||||||
closedConnections []Connection
|
closedConnections []Connection
|
||||||
}
|
}
|
||||||
@@ -52,6 +53,7 @@ func NewCommandServer(handler CommandServerHandler, maxLines int32) *CommandServ
|
|||||||
urlTestUpdate: make(chan struct{}, 1),
|
urlTestUpdate: make(chan struct{}, 1),
|
||||||
modeUpdate: make(chan struct{}, 1),
|
modeUpdate: make(chan struct{}, 1),
|
||||||
logReset: make(chan struct{}, 1),
|
logReset: make(chan struct{}, 1),
|
||||||
|
events: make(chan myEvent, 8),
|
||||||
}
|
}
|
||||||
server.observer = observable.NewObserver[string](server.subscriber, 64)
|
server.observer = observable.NewObserver[string](server.subscriber, 64)
|
||||||
return server
|
return server
|
||||||
@@ -61,6 +63,12 @@ func (s *CommandServer) SetService(newService *BoxService) {
|
|||||||
if newService != nil {
|
if newService != nil {
|
||||||
service.PtrFromContext[urltest.HistoryStorage](newService.ctx).SetHook(s.urlTestUpdate)
|
service.PtrFromContext[urltest.HistoryStorage](newService.ctx).SetHook(s.urlTestUpdate)
|
||||||
newService.instance.Router().ClashServer().(*clashapi.Server).SetModeUpdateHook(s.modeUpdate)
|
newService.instance.Router().ClashServer().(*clashapi.Server).SetModeUpdateHook(s.modeUpdate)
|
||||||
|
newService.platformInterface.openURLFunc = func(url string) {
|
||||||
|
select {
|
||||||
|
case s.events <- &eventOpenURL{URL: url}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
s.service = newService
|
s.service = newService
|
||||||
s.notifyURLTestUpdate()
|
s.notifyURLTestUpdate()
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
package libbox
|
package libbox
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
std_bufio "bufio"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"net"
|
"net"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -9,9 +10,15 @@ import (
|
|||||||
"github.com/sagernet/sing-box/common/conntrack"
|
"github.com/sagernet/sing-box/common/conntrack"
|
||||||
"github.com/sagernet/sing-box/experimental/clashapi"
|
"github.com/sagernet/sing-box/experimental/clashapi"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
|
F "github.com/sagernet/sing/common/format"
|
||||||
"github.com/sagernet/sing/common/memory"
|
"github.com/sagernet/sing/common/memory"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
eventTypeEmpty byte = iota
|
||||||
|
eventTypeOpenURL
|
||||||
|
)
|
||||||
|
|
||||||
type StatusMessage struct {
|
type StatusMessage struct {
|
||||||
Memory int64
|
Memory int64
|
||||||
Goroutines int32
|
Goroutines int32
|
||||||
@@ -44,31 +51,73 @@ func (s *CommandServer) readStatus() StatusMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *CommandServer) handleStatusConn(conn net.Conn) error {
|
func (s *CommandServer) handleStatusConn(conn net.Conn) error {
|
||||||
|
var isMainClient bool
|
||||||
|
err := binary.Read(conn, binary.BigEndian, &isMainClient)
|
||||||
|
if err != nil {
|
||||||
|
return E.Cause(err, "read is main client")
|
||||||
|
}
|
||||||
var interval int64
|
var interval int64
|
||||||
err := binary.Read(conn, binary.BigEndian, &interval)
|
err = binary.Read(conn, binary.BigEndian, &interval)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return E.Cause(err, "read interval")
|
return E.Cause(err, "read interval")
|
||||||
}
|
}
|
||||||
ticker := time.NewTicker(time.Duration(interval))
|
ticker := time.NewTicker(time.Duration(interval))
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
ctx := connKeepAlive(conn)
|
ctx := connKeepAlive(conn)
|
||||||
for {
|
writer := std_bufio.NewWriter(conn)
|
||||||
err = binary.Write(conn, binary.BigEndian, s.readStatus())
|
if isMainClient {
|
||||||
if err != nil {
|
for {
|
||||||
return err
|
writer.WriteByte(eventTypeEmpty)
|
||||||
|
err = binary.Write(conn, binary.BigEndian, s.readStatus())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
writer.Flush()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-ticker.C:
|
||||||
|
case event := <-s.events:
|
||||||
|
event.writeTo(writer)
|
||||||
|
writer.Flush()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
select {
|
} else {
|
||||||
case <-ctx.Done():
|
for {
|
||||||
return ctx.Err()
|
err = binary.Write(conn, binary.BigEndian, s.readStatus())
|
||||||
case <-ticker.C:
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
writer.Flush()
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
case <-ticker.C:
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CommandClient) handleStatusConn(conn net.Conn) {
|
func (c *CommandClient) handleStatusConn(conn net.Conn) {
|
||||||
|
reader := std_bufio.NewReader(conn)
|
||||||
for {
|
for {
|
||||||
|
if c.options.IsMainClient {
|
||||||
|
rawEvent, err := readEvent(reader)
|
||||||
|
if err != nil {
|
||||||
|
c.handler.Disconnected(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch event := rawEvent.(type) {
|
||||||
|
case *eventOpenURL:
|
||||||
|
c.handler.OpenURL(event.URL)
|
||||||
|
continue
|
||||||
|
case nil:
|
||||||
|
default:
|
||||||
|
panic(F.ToString("unexpected event type: ", event))
|
||||||
|
}
|
||||||
|
}
|
||||||
var message StatusMessage
|
var message StatusMessage
|
||||||
err := binary.Read(conn, binary.BigEndian, &message)
|
err := binary.Read(reader, binary.BigEndian, &message)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.handler.Disconnected(err.Error())
|
c.handler.Disconnected(err.Error())
|
||||||
return
|
return
|
||||||
|
@@ -134,6 +134,9 @@ func (s *interfaceMonitorStub) RegisterCallback(callback tun.DefaultInterfaceUpd
|
|||||||
func (s *interfaceMonitorStub) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) {
|
func (s *interfaceMonitorStub) UnregisterCallback(element *list.Element[tun.DefaultInterfaceUpdateCallback]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *platformInterfaceStub) OpenURL(url string) {
|
||||||
|
}
|
||||||
|
|
||||||
func FormatConfig(configContent string) (string, error) {
|
func FormatConfig(configContent string) (string, error) {
|
||||||
options, err := parseConfig(configContent)
|
options, err := parseConfig(configContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -17,8 +17,8 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
|
C "github.com/sagernet/sing-box/constant"
|
||||||
"github.com/sagernet/sing/common"
|
"github.com/sagernet/sing/common"
|
||||||
"github.com/sagernet/sing/common/bufio"
|
"github.com/sagernet/sing/common/bufio"
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
@@ -69,8 +69,9 @@ type httpClient struct {
|
|||||||
|
|
||||||
func NewHTTPClient() HTTPClient {
|
func NewHTTPClient() HTTPClient {
|
||||||
client := new(httpClient)
|
client := new(httpClient)
|
||||||
client.client.Timeout = 15 * time.Second
|
|
||||||
client.client.Transport = &client.transport
|
client.client.Transport = &client.transport
|
||||||
|
client.transport.ForceAttemptHTTP2 = true
|
||||||
|
client.transport.TLSHandshakeTimeout = C.TCPTimeout
|
||||||
client.transport.TLSClientConfig = &client.tls
|
client.transport.TLSClientConfig = &client.tls
|
||||||
client.transport.DisableKeepAlives = true
|
client.transport.DisableKeepAlives = true
|
||||||
return client
|
return client
|
||||||
@@ -127,7 +128,6 @@ func (c *httpClient) TrySocks5(port int32) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *httpClient) KeepAlive() {
|
func (c *httpClient) KeepAlive() {
|
||||||
c.transport.ForceAttemptHTTP2 = true
|
|
||||||
c.transport.DisableKeepAlives = false
|
c.transport.DisableKeepAlives = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -25,4 +25,5 @@ type Interface interface {
|
|||||||
ClearDNSCache()
|
ClearDNSCache()
|
||||||
ReadWIFIState() adapter.WIFIState
|
ReadWIFIState() adapter.WIFIState
|
||||||
process.Searcher
|
process.Searcher
|
||||||
|
OpenURL(url string)
|
||||||
}
|
}
|
||||||
|
@@ -34,9 +34,9 @@ type BoxService struct {
|
|||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
instance *box.Box
|
instance *box.Box
|
||||||
|
platformInterface *platformInterfaceWrapper
|
||||||
pauseManager pause.Manager
|
pauseManager pause.Manager
|
||||||
urlTestHistoryStorage *urltest.HistoryStorage
|
urlTestHistoryStorage *urltest.HistoryStorage
|
||||||
|
|
||||||
servicePauseFields
|
servicePauseFields
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,6 +67,7 @@ func NewService(configContent string, platformInterface PlatformInterface) (*Box
|
|||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
instance: instance,
|
instance: instance,
|
||||||
|
platformInterface: platformWrapper,
|
||||||
urlTestHistoryStorage: urlTestHistoryStorage,
|
urlTestHistoryStorage: urlTestHistoryStorage,
|
||||||
pauseManager: service.FromContext[pause.Manager](ctx),
|
pauseManager: service.FromContext[pause.Manager](ctx),
|
||||||
}, nil
|
}, nil
|
||||||
@@ -102,9 +103,10 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type platformInterfaceWrapper struct {
|
type platformInterfaceWrapper struct {
|
||||||
iif PlatformInterface
|
iif PlatformInterface
|
||||||
useProcFS bool
|
useProcFS bool
|
||||||
router adapter.Router
|
router adapter.Router
|
||||||
|
openURLFunc func(url string)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapter.Router) error {
|
func (w *platformInterfaceWrapper) Initialize(ctx context.Context, router adapter.Router) error {
|
||||||
@@ -238,3 +240,9 @@ func (w *platformInterfaceWrapper) DisableColors() bool {
|
|||||||
func (w *platformInterfaceWrapper) WriteMessage(level log.Level, message string) {
|
func (w *platformInterfaceWrapper) WriteMessage(level log.Level, message string) {
|
||||||
w.iif.WriteLog(message)
|
w.iif.WriteLog(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *platformInterfaceWrapper) OpenURL(url string) {
|
||||||
|
if w.openURLFunc != nil {
|
||||||
|
w.openURLFunc(url)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -11,6 +11,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Outbound) (adapter.Outbound, error) {
|
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.Outbound) (adapter.Outbound, error) {
|
||||||
|
if tag != "" {
|
||||||
|
ctx = adapter.WithContext(ctx, &adapter.InboundContext{
|
||||||
|
Outbound: tag,
|
||||||
|
})
|
||||||
|
}
|
||||||
if options.Type == "" {
|
if options.Type == "" {
|
||||||
return nil, E.New("missing outbound type")
|
return nil, E.New("missing outbound type")
|
||||||
}
|
}
|
||||||
|
@@ -7,7 +7,6 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/geoip"
|
"github.com/sagernet/sing-box/common/geoip"
|
||||||
@@ -161,7 +160,7 @@ func (r *Router) downloadGeoIPDatabase(savePath string) error {
|
|||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
TLSHandshakeTimeout: 5 * time.Second,
|
TLSHandshakeTimeout: C.TCPTimeout,
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
},
|
},
|
||||||
@@ -216,7 +215,7 @@ func (r *Router) downloadGeositeDatabase(savePath string) error {
|
|||||||
httpClient := &http.Client{
|
httpClient := &http.Client{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
ForceAttemptHTTP2: true,
|
ForceAttemptHTTP2: true,
|
||||||
TLSHandshakeTimeout: 5 * time.Second,
|
TLSHandshakeTimeout: C.TCPTimeout,
|
||||||
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
DialContext: func(ctx context.Context, network, addr string) (net.Conn, error) {
|
||||||
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
return detour.DialContext(ctx, network, M.ParseSocksaddr(addr))
|
||||||
},
|
},
|
||||||
|
@@ -67,7 +67,6 @@ func NewRemoteRuleSet(ctx context.Context, router adapter.Router, logger logger.
|
|||||||
logger: logger,
|
logger: logger,
|
||||||
options: options,
|
options: options,
|
||||||
updateInterval: updateInterval,
|
updateInterval: updateInterval,
|
||||||
cacheFile: service.FromContext[adapter.CacheFile](ctx),
|
|
||||||
pauseManager: service.FromContext[pause.Manager](ctx),
|
pauseManager: service.FromContext[pause.Manager](ctx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,6 +80,7 @@ func (s *RemoteRuleSet) String() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter.HTTPStartContext) error {
|
func (s *RemoteRuleSet) StartContext(ctx context.Context, startContext *adapter.HTTPStartContext) error {
|
||||||
|
s.cacheFile = service.FromContext[adapter.CacheFile](s.ctx)
|
||||||
var dialer N.Dialer
|
var dialer N.Dialer
|
||||||
if s.options.RemoteOptions.DownloadDetour != "" {
|
if s.options.RemoteOptions.DownloadDetour != "" {
|
||||||
outbound, loaded := s.router.Outbound(s.options.RemoteOptions.DownloadDetour)
|
outbound, loaded := s.router.Outbound(s.options.RemoteOptions.DownloadDetour)
|
||||||
|
@@ -1079,3 +1079,24 @@ function luci_types(id, m, s, type_name, option_prefix)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function get_std_domain(domain)
|
||||||
|
domain = trim(domain)
|
||||||
|
if domain == "" or domain:find("#") then return "" end
|
||||||
|
-- 删除首尾所有的 .
|
||||||
|
domain = domain:gsub("^[%.]+", ""):gsub("[%.]+$", "")
|
||||||
|
-- 如果 domain 包含 '*',则分割并删除包含 '*' 的部分及其前面的部分
|
||||||
|
if domain:find("%*") then
|
||||||
|
local parts = {}
|
||||||
|
for part in domain:gmatch("[^%.]+") do
|
||||||
|
table.insert(parts, part)
|
||||||
|
end
|
||||||
|
for i = #parts, 1, -1 do
|
||||||
|
if parts[i]:find("%*") then
|
||||||
|
-- 删除包含 '*' 的部分及其前面的部分
|
||||||
|
return parts[i + 1] and parts[i + 1] .. "." .. table.concat(parts, ".", i + 2) or ""
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return domain
|
||||||
|
end
|
||||||
|
@@ -546,6 +546,8 @@ run_chinadns_ng() {
|
|||||||
local _flag _listen_port _dns_local _dns_trust _no_ipv6_trust _use_direct_list _use_proxy_list _gfwlist _chnlist _default_mode _default_tag
|
local _flag _listen_port _dns_local _dns_trust _no_ipv6_trust _use_direct_list _use_proxy_list _gfwlist _chnlist _default_mode _default_tag
|
||||||
eval_set_val $@
|
eval_set_val $@
|
||||||
|
|
||||||
|
lua $APP_PATH/helper_chinadns_add.lua -FLAG $_flag -USE_DIRECT_LIST $_use_direct_list -USE_PROXY_LIST $_use_proxy_list
|
||||||
|
|
||||||
local _CONF_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.conf
|
local _CONF_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.conf
|
||||||
local _LOG_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.log
|
local _LOG_FILE=$TMP_ACL_PATH/$_flag/chinadns_ng.log
|
||||||
_LOG_FILE="/dev/null"
|
_LOG_FILE="/dev/null"
|
||||||
@@ -579,7 +581,7 @@ run_chinadns_ng() {
|
|||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
[ "${_use_direct_list}" = "1" ] && [ -s "${RULES_PATH}/direct_host" ] && {
|
[ "${_use_direct_list}" = "1" ] && [ -s "${TMP_PATH}/direct_host" ] && {
|
||||||
local whitelist4_set="passwall_whitelist"
|
local whitelist4_set="passwall_whitelist"
|
||||||
local whitelist6_set="passwall_whitelist6"
|
local whitelist6_set="passwall_whitelist6"
|
||||||
[ "$nftflag" = "1" ] && {
|
[ "$nftflag" = "1" ] && {
|
||||||
@@ -588,13 +590,13 @@ run_chinadns_ng() {
|
|||||||
}
|
}
|
||||||
cat <<-EOF >> ${_CONF_FILE}
|
cat <<-EOF >> ${_CONF_FILE}
|
||||||
group directlist
|
group directlist
|
||||||
group-dnl ${RULES_PATH}/direct_host
|
group-dnl ${TMP_PATH}/direct_host
|
||||||
group-upstream ${_dns_local}
|
group-upstream ${_dns_local}
|
||||||
group-ipset ${whitelist4_set},${whitelist6_set}
|
group-ipset ${whitelist4_set},${whitelist6_set}
|
||||||
EOF
|
EOF
|
||||||
}
|
}
|
||||||
|
|
||||||
[ "${_use_proxy_list}" = "1" ] && [ -s "${RULES_PATH}/proxy_host" ] && {
|
[ "${_use_proxy_list}" = "1" ] && [ -s "${TMP_PATH}/proxy_host" ] && {
|
||||||
local blacklist4_set="passwall_blacklist"
|
local blacklist4_set="passwall_blacklist"
|
||||||
local blacklist6_set="passwall_blacklist6"
|
local blacklist6_set="passwall_blacklist6"
|
||||||
[ "$nftflag" = "1" ] && {
|
[ "$nftflag" = "1" ] && {
|
||||||
@@ -603,7 +605,7 @@ run_chinadns_ng() {
|
|||||||
}
|
}
|
||||||
cat <<-EOF >> ${_CONF_FILE}
|
cat <<-EOF >> ${_CONF_FILE}
|
||||||
group proxylist
|
group proxylist
|
||||||
group-dnl ${RULES_PATH}/proxy_host
|
group-dnl ${TMP_PATH}/proxy_host
|
||||||
group-upstream ${_dns_trust}
|
group-upstream ${_dns_trust}
|
||||||
group-ipset ${blacklist4_set},${blacklist6_set}
|
group-ipset ${blacklist4_set},${blacklist6_set}
|
||||||
EOF
|
EOF
|
||||||
|
@@ -0,0 +1,50 @@
|
|||||||
|
require 'nixio'
|
||||||
|
local api = require "luci.passwall.api"
|
||||||
|
local appname = "passwall"
|
||||||
|
|
||||||
|
local var = api.get_args(arg)
|
||||||
|
local FLAG = var["-FLAG"]
|
||||||
|
local USE_DIRECT_LIST = var["-USE_DIRECT_LIST"]
|
||||||
|
local USE_PROXY_LIST = var["-USE_PROXY_LIST"]
|
||||||
|
|
||||||
|
local TMP_PATH = "/tmp/etc/" .. appname
|
||||||
|
|
||||||
|
if not nixio.fs.access(TMP_PATH) then
|
||||||
|
nixio.fs.mkdir(TMP_PATH, 493)
|
||||||
|
end
|
||||||
|
|
||||||
|
local tmp_direct_host = TMP_PATH .. "/direct_host"
|
||||||
|
if USE_DIRECT_LIST == "1" and not nixio.fs.access(tmp_direct_host) then
|
||||||
|
local direct_domain = {}
|
||||||
|
for line in io.lines("/usr/share/passwall/rules/direct_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
|
if line ~= "" and not line:find("#") then
|
||||||
|
table.insert(direct_domain, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #direct_domain > 0 then
|
||||||
|
local direct_out = io.open(tmp_direct_host, "a")
|
||||||
|
for i = 1, #direct_domain do
|
||||||
|
direct_out:write(direct_domain[i] .. "\n")
|
||||||
|
end
|
||||||
|
direct_out:close()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local tmp_proxy_host = TMP_PATH .. "/proxy_host"
|
||||||
|
if USE_PROXY_LIST == "1" and not nixio.fs.access(tmp_proxy_host) then
|
||||||
|
local proxy_domain = {}
|
||||||
|
for line in io.lines("/usr/share/passwall/rules/proxy_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
|
if line ~= "" and not line:find("#") then
|
||||||
|
table.insert(proxy_domain, line)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if #proxy_domain > 0 then
|
||||||
|
local proxy_out = io.open(tmp_proxy_host, "a")
|
||||||
|
for i = 1, #proxy_domain do
|
||||||
|
proxy_out:write(proxy_domain[i] .. "\n")
|
||||||
|
end
|
||||||
|
proxy_out:close()
|
||||||
|
end
|
||||||
|
end
|
@@ -196,6 +196,7 @@ if not fs.access(CACHE_DNS_PATH) then
|
|||||||
--屏蔽列表
|
--屏蔽列表
|
||||||
if USE_BLOCK_LIST == "1" then
|
if USE_BLOCK_LIST == "1" then
|
||||||
for line in io.lines("/usr/share/passwall/rules/block_host") do
|
for line in io.lines("/usr/share/passwall/rules/block_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
if line ~= "" and not line:find("#") then
|
if line ~= "" and not line:find("#") then
|
||||||
set_domain_address(line, "")
|
set_domain_address(line, "")
|
||||||
end
|
end
|
||||||
@@ -234,6 +235,7 @@ if not fs.access(CACHE_DNS_PATH) then
|
|||||||
if fwd_dns then
|
if fwd_dns then
|
||||||
--始终用国内DNS解析直连(白名单)列表
|
--始终用国内DNS解析直连(白名单)列表
|
||||||
for line in io.lines("/usr/share/passwall/rules/direct_host") do
|
for line in io.lines("/usr/share/passwall/rules/direct_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
if line ~= "" and not line:find("#") then
|
if line ~= "" and not line:find("#") then
|
||||||
add_excluded_domain(line)
|
add_excluded_domain(line)
|
||||||
set_domain_dns(line, fwd_dns)
|
set_domain_dns(line, fwd_dns)
|
||||||
@@ -255,6 +257,7 @@ if not fs.access(CACHE_DNS_PATH) then
|
|||||||
if fwd_dns then
|
if fwd_dns then
|
||||||
--始终使用远程DNS解析代理(黑名单)列表
|
--始终使用远程DNS解析代理(黑名单)列表
|
||||||
for line in io.lines("/usr/share/passwall/rules/proxy_host") do
|
for line in io.lines("/usr/share/passwall/rules/proxy_host") do
|
||||||
|
line = api.get_std_domain(line)
|
||||||
if line ~= "" and not line:find("#") then
|
if line ~= "" and not line:find("#") then
|
||||||
add_excluded_domain(line)
|
add_excluded_domain(line)
|
||||||
local ipset_flag = setflag_4 .. "passwall_blacklist," .. setflag_6 .. "passwall_blacklist6"
|
local ipset_flag = setflag_4 .. "passwall_blacklist," .. setflag_6 .. "passwall_blacklist6"
|
||||||
|
@@ -103,6 +103,7 @@ ipset_r() {
|
|||||||
$IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j RETURN
|
$IPT -A SS_SPEC_WAN_AC -m set --match-set china dst -j RETURN
|
||||||
$IPT -A SS_SPEC_WAN_AC -m set --match-set gfwlist dst -j SS_SPEC_WAN_FW
|
$IPT -A SS_SPEC_WAN_AC -m set --match-set gfwlist dst -j SS_SPEC_WAN_FW
|
||||||
$IPT -A SS_SPEC_WAN_AC -m set --match-set gmlan src -m set ! --match-set china dst -j SS_SPEC_WAN_FW
|
$IPT -A SS_SPEC_WAN_AC -m set --match-set gmlan src -m set ! --match-set china dst -j SS_SPEC_WAN_FW
|
||||||
|
$IPT -A SS_SPEC_WAN_AC -j SS_SPEC_WAN_FW
|
||||||
;;
|
;;
|
||||||
oversea)
|
oversea)
|
||||||
ipset -N oversea hash:net 2>/dev/null
|
ipset -N oversea hash:net 2>/dev/null
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
ClearMsg,
|
ClearMsg,
|
||||||
SendMsgView,
|
SendMsgView,
|
||||||
SendSnackMsg,
|
SendSnackMsg,
|
||||||
RefreshProfiles
|
RefreshProfiles,
|
||||||
|
StopSpeedtest
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,7 +1,7 @@
|
|||||||
using System.Diagnostics;
|
using ReactiveUI;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
|
|
||||||
namespace ServiceLib.Services
|
namespace ServiceLib.Services
|
||||||
{
|
{
|
||||||
public class SpeedtestService
|
public class SpeedtestService
|
||||||
@@ -80,10 +80,12 @@ namespace ServiceLib.Services
|
|||||||
Task.Run(RunMixedtestAsync);
|
Task.Run(RunMixedtestAsync);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
MessageBus.Current.Listen<string>(EMsgCommand.StopSpeedtest.ToString()).Subscribe(ExitLoop);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void ExitLoop()
|
private void ExitLoop(string x)
|
||||||
{
|
{
|
||||||
|
if(_exitLoop) return;
|
||||||
_exitLoop = true;
|
_exitLoop = true;
|
||||||
UpdateFunc("", ResUI.SpeedtestingStop);
|
UpdateFunc("", ResUI.SpeedtestingStop);
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user