Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.

Commit 5d1d206

Browse files
authored
Merge pull request #70 from sam80180/main
feat: add 'Dev Mode' commands
2 parents 9ffd12c + e4e45f7 commit 5d1d206

14 files changed

+594
-13
lines changed

.gitignore

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
11
.idea/
22
dist/
3-
.sib/
3+
.sib/
4+
sonic-ios-bridge.exe
5+
sonic-ios-bridge
6+
vendor/

cmd/devmode.go

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package cmd
2+
3+
import (
4+
"github.com/SonicCloudOrg/sonic-ios-bridge/cmd/devmode"
5+
"github.com/spf13/cobra"
6+
)
7+
8+
var devmodeCmd = &cobra.Command{
9+
Use: "devmode",
10+
Short: "Enable Developer Mode on iOS 16+ devices or print the current status.",
11+
Long: "Enable Developer Mode on iOS 16+ devices or print the current status.",
12+
Run: func(cmd *cobra.Command, args []string) {
13+
cmd.Help()
14+
},
15+
}
16+
17+
func init() {
18+
rootCmd.AddCommand(devmodeCmd)
19+
devmode.InitDevmode(devmodeCmd)
20+
}

cmd/devmode/arm.go

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package devmode
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
8+
"github.com/sirupsen/logrus"
9+
"github.com/spf13/cobra"
10+
"golang.org/x/xerrors"
11+
)
12+
13+
var devmodeArmCmd = &cobra.Command{
14+
Use: "arm",
15+
Short: "Arm the Developer Mode (device will reboot)",
16+
Long: "Arm the Developer Mode (device will reboot)",
17+
RunE: func(cmd *cobra.Command, args []string) error {
18+
util.InitLogger()
19+
if bCan, eCan := canToggleDevMode(udid); eCan != nil {
20+
strErrMsg := fmt.Sprintf("Failed to check device %s iOS version", udid)
21+
logrus.Warn(strErrMsg)
22+
return xerrors.New(strErrMsg)
23+
} else if !bCan {
24+
strErrMsg := fmt.Sprintf("Device %s iOS version below 16", udid)
25+
logrus.Warn(strErrMsg)
26+
return xerrors.New(strErrMsg)
27+
}
28+
amfi, errAmfi := getAmfiServer()
29+
if errAmfi != nil {
30+
return errAmfi
31+
}
32+
res, errArm := amfi.DevModeArm()
33+
if errArm != nil {
34+
return errArm
35+
}
36+
if res == http.StatusOK {
37+
logrus.Infof("Developer Mode armed.")
38+
return nil
39+
} else {
40+
strErrMsg := fmt.Sprintf("Failed to arm Developer Mode (%d).", res)
41+
logrus.Warn(strErrMsg)
42+
return xerrors.New(strErrMsg)
43+
}
44+
},
45+
}
46+
47+
func initDevModeArmCmd() {
48+
devmodeRootCMD.AddCommand(devmodeArmCmd)
49+
devmodeArmCmd.Flags().StringVarP(&udid, "udid", "u", "", "device's serialNumber")
50+
devmodeArmCmd.MarkFlagRequired("udid")
51+
}

cmd/devmode/confirm.go

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package devmode
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
7+
"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
8+
"github.com/sirupsen/logrus"
9+
"github.com/spf13/cobra"
10+
"golang.org/x/xerrors"
11+
)
12+
13+
var devmodeConfirmCmd = &cobra.Command{
14+
Use: "confirm",
15+
Short: "Confirm enabling of Developer Mode",
16+
Long: "Confirm enabling of Developer Mode",
17+
RunE: func(cmd *cobra.Command, args []string) error {
18+
util.InitLogger()
19+
if bPreCheckIOSVer {
20+
if bCan, eCan := canToggleDevMode(udid); eCan != nil {
21+
strErrMsg := fmt.Sprintf("Failed to check device %s iOS version", udid)
22+
logrus.Warn(strErrMsg)
23+
return xerrors.New(strErrMsg)
24+
} else if !bCan {
25+
strErrMsg := fmt.Sprintf("Device %s iOS version below 16", udid)
26+
logrus.Warn(strErrMsg)
27+
return xerrors.New(strErrMsg)
28+
}
29+
}
30+
amfi, errAmfi := getAmfiServer()
31+
if errAmfi != nil {
32+
return errAmfi
33+
}
34+
res, errReveal := amfi.DevModeEnable()
35+
if errReveal != nil {
36+
return errReveal
37+
}
38+
if res == http.StatusOK {
39+
logrus.Infof("Developer Mode menu enabled successfully.")
40+
return nil
41+
} else {
42+
strErrMsg := fmt.Sprintf("Failed to enable Developer Mode menu (%d).", res)
43+
logrus.Warn(strErrMsg)
44+
return xerrors.New(strErrMsg)
45+
}
46+
},
47+
}
48+
49+
func initDevModeConfirmCmd() {
50+
devmodeRootCMD.AddCommand(devmodeConfirmCmd)
51+
devmodeConfirmCmd.Flags().StringVarP(&udid, "udid", "u", "", "device's serialNumber")
52+
devmodeConfirmCmd.MarkFlagRequired("udid")
53+
}

cmd/devmode/devmodeinit.go

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package devmode
2+
3+
import (
4+
"encoding/json"
5+
"os"
6+
"reflect"
7+
8+
giDevice "github.com/SonicCloudOrg/sonic-gidevice"
9+
"github.com/SonicCloudOrg/sonic-ios-bridge/src/entity"
10+
"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
11+
"github.com/spf13/cobra"
12+
"golang.org/x/xerrors"
13+
)
14+
15+
var devmodeRootCMD *cobra.Command
16+
var bPreCheckIOSVer bool = true
17+
18+
// option bindings
19+
var udid string
20+
var bIsOutputJson bool
21+
22+
func InitDevmode(devmodeCMD *cobra.Command) {
23+
devmodeRootCMD = devmodeCMD
24+
initDevModeListCmd()
25+
initDevModeArmCmd()
26+
initDevModeRevealCmd()
27+
initDevModeEnableCmd()
28+
initDevModeConfirmCmd()
29+
}
30+
31+
func getAmfiServer() (giDevice.Amfi, error) {
32+
device := util.GetDeviceByUdId(udid)
33+
if device == nil {
34+
os.Exit(55 /* https://git.islam.gov.my/mohdrizal/fabric/-/blob/v2.3.3/vendor/golang.org/x/sys/windows/zerrors_windows.go#L195 */)
35+
}
36+
return device.AmfiService()
37+
}
38+
39+
func canToggleDevMode(udid string) (bool, error) {
40+
gidevice := util.GetDeviceByUdId(udid)
41+
if gidevice == nil {
42+
return false, xerrors.Errorf("Device %s not found", udid)
43+
}
44+
device := entity.Device{}
45+
deviceByte, _ := json.Marshal(gidevice.Properties())
46+
json.Unmarshal(deviceByte, &device)
47+
detail, err2 := entity.GetDetail(gidevice)
48+
if err2 != nil {
49+
return false, err2
50+
} else {
51+
device.DeviceDetail = *detail
52+
}
53+
devmode := entity.DevMode{Device: device}
54+
b, e := devmode.CanCheck()
55+
if e != nil {
56+
return false, e
57+
}
58+
return b, nil
59+
}
60+
61+
func __PACKAGE__() string { // https://www.appsloveworld.com/go/3/how-to-get-name-of-current-package-in-go?expand_article=1
62+
type dummy struct{}
63+
return reflect.TypeOf(dummy{}).PkgPath()
64+
}

cmd/devmode/enable.go

+89
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
package devmode
2+
3+
import (
4+
"os"
5+
"strings"
6+
"sync"
7+
"time"
8+
9+
giDevice "github.com/SonicCloudOrg/sonic-gidevice"
10+
"github.com/SonicCloudOrg/sonic-ios-bridge/src/entity"
11+
"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
12+
"github.com/sirupsen/logrus"
13+
"github.com/spf13/cobra"
14+
)
15+
16+
// option bindings
17+
var bWaitReboot, bAutoConfirm bool
18+
var intEnableWaitTimeout int
19+
20+
var devmodeEnableCmd = &cobra.Command{
21+
Use: "enable",
22+
Short: "Enable Developer Mode (device will reboot)",
23+
Long: "Enable Developer Mode (device will reboot)",
24+
RunE: func(cmd *cobra.Command, args []string) error {
25+
//util.InitLogger()
26+
errArm := devmodeArmCmd.RunE(cmd, args)
27+
if errArm != nil {
28+
return errArm
29+
}
30+
if bWaitReboot {
31+
bIsDeviceOnline := true
32+
wg := new(sync.WaitGroup)
33+
wg.Add(1)
34+
shutDownFun, errListen := util.UsbmuxListen(func(gidevice *giDevice.Device, device *entity.Device, e error, cancelFunc func()) {
35+
if device == nil {
36+
return
37+
}
38+
funcDone := func() {
39+
cancelFunc()
40+
bIsDeviceOnline = true
41+
logrus.Infof("Device %s is online.", udid)
42+
wg.Done()
43+
}
44+
if device.Status == "offline" {
45+
bIsDeviceOnline = false
46+
logrus.Infof("Device %s is offline.", udid)
47+
} else if !bIsDeviceOnline && device.Status == "online" {
48+
if device.SerialNumber == udid {
49+
funcDone()
50+
return
51+
}
52+
detail, _ := entity.GetDetail(*gidevice)
53+
if detail != nil && detail.UniqueDeviceID == udid {
54+
funcDone()
55+
return
56+
}
57+
}
58+
})
59+
if errListen != nil {
60+
return errListen
61+
}
62+
go func() {
63+
time.Sleep(time.Duration(intEnableWaitTimeout) * time.Second)
64+
logrus.Warnf("Timeout waiting for device %s to reboot.", udid)
65+
shutDownFun()
66+
wg.Done()
67+
}()
68+
wg.Wait()
69+
if bIsDeviceOnline && bAutoConfirm {
70+
bPreCheckIOSVer = false
71+
devmodeConfirmCmd.RunE(cmd, args)
72+
} else {
73+
executable, _ := os.Executable()
74+
pkgPath := strings.Split(__PACKAGE__(), "/")
75+
logrus.Infof("Please check the device %s is online and then run '%s %s %s -u %s'.", udid, executable, pkgPath[len(pkgPath)-1], devmodeConfirmCmd.Use, udid)
76+
}
77+
}
78+
return nil
79+
},
80+
}
81+
82+
func initDevModeEnableCmd() {
83+
devmodeRootCMD.AddCommand(devmodeEnableCmd)
84+
devmodeEnableCmd.Flags().StringVarP(&udid, "udid", "u", "", "device's serialNumber")
85+
devmodeEnableCmd.MarkFlagRequired("udid")
86+
devmodeEnableCmd.Flags().BoolVar(&bWaitReboot, "wait", false, "wait for reboot to complete")
87+
devmodeEnableCmd.Flags().IntVar(&intEnableWaitTimeout, "wait-timeout", 60, "wait timeout in seconds")
88+
devmodeEnableCmd.Flags().BoolVarP(&bAutoConfirm, "confirm", "y", false, "automatically confirm after reboot")
89+
}

0 commit comments

Comments
 (0)