Skip to content

Commit 5958fd5

Browse files
authored
Merge pull request #489 from tpretz/virtual-media-split
Virtual Media Changes
2 parents 2d0123c + 4d7ee39 commit 5958fd5

File tree

6 files changed

+89
-37
lines changed

6 files changed

+89
-37
lines changed

kvmapp/system/init.d/S03usbdev

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ start_usb_dev(){
9494
ln -s functions/hid.GS2 configs/c.1
9595
fi
9696

97+
# dedicated for media
9798
if [ -e /boot/usb.disk0 ]
9899
then
99100
mkdir functions/mass_storage.disk0
@@ -108,17 +109,20 @@ start_usb_dev(){
108109
disk=$(cat /boot/usb.disk0)
109110
if [ -z "${disk}" ]
110111
then
111-
# if [ ! -e /mnt/usbdisk.img ]
112-
# then
113-
# fallocate -l 8G /mnt/usbdisk.img
114-
# mkfs.vfat /mnt/usbdisk.img
115-
# fi
116-
echo /dev/mmcblk0p3 > functions/mass_storage.disk0/lun.0/file
112+
echo "" > functions/mass_storage.disk0/lun.0/file
117113
else
118114
cat /boot/usb.disk0 > functions/mass_storage.disk0/lun.0/file
119115
fi
120116
fi
121117

118+
# mount data partition
119+
if [ -e /boot/usb.disk1 ]
120+
then
121+
mkdir functions/mass_storage.disk1
122+
ln -s functions/mass_storage.disk1 configs/c.1/
123+
echo /dev/mmcblk0p3 > functions/mass_storage.disk1/lun.0/file
124+
fi
125+
122126
ls /sys/class/udc/ | cat > UDC
123127
echo device > /proc/cviusb/otg_role
124128
}

server/proto/vm.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ type DeleteScriptReq struct {
5757

5858
type GetVirtualDeviceRsp struct {
5959
Network bool `json:"network"`
60+
Media bool `json:"media"`
6061
Disk bool `json:"disk"`
6162
}
6263

server/service/storage/image.go

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ import (
1818

1919
const (
2020
imageDirectory = "/data"
21-
imageNone = "/dev/mmcblk0p3"
2221
cdromFlag = "/sys/kernel/config/usb_gadget/g0/functions/mass_storage.disk0/lun.0/cdrom"
2322
mountDevice = "/sys/kernel/config/usb_gadget/g0/functions/mass_storage.disk0/lun.0/file"
2423
inquiryString = "/sys/kernel/config/usb_gadget/g0/functions/mass_storage.disk0/lun.0/inquiry_string"
2524
roFlag = "/sys/kernel/config/usb_gadget/g0/functions/mass_storage.disk0/lun.0/ro"
25+
usbNoRstMarker = "/boot/usb.norst"
2626
)
2727

2828
func (s *Service) GetImages(c *gin.Context) {
@@ -108,16 +108,20 @@ func (s *Service) MountImage(c *gin.Context) {
108108
return
109109
}
110110

111-
// mount
111+
// mount if file provided
112112
image := req.File
113-
if image == "" {
114-
image = imageNone
113+
if image != "" {
114+
if err := os.WriteFile(mountDevice, []byte(image), 0o666); err != nil {
115+
log.Errorf("mount file %s failed: %s", image, err)
116+
rsp.ErrRsp(c, -2, "mount image failed")
117+
return
118+
}
115119
}
116120

117-
if err := os.WriteFile(mountDevice, []byte(image), 0o666); err != nil {
118-
log.Errorf("mount file %s failed: %s", image, err)
119-
rsp.ErrRsp(c, -2, "mount image failed")
120-
return
121+
// check to see if usb gadget reset is disabled
122+
resetUsb := true
123+
if _, err := os.Stat(usbNoRstMarker); err == nil {
124+
resetUsb = false
121125
}
122126

123127
h := hid.GetHid()
@@ -129,18 +133,20 @@ func (s *Service) MountImage(c *gin.Context) {
129133
}()
130134

131135
// reset usb
132-
commands := []string{
133-
"echo > /sys/kernel/config/usb_gadget/g0/UDC",
134-
"ls /sys/class/udc/ | cat > /sys/kernel/config/usb_gadget/g0/UDC",
135-
}
136+
if resetUsb {
137+
commands := []string{
138+
"echo > /sys/kernel/config/usb_gadget/g0/UDC",
139+
"ls /sys/class/udc/ | cat > /sys/kernel/config/usb_gadget/g0/UDC",
140+
}
136141

137-
for _, command := range commands {
138-
err := exec.Command("sh", "-c", command).Run()
139-
if err != nil {
140-
rsp.ErrRsp(c, -2, "execute command failed")
141-
return
142+
for _, command := range commands {
143+
err := exec.Command("sh", "-c", command).Run()
144+
if err != nil {
145+
rsp.ErrRsp(c, -2, "execute command failed")
146+
return
147+
}
148+
time.Sleep(100 * time.Millisecond)
142149
}
143-
time.Sleep(100 * time.Millisecond)
144150
}
145151

146152
rsp.OkRsp(c)
@@ -157,9 +163,6 @@ func (s *Service) GetMountedImage(c *gin.Context) {
157163
}
158164

159165
image := strings.ReplaceAll(string(content), "\n", "")
160-
if image == imageNone {
161-
image = ""
162-
}
163166

164167
data := &proto.GetMountedImageRsp{
165168
File: image,

server/service/vm/virtual-device.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import (
1414

1515
const (
1616
virtualNetwork = "/boot/usb.rndis0"
17-
virtualDisk = "/boot/usb.disk0"
17+
virtualMedia = "/boot/usb.disk0"
18+
virtualDisk = "/boot/usb.disk1"
1819
)
1920

2021
var (
@@ -31,28 +32,43 @@ var (
3132
"/etc/init.d/S03usbdev start",
3233
}
3334

34-
mountDiskCommands = []string{
35+
mountMediaCommands = []string{
3536
"touch /boot/usb.disk0",
3637
"/etc/init.d/S03usbdev stop",
3738
"/etc/init.d/S03usbdev start",
3839
}
3940

40-
unmountDiskCommands = []string{
41+
unmountMediaCommands = []string{
4142
"/etc/init.d/S03usbdev stop",
4243
"rm -rf /sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk0",
4344
"rm /boot/usb.disk0",
4445
"/etc/init.d/S03usbdev start",
4546
}
47+
48+
mountDiskCommands = []string{
49+
"touch /boot/usb.disk1",
50+
"/etc/init.d/S03usbdev stop",
51+
"/etc/init.d/S03usbdev start",
52+
}
53+
54+
unmountDiskCommands = []string{
55+
"/etc/init.d/S03usbdev stop",
56+
"rm -rf /sys/kernel/config/usb_gadget/g0/configs/c.1/mass_storage.disk1",
57+
"rm /boot/usb.disk1",
58+
"/etc/init.d/S03usbdev start",
59+
}
4660
)
4761

4862
func (s *Service) GetVirtualDevice(c *gin.Context) {
4963
var rsp proto.Response
5064

5165
network, _ := isDeviceExist(virtualNetwork)
66+
media, _ := isDeviceExist(virtualMedia)
5267
disk, _ := isDeviceExist(virtualDisk)
5368

5469
rsp.OkRspWithData(c, &proto.GetVirtualDeviceRsp{
5570
Network: network,
71+
Media: media,
5672
Disk: disk,
5773
})
5874
log.Debugf("get virtual device success")
@@ -80,6 +96,15 @@ func (s *Service) UpdateVirtualDevice(c *gin.Context) {
8096
} else {
8197
commands = unmountNetworkCommands
8298
}
99+
case "media":
100+
device = virtualMedia
101+
102+
exist, _ := isDeviceExist(device)
103+
if !exist {
104+
commands = mountMediaCommands
105+
} else {
106+
commands = unmountMediaCommands
107+
}
83108
case "disk":
84109
device = virtualDisk
85110

web/src/i18n/locales/en.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,9 @@ const en = {
279279
},
280280
hidOnly: 'HID-Only Mode',
281281
disk: 'Virtual Disk',
282-
diskDesc: 'Mount virtual U-disk on the remote host',
282+
diskDesc: 'Mount SD card on the remote host',
283+
media: "Virtual Image",
284+
mediaDesc: 'Attach virtual image device to the remote host',
283285
network: 'Virtual Network',
284286
networkDesc: 'Mount virtual network card on the remote host',
285287
reboot: 'Reboot',

web/src/pages/desktop/menu/settings/device/virtual-devices.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,9 @@ export const VirtualDevices = () => {
88
const { t } = useTranslation();
99

1010
const [isNetworkOn, setIsNetworkOn] = useState(false);
11+
const [isMediaOn, setIsMediaOn] = useState(false);
1112
const [isDiskOn, setIsDiskOn] = useState(false);
12-
const [loading, setLoading] = useState(''); // '' | 'network' | 'disk'
13+
const [loading, setLoading] = useState(''); // '' | 'network' | 'media' | 'disk'
1314

1415
useEffect(() => {
1516
api.getVirtualDevice().then((rsp) => {
@@ -18,11 +19,12 @@ export const VirtualDevices = () => {
1819
}
1920

2021
setIsNetworkOn(rsp.data.network);
22+
setIsMediaOn(rsp.data.media);
2123
setIsDiskOn(rsp.data.disk);
2224
});
2325
}, []);
2426

25-
function update(device: 'network' | 'disk') {
27+
function update(device: 'network' | 'media' | 'disk') {
2628
if (loading) return;
2729
setLoading(device);
2830

@@ -33,10 +35,16 @@ export const VirtualDevices = () => {
3335
return;
3436
}
3537

36-
if (device === 'network') {
37-
setIsNetworkOn(rsp.data.on);
38-
} else {
39-
setIsDiskOn(rsp.data.on);
38+
switch (device) {
39+
case 'network':
40+
setIsNetworkOn(rsp.data.on);
41+
break;
42+
case 'media':
43+
setIsMediaOn(rsp.data.on);
44+
break;
45+
case 'disk':
46+
setIsDiskOn(rsp.data.on);
47+
break;
4048
}
4149
})
4250
.finally(() => {
@@ -46,6 +54,15 @@ export const VirtualDevices = () => {
4654

4755
return (
4856
<>
57+
<div className="flex items-center justify-between">
58+
<div className="flex flex-col">
59+
<span>{t('settings.device.media')}</span>
60+
<span className="text-xs text-neutral-500">{t('settings.device.mediaDesc')}</span>
61+
</div>
62+
63+
<Switch checked={isMediaOn} loading={loading === 'media'} onChange={() => update('media')} />
64+
</div>
65+
4966
<div className="flex items-center justify-between">
5067
<div className="flex flex-col">
5168
<span>{t('settings.device.disk')}</span>

0 commit comments

Comments
 (0)