diff --git a/CREDITS b/CREDITS
index 58b9c64..c7efa74 100644
--- a/CREDITS
+++ b/CREDITS
@@ -163,6 +163,7 @@ Peter Marschall: (current maintainer)
- bwctusb connectiontype for the HD44780 driver
- extensions to CFontz* drivers: support CF631 & CF635
- various fixes in preparation of 0.5
+ - lcd2usb connectiontype for the HD44780 driver
Markus Dolze:
- various fixes (especially for *BSD)
diff --git a/ChangeLog b/ChangeLog
index b942dc5..d8dbe57 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -36,6 +36,7 @@ v.0.5dev (ongoing development)
+ ea65 - driver for VFD in AOpen XC Cube AV EA65 barebones (Karsten Festag)
+ picolcd - driver for Mini-box.com USB LCD picoLCD (Gatewood Green)
+ new ConnectionType pertelian in hd44780 driver (Matteo Pillon)
+ + new ConnectionType lcd2usb in hd44780 driver
v.0.5.1
+ config file support in lcdproc client (Andrew Foss)
diff --git a/LCDd.conf b/LCDd.conf
index 82b48db..13070c6 100644
--- a/LCDd.conf
+++ b/LCDd.conf
@@ -38,7 +38,7 @@
# The following drivers are supported:
# bayrad, CFontz, CFontz633, CFontzPacket, curses, CwLnx, ea65,
# EyeboxOne, g15, glcdlib, glk, hd44780, icp_a106, imon, IOWarrior,
-# irman, joy, lb216,lcdm001, lcterm, lirc,MD8800, ms6931, mtc_s16209x,
+# irman, joy, lb216, lcdm001, lcterm, lirc, MD8800, ms6931, mtc_s16209x,
# MtxOrb, NoritakeVFD, picolcd, pyramid, sed1330, sed1520, serialPOS,
# serialVFD, sli, stv5730, svga, t6963, text, tyan, ula200, xosd
Driver=curses
diff --git a/acinclude.m4 b/acinclude.m4
index ff62658..3ff5aa3 100644
--- a/acinclude.m4
+++ b/acinclude.m4
@@ -190,7 +190,7 @@ dnl else
HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-4bit.o hd44780-hd44780-ext8bit.o hd44780-lcd_sem.o hd44780-hd44780-winamp.o hd44780-hd44780-serialLpt.o"
fi
if test "$enable_libusb" = yes ; then
- HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-bwct-usb.o"
+ HD44780_DRIVERS="$HD44780_DRIVERS hd44780-hd44780-bwct-usb.o hd44780-hd44780-lcd2usb.o"
fi
AC_CHECK_HEADER(linux/i2c-dev.h,
HD44780_DRIVERS="$HD44780_DRIVERS hd44780-i2c.o"
diff --git a/docs/LCDd.8.in b/docs/LCDd.8.in
index 89c53d9..470c5ce 100644
--- a/docs/LCDd.8.in
+++ b/docs/LCDd.8.in
@@ -155,6 +155,9 @@ LIS2 from VLSystem (http://www.vlsys.co.kr), connected to USB
.B bwctusb
USB-to-HD44780 converter by BWCT (http://www.bwct.de)
.TP
+.B lcd2usb
+Till Harbaum's open source/open hardware LCD2USB (http://www.harbaum.org/till/lcd2usb/)
+.TP
.B i2c
LCD in 4-bit mode driven by PCF8574(A) / PCA9554(A), connected via I2C bus
.RE
diff --git a/docs/lcdproc-user/drivers/hd44780.docbook b/docs/lcdproc-user/drivers/hd44780.docbook
index 491e1de..f16264b 100644
--- a/docs/lcdproc-user/drivers/hd44780.docbook
+++ b/docs/lcdproc-user/drivers/hd44780.docbook
@@ -799,9 +799,9 @@ such as portato. Further details can be obtained from:
-http://metalab.unc.edu/pub/linux/system/status/lcdtime-0.2.tar.gz
-http://metalab.unc.edu/pub/linux/system/status/meter-0.2.tar.gz
-http://metalab.unc.edu/pub/linux/system/status/portato-1.2.tar.gz
+
+
+
@@ -986,7 +986,7 @@ Andrew McMeikan andrewm@engineer.com. The original wiring and
driver can be found at:
-http://members.xoom.com/andrewmuck
+
@@ -1249,7 +1249,7 @@ help of the kernel modules ftdi_sio that map the USB port t
LCD on Serial panel device "los-panel"
-See http://www.xs4all.nl/~mlf/los/
+See
for more information on this device.
@@ -1277,7 +1277,7 @@ famous Linux-based VDR that allows to connect an LCD to it and supports LCDproc.
-See http://www.jepsennet.de/vdr/
+See
(German) for more information on VDR-Wakeup.
@@ -1293,8 +1293,8 @@ ftdi_sio modules loaded. Display will be available on /dev/ttyUSB0.
- See product
+ See the
+ product
page for more information.
@@ -1513,13 +1513,38 @@ specifying which one (of multiple BWCT LCD devices) is wanted using the
+
+Till Harbaum's "lcd2usb"
+
+
+LCD2USB
+is a cheap but powerful do-it-yourself interface to connect HD44780 based displays via USB,
+consisting of easily available parts only.
+The device supports software adjustable contrast and backlight as well as dual controller displays
+(required for 4*27 and 4*40).
+
+
+
+It is based upon Atmel AVR Mega8 CPU with a pure software implementation of the USB protocol
+for the Atmel AVR microcontroller series.
+
+
+
+The whole interface incl. the hardware layout is under a GPL like license.
+This means that you can take these schematics and use it as a basis for your own interface
+e.g. for a graphic LCD
+
+
+
+
+
I2C with Port-Expander
If you have an I2C port available that is supported by your kernel
-(through /dev/i2c*), you can add a I2C port expander there
-(PCF8574P in this example).
+(through /dev/i2c*), you can add a I2C
+port expander there (PCF8574P in this example).
@@ -1676,8 +1701,13 @@ can be done by specifying "--enable-drivers=all" or by
serialLpt
winamp
picanlcd
- bwctusb
lcdserializer
+ los-panel
+ vdr-lcd
+ vdr-wakeup
+ pertelian
+ bwctusb
+ lcd2usb
lis2
i2c
@@ -1733,13 +1763,21 @@ can be done by specifying "--enable-drivers=all" or by
VDR-Wakeup module "vdr-wakeup"
- lis2
- LIS2 from VLSystem ()
+ pertelian
+ Pertelian X2040 LCD display ()
bwctusb
BWCT USB device "bwctusb" ()
+
+ lcd2usb
+ Tim Harbaum's LCD2USB ()
+
+
+ lis2
+ LIS2 from VLSystem ()
+
i2c
LCD driven by PCF8574(A)/PCA9554(A) connected via I2C
diff --git a/server/drivers/Makefile.am b/server/drivers/Makefile.am
index b2541f0..c6f08f2 100644
--- a/server/drivers/Makefile.am
+++ b/server/drivers/Makefile.am
@@ -66,12 +66,12 @@ CFontzPacket_SOURCES = lcd.h lcd_lib.h CFontzPacket.c CFontzPacket.h CFontz-char
curses_SOURCES = lcd.h curses_drv.h curses_drv.c report.h
CwLnx_SOURCES = lcd.h lcd_lib.h CwLnx.c CwLnx.h report.h
ea65_SOURCES = lcd.h ea65.h ea65.c report.h
-EyeboxOne_SOURCES = lcd.h lcd_lib.h EyeboxOne.c EyeboxOne.h report.h
-g15_SOURCES = lcd.h lcd_lib.h g15.h g15-num.c g15.c report.h
+EyeboxOne_SOURCES = lcd.h lcd_lib.h EyeboxOne.c EyeboxOne.h report.h
+g15_SOURCES = lcd.h lcd_lib.h g15.h g15-num.c g15.c report.h
glcdlib_SOURCES = lcd.h lcd_lib.h glcdlib.h glcdlib.c report.h
glk_SOURCES = lcd.h glk.c glk.h glkproto.c glkproto.h report.h
hd44780_SOURCES = lcd.h lcd_lib.h hd44780.h hd44780.c hd44780-drivers.h hd44780-low.h hd44780-charmap.h report.h adv_bignum.h
-EXTRA_hd44780_SOURCES = hd44780-4bit.c hd44780-4bit.h hd44780-ext8bit.c hd44780-ext8bit.h lcd_sem.c lcd_sem.h hd44780-serialLpt.c hd44780-serialLpt.h hd44780-serial.c hd44780-serial.h hd44780-winamp.c hd44780-winamp.h hd44780-bwct-usb.c hd44780-bwct-usb.h hd44780-lis2.c hd44780-lis2.h hd44780-i2c.c hd44780-i2c.h port.h lpt-port.h timing.h
+EXTRA_hd44780_SOURCES = hd44780-4bit.c hd44780-4bit.h hd44780-ext8bit.c hd44780-ext8bit.h lcd_sem.c lcd_sem.h hd44780-serialLpt.c hd44780-serialLpt.h hd44780-serial.c hd44780-serial.h hd44780-winamp.c hd44780-winamp.h hd44780-bwct-usb.c hd44780-bwct-usb.h hd44780-lcd2usb.c hd44780-lcd2usb.h hd44780-lis2.c hd44780-lis2.h hd44780-i2c.c hd44780-i2c.h port.h lpt-port.h timing.h
icp_a106_SOURCES = lcd.h lcd_lib.h icp_a106.c icp_a106.h report.h
imon_SOURCES = lcd.h lcd_lib.h imon.h imon.c report.h
diff --git a/server/drivers/hd44780-bwct-usb.c b/server/drivers/hd44780-bwct-usb.c
index ea4e55e..5557a0e 100644
--- a/server/drivers/hd44780-bwct-usb.c
+++ b/server/drivers/hd44780-bwct-usb.c
@@ -41,7 +41,7 @@ int
hd_init_bwct_usb (Driver *drvthis)
{
PrivateData *p = (PrivateData*) drvthis->private_data;
- struct usb_bus *busses;
+
struct usb_bus *bus;
//char device_manufacturer[LCD_MAX_WIDTH+1] = "";
char device_serial[LCD_MAX_WIDTH+1] = DEFAULT_SERIALNO;
@@ -51,6 +51,7 @@ hd_init_bwct_usb (Driver *drvthis)
p->hd44780_functions->senddata = bwct_usb_HD44780_senddata;
p->hd44780_functions->backlight = bwct_usb_HD44780_backlight;
p->hd44780_functions->scankeypad = bwct_usb_HD44780_scankeypad;
+ p->hd44780_functions->close = bwct_usb_HD44780_close;
/* Read config file's contents: serial number and contrast */
@@ -71,17 +72,16 @@ hd_init_bwct_usb (Driver *drvthis)
usb_init();
usb_find_busses();
usb_find_devices();
- busses = usb_get_busses();
bwct_usb = NULL;
- for (bus = busses; bus; bus = bus->next) {
+ for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
struct usb_device *dev;
- for (dev = bus->devices; dev; dev = dev->next) {
+ for (dev = bus->devices; dev != NULL; dev = dev->next) {
int c;
/* Check if this device is a BWCT device */
- if (dev->descriptor.idVendor != 0x03DA) {
+ if (dev->descriptor.idVendor != BWCT_USB_VENDORID) {
continue;
}
/* Loop through all of the configurations */
@@ -92,10 +92,10 @@ hd_init_bwct_usb (Driver *drvthis)
/* Loop through all of the alternate settings */
for (a = 0; a < dev->config[c].interface[bwct_usb_i].num_altsetting; a++) {
- /* Check if this interface is a BWCT ulcd */
- if (((dev->config[c].interface[bwct_usb_i].altsetting[a].bInterfaceClass == 0xFf) &&
+ /* Check if this interface is a BWCT lcd */
+ if (((dev->config[c].interface[bwct_usb_i].altsetting[a].bInterfaceClass == 0xFF) &&
(dev->config[c].interface[bwct_usb_i].altsetting[a].bInterfaceSubClass == 0x01)) ||
- (dev->descriptor.idProduct == 0x0002)) {
+ (dev->descriptor.idProduct == BWCT_USB_PRODUCTID)) {
/* BWCT device found; try to find its description and serial number */
bwct_usb = usb_open(dev);
@@ -167,7 +167,7 @@ hd_init_bwct_usb (Driver *drvthis)
/* set contrast */
if ((0 <= contrast) && (contrast <= 1000)) {
- int res = usb_control_msg(bwct_usb, USB_TYPE_VENDOR, VENDOR_LCD_CONTRAST,
+ int res = usb_control_msg(bwct_usb, USB_TYPE_VENDOR, BWCT_LCD_SET_CONTRAST,
(contrast * 255) / 1000, bwct_usb_i, NULL, 0, 1000);
if (res < 0)
report(RPT_WARNING, "hd_init_bwct_usb: setting contrast failed");
@@ -183,9 +183,9 @@ hd_init_bwct_usb (Driver *drvthis)
void
bwct_usb_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch)
{
-int type = (flags == RS_DATA) ? VENDOR_LCD_DATA : VENDOR_LCD_CMD;
+int type = (flags == RS_DATA) ? BWCT_LCD_DATA : BWCT_LCD_CMD;
- usb_control_msg(bwct_usb, USB_TYPE_VENDOR, type, ch, bwct_usb_i, NULL, 0, 1000);
+ usb_control_msg(bwct_usb, USB_TYPE_VENDOR, type, ch, bwct_usb_i, NULL, 0, 1000);
}
@@ -200,3 +200,15 @@ bwct_usb_HD44780_scankeypad(PrivateData *p)
{
return 0;
}
+
+
+void
+bwct_usb_HD44780_close(PrivateData *p)
+{
+ if (bwct_usb != NULL) {
+ usb_close(bwct_usb);
+ bwct_usb = NULL;
+ }
+}
+
+/* EOF */
diff --git a/server/drivers/hd44780-bwct-usb.h b/server/drivers/hd44780-bwct-usb.h
index 5ea4bbc..8ec4f2e 100644
--- a/server/drivers/hd44780-bwct-usb.h
+++ b/server/drivers/hd44780-bwct-usb.h
@@ -4,10 +4,14 @@
#include "lcd.h" /* for Driver */
#include "hd44780-low.h"
-#define VENDOR_LCD_RESET 1
-#define VENDOR_LCD_CMD 2
-#define VENDOR_LCD_DATA 3
-#define VENDOR_LCD_CONTRAST 4
+/* vendor and product id */
+#define BWCT_USB_VENDORID 0x03DA
+#define BWCT_USB_PRODUCTID 0x0002
+
+#define BWCT_LCD_RESET 1
+#define BWCT_LCD_CMD 2
+#define BWCT_LCD_DATA 3
+#define BWCT_LCD_SET_CONTRAST 4
#define DEFAULT_SERIALNO ""
#define DEFAULT_CONTRAST 300
@@ -18,5 +22,6 @@ int hd_init_bwct_usb(Driver *drvthis);
void bwct_usb_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch);
void bwct_usb_HD44780_backlight(PrivateData *p, unsigned char state);
unsigned char bwct_usb_HD44780_scankeypad(PrivateData *p);
+void bwct_usb_HD44780_close(PrivateData *p);
#endif
diff --git a/server/drivers/hd44780-drivers.h b/server/drivers/hd44780-drivers.h
index 47044e0..01f9348 100644
--- a/server/drivers/hd44780-drivers.h
+++ b/server/drivers/hd44780-drivers.h
@@ -19,6 +19,7 @@
#endif
#ifdef HAVE_LIBUSB
# include "hd44780-bwct-usb.h"
+# include "hd44780-lcd2usb.h"
#endif
#include "hd44780-serial.h"
#include "hd44780-lis2.h"
@@ -49,6 +50,7 @@ static const ConnectionMapping connectionMapping[] = {
{"lis2", hd_init_lis2, "\tnone\n"},
#ifdef HAVE_LIBUSB
{"bwctusb", hd_init_bwct_usb, "\tnone\n"},
+ {"lcd2usb", hd_init_lcd2usb, "\tnone\n"},
#endif
#ifdef HAVE_I2C
{"i2c", hd_init_i2c, "\tnone\n"},
diff --git a/server/drivers/hd44780-lcd2usb.c b/server/drivers/hd44780-lcd2usb.c
new file mode 100644
index 0000000..6fcfaba
--- /dev/null
+++ b/server/drivers/hd44780-lcd2usb.c
@@ -0,0 +1,160 @@
+/* driver module for Hitachi HD44780 based LCD displays
+ * connected to using the lcd2usb interface
+ * (http://www.harbaum.org/till/lcd2usb)
+ *
+ * Copyright (C) 2007 Peter Marschall
+ *
+ * This file is released under the GNU General Public License. Refer to the
+ * COPYING file distributed with this package.
+ */
+
+#include "hd44780-lcd2usb.h"
+
+#include "report.h"
+
+#include
+#include
+#include
+#include
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+
+/* USB device handle & interface index we write to */
+static usb_dev_handle *lcd2usb;
+
+
+// initialize the driver
+int
+hd_init_lcd2usb (Driver *drvthis)
+{
+ PrivateData *p = (PrivateData*) drvthis->private_data;
+
+ struct usb_bus *bus;
+ //char device_manufacturer[LCD_MAX_WIDTH+1] = "";
+ int contrast = -1; /* illegal contrast value (to detect errors) */
+ int brightness = -1; /* illegal brightness value (to detect errors) */
+
+ p->hd44780_functions->senddata = lcd2usb_HD44780_senddata;
+ p->hd44780_functions->backlight = lcd2usb_HD44780_backlight;
+ p->hd44780_functions->scankeypad = lcd2usb_HD44780_scankeypad;
+ p->hd44780_functions->close = lcd2usb_HD44780_close;
+
+ /* Read config file's contents: contrast */
+
+ contrast = drvthis->config_get_int(drvthis->name, "Contrast", 0, DEFAULT_CONTRAST);
+ brightness = drvthis->config_get_int(drvthis->name, "Brightness", 0, DEFAULT_BRIGHTNESS);
+
+ /* try to find USB device */
+#if 0
+ usb_debug = 2;
+#endif
+
+ usb_init();
+ usb_find_busses();
+ usb_find_devices();
+
+ lcd2usb = NULL;
+ for (bus = usb_get_busses(); bus != NULL; bus = bus->next) {
+ struct usb_device *dev;
+
+ for (dev = bus->devices; dev != NULL; dev = dev->next) {
+
+ /* Check if this device is a LCD2USB device */
+ if ((dev->descriptor.idVendor == LCD2USB_VENDORID) &&
+ (dev->descriptor.idProduct == LCD2USB_PRODUCTID)) {
+
+ /* LCD2USB device found; try to find its description */
+ lcd2usb = usb_open(dev);
+ if (lcd2usb == NULL) {
+ report(RPT_WARNING, "hd_init_lcd2usb: unable to open device");
+ // return -1; /* it's better to continue */
+ }
+ else {
+ /* get device information & check for serial number */
+ //if (usb_get_string_simple(lcd2usb, dev->descriptor.iManufacturer,
+ // manufacturer, LCD_MAX_WIDTH) <= 0)
+ // *manufacturer = '\0';
+ //manufacturer[sizeof(manufacturer)-1] = '\0';
+
+ //if (usb_get_string_simple(lcd2usb, dev->descriptor.iProduct,
+ // product, LCD_MAX_WIDTH) <= 0)
+ // *product = '\0';
+ //product[sizeof(product)-1] = '\0';
+
+ //usb_close(lcd2usb);
+ //lcd2usb = NULL;
+ }
+ }
+ }
+ }
+
+ if (lcd2usb != NULL) {
+ debug(RPT_DEBUG, "hd_init_lcd2usb: opening device succeeded");
+
+ }
+ else {
+ report(RPT_ERR, "hd_init_lcd2usb: no (matching) LCD2USB device found");
+ return -1;
+ }
+
+ common_init(p, IF_4BIT);
+
+ /* set contrast */
+ if ((0 <= contrast) && (contrast <= 1000)) {
+ int res = usb_control_msg(lcd2usb, USB_TYPE_VENDOR, LCD2USB_SET_CONTRAST,
+ (contrast * 255) / 1000, 0, NULL, 0, 1000);
+ if (res < 0)
+ report(RPT_WARNING, "hd_init_lcd2usb: setting contrast failed");
+ } else {
+ report(RPT_INFO, "hd_init_lcd2usb: Using default contrast value");
+ }
+
+ /* set brightness */
+ if ((0 <= brightness) && (brightness <= 1000)) {
+ int res = usb_control_msg(lcd2usb, USB_TYPE_VENDOR, LCD2USB_SET_BRIGHTNESS,
+ (brightness * 255) / 1000, 0, NULL, 0, 1000);
+ if (res < 0)
+ report(RPT_WARNING, "hd_init_lcd2usb: setting brightness failed");
+ } else {
+ report(RPT_INFO, "hd_init_lcd2usb: Using default brightness value");
+ }
+
+ return 0;
+}
+
+
+// lcd2usb_HD44780_senddata
+void
+lcd2usb_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch)
+{
+int type = (flags == RS_DATA) ? (LCD2USB_DATA | LCD2USB_CTRL_0) : (LCD2USB_CMD | LCD2USB_CTRL_0);
+
+ usb_control_msg(lcd2usb, USB_TYPE_VENDOR, type, ch, 0, NULL, 0, 1000);
+}
+
+
+void
+lcd2usb_HD44780_backlight(PrivateData *p, unsigned char state)
+{
+}
+
+
+unsigned char
+lcd2usb_HD44780_scankeypad(PrivateData *p)
+{
+ return 0;
+}
+
+void
+lcd2usb_HD44780_close(PrivateData *p)
+{
+ if (lcd2usb != NULL) {
+ usb_close(lcd2usb);
+ lcd2usb = NULL;
+ }
+}
+
+/* EOF */
diff --git a/server/drivers/hd44780-lcd2usb.h b/server/drivers/hd44780-lcd2usb.h
new file mode 100644
index 0000000..224a7ef
--- /dev/null
+++ b/server/drivers/hd44780-lcd2usb.h
@@ -0,0 +1,46 @@
+#ifndef HD_LCD2USB_H
+#define HD_LCD2USB_H
+
+#include "lcd.h" /* for Driver */
+#include "hd44780-low.h"
+
+/* vendor and product id */
+#define LCD2USB_VENDORID 0x0403
+#define LCD2USB_PRODUCTID 0xc630
+
+/* target is a bit map for CMD/DATA */
+#define LCD2USB_CTRL_0 (1<<3)
+#define LCD2USB_CTRL_1 (1<<4)
+#define LCD2USB_CTRL_BOTH (LCD_CTRL_0 | LCD_CTRL_1)
+
+#define LCD2USB_ECHO (0<<5)
+#define LCD2USB_CMD (1<<5)
+#define LCD2USB_DATA (2<<5)
+#define LCD2USB_SET (3<<5)
+#define LCD2USB_GET (4<<5)
+
+/* target is value to set */
+#define LCD2USB_SET_CONTRAST (LCD2USB_SET | (0<<3))
+#define LCD2USB_SET_BRIGHTNESS (LCD2USB_SET | (1<<3))
+#define LCD2USB_SET_RESERVED0 (LCD2USB_SET | (2<<3))
+#define LCD2USB_SET_RESERVED1 (LCD2USB_SET | (3<<3))
+
+/* target is value to get */
+#define LCD2USB_GET_FWVER (LCD2USB_GET | (0<<3))
+#define LCD2USB_GET_KEYS (LCD2USB_GET | (1<<3))
+#define LCD2USB_GET_CTRL (LCD2USB_GET | (2<<3))
+#define LCD2USB_GET_RESERVED1 (LCD2USB_GET | (3<<3))
+
+#define DEFAULT_CONTRAST 300
+#define DEFAULT_BRIGHTNESS 600
+#define DEFAULT_OFFBRIGHTNESS 300
+
+// initialise this particular driver
+int hd_init_lcd2usb(Driver *drvthis);
+
+void lcd2usb_HD44780_senddata(PrivateData *p, unsigned char displayID, unsigned char flags, unsigned char ch);
+void lcd2usb_HD44780_backlight(PrivateData *p, unsigned char state);
+unsigned char lcd2usb_HD44780_scankeypad(PrivateData *p);
+void lcd2usb_HD44780_close(PrivateData *p);
+
+#endif