Fixes to gdriver to make uGFXnet displays work
This commit is contained in:
parent
0c7c74112e
commit
683ac0ab7f
@ -12,7 +12,7 @@
|
|||||||
#define GDISP_DRIVER_VMT GDISPVMT_uGFXnet
|
#define GDISP_DRIVER_VMT GDISPVMT_uGFXnet
|
||||||
#include "drivers/multiple/uGFXnet/gdisp_lld_config.h"
|
#include "drivers/multiple/uGFXnet/gdisp_lld_config.h"
|
||||||
#include "src/gdisp/driver.h"
|
#include "src/gdisp/driver.h"
|
||||||
#include "drivers/multiple/uGFXnet/uGFXnetProtocol.h"
|
#include "uGFXnetProtocol.h"
|
||||||
|
|
||||||
#ifndef GDISP_SCREEN_WIDTH
|
#ifndef GDISP_SCREEN_WIDTH
|
||||||
#define GDISP_SCREEN_WIDTH 640
|
#define GDISP_SCREEN_WIDTH 640
|
||||||
@ -47,6 +47,7 @@
|
|||||||
#if defined(WIN32) || GFX_USE_OS_WIN32
|
#if defined(WIN32) || GFX_USE_OS_WIN32
|
||||||
#include <winsock.h>
|
#include <winsock.h>
|
||||||
#define SOCKET_TYPE SOCKET
|
#define SOCKET_TYPE SOCKET
|
||||||
|
#define socklen_t int
|
||||||
|
|
||||||
static void StopSockets(void) {
|
static void StopSockets(void) {
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
|
@ -36,6 +36,17 @@
|
|||||||
* @name GDISP hardware accelerated support
|
* @name GDISP hardware accelerated support
|
||||||
* @{
|
* @{
|
||||||
*/
|
*/
|
||||||
|
/**
|
||||||
|
* @brief The display hardware can benefit from being de-initialized when usage is complete.
|
||||||
|
* @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT
|
||||||
|
*
|
||||||
|
* @note HARDWARE_AUTODETECT is only meaningful when GDISP_TOTAL_CONTROLLERS > 1
|
||||||
|
* @note This is most useful for displays such as remote network displays.
|
||||||
|
*/
|
||||||
|
#ifndef GDISP_HARDWARE_DEINIT
|
||||||
|
#define GDISP_HARDWARE_DEINIT HARDWARE_DEFAULT
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The display hardware can benefit from being flushed.
|
* @brief The display hardware can benefit from being flushed.
|
||||||
* @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT
|
* @details Can be set to TRUE, FALSE or HARDWARE_AUTODETECT
|
||||||
@ -215,7 +226,7 @@
|
|||||||
|
|
||||||
struct GDisplay {
|
struct GDisplay {
|
||||||
struct GDriver d; // This must be the first element
|
struct GDriver d; // This must be the first element
|
||||||
#define gvmt(g) ((const GDISPVMT const *)(g)->d.vmt) // For ease of access to the vmt member
|
#define gvmt(g) ((const GDISPVMT const *)((g)->d.vmt)) // For ease of access to the vmt member
|
||||||
|
|
||||||
struct GDISPControl {
|
struct GDISPControl {
|
||||||
coord_t Width;
|
coord_t Width;
|
||||||
@ -278,6 +289,7 @@ struct GDisplay {
|
|||||||
typedef struct GDISPVMT {
|
typedef struct GDISPVMT {
|
||||||
GDriverVMT vmtdriver;
|
GDriverVMT vmtdriver;
|
||||||
bool_t (*init)(GDisplay *g);
|
bool_t (*init)(GDisplay *g);
|
||||||
|
void (*deinit)(GDisplay *g);
|
||||||
void (*writestart)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy
|
void (*writestart)(GDisplay *g); // Uses p.x,p.y p.cx,p.cy
|
||||||
void (*writepos)(GDisplay *g); // Uses p.x,p.y
|
void (*writepos)(GDisplay *g); // Uses p.x,p.y
|
||||||
void (*writecolor)(GDisplay *g); // Uses p.color
|
void (*writecolor)(GDisplay *g); // Uses p.color
|
||||||
@ -318,6 +330,17 @@ typedef struct GDISPVMT {
|
|||||||
*/
|
*/
|
||||||
LLDSPEC bool_t gdisp_lld_init(GDisplay *g);
|
LLDSPEC bool_t gdisp_lld_init(GDisplay *g);
|
||||||
|
|
||||||
|
#if GDISP_HARDWARE_DEINIT || defined(__DOXYGEN__)
|
||||||
|
/**
|
||||||
|
* @brief The driver is being de-initialized
|
||||||
|
* @pre GDISP_HARDWARE_FLUSH is TRUE
|
||||||
|
*
|
||||||
|
* @param[in] g The driver structure
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
LLDSPEC void gdisp_lld_deinit(GDisplay *g);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if GDISP_HARDWARE_FLUSH || defined(__DOXYGEN__)
|
#if GDISP_HARDWARE_FLUSH || defined(__DOXYGEN__)
|
||||||
/**
|
/**
|
||||||
* @brief Flush the current drawing operations to the display
|
* @brief Flush the current drawing operations to the display
|
||||||
@ -559,6 +582,7 @@ typedef struct GDISPVMT {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
#define gdisp_lld_init(g) gvmt(g)->init(g)
|
#define gdisp_lld_init(g) gvmt(g)->init(g)
|
||||||
|
#define gdisp_lld_deinit(g) gvmt(g)->deinit(g)
|
||||||
#define gdisp_lld_flush(g) gvmt(g)->flush(g)
|
#define gdisp_lld_flush(g) gvmt(g)->flush(g)
|
||||||
#define gdisp_lld_write_start(g) gvmt(g)->writestart(g)
|
#define gdisp_lld_write_start(g) gvmt(g)->writestart(g)
|
||||||
#define gdisp_lld_write_pos(g) gvmt(g)->writepos(g)
|
#define gdisp_lld_write_pos(g) gvmt(g)->writepos(g)
|
||||||
@ -594,12 +618,18 @@ typedef struct GDISPVMT {
|
|||||||
|
|
||||||
// Routines needed by the general driver VMT
|
// Routines needed by the general driver VMT
|
||||||
bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance);
|
bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance);
|
||||||
void _gdispDeinitDriver(GDriver *g);
|
void _gdispPostInitDriver(GDriver *g);
|
||||||
|
void _gdispDeInitDriver(GDriver *g);
|
||||||
|
|
||||||
// Build the VMT
|
// Build the VMT
|
||||||
const GDISPVMT const GDISP_DRIVER_VMT[1] = {{
|
const GDISPVMT const GDISP_DRIVER_VMT[1] = {{
|
||||||
{ GDRIVER_TYPE_DISPLAY, 0, sizeof(GDisplay), _gdispInitDriver, _gdispDeinitDriver },
|
{ GDRIVER_TYPE_DISPLAY, 0, sizeof(GDisplay), _gdispInitDriver, _gdispPostInitDriver, _gdispDeInitDriver },
|
||||||
gdisp_lld_init,
|
gdisp_lld_init,
|
||||||
|
#if GDISP_HARDWARE_DEINIT
|
||||||
|
gdisp_lld_deinit,
|
||||||
|
#else
|
||||||
|
0,
|
||||||
|
#endif
|
||||||
#if GDISP_HARDWARE_STREAM_WRITE
|
#if GDISP_HARDWARE_STREAM_WRITE
|
||||||
gdisp_lld_write_start,
|
gdisp_lld_write_start,
|
||||||
#if GDISP_HARDWARE_STREAM_POS
|
#if GDISP_HARDWARE_STREAM_POS
|
||||||
|
@ -55,10 +55,12 @@ GDisplay *GDISP;
|
|||||||
#define MUTEX_INIT(g) gfxMutexInit(&(g)->mutex)
|
#define MUTEX_INIT(g) gfxMutexInit(&(g)->mutex)
|
||||||
#define MUTEX_ENTER(g) gfxMutexEnter(&(g)->mutex)
|
#define MUTEX_ENTER(g) gfxMutexEnter(&(g)->mutex)
|
||||||
#define MUTEX_EXIT(g) gfxMutexExit(&(g)->mutex)
|
#define MUTEX_EXIT(g) gfxMutexExit(&(g)->mutex)
|
||||||
|
#define MUTEX_DEINIT(g) gfxMutexDestroy(&(g)->mutex)
|
||||||
#else
|
#else
|
||||||
#define MUTEX_INIT(g)
|
#define MUTEX_INIT(g)
|
||||||
#define MUTEX_ENTER(g)
|
#define MUTEX_ENTER(g)
|
||||||
#define MUTEX_EXIT(g)
|
#define MUTEX_EXIT(g)
|
||||||
|
#define MUTEX_DEINIT(g)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define NEED_CLIPPING (GDISP_HARDWARE_CLIP != TRUE && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP))
|
#define NEED_CLIPPING (GDISP_HARDWARE_CLIP != TRUE && (GDISP_NEED_VALIDATION || GDISP_NEED_CLIP))
|
||||||
@ -564,18 +566,68 @@ static void line_clip(GDisplay *g) {
|
|||||||
|
|
||||||
void _gdispInit(void)
|
void _gdispInit(void)
|
||||||
{
|
{
|
||||||
|
// Both GDISP_CONTROLLER_LIST and GDISP_CONTROLLER_DISPLAYS are defined - create the required numbers of each controller
|
||||||
|
#if defined(GDISP_CONTROLLER_LIST) && defined(GDISP_CONTROLLER_DISPLAYS)
|
||||||
|
{
|
||||||
|
int i, cnt;
|
||||||
|
|
||||||
|
extern GDriverVMTList GDISP_CONTROLLER_LIST;
|
||||||
|
static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST};
|
||||||
|
static const unsigned dnlist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS};
|
||||||
|
|
||||||
|
for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++) {
|
||||||
|
for(cnt = dnlist[i]; cnt; cnt--)
|
||||||
|
gdriverRegister(dclist[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only GDISP_CONTROLLER_LIST is defined - create one of each controller
|
||||||
|
#elif defined(GDISP_CONTROLLER_LIST)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
extern GDriverVMTList GDISP_CONTROLLER_LIST;
|
||||||
|
static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST};
|
||||||
|
|
||||||
|
for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++)
|
||||||
|
gdriverRegister(dclist[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only GDISP_TOTAL_DISPLAYS is defined - create the required number of the one controller
|
||||||
|
#elif GDISP_TOTAL_DISPLAYS > 1
|
||||||
|
{
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
extern GDriverVMTList GDISPVMT_OnlyOne;
|
||||||
|
|
||||||
|
for(cnt = 0; cnt < GDISP_TOTAL_DISPLAYS; cnt++)
|
||||||
|
gdriverRegister(GDISPVMT_OnlyOne);
|
||||||
|
}
|
||||||
|
|
||||||
|
// One and only one display
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
extern GDriverVMTList GDISPVMT_OnlyOne;
|
||||||
|
|
||||||
|
gdriverRegister(GDISPVMT_OnlyOne);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Re-clear the display after the timeout if we added the logo
|
// Re-clear the display after the timeout if we added the logo
|
||||||
#if GDISP_STARTUP_LOGO_TIMEOUT > 0
|
#if GDISP_STARTUP_LOGO_TIMEOUT > 0
|
||||||
GDisplay *g;
|
{
|
||||||
|
GDisplay *g;
|
||||||
|
|
||||||
gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT);
|
gfxSleepMilliseconds(GDISP_STARTUP_LOGO_TIMEOUT);
|
||||||
initDone = TRUE;
|
|
||||||
|
|
||||||
for(g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, 0); g; g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g)) {
|
for(g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, 0); g; g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g)) {
|
||||||
gdispGClear(g, GDISP_STARTUP_COLOR);
|
gdispGClear(g, GDISP_STARTUP_COLOR);
|
||||||
#if GDISP_HARDWARE_FLUSH
|
#if GDISP_HARDWARE_FLUSH
|
||||||
gdispGFlush(g);
|
gdispGFlush(g);
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
initDone = TRUE;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -605,22 +657,32 @@ bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance) {
|
|||||||
MUTEX_ENTER(gd);
|
MUTEX_ENTER(gd);
|
||||||
ret = gdisp_lld_init(gd);
|
ret = gdisp_lld_init(gd);
|
||||||
MUTEX_EXIT(gd);
|
MUTEX_EXIT(gd);
|
||||||
if (!ret) return FALSE;
|
return ret;
|
||||||
|
|
||||||
// Set orientation, clip, blankscreen, startup logo and then flush
|
#undef gd
|
||||||
|
}
|
||||||
|
|
||||||
|
void _gdispPostInitDriver(GDriver *g) {
|
||||||
|
#define gd ((GDisplay *)g)
|
||||||
|
|
||||||
|
// Set orientation, clip
|
||||||
#if defined(GDISP_DEFAULT_ORIENTATION) && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
|
#if defined(GDISP_DEFAULT_ORIENTATION) && GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
|
||||||
gdispGControl(gd, GDISP_CONTROL_ORIENTATION, (void *)GDISP_DEFAULT_ORIENTATION);
|
gdispGControl(gd, GDISP_CONTROL_ORIENTATION, (void *)GDISP_DEFAULT_ORIENTATION);
|
||||||
#endif
|
#endif
|
||||||
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
|
#if GDISP_NEED_VALIDATION || GDISP_NEED_CLIP
|
||||||
gdispGSetClip(gd, 0, 0, gd->g.Width, gd->g.Height);
|
gdispGSetClip(gd, 0, 0, gd->g.Width, gd->g.Height);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Clear the Screen
|
||||||
gdispGClear(gd, GDISP_STARTUP_COLOR);
|
gdispGClear(gd, GDISP_STARTUP_COLOR);
|
||||||
|
|
||||||
|
// Display the startup logo if this is a static initialised display
|
||||||
#if GDISP_STARTUP_LOGO_TIMEOUT > 0
|
#if GDISP_STARTUP_LOGO_TIMEOUT > 0
|
||||||
if (!initDone)
|
if (!initDone)
|
||||||
StartupLogoDisplay(gd);
|
StartupLogoDisplay(gd);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Flush
|
||||||
#if GDISP_HARDWARE_FLUSH
|
#if GDISP_HARDWARE_FLUSH
|
||||||
gdispGFlush(gd);
|
gdispGFlush(gd);
|
||||||
#endif
|
#endif
|
||||||
@ -629,14 +691,28 @@ bool_t _gdispInitDriver(GDriver *g, int driverinstance, int systeminstance) {
|
|||||||
if (!GDISP)
|
if (!GDISP)
|
||||||
GDISP = gd;
|
GDISP = gd;
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
#undef gd
|
#undef gd
|
||||||
}
|
}
|
||||||
|
|
||||||
void _gdispDeinitDriver(GDriver *g) {
|
void _gdispDeInitDriver(GDriver *g) {
|
||||||
(void) g;
|
#define gd ((GDisplay *)g)
|
||||||
// For now do nothing
|
|
||||||
|
if (GDISP == gd)
|
||||||
|
GDISP = (GDisplay *)gdriverGetInstance(GDRIVER_TYPE_DISPLAY, 0);
|
||||||
|
|
||||||
|
#if GDISP_HARDWARE_DEINIT
|
||||||
|
#if GDISP_HARDWARE_DEINIT == HARDWARE_AUTODETECT
|
||||||
|
if (gvmt(gd)->deinit)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
MUTEX_ENTER(gd);
|
||||||
|
gdisp_lld_deinit(gd);
|
||||||
|
MUTEX_EXIT(gd);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
MUTEX_DEINIT(gd);
|
||||||
|
|
||||||
|
#undef gd
|
||||||
}
|
}
|
||||||
|
|
||||||
GDisplay *gdispGetDisplay(unsigned display) {
|
GDisplay *gdispGetDisplay(unsigned display) {
|
||||||
|
@ -14,51 +14,8 @@
|
|||||||
// Define the tables to hold the driver instances.
|
// Define the tables to hold the driver instances.
|
||||||
static GDriver *dhead;
|
static GDriver *dhead;
|
||||||
|
|
||||||
// Definition that allows getting addresses of structures
|
|
||||||
typedef const struct GDriverVMT const VMT_EL[1];
|
|
||||||
|
|
||||||
// The system initialization.
|
// The system initialization.
|
||||||
void _gdriverInit(void) {
|
void _gdriverInit(void) {
|
||||||
#if GFX_USE_GDISP
|
|
||||||
{
|
|
||||||
// Both GDISP_CONTROLLER_LIST and GDISP_CONTROLLER_DISPLAYS are defined - create the required numbers of each controller
|
|
||||||
#if defined(GDISP_CONTROLLER_LIST) && defined(GDISP_CONTROLLER_DISPLAYS)
|
|
||||||
int i, cnt;
|
|
||||||
|
|
||||||
|
|
||||||
extern VMT_EL GDISP_CONTROLLER_LIST;
|
|
||||||
static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST};
|
|
||||||
static const unsigned dnlist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_DISPLAYS};
|
|
||||||
for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++) {
|
|
||||||
for(cnt = dnlist[i]; cnt; cnt--)
|
|
||||||
gdriverRegister(dclist[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only GDISP_CONTROLLER_LIST is defined - create one of each controller
|
|
||||||
#elif defined(GDISP_CONTROLLER_LIST)
|
|
||||||
int i;
|
|
||||||
|
|
||||||
|
|
||||||
extern VMT_EL GDISP_CONTROLLER_LIST;
|
|
||||||
static const struct GDriverVMT const * dclist[GDISP_TOTAL_CONTROLLERS] = {GDISP_CONTROLLER_LIST};
|
|
||||||
for(i = 0; i < GDISP_TOTAL_CONTROLLERS; i++)
|
|
||||||
gdriverRegister(dclist[i]);
|
|
||||||
|
|
||||||
// Only GDISP_TOTAL_DISPLAYS is defined - create the required number of the one controller
|
|
||||||
#elif GDISP_TOTAL_DISPLAYS > 1
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
extern VMT_EL GDISPVMT_OnlyOne;
|
|
||||||
for(cnt = 0; cnt < GDISP_TOTAL_DISPLAYS; cnt++)
|
|
||||||
gdriverRegister(GDISPVMT_OnlyOne);
|
|
||||||
|
|
||||||
// One and only one display
|
|
||||||
#else
|
|
||||||
extern VMT_EL GDISPVMT_OnlyOne;
|
|
||||||
gdriverRegister(GDISPVMT_OnlyOne);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Drivers not loaded yet
|
// Drivers not loaded yet
|
||||||
// GINPUT_NEED_MOUSE
|
// GINPUT_NEED_MOUSE
|
||||||
@ -107,6 +64,10 @@ GDriver *gdriverRegister(const GDriverVMT *vmt) {
|
|||||||
else
|
else
|
||||||
dhead = pd;
|
dhead = pd;
|
||||||
|
|
||||||
|
// Do the post init
|
||||||
|
if (vmt->postinit)
|
||||||
|
vmt->postinit(pd);
|
||||||
|
|
||||||
return pd;
|
return pd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,12 +67,27 @@ typedef struct GDriverVMT {
|
|||||||
uint16_t type; // @< What type of driver this is
|
uint16_t type; // @< What type of driver this is
|
||||||
uint16_t flags; // @< Flags for the driver. Meaning is specific to each driver type.
|
uint16_t flags; // @< Flags for the driver. Meaning is specific to each driver type.
|
||||||
uint32_t objsize; // @< How big the runtime driver structure is
|
uint32_t objsize; // @< How big the runtime driver structure is
|
||||||
bool_t (*init)(GDriver *driver, int driverinstance, int systeminstance); // @< Initialise the driver.
|
bool_t (*init)(GDriver *driver, int driverinstance, int systeminstance); // @< Initialise the driver. Returns TRUE if OK.
|
||||||
// driverinstance is the instance 0..n of this driver.
|
// driverinstance is the instance 0..n of this driver.
|
||||||
// systeminstance is the instance 0..n of this type of device.
|
// systeminstance is the instance 0..n of this type of device.
|
||||||
|
void (*postinit)(GDriver *driver); // @< Called once the driver is registered.
|
||||||
void (*deinit)(GDriver *driver); // @< De-initialise the driver
|
void (*deinit)(GDriver *driver); // @< De-initialise the driver
|
||||||
} GDriverVMT;
|
} GDriverVMT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief A definition that allows getting addresses of GDriverVMT structures to put into a list.
|
||||||
|
* @note eg. <code>
|
||||||
|
* const MyDriverVMTtype a[1] = {{...}};
|
||||||
|
* const MyDriverVMTtype b[1] = {{...}};
|
||||||
|
* ...
|
||||||
|
* #define DRIVER_LIST a, b
|
||||||
|
* extern GDriverVMTList DRIVER_LIST; // Now treated as single element arrays of GDriverVMT
|
||||||
|
* const GDriverVMT const * mylist = { DRIVER_LIST };
|
||||||
|
* </code>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
typedef const struct GDriverVMT const GDriverVMTList[1];
|
||||||
|
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
/* External declarations. */
|
/* External declarations. */
|
||||||
/*===========================================================================*/
|
/*===========================================================================*/
|
||||||
|
Loading…
Reference in New Issue
Block a user