Sync with the new configuration file format and recent changes
to the envsys framework.
This commit is contained in:
parent
4b431f1771
commit
5c2d51b913
@ -1,4 +1,4 @@
|
|||||||
.\" $NetBSD: envsys.4,v 1.34 2007/09/11 22:31:35 wiz Exp $
|
.\" $NetBSD: envsys.4,v 1.35 2007/10/07 04:19:51 xtraeme Exp $
|
||||||
.\"
|
.\"
|
||||||
.\"
|
.\"
|
||||||
.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
|
.\" Copyright (c) 2007 The NetBSD Foundation, Inc.
|
||||||
@ -35,7 +35,7 @@
|
|||||||
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
.\" POSSIBILITY OF SUCH DAMAGE.
|
.\" POSSIBILITY OF SUCH DAMAGE.
|
||||||
.\"
|
.\"
|
||||||
.Dd September 4, 2007
|
.Dd October 7, 2007
|
||||||
.Dt ENVSYS 4
|
.Dt ENVSYS 4
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -74,7 +74,7 @@ for communication between kernel and user space. The following
|
|||||||
types are available:
|
types are available:
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width XX -compact
|
.Bl -tag -width XX -compact
|
||||||
.It Dv ENVSYS_GETDICTIONARY (prop_dictionary_t)
|
.It Dv ENVSYS_GETDICTIONARY (plistref)
|
||||||
.Pp
|
.Pp
|
||||||
This
|
This
|
||||||
.Xr ioctl 2
|
.Xr ioctl 2
|
||||||
@ -95,20 +95,24 @@ and all available properties set on it:
|
|||||||
\&\*[Lt]key\&\*[Gt]device0\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]device0\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]array\&\*[Gt]
|
\&\*[Lt]array\&\*[Gt]
|
||||||
\&\*[Lt]dict\&\*[Gt]
|
\&\*[Lt]dict\&\*[Gt]
|
||||||
|
\&\*[Lt]key\&\*[Gt]allow-rfact\&\*[Lt]\&/key\&\*[Gt]
|
||||||
|
\&\*[Lt]true\&/\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]avg-value\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]avg-value\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]36400\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]36400\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
|
\&\*[Lt]key\&\*[Gt]battery-state\&\*[Lt]\&/key\&\*[Gt]
|
||||||
|
\&\*[Lt]string\&\*[Gt]NORMAL\&\*[Lt]\&/string\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]critical-capacity\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]critical-capacity\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]21417\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]21417\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]critical-max-limit\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]critical-max\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]343150000\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]343150000\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]critical-min-limit\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]critical-min\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]288150000\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]288150000\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]cur-value\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]cur-value\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]406000\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]406000\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]description\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]description\&\*[Lt]\&/key\&\*[Gt]
|
||||||
|
\&\*[Lt]string\&\*[Gt]CPU Temp\&\*[Lt]\&/string\&\*[Gt]
|
||||||
|
\&\*[Lt]string\&\*[Gt]index\&\*[Lt]\&/string\&\*[Gt]
|
||||||
\&\*[Lt]string\&\*[Gt]sensor0\&\*[Lt]\&/string\&\*[Gt]
|
\&\*[Lt]string\&\*[Gt]sensor0\&\*[Lt]\&/string\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]generic-state-string\&\*[Lt]\&/key\&\*[Gt]
|
|
||||||
\&\*[Lt]string\&\*[Gt]NORMAL\&\*[Lt]\&/string\&\*[Gt]
|
|
||||||
\&\*[Lt]key\&\*[Gt]max-value\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]max-value\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]3894000\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]3894000\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]min-value\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]min-value\&\*[Lt]\&/key\&\*[Gt]
|
||||||
@ -139,8 +143,15 @@ and all available properties set on it:
|
|||||||
.Pp
|
.Pp
|
||||||
Let's explain some more about those objects:
|
Let's explain some more about those objects:
|
||||||
.Bl -tag -width "monitoring-state-critical-overxx"
|
.Bl -tag -width "monitoring-state-critical-overxx"
|
||||||
|
.It Fa allow-rfact
|
||||||
|
Set to
|
||||||
|
.Em true
|
||||||
|
mean that the sensor is able to change the resistor factor,
|
||||||
|
only used in Voltage sensors.
|
||||||
.It Fa avg-value
|
.It Fa avg-value
|
||||||
Current average value in the sensor.
|
Current average value in the sensor.
|
||||||
|
.It Fa battery-state
|
||||||
|
Current state for a battery state sensor.
|
||||||
.It Fa critical-capacity
|
.It Fa critical-capacity
|
||||||
Critical capacity set previously by the
|
Critical capacity set previously by the
|
||||||
.Ar ENVSYS_SETDICTIONARY
|
.Ar ENVSYS_SETDICTIONARY
|
||||||
@ -148,11 +159,11 @@ Critical capacity set previously by the
|
|||||||
Only available on sensors with the
|
Only available on sensors with the
|
||||||
.Em want-percentage
|
.Em want-percentage
|
||||||
object enabled.
|
object enabled.
|
||||||
.It Fa critical-max-limit
|
.It Fa critical-max
|
||||||
Critical max limit set previously by the
|
Critical max limit set previously by the
|
||||||
.Ar ENVSYS_SETDICTIONARY
|
.Ar ENVSYS_SETDICTIONARY
|
||||||
.Xr ioctl 2 .
|
.Xr ioctl 2 .
|
||||||
.It Fa critical-min-limit
|
.It Fa critical-min
|
||||||
Critical min limit set previously by the
|
Critical min limit set previously by the
|
||||||
.Ar ENVSYS_SETDICTIONARY
|
.Ar ENVSYS_SETDICTIONARY
|
||||||
.Xr ioctl 2 .
|
.Xr ioctl 2 .
|
||||||
@ -160,13 +171,8 @@ Critical min limit set previously by the
|
|||||||
Current value in the sensor.
|
Current value in the sensor.
|
||||||
.It Fa description
|
.It Fa description
|
||||||
Description of the sensor.
|
Description of the sensor.
|
||||||
.It Fa generic-state-string
|
.It Fa index
|
||||||
This is a generic string that
|
Index position of the sensor.
|
||||||
.Xr envstat 8
|
|
||||||
will use to print as
|
|
||||||
.Em current value .
|
|
||||||
Only used in sensors with type of
|
|
||||||
.Em ENVSYS_GSTRING .
|
|
||||||
.It Fa max-value
|
.It Fa max-value
|
||||||
Current max value in the sensor.
|
Current max value in the sensor.
|
||||||
.It Fa min-value
|
.It Fa min-value
|
||||||
@ -202,6 +208,27 @@ are valid and a percentage may be computed from them.
|
|||||||
.El
|
.El
|
||||||
.Pp
|
.Pp
|
||||||
.Bl -tag -width XX -compact
|
.Bl -tag -width XX -compact
|
||||||
|
.It Dv ENVSYS_REMOVEPROPS (prop_dictionary_t)
|
||||||
|
.Pp
|
||||||
|
This
|
||||||
|
.Xr ioctl 2
|
||||||
|
is used to remove all properties that are currently set via the
|
||||||
|
.Ar ENVSYS_SETDICTIONARY
|
||||||
|
ioctl. The values will be set to defaults, the ones that the driver
|
||||||
|
uses.
|
||||||
|
.Pp
|
||||||
|
Only one object is allowed on this dictionary:
|
||||||
|
.Bd -literal -offset -ident
|
||||||
|
<key>envsys-remove-props</key>
|
||||||
|
<true/>
|
||||||
|
.Ed
|
||||||
|
.Pp
|
||||||
|
It is a boolean object and must be set to
|
||||||
|
.Em true
|
||||||
|
to be effective.
|
||||||
|
.El
|
||||||
|
.Bl -tag -width XX -compact
|
||||||
|
.Pp
|
||||||
.It Dv ENVSYS_SETDICTIONARY (prop_dictionary_t)
|
.It Dv ENVSYS_SETDICTIONARY (prop_dictionary_t)
|
||||||
.Pp
|
.Pp
|
||||||
This
|
This
|
||||||
@ -214,77 +241,49 @@ the kernel part. The following is the property list representation
|
|||||||
of a dictionary with all recognized and required keywords:
|
of a dictionary with all recognized and required keywords:
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
\&\*[Lt]dict\&\*[Gt]
|
\&\*[Lt]dict\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]driver-name\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]description\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]string\&\*[Gt]driver0\&\*[Lt]\&/string\&\*[Gt]
|
\&\*[Lt]string\&\*[Gt]cpu temp\&\*[Lt]\&/string\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]sensor-name\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]rfact\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]string\&\*[Gt]sensor0\&\*[Lt]\&/string\&\*[Gt]
|
|
||||||
\&\*[Lt]key\&\*[Gt]new-description\&\*[Lt]\&/key\&\*[Gt]
|
|
||||||
\&\*[Lt]string\&\*[Gt]mysensor0\&\*[Lt]\&/string\&\*[Gt]
|
|
||||||
\&\*[Lt]key\&\*[Gt]new-rfact\&\*[Lt]\&/key\&\*[Gt]
|
|
||||||
\&\*[Lt]integer\&\*[Gt]56000\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]56000\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]critical-capacity\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]critical-capacity\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]10\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]10\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]critical-max-limit\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]critical-max\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]3400\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]3400\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]critical-min-limit\&\*[Lt]\&/key\&\*[Gt]
|
\&\*[Lt]key\&\*[Gt]critical-min\&\*[Lt]\&/key\&\*[Gt]
|
||||||
\&\*[Lt]integer\&\*[Gt]2800\&\*[Lt]\&/integer\&\*[Gt]
|
\&\*[Lt]integer\&\*[Gt]2800\&\*[Lt]\&/integer\&\*[Gt]
|
||||||
\&\*[Lt]key\&\*[Gt]remove-critical-cap\&\*[Lt]\&/key\&\*[Gt]
|
|
||||||
\&\*[Lt]true\&/\&\*[Gt]
|
|
||||||
\&\*[Lt]key\&\*[Gt]remove-cmax-limit\&\*[Lt]\&/key\&\*[Gt]
|
|
||||||
\&\*[Lt]true\&/\&\*[Gt]
|
|
||||||
\&\*[Lt]key\&\*[Gt]remove-cmin-limit\&\*[Lt]\&/key\&\*[Gt]
|
|
||||||
\&\*[Lt]true\&/\&\*[Gt]
|
|
||||||
\&\*[Lt]\&/dict\&\*[Gt]
|
\&\*[Lt]\&/dict\&\*[Gt]
|
||||||
.Ed
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
A dictionary sent to the kernel with this
|
A dictionary sent to the kernel with this
|
||||||
.Xr ioctl 2
|
.Xr ioctl 2
|
||||||
must
|
should have the following structure:
|
||||||
.Sy always
|
.Bd -literal
|
||||||
have the objects
|
\&\*[Lt]dict\&\*[Gt]
|
||||||
.Ar driver-name
|
\&\*[Lt]key\&\*[Gt]device_name\&\*[Lt]\&/key\&\*[Gt]
|
||||||
and
|
\&\*[Lt]array\&\*[Gt]
|
||||||
.Ar sensor-name .
|
\&\*[Lt]dict\&\*[Gt]
|
||||||
They are used to specify the
|
\&\*[Lt]key\&\*[Gt]index\&\*[Lt]\&/key\&\*[Gt]
|
||||||
.Sy driver
|
\&\*[Lt]string\&\*[Gt]sensor0\&\*[Lt]\&/string\&\*[Gt]
|
||||||
and the
|
\&\*[Lt]key\&\*[Gt]description\&\*[Lt]\&/key\&\*[Gt]
|
||||||
.Sy sensor
|
\&\*[Lt]string\&\*[Gt]cpu temp\&\*[Lt]\&/string\&\*[Gt]
|
||||||
that we want to set a property for.
|
...
|
||||||
|
Another property for this sensor
|
||||||
|
...
|
||||||
|
\&\*[Lt]\&/dict\&\*[Gt]
|
||||||
|
...
|
||||||
|
Another dictionary for other sensor
|
||||||
|
...
|
||||||
|
\&\*[Lt]\&/array\&\*[Gt]
|
||||||
|
...
|
||||||
|
Another device as above
|
||||||
|
...
|
||||||
|
\&\*[Lt]\&/dict\&\*[Gt]
|
||||||
|
.Ed
|
||||||
.Pp
|
.Pp
|
||||||
.Em NOTE :
|
The named device will be an array and will contain dictionaries,
|
||||||
Only one of the following objects must be added into the dictionary
|
any dictionary needs to have the
|
||||||
at a time:
|
.Em index
|
||||||
.Ar new-description ,
|
object specifying the sensor that is required for the new properties.
|
||||||
.Ar new-rfact ,
|
|
||||||
.Ar critical-capacity ,
|
|
||||||
.Ar critical-max-limit ,
|
|
||||||
.Ar critical-min-limit ,
|
|
||||||
.Ar remove-critical-cap ,
|
|
||||||
.Ar remove-cmax-limit ,
|
|
||||||
and
|
|
||||||
.Ar remove-cmin-limit .
|
|
||||||
.Pp
|
|
||||||
The following operation is selected depending what object
|
|
||||||
was added into the dictionary:
|
|
||||||
.Pp
|
|
||||||
.Bl -bullet -offset indent -compact
|
|
||||||
.It
|
|
||||||
change a description.
|
|
||||||
.It
|
|
||||||
change the rfact in a voltage sensor.
|
|
||||||
.It
|
|
||||||
set a critical capacity limit.
|
|
||||||
.It
|
|
||||||
set a critical max limit.
|
|
||||||
.It
|
|
||||||
set a critical min limit.
|
|
||||||
.It
|
|
||||||
remove a critical capacity limit.
|
|
||||||
.It
|
|
||||||
remove a critical max limit.
|
|
||||||
.It
|
|
||||||
remove a critical min limit.
|
|
||||||
.El
|
|
||||||
.Pp
|
.Pp
|
||||||
If an unknown object was sent with the dictionary,
|
If an unknown object was sent with the dictionary,
|
||||||
.Er EINVAL
|
.Er EINVAL
|
||||||
@ -311,79 +310,58 @@ is the following:
|
|||||||
.Em value = (value / 100) * max value .
|
.Em value = (value / 100) * max value .
|
||||||
The max value is available in the sensor's dictionary.
|
The max value is available in the sensor's dictionary.
|
||||||
.Sh EXAMPLES
|
.Sh EXAMPLES
|
||||||
The following example illustrates how to receive the dictionary
|
|
||||||
and to print it in raw XML/plist format:
|
|
||||||
.Bd -literal
|
|
||||||
#define _DEV_SYSMON /dev/sysmon
|
|
||||||
|
|
||||||
int main(void)
|
|
||||||
{
|
|
||||||
prop_dictionary_t dict;
|
|
||||||
char *buf;
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
if ((fd = open(_DEV_SYSMON, O_RDONLY)) == -1)
|
|
||||||
err(EXIT_FAILURE, "open")
|
|
||||||
|
|
||||||
if (prop_dictionary_recv_ioctl(fd, ENVSYS_GETDICTIONARY, \*[Am]dict)) {
|
|
||||||
(void)close(fd);
|
|
||||||
err(EINVAL, "prop_dictionary_recv_ioctl");
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = prop_dictionary_externalize(dict);
|
|
||||||
(void)printf("%s", buf);
|
|
||||||
prop_object_release(dict);
|
|
||||||
free(buf);
|
|
||||||
(void)close(fd);
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
.Ed
|
|
||||||
.Pp
|
.Pp
|
||||||
Another example that shows how to use the
|
The following example shows how to change the description
|
||||||
|
of
|
||||||
|
.Ql sensor0
|
||||||
|
in the
|
||||||
|
.Ql aiboost0
|
||||||
|
device with the
|
||||||
.Ar ENVSYS_SETDICTIONARY
|
.Ar ENVSYS_SETDICTIONARY
|
||||||
.Xr ioctl 2
|
.Xr ioctl 2 :
|
||||||
to change the description in a sensor:
|
|
||||||
.Bd -literal
|
.Bd -literal
|
||||||
int
|
int
|
||||||
main(void)
|
main(void)
|
||||||
{
|
{
|
||||||
prop_dictionary_t dict;
|
prop_dictionary_t global_dict, sensor_dict;
|
||||||
|
prop_array_t;
|
||||||
prop_object_t obj;
|
prop_object_t obj;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
dict = prop_dictionary_create();
|
global_dict = prop_dictionary_create();
|
||||||
|
sensor_dict = prop_dictionary_create();
|
||||||
|
array = prop_array_create();
|
||||||
|
|
||||||
obj = prop_string_create_cstring_nocopy("aiboost0");
|
if (!prop_dictionary_set(global_dict, "aiboost0", array))
|
||||||
|
err(EINVAL, "prop_dictionary_set global");
|
||||||
|
|
||||||
|
obj = prop_string_create_cstring_nocopy("sensor0");
|
||||||
if (obj == NULL ||
|
if (obj == NULL ||
|
||||||
!prop_dictionary_set(dict, "driver-name", obj))
|
!prop_dictionary_set(dict, "index", obj))
|
||||||
err(EINVAL, "driver-name");
|
err(EINVAL, "sensor index");
|
||||||
|
|
||||||
prop_object_release(obj);
|
|
||||||
|
|
||||||
obj = prop_string_create_cstring_nocopy("CPU Temperature");
|
|
||||||
if (obj == NULL ||
|
|
||||||
!prop_dictionary_set(dict, "sensor-name", obj))
|
|
||||||
err(EINVAL, "sensor-name");
|
|
||||||
|
|
||||||
prop_object_release(obj);
|
prop_object_release(obj);
|
||||||
|
|
||||||
/* new description */
|
/* new description */
|
||||||
obj = prop_string_create_cstring_nocopy("CPU temp");
|
obj = prop_string_create_cstring_nocopy("CPU temp");
|
||||||
if (obj == NULL ||
|
if (obj == NULL ||
|
||||||
!prop_dictionary_set(dict, "new-description", obj))
|
!prop_dictionary_set(dict, "description", obj))
|
||||||
err(EINVAL, "new-description");
|
err(EINVAL, "new description");
|
||||||
|
|
||||||
prop_object_release(obj);
|
prop_object_release(obj);
|
||||||
|
|
||||||
if ((fd = open(_DEV_SYSMON, O_RDONLY)) == -1)
|
if (!prop_array_add(array, sensor_dict))
|
||||||
|
err(EINVAL, "prop_array_add");
|
||||||
|
|
||||||
|
if ((fd = open(_DEV_SYSMON, O_RDWR)) == -1)
|
||||||
err(EXIT_FAILURE, "open")
|
err(EXIT_FAILURE, "open")
|
||||||
|
|
||||||
/* we are done, send the dictionary */
|
/* we are done, send the dictionary */
|
||||||
error = prop_dictionary_send_ioctl(dict,
|
error = prop_dictionary_send_ioctl(global_dict,
|
||||||
fd,
|
fd,
|
||||||
ENVSYS_SETDICTIONARY);
|
ENVSYS_SETDICTIONARY);
|
||||||
prop_object_release(dict);
|
prop_object_release(array);
|
||||||
|
prop_object_release(global_dict);
|
||||||
(void)close(fd);
|
(void)close(fd);
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user