This commit is contained in:
Miguel Fuertes committed 2025-10-07 21:44:23 +02:00
1 parent 50774bfbf7
commit 55eb4d0e4a
3 files changed
+84 -48

No files matched your search

@@ -3,6 +3,7 @@
'require form';
'require uci';
'require fs';
'require ui';
return view.extend({
load: function() {
@@ -27,8 +28,9 @@ return view.extend({
s.anonymous = true;
s.addremove = false;
o = s.option(form.Flag, 'enabled', _('Enable USB Gadget'),
_('Disable to use USB port in host mode'));
o = s.option(form.Flag, 'enabled', _('Enable USB Gadget'));
o.description = _('Disable to use USB port in host mode.') + '<br>' +
'<strong>May disconnect USB. Ensure alternative access.</strong>';
o.rmempty = false;
o = s.option(form.Value, 'gadget_name', _('Gadget Name'));
@@ -71,15 +73,10 @@ return view.extend({
_('RNDIS (Windows Ethernet)'),
_('Windows-compatible USB ethernet. Works on all Windows versions.'));
o = s.option(form.Flag, 'enabled', _('Enable RNDIS'));
o = s.option(form.Flag, 'enabled', _('Enable RNDIS'),
_('Plug-and-play on Windows. Automatically adds to LAN bridge.'));
o.rmempty = false;
o = s.option(form.DummyValue, '_desc', _('Description'));
o.rawhtml = true;
o.cfgvalue = function() {
return _('Plug-and-play on Windows. Automatically adds to LAN bridge.');
};
// =================================================================
// ECM
// =================================================================
@@ -87,15 +84,10 @@ return view.extend({
_('ECM (macOS/Linux Ethernet)'),
_('For macOS ≤10.14 and Linux. Do not enable with NCM.'));
o = s.option(form.Flag, 'enabled', _('Enable ECM'));
o = s.option(form.Flag, 'enabled', _('Enable ECM'),
_('CDC Ethernet for macOS and Linux. Disable RNDIS when using.'));
o.rmempty = false;
o = s.option(form.DummyValue, '_desc', _('Description'));
o.rawhtml = true;
o.cfgvalue = function() {
return _('CDC Ethernet for macOS and Linux. Disable RNDIS when using.');
};
// =================================================================
// NCM
// =================================================================
@@ -103,15 +95,10 @@ return view.extend({
_('NCM (Modern Ethernet)'),
_('Best performance. For Windows 11+, macOS ≥10.15, Linux.'));
o = s.option(form.Flag, 'enabled', _('Enable NCM'));
o = s.option(form.Flag, 'enabled', _('Enable NCM'),
_('Modern high-speed USB ethernet. Best choice for new systems.'));
o.rmempty = false;
o = s.option(form.DummyValue, '_desc', _('Description'));
o.rawhtml = true;
o.cfgvalue = function() {
return _('Modern high-speed USB ethernet. Best choice for new systems.');
};
// =================================================================
// ACM Serial
// =================================================================
@@ -138,7 +125,7 @@ return view.extend({
// =================================================================
s = m.section(form.NamedSection, 'ums', 'function',
_('Mass Storage'),
_('Expose storage image as USB drive.'));
_('Expose storage image as USB drive. Does not provide access to the device.'));
o = s.option(form.Flag, 'enabled', _('Enable Mass Storage'));
o.rmempty = false;
@@ -161,7 +148,14 @@ return view.extend({
handleSaveApply: function(ev, mode) {
return this.super('handleSaveApply', [ev, mode]).then(function() {
return fs.exec('/etc/init.d/usb-gadget', ['restart']);
ui.addNotification(null,
E('p', _('Configuration saved. Restarting USB Gadget service...')),
'info');
return fs.exec('/etc/init.d/usb-gadget', ['restart']).then(function() {
ui.addNotification(null,
E('p', _('USB Gadget service restarted successfully')),
'info');
});
});
}
});
@@ -4,19 +4,20 @@
'require ui';
'require uci';
'require poll';
'require network';
return view.extend({
load: function() {
return Promise.all([
uci.load('usbgadget'),
L.resolveDefault(fs.exec('/etc/init.d/usb-gadget', ['status']), null),
L.resolveDefault(fs.list('/sys/class/udc'), [])
L.resolveDefault(fs.list('/sys/class/udc'), []),
network.getDevices()
]);
},
render: function(data) {
var status_result = data[1];
var udc_devices = data[2];
var udc_devices = data[1];
var net_devices = data[2];
var enabled = uci.get('usbgadget', 'usb', 'enabled');
var gadget_name = uci.get('usbgadget', 'usb', 'gadget_name') || 'g1';
@@ -31,6 +32,21 @@ return view.extend({
}
});
// Buscar interfaces USB y crear elementos con puntitos de colores
var usb_interface_elements = [];
net_devices.forEach(function(dev) {
var name = dev.getName();
if (name && name.match(/^usb\d+$/)) {
var isUp = dev.isUp();
usb_interface_elements.push(
E('span', { 'style': 'margin-right: 10px;' }, [
E('span', { 'style': 'color:' + (isUp ? 'green' : 'red') }, '● '),
name
])
);
}
});
// Construir array de filas de la tabla
var tableRows = [
E('tr', { 'class': 'tr' }, [
@@ -61,12 +77,20 @@ return view.extend({
// Añadir fila UDC solo si hay dispositivos
if (udc_devices.length > 0) {
tableRows.splice(3, 0, E('tr', { 'class': 'tr' }, [
tableRows.push(E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td left' }, E('strong', {}, _('USB Controller'))),
E('td', { 'class': 'td left' }, udc_devices.map(function(d) { return d.name; }).join(', '))
]));
}
// Añadir interfaces de red USB con puntitos
if (usb_interface_elements.length > 0) {
tableRows.push(E('tr', { 'class': 'tr' }, [
E('td', { 'class': 'td left' }, E('strong', {}, _('Network Interfaces'))),
E('td', { 'class': 'td left', 'id': 'usb_interfaces' }, usb_interface_elements)
]));
}
var viewElements = [
E('h2', {}, _('USB Gadget Status')),
E('div', { 'class': 'cbi-map-descr' },
@@ -77,11 +101,11 @@ return view.extend({
E('table', { 'class': 'table' }, tableRows)
]),
// Botón alineado a la derecha
E('div', { 'class': 'cbi-section' }, [
E('div', { 'class': 'cbi-section-node' }, [
E('div', { 'class': 'cbi-value' }, [
E('label', { 'class': 'cbi-value-title' }, _('Service Control')),
E('div', { 'class': 'cbi-value-field' }, [
E('div', { 'class': 'cbi-value-field', 'style': 'text-align: right;' }, [
E('button', {
'class': 'cbi-button cbi-button-apply',
'click': function() {
@@ -110,23 +134,14 @@ return view.extend({
])
];
// Añadir output detallado solo si existe
if (status_result && status_result.stdout) {
viewElements.push(
E('div', { 'class': 'cbi-section' }, [
E('h3', {}, _('Detailed Output')),
E('pre', {
'style': 'background:#f9f9f9; padding:10px; overflow:auto; max-height:400px; border:1px solid #ddd'
}, status_result.stdout)
])
);
}
var view = E('div', { 'class': 'cbi-map' }, viewElements);
// Polling cada 5 segundos
poll.add(function() {
return uci.load('usbgadget').then(function() {
return Promise.all([
uci.load('usbgadget'),
network.getDevices()
]).then(function(pollData) {
var newEnabled = uci.get('usbgadget', 'usb', 'enabled');
var statusEl = document.getElementById('status_value');
if (statusEl) {
@@ -137,6 +152,34 @@ return view.extend({
E('span', { 'style': 'color:red' }, '● ' + _('Disabled (Host Mode)'))
);
}
// Actualizar interfaces USB con puntitos
var ifacesEl = document.getElementById('usb_interfaces');
if (ifacesEl) {
var newDevices = pollData[1];
var newUsbElements = [];
newDevices.forEach(function(dev) {
var name = dev.getName();
if (name && name.match(/^usb\d+$/)) {
var isUp = dev.isUp();
newUsbElements.push(
E('span', { 'style': 'margin-right: 10px;' }, [
E('span', { 'style': 'color:' + (isUp ? 'green' : 'red') }, '● '),
name
])
);
}
});
ifacesEl.innerHTML = '';
if (newUsbElements.length > 0) {
newUsbElements.forEach(function(el) {
ifacesEl.appendChild(el);
});
} else {
ifacesEl.appendChild(E('em', {}, _('None')));
}
}
});
}, 5);
@@ -26,11 +26,10 @@
]
},
"file": {
"/etc/config/usbgadget": ["write"]
"/etc/config/usbgadget": ["write"],
"/etc/init.d/usb-gadget": ["exec"]
},
"cgi-io": [
"upload",
"download",
"exec"
]
}