Wake-up the device automatically.
The backend is now in full control of the handshake sequence and does automatically wake-up the device at the appropriate time.
This commit is contained in:
parent
b7fcd5442c
commit
aa7599929e
@ -35,7 +35,6 @@ test_dump_memory (const char* name, const char* filename)
|
||||
{
|
||||
device_t *device = NULL;
|
||||
unsigned char data[REEFNET_SENSUS_MEMORY_SIZE] = {0};
|
||||
unsigned char handshake[REEFNET_SENSUS_HANDSHAKE_SIZE] = {0};
|
||||
|
||||
message ("reefnet_sensus_device_open\n");
|
||||
device_status_t rc = reefnet_sensus_device_open (&device, name);
|
||||
@ -44,14 +43,6 @@ test_dump_memory (const char* name, const char* filename)
|
||||
return rc;
|
||||
}
|
||||
|
||||
message ("device_handshake\n");
|
||||
rc = device_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
WARNING ("Cannot read handshake.");
|
||||
device_close (device);
|
||||
return rc;
|
||||
}
|
||||
|
||||
time_t now = time (NULL);
|
||||
char datetime[21] = {0};
|
||||
strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now));
|
||||
|
||||
@ -35,7 +35,6 @@ test_dump_memory (const char* name, const char* filename)
|
||||
{
|
||||
device_t *device = NULL;
|
||||
unsigned char data[REEFNET_SENSUSPRO_MEMORY_SIZE] = {0};
|
||||
unsigned char handshake[REEFNET_SENSUSPRO_HANDSHAKE_SIZE] = {0};
|
||||
|
||||
message ("reefnet_sensuspro_device_open\n");
|
||||
device_status_t rc = reefnet_sensuspro_device_open (&device, name);
|
||||
@ -44,14 +43,6 @@ test_dump_memory (const char* name, const char* filename)
|
||||
return rc;
|
||||
}
|
||||
|
||||
message ("device_handshake\n");
|
||||
rc = device_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
WARNING ("Cannot read handshake.");
|
||||
device_close (device);
|
||||
return rc;
|
||||
}
|
||||
|
||||
time_t now = time (NULL);
|
||||
char datetime[21] = {0};
|
||||
strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now));
|
||||
|
||||
@ -35,7 +35,6 @@ device_status_t
|
||||
test_dump_memory_dives (const char* name, const char* filename)
|
||||
{
|
||||
device_t *device = NULL;
|
||||
unsigned char handshake[REEFNET_SENSUSULTRA_HANDSHAKE_SIZE] = {0};
|
||||
|
||||
message ("reefnet_sensusultra_device_open\n");
|
||||
device_status_t rc = reefnet_sensusultra_device_open (&device, name);
|
||||
@ -44,14 +43,6 @@ test_dump_memory_dives (const char* name, const char* filename)
|
||||
return rc;
|
||||
}
|
||||
|
||||
message ("device_handshake\n");
|
||||
rc = device_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
WARNING ("Cannot read handshake.");
|
||||
device_close (device);
|
||||
return rc;
|
||||
}
|
||||
|
||||
time_t now = time (NULL);
|
||||
char datetime[21] = {0};
|
||||
strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now));
|
||||
@ -81,7 +72,6 @@ test_dump_memory_data (const char* name, const char* filename)
|
||||
{
|
||||
device_t *device = NULL;
|
||||
unsigned char data[REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE] = {0};
|
||||
unsigned char handshake[REEFNET_SENSUSULTRA_HANDSHAKE_SIZE] = {0};
|
||||
|
||||
message ("reefnet_sensusultra_device_open\n");
|
||||
device_status_t rc = reefnet_sensusultra_device_open (&device, name);
|
||||
@ -90,14 +80,6 @@ test_dump_memory_data (const char* name, const char* filename)
|
||||
return rc;
|
||||
}
|
||||
|
||||
message ("device_handshake\n");
|
||||
rc = device_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
WARNING ("Cannot read handshake.");
|
||||
device_close (device);
|
||||
return rc;
|
||||
}
|
||||
|
||||
time_t now = time (NULL);
|
||||
char datetime[21] = {0};
|
||||
strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now));
|
||||
@ -135,7 +117,6 @@ test_dump_memory_user (const char* name, const char* filename)
|
||||
{
|
||||
device_t *device = NULL;
|
||||
unsigned char data[REEFNET_SENSUSULTRA_MEMORY_USER_SIZE] = {0};
|
||||
unsigned char handshake[REEFNET_SENSUSULTRA_HANDSHAKE_SIZE] = {0};
|
||||
|
||||
message ("reefnet_sensusultra_device_open\n");
|
||||
device_status_t rc = reefnet_sensusultra_device_open (&device, name);
|
||||
@ -144,14 +125,6 @@ test_dump_memory_user (const char* name, const char* filename)
|
||||
return rc;
|
||||
}
|
||||
|
||||
message ("device_handshake\n");
|
||||
rc = device_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
WARNING ("Cannot read handshake.");
|
||||
device_close (device);
|
||||
return rc;
|
||||
}
|
||||
|
||||
time_t now = time (NULL);
|
||||
char datetime[21] = {0};
|
||||
strftime (datetime, sizeof (datetime), "%Y-%m-%dT%H:%M:%SZ", gmtime (&now));
|
||||
|
||||
@ -51,7 +51,6 @@ typedef struct reefnet_sensus_device_t {
|
||||
} reefnet_sensus_device_t;
|
||||
|
||||
static device_status_t reefnet_sensus_device_set_fingerprint (device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static device_status_t reefnet_sensus_device_handshake (device_t *abstract, unsigned char *data, unsigned int size);
|
||||
static device_status_t reefnet_sensus_device_dump (device_t *abstract, unsigned char *data, unsigned int size, unsigned int *result);
|
||||
static device_status_t reefnet_sensus_device_foreach (device_t *abstract, dive_callback_t callback, void *userdata);
|
||||
static device_status_t reefnet_sensus_device_close (device_t *abstract);
|
||||
@ -59,7 +58,7 @@ static device_status_t reefnet_sensus_device_close (device_t *abstract);
|
||||
static const device_backend_t reefnet_sensus_device_backend = {
|
||||
DEVICE_TYPE_REEFNET_SENSUS,
|
||||
reefnet_sensus_device_set_fingerprint, /* set_fingerprint */
|
||||
reefnet_sensus_device_handshake, /* handshake */
|
||||
NULL, /* handshake */
|
||||
NULL, /* version */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
@ -214,13 +213,8 @@ reefnet_sensus_device_set_fingerprint (device_t *abstract, const unsigned char d
|
||||
|
||||
|
||||
static device_status_t
|
||||
reefnet_sensus_device_handshake (device_t *abstract, unsigned char *data, unsigned int size)
|
||||
reefnet_sensus_handshake (reefnet_sensus_device_t *device, unsigned char *data, unsigned int size)
|
||||
{
|
||||
reefnet_sensus_device_t *device = (reefnet_sensus_device_t*) abstract;
|
||||
|
||||
if (! device_is_reefnet_sensus (abstract))
|
||||
return DEVICE_STATUS_TYPE_MISMATCH;
|
||||
|
||||
if (size < REEFNET_SENSUS_HANDSHAKE_SIZE) {
|
||||
WARNING ("Insufficient buffer space available.");
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
@ -278,7 +272,7 @@ reefnet_sensus_device_handshake (device_t *abstract, unsigned char *data, unsign
|
||||
devinfo.model = handshake[2] - '0';
|
||||
devinfo.firmware = handshake[3] - '0';
|
||||
devinfo.serial = array_uint16_le (handshake + 6);
|
||||
device_event_emit (abstract, DEVICE_EVENT_DEVINFO, &devinfo);
|
||||
device_event_emit (&device->base, DEVICE_EVENT_DEVINFO, &devinfo);
|
||||
|
||||
// Wait at least 10 ms to ensures the data line is
|
||||
// clear before transmission from the host begins.
|
||||
@ -307,6 +301,12 @@ reefnet_sensus_device_dump (device_t *abstract, unsigned char *data, unsigned in
|
||||
progress.maximum = 4 + REEFNET_SENSUS_MEMORY_SIZE + 2 + 3;
|
||||
device_event_emit (abstract, DEVICE_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Wake-up the device.
|
||||
unsigned char handshake[REEFNET_SENSUS_HANDSHAKE_SIZE] = {0};
|
||||
device_status_t rc = reefnet_sensus_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// Send the command to the device.
|
||||
unsigned char command = 0x40;
|
||||
int n = serial_write (device->port, &command, 1);
|
||||
|
||||
@ -49,7 +49,6 @@ typedef struct reefnet_sensuspro_device_t {
|
||||
} reefnet_sensuspro_device_t;
|
||||
|
||||
static device_status_t reefnet_sensuspro_device_set_fingerprint (device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static device_status_t reefnet_sensuspro_device_handshake (device_t *abstract, unsigned char *data, unsigned int size);
|
||||
static device_status_t reefnet_sensuspro_device_dump (device_t *abstract, unsigned char *data, unsigned int size, unsigned int *result);
|
||||
static device_status_t reefnet_sensuspro_device_foreach (device_t *abstract, dive_callback_t callback, void *userdata);
|
||||
static device_status_t reefnet_sensuspro_device_close (device_t *abstract);
|
||||
@ -57,7 +56,7 @@ static device_status_t reefnet_sensuspro_device_close (device_t *abstract);
|
||||
static const device_backend_t reefnet_sensuspro_device_backend = {
|
||||
DEVICE_TYPE_REEFNET_SENSUSPRO,
|
||||
reefnet_sensuspro_device_set_fingerprint, /* set_fingerprint */
|
||||
reefnet_sensuspro_device_handshake, /* handshake */
|
||||
NULL, /* handshake */
|
||||
NULL, /* version */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
@ -188,13 +187,8 @@ reefnet_sensuspro_device_set_fingerprint (device_t *abstract, const unsigned cha
|
||||
|
||||
|
||||
static device_status_t
|
||||
reefnet_sensuspro_device_handshake (device_t *abstract, unsigned char *data, unsigned int size)
|
||||
reefnet_sensuspro_handshake (reefnet_sensuspro_device_t *device, unsigned char *data, unsigned int size)
|
||||
{
|
||||
reefnet_sensuspro_device_t *device = (reefnet_sensuspro_device_t*) abstract;
|
||||
|
||||
if (! device_is_reefnet_sensuspro (abstract))
|
||||
return DEVICE_STATUS_TYPE_MISMATCH;
|
||||
|
||||
if (size < REEFNET_SENSUSPRO_HANDSHAKE_SIZE) {
|
||||
WARNING ("Insufficient buffer space available.");
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
@ -247,7 +241,7 @@ reefnet_sensuspro_device_handshake (device_t *abstract, unsigned char *data, uns
|
||||
devinfo.model = handshake[0];
|
||||
devinfo.firmware = handshake[1];
|
||||
devinfo.serial = array_uint16_le (handshake + 4);
|
||||
device_event_emit (abstract, DEVICE_EVENT_DEVINFO, &devinfo);
|
||||
device_event_emit (&device->base, DEVICE_EVENT_DEVINFO, &devinfo);
|
||||
|
||||
serial_sleep (10);
|
||||
|
||||
@ -255,6 +249,26 @@ reefnet_sensuspro_device_handshake (device_t *abstract, unsigned char *data, uns
|
||||
}
|
||||
|
||||
|
||||
static device_status_t
|
||||
reefnet_sensuspro_send (reefnet_sensuspro_device_t *device, unsigned char command)
|
||||
{
|
||||
// Wake-up the device.
|
||||
unsigned char handshake[REEFNET_SENSUSPRO_HANDSHAKE_SIZE] = {0};
|
||||
device_status_t rc = reefnet_sensuspro_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// Send the instruction code to the device.
|
||||
int n = serial_write (device->port, &command, 1);
|
||||
if (n != 1) {
|
||||
WARNING ("Failed to send the command.");
|
||||
return EXITCODE (n);
|
||||
}
|
||||
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static device_status_t
|
||||
reefnet_sensuspro_device_dump (device_t *abstract, unsigned char *data, unsigned int size, unsigned int *result)
|
||||
{
|
||||
@ -273,12 +287,10 @@ reefnet_sensuspro_device_dump (device_t *abstract, unsigned char *data, unsigned
|
||||
progress.maximum = REEFNET_SENSUSPRO_MEMORY_SIZE + 2;
|
||||
device_event_emit (abstract, DEVICE_EVENT_PROGRESS, &progress);
|
||||
|
||||
unsigned char command = 0xB4;
|
||||
int rc = serial_write (device->port, &command, 1);
|
||||
if (rc != 1) {
|
||||
WARNING ("Failed to send the command.");
|
||||
return EXITCODE (rc);
|
||||
}
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensuspro_send (device, 0xB4);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
unsigned int nbytes = 0;
|
||||
unsigned char answer[REEFNET_SENSUSPRO_MEMORY_SIZE + 2] = {0};
|
||||
@ -287,10 +299,10 @@ reefnet_sensuspro_device_dump (device_t *abstract, unsigned char *data, unsigned
|
||||
if (len > 256)
|
||||
len = 256;
|
||||
|
||||
rc = serial_read (device->port, answer + nbytes, len);
|
||||
if (rc != len) {
|
||||
int n = serial_read (device->port, answer + nbytes, len);
|
||||
if (n != len) {
|
||||
WARNING ("Failed to receive the answer.");
|
||||
return EXITCODE (rc);
|
||||
return EXITCODE (n);
|
||||
}
|
||||
|
||||
// Update and emit a progress event.
|
||||
@ -345,19 +357,17 @@ reefnet_sensuspro_device_write_interval (device_t *abstract, unsigned char inter
|
||||
if (interval < 1 || interval > 127)
|
||||
return DEVICE_STATUS_ERROR;
|
||||
|
||||
unsigned char command = 0xB5;
|
||||
int rc = serial_write (device->port, &command, 1);
|
||||
if (rc != 1) {
|
||||
WARNING ("Failed to send the command.");
|
||||
return EXITCODE (rc);
|
||||
}
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensuspro_send (device, 0xB5);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
serial_sleep (10);
|
||||
|
||||
rc = serial_write (device->port, &interval, 1);
|
||||
if (rc != 1) {
|
||||
int n = serial_write (device->port, &interval, 1);
|
||||
if (n != 1) {
|
||||
WARNING ("Failed to send the new value.");
|
||||
return EXITCODE (rc);
|
||||
return EXITCODE (n);
|
||||
}
|
||||
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
|
||||
@ -55,7 +55,6 @@ typedef struct reefnet_sensusultra_device_t {
|
||||
} reefnet_sensusultra_device_t;
|
||||
|
||||
static device_status_t reefnet_sensusultra_device_set_fingerprint (device_t *abstract, const unsigned char data[], unsigned int size);
|
||||
static device_status_t reefnet_sensusultra_device_handshake (device_t *abstract, unsigned char *data, unsigned int size);
|
||||
static device_status_t reefnet_sensusultra_device_dump (device_t *abstract, unsigned char *data, unsigned int size, unsigned int *result);
|
||||
static device_status_t reefnet_sensusultra_device_foreach (device_t *abstract, dive_callback_t callback, void *userdata);
|
||||
static device_status_t reefnet_sensusultra_device_close (device_t *abstract);
|
||||
@ -63,7 +62,7 @@ static device_status_t reefnet_sensusultra_device_close (device_t *abstract);
|
||||
static const device_backend_t reefnet_sensusultra_device_backend = {
|
||||
DEVICE_TYPE_REEFNET_SENSUSULTRA,
|
||||
reefnet_sensusultra_device_set_fingerprint, /* set_fingerprint */
|
||||
reefnet_sensusultra_device_handshake, /* handshake */
|
||||
NULL, /* handshake */
|
||||
NULL, /* version */
|
||||
NULL, /* read */
|
||||
NULL, /* write */
|
||||
@ -292,13 +291,8 @@ reefnet_sensusultra_packet (reefnet_sensusultra_device_t *device, unsigned char
|
||||
|
||||
|
||||
static device_status_t
|
||||
reefnet_sensusultra_device_handshake (device_t *abstract, unsigned char *data, unsigned int size)
|
||||
reefnet_sensusultra_handshake (reefnet_sensusultra_device_t *device, unsigned char *data, unsigned int size)
|
||||
{
|
||||
reefnet_sensusultra_device_t *device = (reefnet_sensusultra_device_t*) abstract;
|
||||
|
||||
if (! device_is_reefnet_sensusultra (abstract))
|
||||
return DEVICE_STATUS_TYPE_MISMATCH;
|
||||
|
||||
if (size < REEFNET_SENSUSULTRA_HANDSHAKE_SIZE) {
|
||||
WARNING ("Insufficient buffer space available.");
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
@ -364,7 +358,7 @@ reefnet_sensusultra_device_handshake (device_t *abstract, unsigned char *data, u
|
||||
devinfo.model = handshake[1];
|
||||
devinfo.firmware = handshake[0];
|
||||
devinfo.serial = array_uint16_le (handshake + 2);
|
||||
device_event_emit (abstract, DEVICE_EVENT_DEVINFO, &devinfo);
|
||||
device_event_emit (&device->base, DEVICE_EVENT_DEVINFO, &devinfo);
|
||||
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
}
|
||||
@ -407,6 +401,24 @@ reefnet_sensusultra_page (reefnet_sensusultra_device_t *device, unsigned char *d
|
||||
}
|
||||
|
||||
|
||||
static device_status_t
|
||||
reefnet_sensusultra_send (reefnet_sensusultra_device_t *device, unsigned short command)
|
||||
{
|
||||
// Wake-up the device.
|
||||
unsigned char handshake[REEFNET_SENSUSULTRA_HANDSHAKE_SIZE] = {0};
|
||||
device_status_t rc = reefnet_sensusultra_handshake (device, handshake, sizeof (handshake));
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
// Send the instruction code to the device.
|
||||
rc = reefnet_sensusultra_send_ushort (device, command);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
return DEVICE_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static device_status_t
|
||||
reefnet_sensusultra_device_dump (device_t *abstract, unsigned char *data, unsigned int size, unsigned int *result)
|
||||
{
|
||||
@ -425,8 +437,8 @@ reefnet_sensusultra_device_dump (device_t *abstract, unsigned char *data, unsign
|
||||
progress.maximum = REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE;
|
||||
device_event_emit (abstract, DEVICE_EVENT_PROGRESS, &progress);
|
||||
|
||||
// Send the instruction code to the device.
|
||||
device_status_t rc = reefnet_sensusultra_send_ushort (device, 0xB421);
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensusultra_send (device, 0xB421);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
@ -473,8 +485,8 @@ reefnet_sensusultra_device_read_user (device_t *abstract, unsigned char *data, u
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
}
|
||||
|
||||
// Send the instruction code to the device.
|
||||
device_status_t rc = reefnet_sensusultra_send_ushort (device, 0xB420);
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensusultra_send (device, 0xB420);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
@ -512,8 +524,8 @@ reefnet_sensusultra_device_write_user (device_t *abstract, const unsigned char *
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
}
|
||||
|
||||
// Send the instruction code to the device.
|
||||
device_status_t rc = reefnet_sensusultra_send_ushort (device, 0xB430);
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensusultra_send (device, 0xB430);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
@ -569,8 +581,8 @@ reefnet_sensusultra_device_write_parameter (device_t *abstract, reefnet_sensusul
|
||||
return DEVICE_STATUS_ERROR;
|
||||
}
|
||||
|
||||
// Send the instruction code to the device.
|
||||
device_status_t rc = reefnet_sensusultra_send_ushort (device, code);
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensusultra_send (device, code);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
@ -596,8 +608,8 @@ reefnet_sensusultra_device_sense (device_t *abstract, unsigned char *data, unsig
|
||||
return DEVICE_STATUS_MEMORY;
|
||||
}
|
||||
|
||||
// Send the instruction code to the device.
|
||||
device_status_t rc = reefnet_sensusultra_send_ushort (device, 0xB440);
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensusultra_send (device, 0xB440);
|
||||
if (rc != DEVICE_STATUS_SUCCESS)
|
||||
return rc;
|
||||
|
||||
@ -708,8 +720,8 @@ reefnet_sensusultra_device_foreach (device_t *abstract, dive_callback_t callback
|
||||
// Initialize the state for the parsing code.
|
||||
unsigned int previous = REEFNET_SENSUSULTRA_MEMORY_DATA_SIZE;
|
||||
|
||||
// Send the instruction code to the device.
|
||||
device_status_t rc = reefnet_sensusultra_send_ushort (device, 0xB421);
|
||||
// Wake-up the device and send the instruction code.
|
||||
device_status_t rc = reefnet_sensusultra_send (device, 0xB421);
|
||||
if (rc != DEVICE_STATUS_SUCCESS) {
|
||||
free (data);
|
||||
return rc;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user