2013-11-13 07:35:20 +00:00
|
|
|
/*
|
|
|
|
* This file is subject to the terms of the GFX License. If a copy of
|
|
|
|
* the license was not distributed with this file, you can obtain one at:
|
|
|
|
*
|
2018-10-01 15:32:39 +00:00
|
|
|
* http://ugfx.io/license.html
|
2013-11-13 07:35:20 +00:00
|
|
|
*/
|
|
|
|
|
2015-02-20 23:23:33 +00:00
|
|
|
// We need to include stdio.h below. Turn off GFILE_NEED_STDIO just for this file to prevent conflicts
|
|
|
|
#define GFILE_NEED_STDIO_MUST_BE_OFF
|
|
|
|
|
2013-11-13 07:35:20 +00:00
|
|
|
#include "gfx.h"
|
|
|
|
|
|
|
|
#if GFX_USE_GDISP
|
|
|
|
|
|
|
|
#define GDISP_DRIVER_VMT GDISPVMT_uGFXnet
|
2014-09-29 07:51:23 +00:00
|
|
|
#include "gdisp_lld_config.h"
|
2015-11-21 09:27:08 +00:00
|
|
|
#include "../../../src/gdisp/gdisp_driver.h"
|
2014-09-13 04:50:32 +00:00
|
|
|
#include "uGFXnetProtocol.h"
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
#ifndef GDISP_SCREEN_WIDTH
|
|
|
|
#define GDISP_SCREEN_WIDTH 640
|
|
|
|
#endif
|
|
|
|
#ifndef GDISP_SCREEN_HEIGHT
|
|
|
|
#define GDISP_SCREEN_HEIGHT 480
|
|
|
|
#endif
|
|
|
|
#ifndef GDISP_GFXNET_PORT
|
2013-11-15 16:02:45 +00:00
|
|
|
#define GDISP_GFXNET_PORT GNETCODE_DEFAULT_PORT
|
|
|
|
#endif
|
|
|
|
#ifndef GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
2018-02-27 07:44:21 +00:00
|
|
|
#define GDISP_DONT_WAIT_FOR_NET_DISPLAY GFXOFF
|
2013-11-15 16:02:45 +00:00
|
|
|
#endif
|
2013-11-17 10:26:49 +00:00
|
|
|
#ifndef GDISP_GFXNET_UNSAFE_SOCKETS
|
2018-02-27 07:44:21 +00:00
|
|
|
#define GDISP_GFXNET_UNSAFE_SOCKETS GFXOFF
|
2013-11-17 10:26:49 +00:00
|
|
|
#endif
|
2013-11-30 01:13:13 +00:00
|
|
|
#ifndef GDISP_GFXNET_BROKEN_LWIP_ACCEPT
|
2018-02-27 07:44:21 +00:00
|
|
|
#define GDISP_GFXNET_BROKEN_LWIP_ACCEPT GFXOFF
|
2013-11-30 01:13:13 +00:00
|
|
|
#endif
|
2013-11-17 10:26:49 +00:00
|
|
|
|
2014-09-29 07:51:23 +00:00
|
|
|
#if GINPUT_NEED_MOUSE
|
|
|
|
// Include mouse support code
|
|
|
|
#define GMOUSE_DRIVER_VMT GMOUSEVMT_uGFXnet
|
2015-11-21 09:27:08 +00:00
|
|
|
#include "../../../src/ginput/ginput_driver_mouse.h"
|
2014-09-29 07:51:23 +00:00
|
|
|
|
|
|
|
// Forward definitions
|
2018-06-23 03:02:07 +00:00
|
|
|
static gBool NMouseInit(GMouse *m, unsigned driverinstance);
|
|
|
|
static gBool NMouseRead(GMouse *m, GMouseReading *prd);
|
2014-09-29 07:51:23 +00:00
|
|
|
|
|
|
|
const GMouseVMT const GMOUSE_DRIVER_VMT[1] = {{
|
|
|
|
{
|
|
|
|
GDRIVER_TYPE_MOUSE,
|
|
|
|
GMOUSE_VFLG_NOPOLL|GMOUSE_VFLG_DYNAMICONLY,
|
|
|
|
// Extra flags for testing only
|
|
|
|
//GMOUSE_VFLG_TOUCH|GMOUSE_VFLG_SELFROTATION|GMOUSE_VFLG_DEFAULTFINGER
|
|
|
|
//GMOUSE_VFLG_CALIBRATE|GMOUSE_VFLG_CAL_EXTREMES|GMOUSE_VFLG_CAL_TEST|GMOUSE_VFLG_CAL_LOADFREE
|
|
|
|
//GMOUSE_VFLG_ONLY_DOWN|GMOUSE_VFLG_POORUPDOWN
|
|
|
|
sizeof(GMouse),
|
|
|
|
_gmouseInitDriver, _gmousePostInitDriver, _gmouseDeInitDriver
|
|
|
|
},
|
|
|
|
1, // z_max
|
|
|
|
0, // z_min
|
|
|
|
1, // z_touchon
|
|
|
|
0, // z_touchoff
|
|
|
|
{ // pen_jitter
|
|
|
|
0, // calibrate
|
|
|
|
0, // click
|
|
|
|
0 // move
|
|
|
|
},
|
|
|
|
{ // finger_jitter
|
|
|
|
0, // calibrate
|
|
|
|
2, // click
|
|
|
|
2 // move
|
|
|
|
},
|
|
|
|
NMouseInit, // init
|
|
|
|
0, // deinit
|
|
|
|
NMouseRead, // get
|
|
|
|
0, // calsave
|
|
|
|
0 // calload
|
|
|
|
}};
|
|
|
|
#endif
|
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GNETCODE_VERSION != GNETCODE_VERSION_1_0
|
|
|
|
#error "GDISP: uGFXnet - This driver only support protocol V1.0"
|
|
|
|
#endif
|
|
|
|
#if GDISP_LLD_PIXELFORMAT != GNETCODE_PIXELFORMAT
|
|
|
|
#error "GDISP: uGFXnet - The driver pixel format must match the protocol"
|
2013-11-13 07:35:20 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
|
|
|
#if defined(WIN32) || GFX_USE_OS_WIN32
|
|
|
|
#include <winsock.h>
|
2013-11-16 12:50:05 +00:00
|
|
|
#define SOCKET_TYPE SOCKET
|
2014-09-13 04:50:32 +00:00
|
|
|
#define socklen_t int
|
2013-11-13 12:56:13 +00:00
|
|
|
|
|
|
|
static void StopSockets(void) {
|
|
|
|
WSACleanup();
|
|
|
|
}
|
|
|
|
static void StartSockets(void) {
|
|
|
|
WSADATA wsaData;
|
|
|
|
if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0)
|
|
|
|
gfxHalt("GDISP: uGFXnet - WSAStartup failed");
|
|
|
|
atexit(StopSockets);
|
|
|
|
}
|
|
|
|
|
2013-11-16 11:03:46 +00:00
|
|
|
#elif GFX_USE_OS_LINUX || GFX_USE_OS_OSX
|
2013-11-13 07:35:20 +00:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
|
|
|
#include <netdb.h>
|
|
|
|
|
|
|
|
#define closesocket(fd) close(fd)
|
|
|
|
#define ioctlsocket(fd,cmd,arg) ioctl(fd,cmd,arg)
|
2013-11-13 12:56:13 +00:00
|
|
|
#define StartSockets()
|
2013-11-16 12:50:05 +00:00
|
|
|
#define SOCKET_TYPE int
|
2013-11-16 11:03:46 +00:00
|
|
|
|
|
|
|
#else
|
|
|
|
#include <lwip/sockets.h>
|
2013-11-16 14:52:52 +00:00
|
|
|
|
|
|
|
#if GDISP_GFXNET_CUSTOM_LWIP_STARTUP
|
|
|
|
extern void Start_LWIP(void); // Where the application does the lwip stack setup
|
|
|
|
#define StartSockets() Start_LWIP();
|
|
|
|
#else
|
|
|
|
#include "lwipthread.h"
|
2018-07-08 05:32:26 +00:00
|
|
|
#define StartSockets() gfxThreadClose(gfxThreadCreate(wa_lwip_thread, LWIP_THREAD_STACK_SIZE, gThreadpriorityNormal, lwip_thread, 0))
|
2013-11-16 14:52:52 +00:00
|
|
|
#endif
|
|
|
|
|
2013-11-16 11:03:46 +00:00
|
|
|
#if !LWIP_SOCKET
|
|
|
|
#error "GDISP: uGFXnet - LWIP_SOCKETS must be defined in your lwipopts.h file"
|
|
|
|
#endif
|
|
|
|
#if !LWIP_COMPAT_SOCKETS
|
|
|
|
#error "GDISP: uGFXnet - LWIP_COMPAT_SOCKETS must be defined in your lwipopts.h file"
|
|
|
|
#endif
|
2013-11-16 12:50:05 +00:00
|
|
|
#define SOCKET_TYPE int
|
2013-11-17 10:26:49 +00:00
|
|
|
|
|
|
|
// Mutex protection is required for LWIP
|
|
|
|
#if !GDISP_GFXNET_UNSAFE_SOCKETS
|
2017-06-30 09:43:51 +00:00
|
|
|
#if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
|
|
|
|
#warning "GDISP: uGFXnet - LWIP sockets are not thread-safe. GDISP_GFXNET_UNSAFE_SOCKETS has been turned on for you."
|
|
|
|
#elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
|
|
|
|
COMPILER_WARNING("GDISP: uGFXnet - LWIP sockets are not thread-safe. GDISP_GFXNET_UNSAFE_SOCKETS has been turned on for you.")
|
|
|
|
#endif
|
2013-11-17 10:26:49 +00:00
|
|
|
#undef GDISP_GFXNET_UNSAFE_SOCKETS
|
2018-02-27 07:44:21 +00:00
|
|
|
#define GDISP_GFXNET_UNSAFE_SOCKETS GFXON
|
2013-11-17 10:26:49 +00:00
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
#endif
|
|
|
|
|
2014-09-29 07:51:23 +00:00
|
|
|
#define GDISP_FLG_CONNECTED (GDISP_FLG_DRIVER<<0)
|
|
|
|
#define GDISP_FLG_HAVEDATA (GDISP_FLG_DRIVER<<1)
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
/*===========================================================================*/
|
|
|
|
/* Driver local routines . */
|
|
|
|
/*===========================================================================*/
|
|
|
|
|
|
|
|
typedef struct netPriv {
|
2013-11-16 12:50:05 +00:00
|
|
|
SOCKET_TYPE netfd; // The current socket
|
2013-11-13 07:35:20 +00:00
|
|
|
unsigned databytes; // How many bytes have been read
|
|
|
|
uint16_t data[2]; // Buffer for storing data read.
|
|
|
|
#if GINPUT_NEED_MOUSE
|
2018-07-08 00:54:19 +00:00
|
|
|
gCoord mousex, mousey;
|
2013-11-13 07:35:20 +00:00
|
|
|
uint16_t mousebuttons;
|
2014-09-29 07:51:23 +00:00
|
|
|
GMouse * mouse;
|
2013-11-13 07:35:20 +00:00
|
|
|
#endif
|
|
|
|
} netPriv;
|
|
|
|
|
2018-07-08 05:40:27 +00:00
|
|
|
static gThread hThread;
|
2013-11-16 11:03:46 +00:00
|
|
|
|
2013-11-17 10:26:49 +00:00
|
|
|
#if GDISP_GFXNET_UNSAFE_SOCKETS
|
|
|
|
static gfxMutex uGFXnetMutex;
|
|
|
|
#define MUTEX_INIT gfxMutexInit(&uGFXnetMutex)
|
|
|
|
#define MUTEX_ENTER gfxMutexEnter(&uGFXnetMutex)
|
|
|
|
#define MUTEX_EXIT gfxMutexExit(&uGFXnetMutex)
|
|
|
|
#else
|
|
|
|
#define MUTEX_INIT
|
|
|
|
#define MUTEX_ENTER
|
|
|
|
#define MUTEX_EXIT
|
|
|
|
#endif
|
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
/**
|
|
|
|
* Send a whole packet of data.
|
|
|
|
* Len is specified in the number of uint16_t's we want to send as our protocol only talks uint16_t's.
|
|
|
|
* Note that contents of the packet are modified to ensure it will cross the wire in the correct format.
|
2018-06-23 03:02:07 +00:00
|
|
|
* If the connection closes before we send all the data - the call returns gFalse.
|
2013-11-15 16:02:45 +00:00
|
|
|
*/
|
2018-06-23 03:02:07 +00:00
|
|
|
static gBool sendpkt(SOCKET_TYPE netfd, uint16_t *pkt, int len) {
|
2013-11-15 16:02:45 +00:00
|
|
|
int i;
|
|
|
|
|
|
|
|
// Convert each uint16_t to network order
|
|
|
|
for(i = 0; i < len; i++)
|
|
|
|
pkt[i] = htons(pkt[i]);
|
|
|
|
|
|
|
|
// Send it
|
|
|
|
len *= sizeof(uint16_t);
|
|
|
|
return send(netfd, (const char *)pkt, len, 0) == len;
|
|
|
|
}
|
|
|
|
|
2018-06-23 03:02:07 +00:00
|
|
|
static gBool newconnection(SOCKET_TYPE clientfd) {
|
2014-09-29 07:51:23 +00:00
|
|
|
GDisplay * g;
|
|
|
|
netPriv * priv;
|
|
|
|
|
|
|
|
// Look for a display that isn't connected
|
|
|
|
for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
|
|
|
|
// Ignore displays for other controllers
|
|
|
|
#ifdef GDISP_DRIVER_LIST
|
|
|
|
if (gvmt(g) != &GDISPVMT_uGFXnet)
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Was anything found?
|
|
|
|
if (!g)
|
2018-06-23 03:02:07 +00:00
|
|
|
return gFalse;
|
2014-09-29 07:51:23 +00:00
|
|
|
|
|
|
|
// Reset the priv area
|
|
|
|
priv = g->priv;
|
|
|
|
priv->netfd = clientfd;
|
|
|
|
priv->databytes = 0;
|
|
|
|
priv->mousebuttons = 0;
|
|
|
|
|
|
|
|
// Send the initialisation data (2 words at a time)
|
|
|
|
priv->data[0] = GNETCODE_INIT;
|
|
|
|
priv->data[1] = GNETCODE_VERSION;
|
|
|
|
sendpkt(priv->netfd, priv->data, 2);
|
|
|
|
priv->data[0] = GDISP_SCREEN_WIDTH;
|
|
|
|
priv->data[1] = GDISP_SCREEN_HEIGHT;
|
|
|
|
sendpkt(priv->netfd, priv->data, 2);
|
|
|
|
priv->data[0] = GDISP_LLD_PIXELFORMAT;
|
|
|
|
priv->data[1] = 1; // We have a mouse
|
|
|
|
MUTEX_ENTER;
|
|
|
|
sendpkt(priv->netfd, priv->data, 2);
|
|
|
|
MUTEX_EXIT;
|
|
|
|
|
|
|
|
// The display is now working
|
|
|
|
g->flags |= GDISP_FLG_CONNECTED;
|
|
|
|
|
|
|
|
// Send a redraw all
|
|
|
|
#if GFX_USE_GWIN && GWIN_NEED_WINDOWMANAGER
|
|
|
|
gdispGClear(g, gwinGetDefaultBgColor());
|
2018-06-23 03:02:07 +00:00
|
|
|
gwinRedrawDisplay(g, gFalse);
|
2014-09-29 07:51:23 +00:00
|
|
|
#endif
|
|
|
|
|
2018-06-23 03:02:07 +00:00
|
|
|
return gTrue;
|
2014-09-29 07:51:23 +00:00
|
|
|
}
|
|
|
|
|
2018-06-23 03:02:07 +00:00
|
|
|
static gBool rxdata(SOCKET_TYPE fd) {
|
2014-09-29 07:51:23 +00:00
|
|
|
GDisplay * g;
|
|
|
|
netPriv * priv;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
// Look for a display that is connected and the socket descriptor matches
|
|
|
|
for(g = 0; (g = (GDisplay *)gdriverGetNext(GDRIVER_TYPE_DISPLAY, (GDriver *)g));) {
|
|
|
|
// Ignore displays for other controllers
|
|
|
|
#ifdef GDISP_DRIVER_LIST
|
|
|
|
if (gvmt(g) != &GDISPVMT_uGFXnet)
|
|
|
|
continue;
|
|
|
|
#endif
|
|
|
|
priv = g->priv;
|
|
|
|
if ((g->flags & GDISP_FLG_CONNECTED) && priv->netfd == fd)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
if (!g)
|
|
|
|
gfxHalt("GDISP: uGFXnet - Got data from unrecognized connection");
|
|
|
|
|
|
|
|
if ((g->flags & GDISP_FLG_HAVEDATA)) {
|
|
|
|
// The higher level is still processing the previous data.
|
|
|
|
// Give it a chance to run by coming back to this data.
|
|
|
|
gfxSleepMilliseconds(1);
|
2018-06-23 03:02:07 +00:00
|
|
|
return gTrue;
|
2014-09-29 07:51:23 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/* handle data from a client */
|
|
|
|
MUTEX_ENTER;
|
|
|
|
if ((len = recv(fd, ((char *)priv->data)+priv->databytes, sizeof(priv->data)-priv->databytes, 0)) <= 0) {
|
|
|
|
// Socket closed or in error state
|
|
|
|
MUTEX_EXIT;
|
|
|
|
g->flags &= ~GDISP_FLG_CONNECTED;
|
2018-06-23 03:02:07 +00:00
|
|
|
return gFalse;
|
2014-09-29 07:51:23 +00:00
|
|
|
}
|
|
|
|
MUTEX_EXIT;
|
|
|
|
|
|
|
|
// Do we have a full reply yet
|
|
|
|
priv->databytes += len;
|
|
|
|
if (priv->databytes < sizeof(priv->data))
|
2018-06-23 03:02:07 +00:00
|
|
|
return gTrue;
|
2014-09-29 07:51:23 +00:00
|
|
|
priv->databytes = 0;
|
|
|
|
|
|
|
|
// Convert network byte or to host byte order
|
|
|
|
priv->data[0] = ntohs(priv->data[0]);
|
|
|
|
priv->data[1] = ntohs(priv->data[1]);
|
|
|
|
|
|
|
|
// Process the data received
|
|
|
|
switch(priv->data[0]) {
|
|
|
|
#if GINPUT_NEED_MOUSE
|
|
|
|
case GNETCODE_MOUSE_X: priv->mousex = priv->data[1]; break;
|
|
|
|
case GNETCODE_MOUSE_Y: priv->mousey = priv->data[1]; break;
|
|
|
|
case GNETCODE_MOUSE_B:
|
|
|
|
priv->mousebuttons = priv->data[1];
|
|
|
|
// Treat the button event as the sync signal
|
|
|
|
_gmouseWakeup(priv->mouse);
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
case GNETCODE_CONTROL:
|
|
|
|
case GNETCODE_READ:
|
|
|
|
g->flags |= GDISP_FLG_HAVEDATA;
|
|
|
|
break;
|
|
|
|
case GNETCODE_KILL:
|
|
|
|
gfxHalt("GDISP: uGFXnet - Display sent KILL command");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
// Just ignore unrecognised data
|
|
|
|
break;
|
|
|
|
}
|
2018-06-23 03:02:07 +00:00
|
|
|
return gTrue;
|
2014-09-29 07:51:23 +00:00
|
|
|
}
|
|
|
|
|
2013-11-17 10:26:49 +00:00
|
|
|
static DECLARE_THREAD_STACK(waNetThread, 512);
|
2013-11-13 07:35:20 +00:00
|
|
|
static DECLARE_THREAD_FUNCTION(NetThread, param) {
|
2013-11-16 12:50:05 +00:00
|
|
|
SOCKET_TYPE listenfd, fdmax, i, clientfd;
|
2013-11-16 11:03:46 +00:00
|
|
|
socklen_t len;
|
2013-11-13 07:35:20 +00:00
|
|
|
fd_set master, read_fds;
|
2013-11-15 16:02:45 +00:00
|
|
|
struct sockaddr_in addr;
|
2013-11-13 07:35:20 +00:00
|
|
|
(void)param;
|
|
|
|
|
2013-11-13 12:56:13 +00:00
|
|
|
// Start the sockets layer
|
|
|
|
StartSockets();
|
2013-11-16 12:50:05 +00:00
|
|
|
gfxSleepMilliseconds(100); // Make sure the thread has time to start.
|
2013-11-13 12:56:13 +00:00
|
|
|
|
2013-11-13 07:35:20 +00:00
|
|
|
/* clear the master and temp sets */
|
|
|
|
FD_ZERO(&master);
|
|
|
|
FD_ZERO(&read_fds);
|
|
|
|
|
2013-11-16 12:50:05 +00:00
|
|
|
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == (SOCKET_TYPE)-1)
|
2013-11-13 07:35:20 +00:00
|
|
|
gfxHalt("GDISP: uGFXnet - Socket failed");
|
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
memset(&addr, 0, sizeof(addr));
|
|
|
|
addr.sin_family = AF_INET;
|
|
|
|
addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
|
|
|
addr.sin_port = htons(GDISP_GFXNET_PORT);
|
2013-11-13 07:35:20 +00:00
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
if (bind(listenfd, (struct sockaddr*)&addr, sizeof(addr)) == -1)
|
2013-11-13 07:35:20 +00:00
|
|
|
gfxHalt("GDISP: uGFXnet - Bind failed");
|
|
|
|
|
|
|
|
if (listen(listenfd, 10) == -1)
|
|
|
|
gfxHalt("GDISP: uGFXnet - Listen failed");
|
|
|
|
|
|
|
|
|
|
|
|
/* add the listener to the master set */
|
|
|
|
FD_SET(listenfd, &master);
|
|
|
|
|
|
|
|
/* keep track of the biggest file descriptor */
|
|
|
|
fdmax = listenfd; /* so far, it's this one*/
|
|
|
|
|
2013-11-30 01:13:13 +00:00
|
|
|
#if GDISP_GFXNET_BROKEN_LWIP_ACCEPT
|
2017-06-30 09:43:51 +00:00
|
|
|
#if GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_DIRECT
|
|
|
|
#warning "Using GDISP_GFXNET_BROKEN_LWIP_ACCEPT limits the number of displays and the use of GFXNET. Avoid if possible!"
|
|
|
|
#elif GFX_COMPILER_WARNING_TYPE == GFX_COMPILER_WARNING_MACRO
|
|
|
|
COMPILER_WARNING("Using GDISP_GFXNET_BROKEN_LWIP_ACCEPT limits the number of displays and the use of GFXNET. Avoid if possible!")
|
|
|
|
#endif
|
2013-11-30 01:13:13 +00:00
|
|
|
len = sizeof(addr);
|
|
|
|
if((clientfd = accept(listenfd, (struct sockaddr *)&addr, &len)) == (SOCKET_TYPE)-1)
|
|
|
|
gfxHalt("GDISP: uGFXnet - Accept failed");
|
2014-09-29 07:51:23 +00:00
|
|
|
//printf("New connection from %s on socket %d\n", inet_ntoa(addr.sin_addr), clientfd);
|
2013-11-30 01:13:13 +00:00
|
|
|
|
2014-09-29 07:51:23 +00:00
|
|
|
if (!newconnection(clientfd)) {
|
2013-11-30 01:13:13 +00:00
|
|
|
// No Just close the connection
|
|
|
|
closesocket(clientfd);
|
|
|
|
gfxHalt("GDISP: uGFXnet - Can't find display for connection");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save the descriptor
|
|
|
|
FD_SET(clientfd, &master);
|
|
|
|
if (clientfd > fdmax) fdmax = clientfd;
|
|
|
|
#endif
|
|
|
|
|
2013-11-13 07:35:20 +00:00
|
|
|
/* loop */
|
|
|
|
for(;;) {
|
|
|
|
/* copy it */
|
|
|
|
read_fds = master;
|
|
|
|
if (select(fdmax+1, &read_fds, 0, 0, 0) == -1)
|
|
|
|
gfxHalt("GDISP: uGFXnet - Select failed");
|
|
|
|
|
|
|
|
// Run through the existing connections looking for data to be read
|
|
|
|
for(i = 0; i <= fdmax; i++) {
|
|
|
|
if(!FD_ISSET(i, &read_fds))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// Handle new connections
|
|
|
|
if(i == listenfd) {
|
2014-09-29 07:51:23 +00:00
|
|
|
|
|
|
|
// Accept the connection
|
2013-11-15 16:02:45 +00:00
|
|
|
len = sizeof(addr);
|
2013-11-16 12:50:05 +00:00
|
|
|
if((clientfd = accept(listenfd, (struct sockaddr *)&addr, &len)) == (SOCKET_TYPE)-1)
|
2013-11-13 07:35:20 +00:00
|
|
|
gfxHalt("GDISP: uGFXnet - Accept failed");
|
2014-09-29 07:51:23 +00:00
|
|
|
//printf("New connection from %s on socket %d\n", inet_ntoa(addr.sin_addr), clientfd);
|
|
|
|
|
|
|
|
// Can we handle it?
|
|
|
|
if (!newconnection(clientfd)) {
|
2013-11-13 07:35:20 +00:00
|
|
|
|
2014-09-29 07:51:23 +00:00
|
|
|
// No - Just close the connection
|
2013-11-13 07:35:20 +00:00
|
|
|
closesocket(clientfd);
|
2014-09-29 07:51:23 +00:00
|
|
|
|
|
|
|
//printf("Rejected connection as all displays are already connected\n");
|
2013-11-13 07:35:20 +00:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Save the descriptor
|
|
|
|
FD_SET(clientfd, &master);
|
|
|
|
if (clientfd > fdmax) fdmax = clientfd;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handle data from a client
|
2014-09-29 07:51:23 +00:00
|
|
|
if (!rxdata(i)) {
|
2013-11-13 07:35:20 +00:00
|
|
|
closesocket(i);
|
2014-09-29 07:51:23 +00:00
|
|
|
FD_CLR(clientfd, &master);
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*===========================================================================*/
|
|
|
|
/* Driver exported functions. */
|
|
|
|
/*===========================================================================*/
|
|
|
|
|
2018-06-23 03:02:07 +00:00
|
|
|
LLDSPEC gBool gdisp_lld_init(GDisplay *g) {
|
2013-11-13 07:35:20 +00:00
|
|
|
netPriv * priv;
|
|
|
|
|
|
|
|
// Initialise the receiver thread (if it hasn't been done already)
|
|
|
|
if (!hThread) {
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_INIT;
|
2018-07-08 05:32:26 +00:00
|
|
|
hThread = gfxThreadCreate(waNetThread, sizeof(waNetThread), gThreadpriorityHigh, NetThread, 0);
|
2013-11-13 07:35:20 +00:00
|
|
|
gfxThreadClose(hThread);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create a private area for this window
|
2014-02-02 11:59:36 +00:00
|
|
|
if (!(priv = gfxAlloc(sizeof(netPriv))))
|
2013-11-13 07:35:20 +00:00
|
|
|
gfxHalt("GDISP: uGFXnet - Memory allocation failed");
|
|
|
|
memset(priv, 0, sizeof(netPriv));
|
|
|
|
g->priv = priv;
|
|
|
|
g->board = 0; // no board interface for this controller
|
|
|
|
|
2014-09-29 07:51:23 +00:00
|
|
|
// Create the associated mouse
|
|
|
|
#if GINPUT_NEED_MOUSE
|
|
|
|
priv->mouse = (GMouse *)gdriverRegister((const GDriverVMT const *)GMOUSE_DRIVER_VMT, g);
|
|
|
|
#endif
|
|
|
|
|
2013-11-13 07:35:20 +00:00
|
|
|
// Initialise the GDISP structure
|
2018-07-08 03:51:20 +00:00
|
|
|
g->g.Orientation = gOrientation0;
|
2018-07-08 01:47:36 +00:00
|
|
|
g->g.Powermode = gPowerOn;
|
2013-11-13 07:35:20 +00:00
|
|
|
g->g.Backlight = 100;
|
|
|
|
g->g.Contrast = 50;
|
|
|
|
g->g.Width = GDISP_SCREEN_WIDTH;
|
|
|
|
g->g.Height = GDISP_SCREEN_HEIGHT;
|
|
|
|
|
2018-06-23 03:02:07 +00:00
|
|
|
return gTrue;
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#if GDISP_HARDWARE_FLUSH
|
|
|
|
LLDSPEC void gdisp_lld_flush(GDisplay *g) {
|
|
|
|
netPriv * priv;
|
|
|
|
uint16_t buf[1];
|
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
while(!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
gfxSleepMilliseconds(200);
|
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
priv = g->priv;
|
2013-11-15 16:02:45 +00:00
|
|
|
buf[0] = GNETCODE_FLUSH;
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_ENTER;
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 1);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_EXIT;
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if GDISP_HARDWARE_DRAWPIXEL
|
|
|
|
LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) {
|
|
|
|
netPriv * priv;
|
|
|
|
uint16_t buf[4];
|
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
while(!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
gfxSleepMilliseconds(200);
|
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
priv = g->priv;
|
2013-11-15 16:02:45 +00:00
|
|
|
buf[0] = GNETCODE_PIXEL;
|
|
|
|
buf[1] = g->p.x;
|
|
|
|
buf[2] = g->p.y;
|
2013-11-17 13:32:19 +00:00
|
|
|
buf[3] = gdispColor2Native(g->p.color);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_ENTER;
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 4);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_EXIT;
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/* ---- Optional Routines ---- */
|
|
|
|
|
|
|
|
#if GDISP_HARDWARE_FILLS
|
|
|
|
LLDSPEC void gdisp_lld_fill_area(GDisplay *g) {
|
|
|
|
netPriv * priv;
|
|
|
|
uint16_t buf[6];
|
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
while(!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
gfxSleepMilliseconds(200);
|
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
priv = g->priv;
|
2013-11-15 16:02:45 +00:00
|
|
|
buf[0] = GNETCODE_FILL;
|
|
|
|
buf[1] = g->p.x;
|
|
|
|
buf[2] = g->p.y;
|
|
|
|
buf[3] = g->p.cx;
|
|
|
|
buf[4] = g->p.cy;
|
2013-11-17 13:32:19 +00:00
|
|
|
buf[5] = gdispColor2Native(g->p.color);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_ENTER;
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 6);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_EXIT;
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if GDISP_HARDWARE_BITFILLS
|
|
|
|
LLDSPEC void gdisp_lld_blit_area(GDisplay *g) {
|
|
|
|
netPriv * priv;
|
2018-07-08 01:08:55 +00:00
|
|
|
gPixel * buffer;
|
2013-11-13 07:35:20 +00:00
|
|
|
uint16_t buf[5];
|
2018-07-08 00:54:19 +00:00
|
|
|
gCoord x, y;
|
2013-11-13 07:35:20 +00:00
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
while(!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
gfxSleepMilliseconds(200);
|
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
// Make everything relative to the start of the line
|
|
|
|
buffer = g->p.ptr;
|
|
|
|
buffer += g->p.x2*g->p.y1;
|
2014-09-16 22:43:11 +00:00
|
|
|
|
2013-11-13 07:35:20 +00:00
|
|
|
priv = g->priv;
|
2013-11-15 16:02:45 +00:00
|
|
|
buf[0] = GNETCODE_BLIT;
|
|
|
|
buf[1] = g->p.x;
|
|
|
|
buf[2] = g->p.y;
|
|
|
|
buf[3] = g->p.cx;
|
|
|
|
buf[4] = g->p.cy;
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_ENTER;
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 5);
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
for(y = 0; y < g->p.cy; y++, buffer += g->p.x2 - g->p.cx) {
|
|
|
|
for(x = 0; x < g->p.cx; x++, buffer++) {
|
2013-11-17 13:32:19 +00:00
|
|
|
buf[0] = gdispColor2Native(buffer[0]);
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 1);
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
}
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_EXIT;
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if GDISP_HARDWARE_PIXELREAD
|
2018-07-08 01:19:43 +00:00
|
|
|
LLDSPEC gColor gdisp_lld_get_pixel_color(GDisplay *g) {
|
2013-11-13 07:35:20 +00:00
|
|
|
netPriv * priv;
|
|
|
|
uint16_t buf[3];
|
2018-07-08 01:19:43 +00:00
|
|
|
gColor data;
|
2013-11-13 07:35:20 +00:00
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
return 0;
|
|
|
|
#else
|
|
|
|
while(!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
gfxSleepMilliseconds(200);
|
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
priv = g->priv;
|
2013-11-15 16:02:45 +00:00
|
|
|
buf[0] = GNETCODE_READ;
|
|
|
|
buf[1] = g->p.x;
|
|
|
|
buf[2] = g->p.y;
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_ENTER;
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 3);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_EXIT;
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
// Now wait for a reply
|
|
|
|
while(!(g->flags & GDISP_FLG_HAVEDATA) || priv->data[0] != GNETCODE_READ)
|
|
|
|
gfxSleepMilliseconds(1);
|
2014-09-16 22:43:11 +00:00
|
|
|
|
2013-11-17 13:32:19 +00:00
|
|
|
data = gdispNative2Color(priv->data[1]);
|
2013-11-13 07:35:20 +00:00
|
|
|
g->flags &= ~GDISP_FLG_HAVEDATA;
|
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if GDISP_NEED_SCROLL && GDISP_HARDWARE_SCROLL
|
|
|
|
LLDSPEC void gdisp_lld_vertical_scroll(GDisplay *g) {
|
|
|
|
netPriv * priv;
|
|
|
|
uint16_t buf[6];
|
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
while(!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
gfxSleepMilliseconds(200);
|
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
priv = g->priv;
|
2013-11-15 16:02:45 +00:00
|
|
|
buf[0] = GNETCODE_SCROLL;
|
|
|
|
buf[1] = g->p.x;
|
|
|
|
buf[2] = g->p.y;
|
|
|
|
buf[3] = g->p.cx;
|
|
|
|
buf[4] = g->p.cy;
|
|
|
|
buf[5] = g->p.y1;
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_ENTER;
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 6);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_EXIT;
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if GDISP_NEED_CONTROL && GDISP_HARDWARE_CONTROL
|
|
|
|
LLDSPEC void gdisp_lld_control(GDisplay *g) {
|
|
|
|
netPriv * priv;
|
|
|
|
uint16_t buf[3];
|
2018-06-23 03:02:07 +00:00
|
|
|
gBool allgood;
|
2013-11-13 07:35:20 +00:00
|
|
|
|
2013-11-15 16:02:45 +00:00
|
|
|
#if GDISP_DONT_WAIT_FOR_NET_DISPLAY
|
|
|
|
if (!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
return;
|
|
|
|
#else
|
|
|
|
while(!(g->flags & GDISP_FLG_CONNECTED))
|
|
|
|
gfxSleepMilliseconds(200);
|
|
|
|
#endif
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
// Check if we might support the code
|
|
|
|
switch(g->p.x) {
|
|
|
|
case GDISP_CONTROL_ORIENTATION:
|
2018-07-08 03:51:20 +00:00
|
|
|
if (g->g.Orientation == (gOrientation)g->p.ptr)
|
2013-11-13 07:35:20 +00:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
case GDISP_CONTROL_POWER:
|
2018-07-08 01:47:36 +00:00
|
|
|
if (g->g.Powermode == (gPowermode)g->p.ptr)
|
2013-11-13 07:35:20 +00:00
|
|
|
return;
|
|
|
|
break;
|
|
|
|
case GDISP_CONTROL_BACKLIGHT:
|
|
|
|
if (g->g.Backlight == (uint16_t)(int)g->p.ptr)
|
|
|
|
return;
|
|
|
|
if ((uint16_t)(int)g->p.ptr > 100)
|
|
|
|
g->p.ptr = (void *)100;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Send the command
|
|
|
|
priv = g->priv;
|
2013-11-15 16:02:45 +00:00
|
|
|
buf[0] = GNETCODE_CONTROL;
|
|
|
|
buf[1] = g->p.x;
|
|
|
|
buf[2] = (uint16_t)(int)g->p.ptr;
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_ENTER;
|
2013-11-15 16:02:45 +00:00
|
|
|
sendpkt(priv->netfd, buf, 3);
|
2013-11-17 10:26:49 +00:00
|
|
|
MUTEX_EXIT;
|
2013-11-13 07:35:20 +00:00
|
|
|
|
|
|
|
// Now wait for a reply
|
|
|
|
while(!(g->flags & GDISP_FLG_HAVEDATA) || priv->data[0] != GNETCODE_CONTROL)
|
|
|
|
gfxSleepMilliseconds(1);
|
|
|
|
|
|
|
|
// Extract the return status
|
2018-06-23 03:02:07 +00:00
|
|
|
allgood = priv->data[1] ? gTrue : gFalse;
|
2013-11-13 07:35:20 +00:00
|
|
|
g->flags &= ~GDISP_FLG_HAVEDATA;
|
|
|
|
|
|
|
|
// Do nothing more if the operation failed
|
|
|
|
if (!allgood) return;
|
|
|
|
|
|
|
|
// Update the local stuff
|
|
|
|
switch(g->p.x) {
|
|
|
|
case GDISP_CONTROL_ORIENTATION:
|
2018-07-08 03:51:20 +00:00
|
|
|
switch((gOrientation)g->p.ptr) {
|
|
|
|
case gOrientation0:
|
|
|
|
case gOrientation180:
|
2013-11-13 07:35:20 +00:00
|
|
|
g->g.Width = GDISP_SCREEN_WIDTH;
|
|
|
|
g->g.Height = GDISP_SCREEN_HEIGHT;
|
|
|
|
break;
|
2018-07-08 03:51:20 +00:00
|
|
|
case gOrientation90:
|
|
|
|
case gOrientation270:
|
2013-11-13 07:35:20 +00:00
|
|
|
g->g.Height = GDISP_SCREEN_WIDTH;
|
|
|
|
g->g.Width = GDISP_SCREEN_HEIGHT;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
return;
|
|
|
|
}
|
2018-07-08 03:51:20 +00:00
|
|
|
g->g.Orientation = (gOrientation)g->p.ptr;
|
2013-11-13 07:35:20 +00:00
|
|
|
break;
|
|
|
|
case GDISP_CONTROL_POWER:
|
2018-07-08 01:47:36 +00:00
|
|
|
g->g.Powermode = (gPowermode)g->p.ptr;
|
2013-11-13 07:35:20 +00:00
|
|
|
break;
|
|
|
|
case GDISP_CONTROL_BACKLIGHT:
|
|
|
|
g->g.Backlight = (uint16_t)(int)g->p.ptr;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if GINPUT_NEED_MOUSE
|
2018-06-23 03:02:07 +00:00
|
|
|
static gBool NMouseInit(GMouse *m, unsigned driverinstance) {
|
2014-09-29 07:51:23 +00:00
|
|
|
(void) m;
|
|
|
|
(void) driverinstance;
|
2018-06-23 03:02:07 +00:00
|
|
|
return gTrue;
|
2014-09-29 07:51:23 +00:00
|
|
|
}
|
2018-06-23 03:02:07 +00:00
|
|
|
static gBool NMouseRead(GMouse *m, GMouseReading *pt) {
|
2013-11-13 07:35:20 +00:00
|
|
|
GDisplay * g;
|
|
|
|
netPriv * priv;
|
|
|
|
|
2014-09-29 07:51:23 +00:00
|
|
|
g = m->display;
|
2013-11-13 07:35:20 +00:00
|
|
|
priv = g->priv;
|
|
|
|
|
|
|
|
pt->x = priv->mousex;
|
|
|
|
pt->y = priv->mousey;
|
2014-09-29 07:51:23 +00:00
|
|
|
pt->z = (priv->mousebuttons & GINPUT_MOUSE_BTN_LEFT) ? 1 : 0;
|
2013-11-13 07:35:20 +00:00
|
|
|
pt->buttons = priv->mousebuttons;
|
2018-06-23 03:02:07 +00:00
|
|
|
return gTrue;
|
2013-11-13 07:35:20 +00:00
|
|
|
}
|
|
|
|
#endif /* GINPUT_NEED_MOUSE */
|
|
|
|
|
|
|
|
#endif /* GFX_USE_GDISP */
|