Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add 'Dev Mode' commands #70

Merged
merged 1 commit into from
Nov 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.idea/
dist/
.sib/
.sib/
sonic-ios-bridge.exe
sonic-ios-bridge
vendor/
20 changes: 20 additions & 0 deletions cmd/devmode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package cmd

import (
"github.com/SonicCloudOrg/sonic-ios-bridge/cmd/devmode"
"github.com/spf13/cobra"
)

var devmodeCmd = &cobra.Command{
Use: "devmode",
Short: "Enable Developer Mode on iOS 16+ devices or print the current status.",
Long: "Enable Developer Mode on iOS 16+ devices or print the current status.",
Run: func(cmd *cobra.Command, args []string) {
cmd.Help()
},
}

func init() {
rootCmd.AddCommand(devmodeCmd)
devmode.InitDevmode(devmodeCmd)
}
51 changes: 51 additions & 0 deletions cmd/devmode/arm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package devmode

import (
"fmt"
"net/http"

"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
)

var devmodeArmCmd = &cobra.Command{
Use: "arm",
Short: "Arm the Developer Mode (device will reboot)",
Long: "Arm the Developer Mode (device will reboot)",
RunE: func(cmd *cobra.Command, args []string) error {
util.InitLogger()
if bCan, eCan := canToggleDevMode(udid); eCan != nil {
strErrMsg := fmt.Sprintf("Failed to check device %s iOS version", udid)
logrus.Warn(strErrMsg)
return xerrors.New(strErrMsg)
} else if !bCan {
strErrMsg := fmt.Sprintf("Device %s iOS version below 16", udid)
logrus.Warn(strErrMsg)
return xerrors.New(strErrMsg)
}
amfi, errAmfi := getAmfiServer()
if errAmfi != nil {
return errAmfi
}
res, errArm := amfi.DevModeArm()
if errArm != nil {
return errArm
}
if res == http.StatusOK {
logrus.Infof("Developer Mode armed.")
return nil
} else {
strErrMsg := fmt.Sprintf("Failed to arm Developer Mode (%d).", res)
logrus.Warn(strErrMsg)
return xerrors.New(strErrMsg)
}
},
}

func initDevModeArmCmd() {
devmodeRootCMD.AddCommand(devmodeArmCmd)
devmodeArmCmd.Flags().StringVarP(&udid, "udid", "u", "", "device's serialNumber")
devmodeArmCmd.MarkFlagRequired("udid")
}
53 changes: 53 additions & 0 deletions cmd/devmode/confirm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package devmode

import (
"fmt"
"net/http"

"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
)

var devmodeConfirmCmd = &cobra.Command{
Use: "confirm",
Short: "Confirm enabling of Developer Mode",
Long: "Confirm enabling of Developer Mode",
RunE: func(cmd *cobra.Command, args []string) error {
util.InitLogger()
if bPreCheckIOSVer {
if bCan, eCan := canToggleDevMode(udid); eCan != nil {
strErrMsg := fmt.Sprintf("Failed to check device %s iOS version", udid)
logrus.Warn(strErrMsg)
return xerrors.New(strErrMsg)
} else if !bCan {
strErrMsg := fmt.Sprintf("Device %s iOS version below 16", udid)
logrus.Warn(strErrMsg)
return xerrors.New(strErrMsg)
}
}
amfi, errAmfi := getAmfiServer()
if errAmfi != nil {
return errAmfi
}
res, errReveal := amfi.DevModeEnable()
if errReveal != nil {
return errReveal
}
if res == http.StatusOK {
logrus.Infof("Developer Mode menu enabled successfully.")
return nil
} else {
strErrMsg := fmt.Sprintf("Failed to enable Developer Mode menu (%d).", res)
logrus.Warn(strErrMsg)
return xerrors.New(strErrMsg)
}
},
}

func initDevModeConfirmCmd() {
devmodeRootCMD.AddCommand(devmodeConfirmCmd)
devmodeConfirmCmd.Flags().StringVarP(&udid, "udid", "u", "", "device's serialNumber")
devmodeConfirmCmd.MarkFlagRequired("udid")
}
64 changes: 64 additions & 0 deletions cmd/devmode/devmodeinit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package devmode

import (
"encoding/json"
"os"
"reflect"

giDevice "github.com/SonicCloudOrg/sonic-gidevice"
"github.com/SonicCloudOrg/sonic-ios-bridge/src/entity"
"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
"github.com/spf13/cobra"
"golang.org/x/xerrors"
)

var devmodeRootCMD *cobra.Command
var bPreCheckIOSVer bool = true

// option bindings
var udid string
var bIsOutputJson bool

func InitDevmode(devmodeCMD *cobra.Command) {
devmodeRootCMD = devmodeCMD
initDevModeListCmd()
initDevModeArmCmd()
initDevModeRevealCmd()
initDevModeEnableCmd()
initDevModeConfirmCmd()
}

func getAmfiServer() (giDevice.Amfi, error) {
device := util.GetDeviceByUdId(udid)
if device == nil {
os.Exit(55 /* https://git.islam.gov.my/mohdrizal/fabric/-/blob/v2.3.3/vendor/golang.org/x/sys/windows/zerrors_windows.go#L195 */)
}
return device.AmfiService()
}

func canToggleDevMode(udid string) (bool, error) {
gidevice := util.GetDeviceByUdId(udid)
if gidevice == nil {
return false, xerrors.Errorf("Device %s not found", udid)
}
device := entity.Device{}
deviceByte, _ := json.Marshal(gidevice.Properties())
json.Unmarshal(deviceByte, &device)
detail, err2 := entity.GetDetail(gidevice)
if err2 != nil {
return false, err2
} else {
device.DeviceDetail = *detail
}
devmode := entity.DevMode{Device: device}
b, e := devmode.CanCheck()
if e != nil {
return false, e
}
return b, nil
}

func __PACKAGE__() string { // https://www.appsloveworld.com/go/3/how-to-get-name-of-current-package-in-go?expand_article=1
type dummy struct{}
return reflect.TypeOf(dummy{}).PkgPath()
}
89 changes: 89 additions & 0 deletions cmd/devmode/enable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package devmode

import (
"os"
"strings"
"sync"
"time"

giDevice "github.com/SonicCloudOrg/sonic-gidevice"
"github.com/SonicCloudOrg/sonic-ios-bridge/src/entity"
"github.com/SonicCloudOrg/sonic-ios-bridge/src/util"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

// option bindings
var bWaitReboot, bAutoConfirm bool
var intEnableWaitTimeout int

var devmodeEnableCmd = &cobra.Command{
Use: "enable",
Short: "Enable Developer Mode (device will reboot)",
Long: "Enable Developer Mode (device will reboot)",
RunE: func(cmd *cobra.Command, args []string) error {
//util.InitLogger()
errArm := devmodeArmCmd.RunE(cmd, args)
if errArm != nil {
return errArm
}
if bWaitReboot {
bIsDeviceOnline := true
wg := new(sync.WaitGroup)
wg.Add(1)
shutDownFun, errListen := util.UsbmuxListen(func(gidevice *giDevice.Device, device *entity.Device, e error, cancelFunc func()) {
if device == nil {
return
}
funcDone := func() {
cancelFunc()
bIsDeviceOnline = true
logrus.Infof("Device %s is online.", udid)
wg.Done()
}
if device.Status == "offline" {
bIsDeviceOnline = false
logrus.Infof("Device %s is offline.", udid)
} else if !bIsDeviceOnline && device.Status == "online" {
if device.SerialNumber == udid {
funcDone()
return
}
detail, _ := entity.GetDetail(*gidevice)
if detail != nil && detail.UniqueDeviceID == udid {
funcDone()
return
}
}
})
if errListen != nil {
return errListen
}
go func() {
time.Sleep(time.Duration(intEnableWaitTimeout) * time.Second)
logrus.Warnf("Timeout waiting for device %s to reboot.", udid)
shutDownFun()
wg.Done()
}()
wg.Wait()
if bIsDeviceOnline && bAutoConfirm {
bPreCheckIOSVer = false
devmodeConfirmCmd.RunE(cmd, args)
} else {
executable, _ := os.Executable()
pkgPath := strings.Split(__PACKAGE__(), "/")
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)
}
}
return nil
},
}

func initDevModeEnableCmd() {
devmodeRootCMD.AddCommand(devmodeEnableCmd)
devmodeEnableCmd.Flags().StringVarP(&udid, "udid", "u", "", "device's serialNumber")
devmodeEnableCmd.MarkFlagRequired("udid")
devmodeEnableCmd.Flags().BoolVar(&bWaitReboot, "wait", false, "wait for reboot to complete")
devmodeEnableCmd.Flags().IntVar(&intEnableWaitTimeout, "wait-timeout", 60, "wait timeout in seconds")
devmodeEnableCmd.Flags().BoolVarP(&bAutoConfirm, "confirm", "y", false, "automatically confirm after reboot")
}
Loading
Loading