motorola-payton: new device (Motorola Moto X4) (MR 1301)

What works:
- Booting
- Display
- Touch
- USB Ethernet

What doesn't:
- Sound
- Wi-Fi
- Modem
- Camera

(NOTE: If the display doesn't work, try flashing your phone back to stock, then trying again.)
This commit is contained in:
Dyna 2020-06-13 21:59:01 -05:00 committed by Minecrell
parent bed9029ff2
commit 7e2554714a
No known key found for this signature in database
GPG key ID: B77CE638A6C2E562
10 changed files with 6054 additions and 0 deletions

View file

@ -0,0 +1,27 @@
# Reference: <https://postmarketos.org/devicepkg>
pkgname=device-motorola-payton
pkgdesc="Motorola Moto X4"
pkgver=0.1
pkgrel=0
url="https://postmarketos.org"
license="MIT"
arch="aarch64"
options="!check !archcheck"
depends="postmarketos-base linux-motorola-payton mkbootimg mesa-dri-gallium msm-fb-refresher"
makedepends="devicepkg-dev"
source="deviceinfo directfbrc fb.modes"
build() {
devicepkg_build $startdir $pkgname
}
package() {
devicepkg_package $startdir $pkgname
install -Dm644 "$srcdir"/fb.modes "$pkgdir"/etc/fb.modes
install -Dm644 "$srcdir"/directfbrc "$pkgdir"/etc/directfbrc
}
sha512sums="7462ea9a2a4ddc872e7f5f798ae83faff9fad3072dcf5c95ad25d071473d403b7d4ac47f6d5bebd549a7bc2360d822b0cb981fcc25c19a1c31bfe261fa7dd649 deviceinfo
3db3ec596e159be926ea2b5b2496c18e9bc7be24a64a232a56c89a0c9ee710aa2efb2b6fa9fc08efa34759e8242e6c629d08a4ce688ec8aa125830717c191515 directfbrc
fed190ea8ef9470e30046bcd421b475684b88a03912730813d6364bf669dc01b1e311ceb68c3ae7fdd0b3a7ce75ff24ee546ecd0be40119ecf79a097870613ea fb.modes"

View file

@ -0,0 +1,35 @@
# Reference: <https://postmarketos.org/deviceinfo>
# Please use double quotes only. You can source this file in shell scripts.
deviceinfo_format_version="0"
deviceinfo_name="Motorola Moto X4"
deviceinfo_manufacturer="Motorola"
deviceinfo_codename="motorola-payton"
deviceinfo_year="2017"
deviceinfo_dtb=""
deviceinfo_modules_initfs=""
deviceinfo_arch="aarch64"
# Device related
deviceinfo_chassis="handset"
deviceinfo_keyboard="false"
deviceinfo_external_storage="true"
deviceinfo_screen_width="1080"
deviceinfo_screen_height="1920"
# Bootloader related
deviceinfo_flash_method="fastboot"
deviceinfo_kernel_cmdline="console=ttyMSM0,115200,n8 androidboot.console=ttyMSM0 earlycon=msm_serial_dm,0xc170000 androidboot.hardware=qcom user_debug=31 msm_rtb.filter=0x37 ehci-hcd.park=3 lpm_levels.sleep_disabled=1 sched_enable_hmp=1 sched_enable_power_aware=1 service_locator.enable=1 swiotlb=1 androidboot.configfs=true androidboot.usbcontroller=a800000.dwc3 androidboot.hab.csv=2 androidboot.hab.product=payton androidboot.hab.cid=50 androidboot.fastboot=1 buildvariant=eng"
deviceinfo_generate_bootimg="true"
deviceinfo_bootimg_qcdt="false"
deviceinfo_bootimg_dtb_second="false"
deviceinfo_flash_offset_base="0x00000000"
deviceinfo_flash_offset_kernel="0x00008000"
deviceinfo_flash_offset_ramdisk="0x01000000"
deviceinfo_flash_offset_second="0x00f00000"
deviceinfo_flash_offset_tags="0x00000100"
deviceinfo_flash_pagesize="4096"
deviceinfo_flash_sparse="true"
# USB related
deviceinfo_usb_rndis_function="rndis_bam.rndis"

View file

@ -0,0 +1 @@
pixelformat=ARGB

View file

@ -0,0 +1,7 @@
mode "1080x1920-60"
# D: 149.477 MHz, H: 116.053 kHz, V: 60.007 Hz
geometry 1080 1920 1080 1920 16
timings 6690 100 104 12 0 4 2
accel false
rgba 8/16,8/8,8/0,8/24
endmode

View file

@ -0,0 +1,42 @@
This is needed for the display to display colors correctly.
---
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 075ee8a3880..b4531f66a06 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -868,7 +868,8 @@ static int mdss_fb_probe(struct platform_device *pdev)
mfd->bl_scale = 1024;
mfd->bl_min_lvl = 30;
mfd->ad_bl_level = 0;
- mfd->fb_imgType = MDP_RGBA_8888;
+ // Default framebuffer format.
+ mfd->fb_imgType = MDP_BGRA_8888;
mfd->calib_mode_bl = 0;
if (mfd->panel.type == MIPI_VIDEO_PANEL ||
@@ -2143,6 +2144,25 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd)
bpp = 4;
break;
+ case MDP_BGRA_8888:
+ fix->type = FB_TYPE_PACKED_PIXELS;
+ fix->xpanstep = 1;
+ fix->ypanstep = 1;
+ var->vmode = FB_VMODE_NONINTERLACED;
+ var->blue.offset = 0;
+ var->green.offset = 8;
+ var->red.offset = 16;
+ var->blue.length = 8;
+ var->green.length = 8;
+ var->red.length = 8;
+ var->blue.msb_right = 0;
+ var->green.msb_right = 0;
+ var->red.msb_right = 0;
+ var->transp.offset = 24;
+ var->transp.length = 8;
+ bpp = 4;
+ break;
+
case MDP_YCRYCB_H2V1:
fix->type = FB_TYPE_INTERLEAVED_PLANES;
fix->xpanstep = 2;

View file

@ -0,0 +1,52 @@
# Reference: <https://postmarketos.org/vendorkernel>
# Kernel config based on: arch/arm64/configs/lineageos_payton_defconfig
pkgname=linux-motorola-payton
pkgver=4.4.219
pkgrel=0
pkgdesc="Motorola Moto X4 kernel fork"
arch="aarch64"
_carch="arm64"
_flavor="motorola-payton"
url="https://kernel.org"
license="GPL-2.0-only"
options="!strip !check !tracedeps pmb:cross-native"
makedepends="bash bc bison devicepkg-dev flex openssl-dev perl"
# Source
_repository="android_kernel_motorola_msm8998"
_commit="ce9ea8f125c7302ae9b2fec84f23a69271e957c3"
_config="config-$_flavor.$arch"
source="
$pkgname-$_commit.tar.gz::https://github.com/LineageOS/$_repository/archive/$_commit.tar.gz
$_config
fix-virtual-terminal.patch
remove_bootloader_cmdline_opts.patch
mdss-panel-to-fb-var.patch
99_framebuffer.patch
"
builddir="$srcdir/$_repository-$_commit"
_outdir="out"
prepare() {
default_prepare
. downstreamkernel_prepare
}
build() {
unset LDFLAGS
make O="$_outdir" ARCH="$_carch" CC="${CC:-gcc}" \
KBUILD_BUILD_VERSION="$((pkgrel + 1 ))-postmarketOS" \
KBUILD_MODPOST_WARN=1
}
package() {
downstreamkernel_package "$builddir" "$pkgdir" "$_carch" "$_flavor" "$_outdir"
}
sha512sums="7e109d8e04706fe43c7eceaacc2c50371e35e9256c3eb2f3d3a4cceb2580df6a7a054852a31bf661810bd934cedab49179484417fd7ea762a254e3c66d6a9d5e linux-motorola-payton-ce9ea8f125c7302ae9b2fec84f23a69271e957c3.tar.gz
58225a9e8ddd009e6cfe0cd244bcf4ba541571f0b176ce133bc641abf8ee1224234c92d6d8dfcc70cbb0d1ab1d44e457feaeb3db4f814cef14d83f9cc10957b5 config-motorola-payton.aarch64
a62883a325d858eaff4e44e7e1f85f84803ee8360073f83f9657ba5bf1676618ff77e7e62971ecdfb661956ba081196bc2618179d4d7cafadf528d2aa00062cd fix-virtual-terminal.patch
9ce867c4254b537ef5d2485780c26b72da8a3a8767ba71557f3b48d6c550e0e14c8c3e575b31bf65d2878f08a8a4926e48a1c2f1be534bf80a7a57f58313b0fd remove_bootloader_cmdline_opts.patch
d5b868c64b8ebddcf74cb3aa478f30f0897af1e14e4fc42d977921104a6c568cc0bf36fc8a3b0f538cd3ca2ebf59244fdf23186a903259e5acc14d1c4ef4ccc3 mdss-panel-to-fb-var.patch
d64746ff65de81cc894e33cd8f9b3bf0a5ee9e979d95f67a50a4c0bc7072aa459632841db4b64b68cfc01fa3503d2e8122d03f177932a5f0fbe0ddad5db3bb4d 99_framebuffer.patch"

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,167 @@
This is needed in order for the kernel to work. Without it, the kernel panics on startup.
---
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index fd191761bfa1..844c7617b9e6 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -62,7 +62,6 @@
#include <linux/ipc_logging.h>
#include <asm/irq.h>
#include <linux/kthread.h>
-#include <uapi/linux/sched.h>
#include <linux/msm-sps.h>
#include <linux/platform_data/msm_serial_hs.h>
@@ -3395,7 +3394,6 @@ static void msm_serial_hs_rt_init(struct uart_port *uport)
msm_uport->pm_state = MSM_HS_PM_SUSPENDED;
mutex_unlock(&msm_uport->mtx);
pm_runtime_enable(uport->dev);
- tty_port_set_policy(&uport->state->port, SCHED_FIFO, 1);
}
static int msm_hs_runtime_suspend(struct device *dev)
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
index 92af201f9030..4706df20191b 100644
--- a/drivers/tty/tty_buffer.c
+++ b/drivers/tty/tty_buffer.c
@@ -71,7 +71,7 @@ void tty_buffer_unlock_exclusive(struct tty_port *port)
atomic_dec(&buf->priority);
mutex_unlock(&buf->lock);
if (restart)
- queue_kthread_work(&port->worker, &buf->work);
+ queue_work(system_unbound_wq, &buf->work);
}
EXPORT_SYMBOL_GPL(tty_buffer_unlock_exclusive);
@@ -132,8 +132,6 @@ void tty_buffer_free_all(struct tty_port *port)
buf->tail = &buf->sentinel;
atomic_set(&buf->mem_used, 0);
- if (!IS_ERR_OR_NULL(port->worker_thread))
- kthread_stop(port->worker_thread);
}
/**
@@ -406,7 +404,7 @@ void tty_schedule_flip(struct tty_port *port)
* flush_to_ldisc() sees buffer data.
*/
smp_store_release(&buf->tail->commit, buf->tail->used);
- queue_kthread_work(&port->worker, &buf->work);
+ queue_work(system_unbound_wq, &buf->work);
}
EXPORT_SYMBOL(tty_schedule_flip);
@@ -474,7 +472,7 @@ receive_buf(struct tty_struct *tty, struct tty_buffer *head, int count)
* 'consumer'
*/
-static void flush_to_ldisc(struct kthread_work *work)
+static void flush_to_ldisc(struct work_struct *work)
{
struct tty_port *port = container_of(work, struct tty_port, buf.work);
struct tty_bufhead *buf = &port->buf;
@@ -564,20 +562,8 @@ void tty_buffer_init(struct tty_port *port)
init_llist_head(&buf->free);
atomic_set(&buf->mem_used, 0);
atomic_set(&buf->priority, 0);
+ INIT_WORK(&buf->work, flush_to_ldisc);
buf->mem_limit = TTYB_DEFAULT_MEM_LIMIT;
- init_kthread_work(&buf->work, flush_to_ldisc);
- init_kthread_worker(&port->worker);
- port->worker_thread = kthread_run(kthread_worker_fn, &port->worker,
- "tty_worker_thread");
- if (IS_ERR(port->worker_thread)) {
- /*
- * Not good, we can't unwind, this tty is going to be really
- * sad...
- */
- pr_err("Unable to start tty_worker_thread\n");
- }
-
-
}
/**
@@ -605,15 +591,15 @@ void tty_buffer_set_lock_subclass(struct tty_port *port)
bool tty_buffer_restart_work(struct tty_port *port)
{
- return queue_kthread_work(&port->worker, &port->buf.work);
+ return queue_work(system_unbound_wq, &port->buf.work);
}
bool tty_buffer_cancel_work(struct tty_port *port)
{
- return kthread_cancel_work_sync(&port->buf.work);
+ return cancel_work_sync(&port->buf.work);
}
void tty_buffer_flush_work(struct tty_port *port)
{
- flush_kthread_work(&port->buf.work);
+ flush_work(&port->buf.work);
}
diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
index 9f06fc11bc5f..482f33f20043 100644
--- a/drivers/tty/tty_port.c
+++ b/drivers/tty/tty_port.c
@@ -16,7 +16,6 @@
#include <linux/bitops.h>
#include <linux/delay.h>
#include <linux/module.h>
-#include <uapi/linux/sched.h>
void tty_port_init(struct tty_port *port)
{
@@ -599,12 +598,3 @@ int tty_port_open(struct tty_port *port, struct tty_struct *tty,
}
EXPORT_SYMBOL(tty_port_open);
-
-int tty_port_set_policy(struct tty_port *port, int policy, int sched_priority)
-{
- struct sched_param param = { .sched_priority = sched_priority };
-
- return sched_setscheduler(port->worker_thread, policy, &param);
-}
-EXPORT_SYMBOL_GPL(tty_port_set_policy);
-
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 1c1bb90f6819..572af7c9a65d 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -12,7 +12,6 @@
#include <uapi/linux/tty.h>
#include <linux/rwsem.h>
#include <linux/llist.h>
-#include <linux/kthread.h>
/*
* Lock subclasses for tty locks
@@ -82,7 +81,7 @@ static inline char *flag_buf_ptr(struct tty_buffer *b, int ofs)
struct tty_bufhead {
struct tty_buffer *head; /* Queue head */
- struct kthread_work work;
+ struct work_struct work;
struct mutex lock;
atomic_t priority;
struct tty_buffer sentinel;
@@ -240,8 +239,6 @@ struct tty_port {
based drain is needed else
set to size of fifo */
struct kref kref; /* Ref counter */
- struct kthread_worker worker; /* worker thread */
- struct task_struct *worker_thread; /* worker thread */
};
/*
@@ -582,8 +579,6 @@ static inline int tty_port_users(struct tty_port *port)
{
return port->count + port->blocked_open;
}
-extern int tty_port_set_policy(struct tty_port *port, int policy,
- int sched_priority);
extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
extern int tty_unregister_ldisc(int disc);

View file

@ -0,0 +1,118 @@
From fe5131b250c373d152b7e73895f17846d1f1e6bd Mon Sep 17 00:00:00 2001
From: Ion Agorria <ion@agorria.com>
Date: Thu, 24 Jan 2019 18:52:58 +0100
Subject: [PATCH] mdss: update fb mode at mdss_panelinfo_to_fb_var to fix Xorg
When mdss_panelinfo_to_fb_var is called at
screen unblank it updates the values in fb_info->var,
meanwhile the fb_info->mode and modelist remain with old
values set at registering the fb causing mismatch when
Xorg attempts to set mode.
---
drivers/video/fbdev/msm/mdss_fb.c | 25 ++++++++++++++++------
drivers/video/fbdev/msm/mdss_fb.h | 3 +--
drivers/video/fbdev/msm/mdss_mdp_overlay.c | 2 +-
3 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 3e632076639d..2d2b37bffa5d 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -2339,7 +2339,7 @@ static void mdss_panel_validate_debugfs_info(struct msm_fb_data_type *mfd)
if (is_panel_split(mfd) && pdata->next)
mdss_fb_validate_split(pdata->panel_info.xres,
pdata->next->panel_info.xres, mfd);
- mdss_panelinfo_to_fb_var(panel_info, var);
+ mdss_panelinfo_to_fb_var(mfd);
if (mdss_fb_send_panel_event(mfd, MDSS_EVENT_CHECK_PARAMS,
panel_info))
pr_err("Failed to send panel event CHECK_PARAMS\n");
@@ -2452,7 +2452,7 @@ static int mdss_fb_blank_unblank(struct msm_fb_data_type *mfd)
* programmed in the controller.
* Update this info in the upstream structs.
*/
- mdss_panelinfo_to_fb_var(panel_info, var);
+ mdss_panelinfo_to_fb_var(mfd);
/* Start the work thread to signal idle time */
if (mfd->idle_time)
@@ -3196,7 +3196,7 @@ static int mdss_fb_register(struct msm_fb_data_type *mfd)
return ret;
}
- mdss_panelinfo_to_fb_var(panel_info, var);
+ mdss_panelinfo_to_fb_var(mfd);
fix->type = panel_info->is_3d_panel;
if (mfd->mdp.fb_stride)
@@ -3900,7 +3900,7 @@ static void mdss_fb_update_resolution(struct msm_fb_data_type *mfd,
}
var->xres_virtual = var->xres;
var->yres_virtual = pinfo->yres * mfd->fb_page;
- mdss_panelinfo_to_fb_var(pinfo, var);
+ mdss_panelinfo_to_fb_var(mfd);
}
int mdss_fb_atomic_commit(struct fb_info *info,
@@ -4149,9 +4149,14 @@ static void mdss_fb_var_to_panelinfo(struct fb_var_screeninfo *var,
pinfo->lcdc.v_polarity = 1;
}
-void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo,
- struct fb_var_screeninfo *var)
+void mdss_panelinfo_to_fb_var(struct msm_fb_data_type *mfd)
{
+ if (!mfd)
+ return -EINVAL;
+
+ struct mdss_panel_info *pinfo = mfd->panel_info;
+ struct fb_info *fbi = mfd->fbi;
+ struct fb_var_screeninfo *var = &fbi->var;
u32 frame_rate;
var->xres = mdss_fb_get_panel_xres(pinfo);
@@ -4185,7 +4190,13 @@ void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo,
if (pinfo->physical_height)
var->height = pinfo->physical_height;
- pr_debug("ScreenInfo: res=%dx%d [%d, %d] [%d, %d]\n",
+ //Hack to update current fbi->mode according to fbi->var when var is updated from panel info
+ if (fbi->mode) {
+ printk("Updating mdss fb mode from fb var\n");
+ fb_var_to_videomode(fbi->mode, var);
+ }
+
+ printk("ScreenInfo: res=%dx%d [%d, %d] [%d, %d]\n",
var->xres, var->yres, var->left_margin,
var->right_margin, var->upper_margin,
var->lower_margin);
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index c6e8d37d7bc8..bbd17e1c72e2 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -484,8 +484,7 @@ int mdss_fb_async_position_update(struct fb_info *info,
u32 mdss_fb_get_mode_switch(struct msm_fb_data_type *mfd);
void mdss_fb_report_panel_dead(struct msm_fb_data_type *mfd);
-void mdss_panelinfo_to_fb_var(struct mdss_panel_info *pinfo,
- struct fb_var_screeninfo *var);
+void mdss_panelinfo_to_fb_var(struct msm_fb_data_type *mfd);
void mdss_fb_calc_fps(struct msm_fb_data_type *mfd);
void mdss_fb_idle_pc(struct msm_fb_data_type *mfd);
#endif /* MDSS_FB_H */
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 81218319d58b..cee8a8e5e449 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -3534,7 +3534,7 @@ int mdss_mdp_dfps_update_params(struct msm_fb_data_type *mfd,
* data, so any further call to get the screen
* info has the updated timings.
*/
- mdss_panelinfo_to_fb_var(&pdata->panel_info, var);
+ mdss_panelinfo_to_fb_var(mfd);
MDSS_XLOG(dfps);
mutex_unlock(&mdp5_data->dfps_lock);
--
2.25.1

View file

@ -0,0 +1,80 @@
From 92e3310d2db157deacb86ef5db8c8c8d38251312 Mon Sep 17 00:00:00 2001
From: Alexey Min <alexey.min@gmail.com>
Date: Wed, 11 Sep 2019 21:51:40 +0300
Subject: [PATCH 3/6] Add config option to fix bootloader cmdline args
Android bootloader passes some arguments in kernel command
line, that make booting custom OSes harder:
* skip_initramfs
* root=PARTUUID=...
* init=/init
Those parameters override default boot partition to hardcoded,
set init binary to /init, disable booting from initramfs.
If enabled, those parameters will be erased from bootloader's
command line, and custom OS can boot the way it likes.
Signed-off-by: Alexey Min <alexey.min@gmail.com>
---
arch/arm64/Kconfig | 17 +++++++++++++++++
drivers/of/fdt.c | 14 ++++++++++++++
2 files changed, 31 insertions(+)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 2829edba6aa5..bd9f05f83c7e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -1125,6 +1125,23 @@ config CMDLINE_FORCE
command-line options your boot loader passes to the kernel.
endchoice
+config CMDLINE_DROP_DANGEROUS_ANDROID_OPTIONS
+ bool "Drop certain dangerous options from cmdline"
+ default n
+ help
+ Android bootloader passes some arguments in kernel command
+ line, that make booting custom OSes harder:
+
+ * skip_initramfs
+ * root=PARTUUID=...
+ * init=/init
+
+ Those parameters override default boot partition to hardcoded,
+ set init binary to /init, disable booting from initramfs.
+
+ If enabled, those parameters will be erased from bootloader's
+ command line, and custom OS can boot the way it likes.
+
config EFI_STUB
bool
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index ca175710c4c8..fd8257589648 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -1012,6 +1012,20 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
pr_debug("Command line is: %s\n", (char*)data);
+#ifdef CONFIG_CMDLINE_DROP_DANGEROUS_ANDROID_OPTIONS
+ pr_err("Replacing dangerous cmdline options...");
+ cmdline = strstr((const char *)data, "skip_initramfs");
+ if (cmdline)
+ *cmdline = '_';
+ cmdline = strstr((const char *)data, "root=");
+ if (cmdline)
+ *cmdline = '_';
+ cmdline = strstr((const char *)data, "init=");
+ if (cmdline)
+ *cmdline = '_';
+ pr_err("Command line now is: %s\n", (char*)data);
+#endif
+
/* break now */
return 1;
}
--
2.24.1