Skip to content

Commit aea72aa

Browse files
committed
Move Linux USB permission checks into transports
Move platform-specific Linux USB permission detection and user prompts from GetDevicesInfo into each transport implementation (Adb, Fastboot, Hdc). Each transport now imports dialog/notification APIs, adds a small GetTranslation helper, and shows a warning dialog when permission errors are detected (with action to run sudo chmod -R 777 /dev/bus/usb/). Fastboot and Hdc also use lsusb checks (and Fastboot respects UseNative) to better detect permission issues. The centralized CheckLinuxPermissionsAsync method and its call from SetDevicesInfoLittle were removed. Small variable/refactor changes return device lists after potential prompt handling and set Global.root to false after prompting.
1 parent 19622b7 commit aea72aa

4 files changed

Lines changed: 83 additions & 74 deletions

File tree

UotanToolbox/Common/Devices/AdbTransport.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,18 @@
22
using System.Collections.Generic;
33
using System.Threading;
44
using System.Threading.Tasks;
5+
using SukiUI.Dialogs;
6+
using Avalonia.Controls.Notifications;
57

68
namespace UotanToolbox.Common.Devices
79
{
810
public class AdbTransport : IDeviceTransport
911
{
12+
private static string GetTranslation(string key)
13+
{
14+
return FeaturesHelper.GetTranslation(key);
15+
}
16+
1017
public TransportType Type => TransportType.Adb;
1118

1219
public async Task<IEnumerable<DeviceInfo>> ProbeAsync(CancellationToken cancel = default)
@@ -15,6 +22,27 @@ public async Task<IEnumerable<DeviceInfo>> ProbeAsync(CancellationToken cancel =
1522
var result = new List<DeviceInfo>();
1623
var lines = output.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
1724

25+
if (Global.System.Contains("Linux") && Global.root)
26+
{
27+
if (output.Contains("failed to check server version: cannot connect to daemon"))
28+
{
29+
Global.MainDialogManager.CreateDialog()
30+
.WithTitle(GetTranslation("Common_Warn"))
31+
.WithContent(GetTranslation("Common_ADBRoot"))
32+
.OfType(NotificationType.Warning)
33+
.WithActionButton(GetTranslation("ConnectionDialog_Confirm"), async _ =>
34+
{
35+
await CallExternalProgram.Sudo("chmod -R 777 /dev/bus/usb/");
36+
output = await CallExternalProgram.ADB("devices");
37+
var lines = output.Split(new[] { '\r', '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
38+
}, true)
39+
.WithActionButton(GetTranslation("ConnectionDialog_Cancel"), _ => { }, true)
40+
.TryShow();
41+
Global.root = false;
42+
}
43+
44+
}
45+
1846
foreach (var line in lines)
1947
{
2048
var trimmed = line.Trim();

UotanToolbox/Common/Devices/FastbootTransport.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,44 @@
33
using System.Linq;
44
using System.Threading;
55
using System.Threading.Tasks;
6+
using SukiUI.Dialogs;
7+
using Avalonia.Controls.Notifications;
68

79
namespace UotanToolbox.Common.Devices
810
{
911
public class FastbootTransport : IDeviceTransport
1012
{
13+
private static string GetTranslation(string key)
14+
{
15+
return FeaturesHelper.GetTranslation(key);
16+
}
1117
public TransportType Type => TransportType.Fastboot;
1218

1319
public async Task<IEnumerable<DeviceInfo>> ProbeAsync(CancellationToken cancel = default)
1420
{
1521
string output = await CallExternalProgram.Fastboot("devices");
1622
var ids = StringHelper.FastbootDevices(output);
17-
return ids.Select(id => new DeviceInfo(id, TransportType.Fastboot));
23+
var fids = ids.Select(id => new DeviceInfo(id, TransportType.Fastboot));
24+
if (Global.System.Contains("Linux") && Global.root)
25+
{
26+
string devcon = await CallExternalProgram.LsUSB();
27+
if (output.Contains("no permissions") || (UotanToolbox.Settings.Default.UseNative && devcon.Contains("(fastboot)") && ids.Length == 0))
28+
{
29+
Global.MainDialogManager.CreateDialog()
30+
.WithTitle(GetTranslation("Common_Warn"))
31+
.WithContent(GetTranslation("Common_FBRoot"))
32+
.OfType(NotificationType.Warning)
33+
.WithActionButton(GetTranslation("ConnectionDialog_Confirm"), async _ =>
34+
{
35+
await CallExternalProgram.Sudo("chmod -R 777 /dev/bus/usb/");
36+
fids = ids.Select(id => new DeviceInfo(id, TransportType.Fastboot));
37+
}, true)
38+
.WithActionButton(GetTranslation("ConnectionDialog_Cancel"), _ => { }, true)
39+
.TryShow();
40+
Global.root = false;
41+
}
42+
}
43+
return fids;
1844
}
1945

2046
public Task<string> RunAsync(DeviceInfo device, string command, CancellationToken cancel = default, Action<string>? outputCallback = null)

UotanToolbox/Common/Devices/HdcTransport.cs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,45 @@
33
using System.Linq;
44
using System.Threading;
55
using System.Threading.Tasks;
6+
using SukiUI.Dialogs;
7+
using Avalonia.Controls.Notifications;
68

79
namespace UotanToolbox.Common.Devices
810
{
911
public class HdcTransport : IDeviceTransport
1012
{
13+
private static string GetTranslation(string key)
14+
{
15+
return FeaturesHelper.GetTranslation(key);
16+
}
17+
1118
public TransportType Type => TransportType.Hdc;
1219

1320
public async Task<IEnumerable<DeviceInfo>> ProbeAsync(CancellationToken cancel = default)
1421
{
1522
string output = await CallExternalProgram.HDC("list targets");
1623
var ids = StringHelper.HDCDevices(output);
17-
return ids.Select(id => new DeviceInfo(id, TransportType.Hdc));
24+
var hids = ids.Select(id => new DeviceInfo(id, TransportType.Hdc));
25+
if (Global.System.Contains("Linux") && Global.root)
26+
{
27+
string devcon = await CallExternalProgram.LsUSB();
28+
if (devcon.Contains("HDC Device") && ids.Length == 0)
29+
{
30+
Global.MainDialogManager.CreateDialog()
31+
.WithTitle(GetTranslation("Common_Warn"))
32+
.WithContent(GetTranslation("Common_HDCRoot"))
33+
.OfType(NotificationType.Warning)
34+
.WithActionButton(GetTranslation("ConnectionDialog_Confirm"), async _ =>
35+
{
36+
await CallExternalProgram.Sudo("chmod -R 777 /dev/bus/usb/");
37+
hids = ids.Select(id => new DeviceInfo(id, TransportType.Hdc));
38+
}, true)
39+
.WithActionButton(GetTranslation("ConnectionDialog_Cancel"), _ => { }, true)
40+
.TryShow();
41+
Global.root = false;
42+
}
43+
}
44+
return hids;
1845
}
1946

2047
public Task<string> RunAsync(DeviceInfo device, string command, CancellationToken cancel = default, Action<string>? outputCallback = null)

UotanToolbox/Common/GetDevicesInfo.cs

Lines changed: 0 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -66,75 +66,6 @@ public static async Task<string[]> DevicesList()
6666
return Global.DeviceManager.Devices.Select(d => d.Id).ToArray();
6767
}
6868

69-
private static async Task CheckLinuxPermissionsAsync()
70-
{
71-
if (!Global.System.Contains("Linux") || !Global.root)
72-
{
73-
return;
74-
}
75-
76-
string adbOutput = await CallExternalProgram.ADB("devices");
77-
if (adbOutput.Contains("failed to check server version: cannot connect to daemon"))
78-
{
79-
Global.MainDialogManager.CreateDialog()
80-
.WithTitle(GetTranslation("Common_Warn"))
81-
.WithContent(GetTranslation("Common_ADBRoot"))
82-
.OfType(NotificationType.Warning)
83-
.WithActionButton(GetTranslation("ConnectionDialog_Confirm"), async _ =>
84-
{
85-
await CallExternalProgram.Sudo("chmod -R 777 /dev/bus/usb/");
86-
if (Global.DeviceManager != null)
87-
{
88-
await Global.DeviceManager.ScanAsync();
89-
}
90-
}, true)
91-
.WithActionButton(GetTranslation("ConnectionDialog_Cancel"), _ => { }, true)
92-
.TryShow();
93-
Global.root = false;
94-
}
95-
96-
string fbOutput = await CallExternalProgram.Fastboot("devices");
97-
if (fbOutput.Contains("no permissions"))
98-
{
99-
Global.MainDialogManager.CreateDialog()
100-
.WithTitle(GetTranslation("Common_Warn"))
101-
.WithContent(GetTranslation("Common_FBRoot"))
102-
.OfType(NotificationType.Warning)
103-
.WithActionButton(GetTranslation("ConnectionDialog_Confirm"), async _ =>
104-
{
105-
await CallExternalProgram.Sudo("chmod -R 777 /dev/bus/usb/");
106-
if (Global.DeviceManager != null)
107-
{
108-
await Global.DeviceManager.ScanAsync();
109-
}
110-
}, true)
111-
.WithActionButton(GetTranslation("ConnectionDialog_Cancel"), _ => { }, true)
112-
.TryShow();
113-
Global.root = false;
114-
}
115-
116-
string devcon = await CallExternalProgram.LsUSB();
117-
string[] hdcDevices = StringHelper.HDCDevices(await CallExternalProgram.HDC("list targets"));
118-
if (devcon.Contains("HDC Device") && hdcDevices.Length == 0)
119-
{
120-
Global.MainDialogManager.CreateDialog()
121-
.WithTitle(GetTranslation("Common_Warn"))
122-
.WithContent(GetTranslation("Common_HDCRoot"))
123-
.OfType(NotificationType.Warning)
124-
.WithActionButton(GetTranslation("ConnectionDialog_Confirm"), async _ =>
125-
{
126-
await CallExternalProgram.Sudo("chmod -R 777 /dev/bus/usb/");
127-
if (Global.DeviceManager != null)
128-
{
129-
await Global.DeviceManager.ScanAsync();
130-
}
131-
}, true)
132-
.WithActionButton(GetTranslation("ConnectionDialog_Cancel"), _ => { }, true)
133-
.TryShow();
134-
Global.root = false;
135-
}
136-
}
137-
13869
public static async Task<bool> SetDevicesInfoLittle()
13970
{
14071
if (Global.DeviceManager == null)
@@ -146,9 +77,6 @@ public static async Task<bool> SetDevicesInfoLittle()
14677
// 确保扫描过一次
14778
await Global.DeviceManager.ScanAsync();
14879

149-
// Linux 下检测 USB 权限问题并弹窗提示
150-
await CheckLinuxPermissionsAsync();
151-
15280
var list = Global.DeviceManager.Devices.Select(d => d.Id).ToArray();
15381
if (list.Length != 0)
15482
{

0 commit comments

Comments
 (0)