From nobody Mon Apr 29 05:51:43 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 1495496930747828.2143537584169; Mon, 22 May 2017 16:48:50 -0700 (PDT) Received: from localhost ([::1]:45348 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dCx4C-0007pb-C7 for importer@patchew.org; Mon, 22 May 2017 19:48:48 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44262) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dCx3C-0007Xc-Ay for qemu-devel@nongnu.org; Mon, 22 May 2017 19:47:48 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dCx39-0003Z5-51 for qemu-devel@nongnu.org; Mon, 22 May 2017 19:47:46 -0400 Received: from nm14-vm5.bullet.mail.ir2.yahoo.com ([212.82.96.193]:52115) by eggs.gnu.org with esmtps (TLS1.0:RSA_ARCFOUR_SHA1:16) (Exim 4.71) (envelope-from ) id 1dCx38-0003Yk-PM for qemu-devel@nongnu.org; Mon, 22 May 2017 19:47:43 -0400 Received: from [212.82.98.61] by nm14.bullet.mail.ir2.yahoo.com with NNFMP; 22 May 2017 23:47:39 -0000 Received: from [46.228.39.89] by tm14.bullet.mail.ir2.yahoo.com with NNFMP; 22 May 2017 23:47:39 -0000 Received: from [127.0.0.1] by smtp126.mail.ir2.yahoo.com with NNFMP; 22 May 2017 23:47:39 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rocketmail.com; s=s2048; t=1495496859; bh=G5hWb/4nnaUFnYKOkLiEIgn42vn9oBoiiZPcMlkXWXI=; h=Date:From:CC:To:Subject:From:Subject; b=tdMEnYbT0T8IO/4AEx44beyGlVN+LyYI3znhifAOce3wVE9/RZ0auKPKcgaDfK/zCkF5UoIl14TkCwlmNStxWi3SG4hPFz3tNlRRcjkXgIIQr6KZwMLA5j0IqpBLHiAULlcJn42dpX3gJvjucuBzSXsav2XIuVvolp6X76jSC2KlNRzVRlsoTtJSR4oVQauJpftb2YZRgs6MjjGsqInf0tlnRX8hUNNgUVrsLpzD6u05eY3Urc2fGJObj/DCv44yR98CHxVibrhOVXLJ6o/h+MzlVhUqzCBS+fDh8J9Wv68ejQkV7nONxLel6xcjedzi/8IIIAdx/cUSowzekCZrug== X-Yahoo-Newman-Id: 872833.65091.bm@smtp126.mail.ir2.yahoo.com X-Yahoo-Newman-Property: ymail-3 X-YMail-OSG: Kj63yLkVM1kuJ8GK_YvWgxPXnT.UPE049AEPvBXxyTy06h8 ONHplbOxwJdZwZa9tMFKtl1tEVfsjlEV7d3wI3doaxe5xVlV3mgKBJRRikg5 6mgDV5VrU83xFMVi1LyTxkeNoIN3B1rCCo0PlTjfa.fMk9rMmzc_LxUTGlNu OyfyI4EacjJjKSz0NutR6WNyVyAY7Z3.6.djHMbdmEJLs9rIqNrcfSVo91pr k_wOpSkSBvEkMCmrKcYyXKrgn6ynmxv07sTnuFI6mQWmMS54gx_wMXeR.ZUB 65pkBigIfS4ViOCc6_c1JyZ27r9sjUCLEtRpkXUh.KD9SavDvCAU1DglkVGS sXRaqBLQaZywIf_n3D.UIevEG9fJ.VuYmA4UAdcLjv6DrQFVeWxKYpnLG49c d_XPfe_c7qQRD80Y1z.j5ctFN.qpI3iBrJdPdeBsWDT7IB1MRe3eGpSHPbG6 QNS0qZRttXOcPQOJ1tBo0.JjtTHb5Nme51vDe3tqVKryrURGZcbsMv6BG9nm dhLC3bfWuuyx4ss211C_2rSmwuM6cUtPyopYdhn.ZihZbxDIbyc_qewaP.ik uVV2me2Ep5jqhb7rn X-Yahoo-SMTP: Zay5iG2swBBwBjVsWquSqCXzMrQnnj5rR6LdlZsQ7MCyug-- Date: Tue, 23 May 2017 00:47:38 +0000 To: Message-ID: <56fa8a79-fa90-4adc-aa0e-0527c9d96698@ONE.local> 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.96.193 Subject: [Qemu-devel] [PATCH] [PATCH V2] GDummyPanel Fix formatingissues. 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 468b7c74d36b1e9d56ca014531301f0485254866 Mon Sep 17 00:00:00 2001 From: John Bradley Date: Fri, 19 May 2017 00:01:07 +0100 Subject: [PATCH] [PATCH V2] GDummyPanel Fix formatingissues. 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 | 316 ++++++++++++++++++++++---------------= -- include/hw/gpio/bcm2835_gpio.h | 4 + include/qemu/PanelEmu.h | 53 +++++++ util/Makefile.objs | 1 + util/PanelEmu.c | 327 +++++++++++++++++++++++++++++++++++++= ++++ 5 files changed, 570 insertions(+), 131 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..2c9026c597 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 @@ -55,7 +57,7 @@ static uint32_t gpfsel_get(BCM2835GpioState *s, uint8_t r= eg) uint32_t value =3D 0; for (i =3D 0; i < 10; i++) { uint32_t index =3D 10 * reg + i; - if (index < sizeof(s->fsel)) { + if (index < sizeof (s->fsel)) { value |=3D (s->fsel[index] & 0x7) << (3 * i); } } @@ -67,7 +69,7 @@ static void gpfsel_set(BCM2835GpioState *s, uint8_t reg, = uint32_t value) int i; for (i =3D 0; i < 10; i++) { uint32_t index =3D 10 * reg + i; - if (index < sizeof(s->fsel)) { + if (index < sizeof (s->fsel)) { int fsel =3D (value >> (3 * i)) & 0x7; s->fsel[index] =3D fsel; } @@ -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,9 +110,9 @@ 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 changes =3D val & ~ *lev; uint32_t cur =3D 1; =20 int i; @@ -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,116 +143,153 @@ 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: - case GPFSEL2: - case GPFSEL3: - case GPFSEL4: - case GPFSEL5: - return gpfsel_get(s, offset / 4); - case GPSET0: - case GPSET1: - /* Write Only */ - return 0; - case GPCLR0: - case GPCLR1: - /* Write Only */ - return 0; - case GPLEV0: - return s->lev0; - case GPLEV1: - return s->lev1; - case GPEDS0: - case GPEDS1: - case GPREN0: - case GPREN1: - case GPFEN0: - case GPFEN1: - case GPHEN0: - case GPHEN1: - case GPLEN0: - case GPLEN1: - case GPAREN0: - case GPAREN1: - case GPAFEN0: - case GPAFEN1: - case GPPUD: - case GPPUDCLK0: - case GPPUDCLK1: - /* Not implemented */ - return 0; - default: - qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\n", - __func__, offset); - break; + case GPFSEL0: + case GPFSEL1: + case GPFSEL2: + case GPFSEL3: + case GPFSEL4: + case GPFSEL5: + return gpfsel_get(s, offset / 4); + case GPSET0: + case GPSET1: + /* Write Only */ + return 0; + case GPCLR0: + case GPCLR1: + /* 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: + case GPREN0: + case GPREN1: + case GPFEN0: + case GPFEN1: + case GPHEN0: + case GPHEN1: + case GPLEN0: + case GPLEN1: + case GPAREN0: + case GPAREN1: + case GPAFEN0: + case GPAFEN1: + case GPPUD: + case GPPUDCLK0: + case GPPUDCLK1: + /* Not implemented */ + return 0; + default: + qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad offset %"HWADDR_PRIx"\= n", + __func__, offset); + break; } =20 return 0; } =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: - case GPFSEL1: - case GPFSEL2: - case GPFSEL3: - case GPFSEL4: - case GPFSEL5: - gpfsel_set(s, offset / 4, value); - break; - case GPSET0: - gpset(s, value, 0, 32, &s->lev0); - break; - case GPSET1: - gpset(s, value, 32, 22, &s->lev1); - break; - case GPCLR0: - gpclr(s, value, 0, 32, &s->lev0); - break; - case GPCLR1: - gpclr(s, value, 32, 22, &s->lev1); - break; - case GPLEV0: - case GPLEV1: - /* Read Only */ - break; - case GPEDS0: - case GPEDS1: - case GPREN0: - case GPREN1: - case GPFEN0: - case GPFEN1: - case GPHEN0: - case GPHEN1: - case GPLEN0: - case GPLEN1: - case GPAREN0: - case GPAREN1: - case GPAFEN0: - case GPAFEN1: - case GPPUD: - case GPPUDCLK0: - case GPPUDCLK1: - /* Not implemented */ - break; - default: - goto err_out; + case GPFSEL0: + case GPFSEL1: + case GPFSEL2: + case GPFSEL3: + case GPFSEL4: + case GPFSEL5: + gpfsel_set(s, offset / 4, value); + 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: + /* Read Only */ + break; + case GPEDS0: + case GPEDS1: + case GPREN0: + case GPREN1: + case GPFEN0: + case GPFEN1: + case GPHEN0: + case GPHEN1: + case GPLEN0: + case GPLEN1: + case GPAREN0: + case GPAREN1: + case GPAFEN0: + case GPAFEN1: + case GPPUD: + case GPPUDCLK0: + case GPPUDCLK1: + /* Not implemented */ + break; + default: + goto err_out; } return; =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_re= ad, + .write =3D bcm2835_gpio_w= rite, + .endianness =3D DEVICE_NA= TIVE_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_i= d =3D 1, + .fields =3D (VMSta= teField[]) + { + VMSTATE_UINT8_ARRAY(fsel, BCM2835GpioState, 54), + VMSTATE_UINT32(lev0, BCM2835GpioState), + VMSTATE_UINT32(lev1, BCM2835GpioState), + VMSTATE_UINT8(sd_fsel, BCM2835GpioState), + VMSTATE_END_OF_LIST() } }; =20 @@ -296,13 +336,27 @@ static void bcm2835_gpio_init(Object *obj) DeviceState *dev =3D DEVICE(obj); SysBusDevice *sbd =3D SYS_BUS_DEVICE(obj); =20 - qbus_create_inplace(&s->sdbus, sizeof(s->sdbus), + qbus_create_inplace(&s->sdbus, sizeof (s->sdbus), 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 (BCM2= 835GpioState), + .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..35a0b2c3af --- /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..4700f951ec --- /dev/null +++ b/util/PanelEmu.c @@ -0,0 +1,327 @@ +/* + * 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; + + 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 (int 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 (int 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