From nobody Mon Apr 29 16:13:46 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zoho.com; dkim=fail spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1495504361738279.25252737184746; Mon, 22 May 2017 18:52:41 -0700 (PDT) Received: from localhost ([::1]:45627 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dCz04-0004mP-AS for importer@patchew.org; Mon, 22 May 2017 21:52:40 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:41123) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dCyz7-0004Ci-FY for qemu-devel@nongnu.org; Mon, 22 May 2017 21:51:44 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dCyz3-0002UT-HM for qemu-devel@nongnu.org; Mon, 22 May 2017 21:51:41 -0400 Received: from nm38-vm8.bullet.mail.ir2.yahoo.com ([212.82.97.158]:55004) by eggs.gnu.org with esmtps (TLS1.0:RSA_ARCFOUR_SHA1:16) (Exim 4.71) (envelope-from ) id 1dCyz3-0002UN-3B for qemu-devel@nongnu.org; Mon, 22 May 2017 21:51:37 -0400 Received: from [212.82.98.52] by nm38.bullet.mail.ir2.yahoo.com with NNFMP; 23 May 2017 01:51:35 -0000 Received: from [46.228.39.107] by tm5.bullet.mail.ir2.yahoo.com with NNFMP; 23 May 2017 01:51:35 -0000 Received: from [127.0.0.1] by smtp144.mail.ir2.yahoo.com with NNFMP; 23 May 2017 01:51:35 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rocketmail.com; s=s2048; t=1495504295; bh=+rFl87kmDerctivNqjQIrJkKOx6qJ2kooHT4acvbxtI=; h=Date:From:CC:To:Subject:From:Subject; b=HWHidvA6OjOXCxg26f6jlPAQCDejhfyHxjchuIQCUUGLUTZeo2tAN47zLyMYWu60i3UMX3pRSHm6dOyDC7phciBahDjMA0gUfx5jewJrg6NZB15qaHPv8YjBtmvJ+s0xltjfHFgfEQ6mMBodD6HyelTpYTlyDwRFp34iADmwbGmMsXaKdHIJc7gyks8HRtVf9R07LzvNhbxalLflBO/YnpskOocQILbcYAXRySl+/7fHku23JGP6hoQcjxRLBEeU1g8RZhInKFxmwGnXKijigtHVZVIRkSkBItKYtd1rbpZXSOjVakjbaGJ8kFNCRQaoifPxb4DYhr4VVhKBpQEtfQ== X-Yahoo-Newman-Id: 837729.54934.bm@smtp144.mail.ir2.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: Mctdqz0VM1mkfpRs4j0emakp4NnrJH8FlrTK6UkNidVqzqz n9XF7c8hhRyrzf5XHx2G4m.CERh_Rmc7E1hkZ4k_ZY0wnCSM5d3EcrY61tsr VHWHrcBmOQae8NVBXTehDu5W0vJP.Np_9NCj.u0mLohJhiQLItDfdG7l17Ov MSprQsHlRm9VfSxI0kqUCuctlZZYL42dhaB1g4hj_WsaEaGnvgcEjT4ZQoMg mh4Lvs2L0BxnazLqnVsShQCAgjA4xUA1clXklmFBNauXU.i14lBOGz9zRAgV BvIPmOzNfVgzN0I.32meUbprALWbdUZiSLFOHB49OrhRyfCjrjcpxfcdsnV7 aNBsIAnOcqdre514N3tXNvwCQArKY9tNLQrxolSIhMlwkaaHfYV2qTi7KH1b 5NJ66pZ8eZxtpFqU6_kYytYG.8zBYXAC2ksvoQu2qRfoDzKiAbEQbg2Ql.Pz 6Ck2Ca.oMkuqJlsrTu_24ChFBviLdatDptycoU8eru5DLbMdEhzHQrUTfW3A 2j0h.WsGy83lVIgqmzmjzx8rJRyX7N4f.VeGYpRh8.Zd7ty.RnubWo5I.Idh zTKlCHZpyhHDFtZ.d X-Yahoo-SMTP: Zay5iG2swBBwBjVsWquSqCXzMrQnnj5rR6LdlZsQ7MCyug-- Date: Tue, 23 May 2017 02:51:34 +0000 To: Message-ID: X-Mailer: TortoiseGit MIME-Version: 1.0 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 3.x [fuzzy] X-Received-From: 212.82.97.158 Subject: [Qemu-devel] [PATCH V2] Add code to connect to external panel, for ARM X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: John Bradley via Qemu-devel Reply-To: John Bradley Cc: flypie@rocketmail.com, peter.maydell@linaro.org, qemu-arm@nongnu.org, qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; ; charset="utf-8" From 5f5c186162ef5f56872095318106e9fe360ae310 Mon Sep 17 00:00:00 2001 From: John Bradley Date: Tue, 23 May 2017 01:43:32 +0100 Subject: [PATCH] Add code to connect to external panel, for ARM Has no effect if panel not found. GDummyPanel Fix formating issues. Add inital discussion of protocol version. Add code to connect with https://github.com/flypie/GDummyPanel The code use= s GNU Sockets & Windows sockets as on MINGW GNU no available. This is inteded as a Demo for RFC. Signed-off-by: John Bradley --- hw/gpio/bcm2835_gpio.c | 136 +++++++++++------ include/hw/gpio/bcm2835_gpio.h | 4 + include/qemu/PanelEmu.h | 53 +++++++ util/Makefile.objs | 1 + util/PanelEmu.c | 326 +++++++++++++++++++++++++++++++++++++= ++++ 5 files changed, 479 insertions(+), 41 deletions(-) create mode 100644 include/qemu/PanelEmu.h create mode 100644 util/PanelEmu.c diff --git a/hw/gpio/bcm2835_gpio.c b/hw/gpio/bcm2835_gpio.c index acc2e3cf9e..5df3f4cddf 100644 --- a/hw/gpio/bcm2835_gpio.c +++ b/hw/gpio/bcm2835_gpio.c @@ -19,6 +19,8 @@ #include "hw/sd/sd.h" #include "hw/gpio/bcm2835_gpio.h" =20 + + #define GPFSEL0 0x00 #define GPFSEL1 0x04 #define GPFSEL2 0x08 @@ -75,24 +77,24 @@ static void gpfsel_set(BCM2835GpioState *s, uint8_t reg= , uint32_t value) =20 /* SD controller selection (48-53) */ if (s->sd_fsel !=3D 0 - && (s->fsel[48] =3D=3D 0) /* SD_CLK_R */ - && (s->fsel[49] =3D=3D 0) /* SD_CMD_R */ - && (s->fsel[50] =3D=3D 0) /* SD_DATA0_R */ - && (s->fsel[51] =3D=3D 0) /* SD_DATA1_R */ - && (s->fsel[52] =3D=3D 0) /* SD_DATA2_R */ - && (s->fsel[53] =3D=3D 0) /* SD_DATA3_R */ - ) { + && (s->fsel[48] =3D=3D 0) /* SD_CLK_R */ + && (s->fsel[49] =3D=3D 0) /* SD_CMD_R */ + && (s->fsel[50] =3D=3D 0) /* SD_DATA0_R */ + && (s->fsel[51] =3D=3D 0) /* SD_DATA1_R */ + && (s->fsel[52] =3D=3D 0) /* SD_DATA2_R */ + && (s->fsel[53] =3D=3D 0) /* SD_DATA3_R */ + ) { /* SDHCI controller selected */ sdbus_reparent_card(s->sdbus_sdhost, s->sdbus_sdhci); s->sd_fsel =3D 0; } else if (s->sd_fsel !=3D 4 - && (s->fsel[48] =3D=3D 4) /* SD_CLK_R */ - && (s->fsel[49] =3D=3D 4) /* SD_CMD_R */ - && (s->fsel[50] =3D=3D 4) /* SD_DATA0_R */ - && (s->fsel[51] =3D=3D 4) /* SD_DATA1_R */ - && (s->fsel[52] =3D=3D 4) /* SD_DATA2_R */ - && (s->fsel[53] =3D=3D 4) /* SD_DATA3_R */ - ) { + && (s->fsel[48] =3D=3D 4) /* SD_CLK_R */ + && (s->fsel[49] =3D=3D 4) /* SD_CMD_R */ + && (s->fsel[50] =3D=3D 4) /* SD_DATA0_R */ + && (s->fsel[51] =3D=3D 4) /* SD_DATA1_R */ + && (s->fsel[52] =3D=3D 4) /* SD_DATA2_R */ + && (s->fsel[53] =3D=3D 4) /* SD_DATA3_R */ + ) { /* SDHost controller selected */ sdbus_reparent_card(s->sdbus_sdhci, s->sdbus_sdhost); s->sd_fsel =3D 4; @@ -108,7 +110,7 @@ static int gpfsel_is_out(BCM2835GpioState *s, int index) } =20 static void gpset(BCM2835GpioState *s, - uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) + uint32_t val, uint8_t start, uint8_t count, uint32_t *le= v) { uint32_t changes =3D val & ~*lev; uint32_t cur =3D 1; @@ -125,7 +127,7 @@ static void gpset(BCM2835GpioState *s, } =20 static void gpclr(BCM2835GpioState *s, - uint32_t val, uint8_t start, uint8_t count, uint32_t *lev) + uint32_t val, uint8_t start, uint8_t count, uint32_t *le= v) { uint32_t changes =3D val & *lev; uint32_t cur =3D 1; @@ -141,11 +143,12 @@ static void gpclr(BCM2835GpioState *s, *lev &=3D ~val; } =20 -static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset, - unsigned size) +static uint64_t bcm2835_gpio_read(void *opaque, hwaddr offset, unsigned si= ze) { BCM2835GpioState *s =3D (BCM2835GpioState *)opaque; =20 + uint64_t Data; + switch (offset) { case GPFSEL0: case GPFSEL1: @@ -163,8 +166,20 @@ static uint64_t bcm2835_gpio_read(void *opaque, hwaddr= offset, /* Write Only */ return 0; case GPLEV0: + if (s->panel.socket !=3D -1) { + if (panel_read(&s->panel, &Data)) { + s->lev0 =3D (uint32_t)Data; + s->lev1 =3D (uint32_t)(Data >> 32); + } + } return s->lev0; case GPLEV1: + if (s->panel.socket !=3D -1) { + if (panel_read(&s->panel, &Data)) { + s->lev0 =3D (uint32_t)Data; + s->lev1 =3D (uint32_t)(Data >> 32); + } + } return s->lev1; case GPEDS0: case GPEDS1: @@ -187,7 +202,7 @@ static uint64_t bcm2835_gpio_read(void *opaque, hwaddr = offset, return 0; default: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); + __func__, offset); break; } =20 @@ -195,9 +210,11 @@ static uint64_t bcm2835_gpio_read(void *opaque, hwaddr= offset, } =20 static void bcm2835_gpio_write(void *opaque, hwaddr offset, - uint64_t value, unsigned size) + uint64_t value, unsigned size) { BCM2835GpioState *s =3D (BCM2835GpioState *)opaque; + uint64_t Data; + =20 switch (offset) { case GPFSEL0: @@ -210,15 +227,37 @@ static void bcm2835_gpio_write(void *opaque, hwaddr o= ffset, break; case GPSET0: gpset(s, value, 0, 32, &s->lev0); + if (s->panel.socket !=3D -1) { + Data =3D value; + /* John Bradley dummy GPIO Panel */ + senddatatopanel(&s->panel, Data, true); + } break; case GPSET1: gpset(s, value, 32, 22, &s->lev1); + if (s->panel.socket !=3D -1) { + Data =3D value; + Data <<=3D 32; + /* John Bradley dummy GPIO Panel */ + senddatatopanel(&s->panel, Data, true); + } break; case GPCLR0: gpclr(s, value, 0, 32, &s->lev0); + if (s->panel.socket !=3D -1) { + Data =3D value; + /* John Bradley dummy GPIO Panel */ + senddatatopanel(&s->panel, Data, false); + } break; case GPCLR1: gpclr(s, value, 32, 22, &s->lev1); + if (s->panel.socket !=3D -1) { + Data =3D value; + Data <<=3D 32; + /* John Bradley dummy GPIO Panel */ + senddatatopanel(&s->panel, Data, false); + } break; case GPLEV0: case GPLEV1: @@ -250,7 +289,7 @@ static void bcm2835_gpio_write(void *opaque, hwaddr off= set, =20 err_out: qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); + __func__, offset); } =20 static void bcm2835_gpio_reset(DeviceState *dev) @@ -272,21 +311,22 @@ static void bcm2835_gpio_reset(DeviceState *dev) } =20 static const MemoryRegionOps bcm2835_gpio_ops =3D { - .read =3D bcm2835_gpio_read, - .write =3D bcm2835_gpio_write, - .endianness =3D DEVICE_NATIVE_ENDIAN, + .read =3D bcm2835_gpio_read, + .write =3D bcm2835_gpio_write, + .endianness =3D DEVICE_NATIVE_ENDIAN, }; =20 static const VMStateDescription vmstate_bcm2835_gpio =3D { - .name =3D "bcm2835_gpio", - .version_id =3D 1, - .minimum_version_id =3D 1, - .fields =3D (VMStateField[]) { - VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54), - VMSTATE_UINT32(lev0, BCM2835GpioState), - VMSTATE_UINT32(lev1, BCM2835GpioState), - VMSTATE_UINT8(sd_fsel, BCM2835GpioState), - VMSTATE_END_OF_LIST() + .name =3D "bcm2835_gpio", + .version_id =3D 1, + .minimum_version_id =3D 1, + .fields =3D (VMStateField[]) + { + VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54), + VMSTATE_UINT32(lev0, BCM2835GpioState), + VMSTATE_UINT32(lev1, BCM2835GpioState), + VMSTATE_UINT8(sd_fsel, BCM2835GpioState), + VMSTATE_END_OF_LIST() } }; =20 @@ -300,9 +340,23 @@ static void bcm2835_gpio_init(Object *obj) TYPE_SD_BUS, DEVICE(s), "sd-bus"); =20 memory_region_init_io(&s->iomem, obj, - &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000); + &bcm2835_gpio_ops, s, "bcm2835_gpio", 0x1000); sysbus_init_mmio(sbd, &s->iomem); qdev_init_gpio_out(dev, s->out, 54); + + /* Get access to the GPIO panel, program will quit on fail */ + if (panel_open(&s->panel)) { + /* PI Has 54 Pins */ + sendpincount(&s->panel, 54); + /* Pins 0 & 1 are I2C so disable */ + sendenabledmap(&s->panel, 0x003FFFFFFFFFFFFC); + /* There are no dedicated input pins I know of */ + sendinputmap(&s->panel, 0x0000000000000000); + /* Pin 53 is dedicated output LED */ + sendoutputmap(&s->panel, 0x0000800000000000); + } else { + printf("Couldn't connect to a GPIO panel\n"); + } } =20 static void bcm2835_gpio_realize(DeviceState *dev, Error **errp) @@ -314,7 +368,7 @@ static void bcm2835_gpio_realize(DeviceState *dev, Erro= r **errp) obj =3D object_property_get_link(OBJECT(dev), "sdbus-sdhci", &err); if (obj =3D=3D NULL) { error_setg(errp, "%s: required sdhci link not found: %s", - __func__, error_get_pretty(err)); + __func__, error_get_pretty(err)); return; } s->sdbus_sdhci =3D SD_BUS(obj); @@ -322,7 +376,7 @@ static void bcm2835_gpio_realize(DeviceState *dev, Erro= r **errp) obj =3D object_property_get_link(OBJECT(dev), "sdbus-sdhost", &err); if (obj =3D=3D NULL) { error_setg(errp, "%s: required sdhost link not found: %s", - __func__, error_get_pretty(err)); + __func__, error_get_pretty(err)); return; } s->sdbus_sdhost =3D SD_BUS(obj); @@ -338,11 +392,11 @@ static void bcm2835_gpio_class_init(ObjectClass *klas= s, void *data) } =20 static const TypeInfo bcm2835_gpio_info =3D { - .name =3D TYPE_BCM2835_GPIO, - .parent =3D TYPE_SYS_BUS_DEVICE, - .instance_size =3D sizeof(BCM2835GpioState), - .instance_init =3D bcm2835_gpio_init, - .class_init =3D bcm2835_gpio_class_init, + .name =3D TYPE_BCM2835_GPIO, + .parent =3D TYPE_SYS_BUS_DEVICE, + .instance_size =3D sizeof(BCM28= 35GpioState), + .instance_init =3D bcm2835_gpio= _init, + .class_init =3D bcm2835_gpio_cl= ass_init, }; =20 static void bcm2835_gpio_register_types(void) diff --git a/include/hw/gpio/bcm2835_gpio.h b/include/hw/gpio/bcm2835_gpio.h index 9f8e0c720c..f7d7c79aa2 100644 --- a/include/hw/gpio/bcm2835_gpio.h +++ b/include/hw/gpio/bcm2835_gpio.h @@ -15,6 +15,7 @@ #define BCM2835_GPIO_H =20 #include "hw/sd/sd.h" +#include "qemu/PanelEmu.h" =20 typedef struct BCM2835GpioState { SysBusDevice parent_obj; @@ -30,6 +31,9 @@ typedef struct BCM2835GpioState { uint32_t lev0, lev1; uint8_t sd_fsel; qemu_irq out[54]; + + panel_connection_t panel; + } BCM2835GpioState; =20 #define TYPE_BCM2835_GPIO "bcm2835_gpio" diff --git a/include/qemu/PanelEmu.h b/include/qemu/PanelEmu.h new file mode 100644 index 0000000000..1d97a80492 --- /dev/null +++ b/include/qemu/PanelEmu.h @@ -0,0 +1,53 @@ +/* + * To change this license header, choose License Headers in Project Proper= ties. + * To change this template file, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * File: PanelEmu.h + * Author: John Bradley + * + * Created on 22 April 2017, 22:26 + */ + +#ifndef PANELEMU_H +#define PANELEMU_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#define DRIVER_NAME "RDC-GPIO: " +#define PANEL_NAME "GPIO panel: " + + +#define DEFAULT_PORT 0xb1ff /*45567*/ + +#define PANEL_PINS 54 + + typedef struct panel_connection { + int socket; /* socket we'll connect to the panel with */ + fd_set fds; /* list of descriptors (only the above socket */ + char last[PANEL_PINS / 8]; /* we don't want to send updates to the= panel + unless something changed */ + int ProtocolInUse; /*What version of the protocol are we using. */ + } panel_connection_t; + + bool panel_open(panel_connection_t *h); + + bool panel_read(panel_connection_t *h, uint64_t *pinS); + void senddatatopanel(panel_connection_t *h, uint64_t pinS, bool Value); + void panel_send_read_command(panel_connection_t *h); + void sendpincount(panel_connection_t *h, int Num); + void sendenabledmap(panel_connection_t *h, uint64_t pins); + void sendinputmap(panel_connection_t *h, uint64_t pins); + void sendoutputmap(panel_connection_t *h, uint64_t pins); + +#ifdef __cplusplus +} +#endif + +#endif /* PANELEMU_H */ + diff --git a/util/Makefile.objs b/util/Makefile.objs index c6205ebf86..8316ed79ba 100644 --- a/util/Makefile.objs +++ b/util/Makefile.objs @@ -43,3 +43,4 @@ util-obj-y +=3D qdist.o util-obj-y +=3D qht.o util-obj-y +=3D range.o util-obj-y +=3D systemd.o +util-obj-y +=3D PanelEmu.o \ No newline at end of file diff --git a/util/PanelEmu.c b/util/PanelEmu.c new file mode 100644 index 0000000000..1aa29c6479 --- /dev/null +++ b/util/PanelEmu.c @@ -0,0 +1,326 @@ +/* + * Emulation for Rasp PI GPIO via Server connected to via Socket + * + */ +#include "qemu/osdep.h" + +#include +#include +#include +#include +#include +#include +#ifdef __MINGW32__ +#include +#else +#include +#include +#include +#endif + +#include "qemu/PanelEmu.h" + +typedef enum { + PROTOCOLDESCFROMQEMU =3D 0, + PROTOCOLDESCFROMPANEL =3D 1, + PINSTOPANEL =3D 2, + READREQ =3D 3, + PINCOUNT =3D 4, + ENABLEMAP =3D 5, + INPUTMAP =3D 6, + OUTPUTMAP =3D 7, + PINSTOQEMU =3D 8 +} PacketType; + +#define MINPROTOCOL 0 +#define MAXPROTOCOL 0 + +#define MAXPACKET 255 + +#define PACKETLEN 0 /* Includes Packet Length */ +#define PACKETTYPE 1 + +typedef struct { + unsigned short int Data[MAXPACKET]; +} CommandPacket; + +static void panel_command(panel_connection_t *h, CommandPacket *Pkt); + +static void panel_send_protocol_command(panel_connection_t *h) +{ + CommandPacket Pkt; + + Pkt.Data[PACKETLEN] =3D 8; + Pkt.Data[PACKETTYPE] =3D PROTOCOLDESCFROMQEMU; + Pkt.Data[2] =3D MINPROTOCOL; + Pkt.Data[3] =3D MAXPROTOCOL; + + panel_command(h, &Pkt); +} + +void panel_send_read_command(panel_connection_t *h) +{ + CommandPacket Pkt; + + Pkt.Data[PACKETLEN] =3D 4; + Pkt.Data[PACKETTYPE] =3D READREQ; + + panel_command(h, &Pkt); +} + +/* Set a pin to a specified value */ +void senddatatopanel(panel_connection_t *h, uint64_t pin, bool val) +{ + CommandPacket Pkt; + + Pkt.Data[PACKETLEN] =3D (char *)&Pkt.Data[6 + 1] - (char *)&Pkt.Data[0= ]; + Pkt.Data[PACKETTYPE] =3D PINSTOPANEL; + Pkt.Data[2] =3D (unsigned short int)(pin & 0xFFFF); + Pkt.Data[3] =3D (unsigned short int)((pin >> 16) & 0xFFFF); + Pkt.Data[4] =3D (unsigned short int)(pin >> 32 & 0xFFFF); + Pkt.Data[5] =3D (unsigned short int)((pin >> 48) & 0xFFFF); + Pkt.Data[6] =3D val; + + panel_command(h, &Pkt); +} + +void sendpincount(panel_connection_t *h, int val) +{ + CommandPacket Pkt; + + Pkt.Data[PACKETLEN] =3D (char *)&Pkt.Data[2 + 1] - (char *)&Pkt.Data[0= ]; + Pkt.Data[PACKETTYPE] =3D PINCOUNT; + Pkt.Data[2] =3D val; + + panel_command(h, &Pkt); +} + +void sendenabledmap(panel_connection_t *h, uint64_t pin) +{ + CommandPacket Pkt; + + Pkt.Data[PACKETLEN] =3D (char *)&Pkt.Data[5 + 1] - (char *)&Pkt.Data[0= ]; + Pkt.Data[PACKETTYPE] =3D ENABLEMAP; + Pkt.Data[2] =3D (unsigned short int)(pin & 0xFFFF); + Pkt.Data[3] =3D (unsigned short int)((pin >> 16) & 0xFFFF); + Pkt.Data[4] =3D (unsigned short int)(pin >> 32 & 0xFFFF); + Pkt.Data[5] =3D (unsigned short int)((pin >> 48) & 0xFFFF); + + panel_command(h, &Pkt); +} + +void sendinputmap(panel_connection_t *h, uint64_t pin) +{ + CommandPacket Pkt; + + Pkt.Data[PACKETLEN] =3D (char *)&Pkt.Data[5 + 1] - (char *)&Pkt.Data[0= ]; + Pkt.Data[PACKETTYPE] =3D INPUTMAP; + Pkt.Data[2] =3D (unsigned short int)(pin & 0xFFFF); + Pkt.Data[3] =3D (unsigned short int)((pin >> 16) & 0xFFFF); + Pkt.Data[4] =3D (unsigned short int)(pin >> 32 & 0xFFFF); + Pkt.Data[5] =3D (unsigned short int)((pin >> 48) & 0xFFFF); + + panel_command(h, &Pkt); +} + +void sendoutputmap(panel_connection_t *h, uint64_t pin) +{ + CommandPacket Pkt; + + Pkt.Data[PACKETLEN] =3D (char *)&Pkt.Data[5 + 1] - (char *)&Pkt.Data[0= ]; + Pkt.Data[PACKETTYPE] =3D OUTPUTMAP; + Pkt.Data[2] =3D (unsigned short int)(pin & 0xFFFF); + Pkt.Data[3] =3D (unsigned short int)((pin >> 16) & 0xFFFF); + Pkt.Data[4] =3D (unsigned short int)(pin >> 32 & 0xFFFF); + Pkt.Data[5] =3D (unsigned short int)((pin >> 48) & 0xFFFF); + + panel_command(h, &Pkt); +} + +static void panel_command(panel_connection_t *h, CommandPacket *Pkt) +{ + if (send(h->socket, (char *)Pkt, Pkt->Data[PACKETLEN], 0) =3D=3D -1) { + perror(PANEL_NAME "send"); +#ifdef __MINGW32__ + closesocket(h->socket); +#else + close(h->socket); +#endif + h->socket =3D -1; /* act like we never connected */ + } +} + +/* Wait for values to be read back from panel */ +bool panel_read(panel_connection_t *h, uint64_t* Data) +{ + fd_set rfds, efds; + int LengthInBuffer; + int select_res =3D 0; + + CommandPacket *PktPtr =3D (CommandPacket *)malloc(sizeof(CommandPacket= )); + CommandPacket *Pkt; + bool NoError =3D true; + bool NewData =3D false; + bool NoData =3D false; + struct timeval timeout; + + int ReadStart =3D 0; + int i , j; + + timeout.tv_sec =3D 0; + timeout.tv_usec =3D 0; + + if (h->socket !=3D -1) { + rfds =3D h->fds; + efds =3D h->fds; + + Pkt =3D PktPtr; + while (NoError && !NoData) { + select_res =3D select(h->socket + 1, &rfds, NULL, &efds, &time= out); + if (select_res > 0) { + if (FD_ISSET(h->socket, &rfds)) { + /* receive more data */ + LengthInBuffer =3D recv(h->socket, (char *)&Pkt[ReadSt= art], + sizeof(*Pkt) - ReadStart, 0); + if (LengthInBuffer > 0) { + LengthInBuffer +=3D ReadStart; + for (i =3D 0; LengthInBuffer > 0; i++) { + if (LengthInBuffer >=3D Pkt->Data[i + PACKETLE= N]) { + switch (Pkt->Data[i + PACKETTYPE]) { + case PINSTOQEMU: + *Data =3D (uint64_t)Pkt->Data[i + 2]; + *Data |=3D ((uint64_t)Pkt->Data[i + 3]= ) << 16; + *Data |=3D ((uint64_t)Pkt->Data[i + 4]= ) << 32; + *Data |=3D ((uint64_t)Pkt->Data[i + 5]= ) << 48; + + NewData =3D true; + break; + + case PROTOCOLDESCFROMPANEL: + h->ProtocolInUse =3D (int)Pkt->Data[i = + 2]; + if (h->ProtocolInUse !=3D -1) { + printf(PANEL_NAME "Protocol %d\n", + h->ProtocolInUse); + } else { + printf(PANEL_NAME "No Common Pcol\= n"); + } + break; + + default: + printf(PANEL_NAME "Invalid data receiv= e\n"); + break; + } + LengthInBuffer -=3D Pkt->Data[PACKETLEN]; + i +=3D Pkt->Data[PACKETLEN]; + } else { + ReadStart =3D LengthInBuffer; + for (j =3D 0; j < LengthInBuffer; j++) { + Pkt->Data[j] =3D Pkt->Data[i + j]; + } + printf(PANEL_NAME "Partial Packet Read"); + } + } + } else { + if (LengthInBuffer < 0) { + if (errno !=3D EINTR) { + printf(PANEL_NAME "recv"); + NoError =3D FALSE; + } + } else { + printf(PANEL_NAME "closed connection\n"); + NoError =3D FALSE; + } + } + } + } else if (select_res =3D=3D 0) { + NoData =3D true; + } else if (errno !=3D EINTR) { +#ifdef __MINGW32__ + closesocket(h->socket); +#else + close(h->socket); +#endif + h->socket =3D -1; /* act like we never connected */ + perror(PANEL_NAME "select error"); + NoError =3D FALSE; + } + } + } + + free(PktPtr); + + return NewData; +} + +bool panel_open(panel_connection_t *h) +{ + int rv; +#ifdef __MINGW32__ + struct sockaddr_in remote; +#else + struct sockaddr_in remote; +#endif + + bool returnval =3D false; + +#ifdef __MINGW32__ + printf("__MINGW32__\n"); +#else + printf("NOT __MINGW32__\n"); +#endif + + h->socket =3D -1; + h->ProtocolInUse =3D -1; + +#ifdef __MINGW32__ + WSADATA wsadata; + if (WSAStartup(MAKEWORD(1, 1), &wsadata) =3D=3D SOCKET_ERROR) { + printf("Error creating socket.\n"); + } else { +#endif + h->socket =3D socket(AF_INET, SOCK_STREAM, 0); + if (h->socket !=3D -1) { +#ifdef __MINGW32__ + memset((char *)&remote, 0, sizeof(remote)); + remote.sin_family =3D AF_INET; + remote.sin_port =3D htons(DEFAULT_PORT); + remote.sin_addr.s_addr =3D inet_addr("127.0.0.1"); +#else + memset((char *)&remote, 0, sizeof(remote)); + remote.sin_family =3D AF_INET; + remote.sin_port =3D htons(DEFAULT_PORT); + remote.sin_addr.s_addr =3D inet_addr("127.0.0.1"); +#endif + rv =3D connect(h->socket, + (struct sockaddr *)&remote, sizeof(remote)); + if (rv !=3D -1) { +#ifdef __MINGW32__ + char value =3D 1; + setsockopt(h->socket, IPPROTO_TCP, TCP_NODELAY, + &value, sizeof(value)); +#endif + FD_ZERO(&h->fds); + + /* Set our connected socket */ + FD_SET(h->socket, &h->fds); + + printf(PANEL_NAME "Connected OK %d\n", rv); + + panel_send_protocol_command(h); + + returnval =3D true; + } else { + printf(PANEL_NAME "connection Fails %d\n", rv); +#ifdef __MINGW32__ + closesocket(h->socket); +#else + close(h->socket); +#endif + h->socket =3D -1; + } + } +#ifdef __MINGW32__ + } +#endif + return returnval; +} --=20 2.13.0.windows.1