Major rework of xmm6260 common code (MIPI and HSIC) and xmm6260 devices code
authorPaul Kocialkowski <contact@paulk.fr>
Wed, 3 Jul 2013 14:10:04 +0000 (16:10 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Wed, 3 Jul 2013 14:10:04 +0000 (16:10 +0200)
Change-Id: I49fba6329824e1f1ab0aceef91a57f75727a41ab
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
31 files changed:
Android.mk
samsung-ipc/Makefile.am
samsung-ipc/device/galaxys2/galaxys2_ipc.c
samsung-ipc/device/galaxys2/galaxys2_ipc.h [new file with mode: 0644]
samsung-ipc/device/galaxys2/galaxys2_loader.c [deleted file]
samsung-ipc/device/galaxys2/galaxys2_loader.h [deleted file]
samsung-ipc/device/maguro/maguro_ipc.c
samsung-ipc/device/maguro/maguro_ipc.h [new file with mode: 0644]
samsung-ipc/device/maguro/maguro_loader.c [deleted file]
samsung-ipc/device/maguro/maguro_loader.h [deleted file]
samsung-ipc/device/piranha/piranha_ipc.c
samsung-ipc/device/piranha/piranha_ipc.h [new file with mode: 0644]
samsung-ipc/device/piranha/piranha_loader.c [deleted file]
samsung-ipc/device/piranha/piranha_loader.h [deleted file]
samsung-ipc/device/xmm6260/modem.h [new file with mode: 0644]
samsung-ipc/device/xmm6260/modem_link_device_hsic.h [new file with mode: 0755]
samsung-ipc/device/xmm6260/modem_prj.h
samsung-ipc/device/xmm6260/xmm6260.c [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260.h [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260_hsic.c [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260_hsic.h [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260_ipc.c [deleted file]
samsung-ipc/device/xmm6260/xmm6260_ipc.h [deleted file]
samsung-ipc/device/xmm6260/xmm6260_loader.c [deleted file]
samsung-ipc/device/xmm6260/xmm6260_loader.h [deleted file]
samsung-ipc/device/xmm6260/xmm6260_mipi.c [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260_mipi.h [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260_modemctl.c [deleted file]
samsung-ipc/device/xmm6260/xmm6260_modemctl.h [deleted file]
samsung-ipc/device/xmm6260/xmm6260_sec_modem.c [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260_sec_modem.h [new file with mode: 0644]

index 1e47081..9b5cf17 100644 (file)
@@ -60,17 +60,15 @@ samsung-ipc_files := \
        samsung-ipc/sec.c \
        samsung-ipc/sms.c \
        samsung-ipc/util.c \
+       samsung-ipc/device/xmm6160/xmm6160.c \
+       samsung-ipc/device/xmm6260/xmm6260.c \
+       samsung-ipc/device/xmm6260/xmm6260_hsic.c \
+       samsung-ipc/device/xmm6260/xmm6260_mipi.c \
+       samsung-ipc/device/xmm6260/xmm6260_sec_modem.c \
        samsung-ipc/device/crespo/crespo_ipc.c \
        samsung-ipc/device/aries/aries_ipc.c \
-       samsung-ipc/device/xmm6160/xmm6160.c \
-       samsung-ipc/device/xmm6260/xmm6260_loader.c \
-       samsung-ipc/device/xmm6260/xmm6260_modemctl.c \
-       samsung-ipc/device/xmm6260/xmm6260_ipc.c \
-       samsung-ipc/device/galaxys2/galaxys2_loader.c \
        samsung-ipc/device/galaxys2/galaxys2_ipc.c \
-       samsung-ipc/device/maguro/maguro_loader.c \
        samsung-ipc/device/maguro/maguro_ipc.c \
-       samsung-ipc/device/piranha/piranha_loader.c \
        samsung-ipc/device/piranha/piranha_ipc.c
 
 LOCAL_SRC_FILES := $(samsung-ipc_files)
index 154bb70..8145ba2 100644 (file)
@@ -32,32 +32,33 @@ libsamsung_ipc_la_SOURCES = \
        ipc.h \
        ipc_devices.h \
        util.h \
+       device/xmm6160/xmm6160.c \
+       device/xmm6160/xmm6160.h \
+       device/xmm6260/xmm6260.c \
+       device/xmm6260/xmm6260_hsic.c \
+       device/xmm6260/xmm6260_mipi.c \
+       device/xmm6260/xmm6260_sec_modem.c \
+       device/xmm6260/xmm6260.h \
+       device/xmm6260/xmm6260_hsic.h \
+       device/xmm6260/xmm6260_mipi.h \
+       device/xmm6260/xmm6260_sec_modem.h \
+       device/xmm6260/modem.h \
+       device/xmm6260/modem_link_device_hsic.h \
+       device/xmm6260/modem_prj.h \
        device/crespo/crespo_ipc.c \
+       device/crespo/crespo_ipc.h \
+       device/crespo/crespo_modem_ctl.h \
        device/aries/aries_ipc.c \
-       device/aries/sipc4.h \
        device/aries/aries_ipc.h \
+       device/aries/sipc4.h \
        device/aries/onedram.h \
        device/aries/phonet.h \
-       device/crespo/crespo_modem_ctl.h \
-       device/crespo/crespo_ipc.h \
-       device/xmm6160/xmm6160.c \
-       device/xmm6160/xmm6160.h \
-       device/xmm6260/xmm6260_loader.c \
-       device/xmm6260/xmm6260_loader.h \
-       device/xmm6260/xmm6260_modemctl.c \
-       device/xmm6260/xmm6260_modemctl.h \
-       device/xmm6260/xmm6260_ipc.c \
-       device/xmm6260/xmm6260_ipc.h \
-       device/xmm6260/modem_prj.h \
-       device/galaxys2/galaxys2_loader.c \
-       device/galaxys2/galaxys2_loader.h \
        device/galaxys2/galaxys2_ipc.c \
-       device/maguro/maguro_loader.c \
-       device/maguro/maguro_loader.h \
+       device/galaxys2/galaxys2_ipc.h \
        device/maguro/maguro_ipc.c \
-       device/piranha/piranha_loader.c \
-       device/piranha/piranha_loader.h \
+       device/maguro/maguro_ipc.h \
        device/piranha/piranha_ipc.c \
+       device/piranha/piranha_ipc.h \
        $(NULL)
 
 libsamsung_ipc_la_LIBADD = \
index d68cf0d..5c1c9c3 100644 (file)
@@ -1,13 +1,7 @@
-/**
+/*
  * This file is part of libsamsung-ipc.
  *
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- * based on crespo IPC code which is:
- *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- *                    Joerie de Gram <j.de.gram@gmail.com>
- *                    Simon Busch <morphis@gravedo.de>
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
  *
  * libsamsung-ipc is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 
 #include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <samsung-ipc.h>
+#include <ipc.h>
+
+#include "xmm6260.h"
+#include "xmm6260_hsic.h"
+#include "xmm6260_sec_modem.h"
+#include "galaxys2_ipc.h"
+
+int galaxys2_ipc_bootstrap(struct ipc_client *client)
+{
+    void *modem_image_data = NULL;
+    int modem_image_fd = -1;
+    int modem_boot_fd = -1;
+    int modem_link_fd = -1;
+
+    unsigned char *p;
+    int rc;
+
+    if (client == NULL)
+        return -1;
+
+    ipc_client_log(client, "Starting galaxys2 modem bootstrap");
+
+    modem_image_fd = open(GALAXYS2_MODEM_IMAGE_DEVICE, O_RDONLY);
+    if (modem_image_fd < 0) {
+        ipc_client_log(client, "Opening modem image device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem image device");
+
+    modem_image_data = mmap(0, GALAXYS2_MODEM_IMAGE_SIZE, PROT_READ, MAP_SHARED, modem_image_fd, 0);
+    if (modem_image_data == NULL || modem_image_data == (void *) 0xffffffff) {
+            ipc_client_log(client, "Mapping modem image data to memory failed");
+            goto error;
+    }
+    ipc_client_log(client, "Mapped modem image data to memory");
+
+    modem_boot_fd = open(XMM6260_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (modem_boot_fd < 0) {
+        ipc_client_log(client, "Opening modem boot device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem boot device");
+
+    modem_link_fd = open(XMM6260_SEC_MODEM_LINK_PM_DEVICE, O_RDWR);
+    if (modem_link_fd < 0) {
+        ipc_client_log(client, "Opening modem link device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem link device");
+
+    rc = xmm6260_sec_modem_power(modem_boot_fd, 0);
+    rc |= xmm6260_sec_modem_link_control_enable(modem_link_fd, 0);
+    rc |= xmm6260_sec_modem_hci_power(0);
+    rc |= xmm6260_sec_modem_link_control_active(modem_link_fd, 0);
+
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem off failed");
+        goto error;
+    }
+    ipc_client_log(client, "Turned the modem off");
+
+    rc = xmm6260_sec_modem_power(modem_boot_fd, 1);
+    rc |= xmm6260_sec_modem_link_control_enable(modem_link_fd, 1);
+    rc |= xmm6260_sec_modem_hci_power(1);
+    rc |= xmm6260_sec_modem_link_control_active(modem_link_fd, 1);
+
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem on failed");
+        goto error;
+    }
+    ipc_client_log(client, "Turned the modem on");
+
+    rc = xmm6260_sec_modem_link_connected_wait(modem_link_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Waiting for link connected failed");
+        goto error;
+    }
+    ipc_client_log(client, "Waited for link connected");
+
+    p = (unsigned char *) modem_image_data + GALAXYS2_PSI_OFFSET;
+
+    rc = xmm6260_hsic_psi_send(client, modem_boot_fd, (void *) p, GALAXYS2_PSI_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC PSI failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC PSI");
+
+    p = (unsigned char *) modem_image_data + GALAXYS2_EBL_OFFSET;
+
+    rc = xmm6260_hsic_ebl_send(client, modem_boot_fd, (void *) p, GALAXYS2_EBL_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC EBL failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC EBL");
+
+    rc = xmm6260_hsic_port_config_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC port config failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC port config");
+
+    p = (unsigned char *) modem_image_data + GALAXYS2_SEC_START_OFFSET;
+
+    rc = xmm6260_hsic_sec_start_send(client, modem_boot_fd, (void *) p, GALAXYS2_SEC_START_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC SEC start failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC SEC start");
+
+    p = (unsigned char *) modem_image_data + GALAXYS2_FIRMWARE_OFFSET;
+
+    rc = xmm6260_hsic_firmware_send(client, modem_boot_fd, (void *) p, GALAXYS2_FIRMWARE_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC firmware failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC firmware");
+
+    rc = xmm6260_hsic_nv_data_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC nv_data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC nv_data");
+
+    rc = xmm6260_hsic_sec_end_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC SEC end failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC SEC end");
+
+    rc = xmm6260_hsic_hw_reset_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 HSIC HW reset failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 HSIC HW reset");
+
+    usleep(300000);
+
+    rc = xmm6260_sec_modem_link_get_hostwake_wait(modem_link_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Waiting for host wake failed");
+    }
+
+    rc = xmm6260_sec_modem_link_control_enable(modem_link_fd, 0);
+    rc |= xmm6260_sec_modem_hci_power(0);
+    rc |= xmm6260_sec_modem_link_control_active(modem_link_fd, 0);
+
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem off failed");
+        goto error;
+    }
+
+    rc = xmm6260_sec_modem_link_get_hostwake_wait(modem_link_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Waiting for host wake failed");
+        goto error;
+    }
+    ipc_client_log(client, "Waited for host wake");
+
+    rc = xmm6260_sec_modem_link_control_enable(modem_link_fd, 1);
+    rc |= xmm6260_sec_modem_hci_power(1);
+    rc |= xmm6260_sec_modem_link_control_active(modem_link_fd, 1);
+
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem on failed");
+        goto error;
+    }
+
+    rc = xmm6260_sec_modem_link_connected_wait(modem_link_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Waiting for link connected failed");
+        goto error;
+    }
+    ipc_client_log(client, "Waited for link connected");
+
+    usleep(300000);
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (modem_image_data != NULL)
+        munmap(modem_image_data, GALAXYS2_MODEM_IMAGE_SIZE);
+
+    if (modem_image_fd >= 0)
+        close(modem_image_fd);
+
+    if (modem_boot_fd >= 0)
+        close(modem_boot_fd);
+
+    if (modem_link_fd >= 0)
+        close(modem_link_fd);
+
+    return rc;
+}
+
+
+int galaxys2_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    return xmm6260_sec_modem_ipc_fmt_send(client, request);
+}
+
+int galaxys2_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    return xmm6260_sec_modem_ipc_fmt_recv(client, response);
+}
+
+int galaxys2_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    return xmm6260_sec_modem_ipc_rfs_send(client, request);
+}
+
+int galaxys2_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    return xmm6260_sec_modem_ipc_rfs_recv(client, response);
+}
+
+int galaxys2_ipc_open(void *data, int type)
+{
+    struct galaxys2_ipc_transport_data *transport_data;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct galaxys2_ipc_transport_data *) data;
+
+    transport_data->fd = xmm6260_sec_modem_ipc_open(type);
+    if (transport_data->fd < 0)
+        return -1;
+
+    return 0;
+}
+
+int galaxys2_ipc_close(void *data)
+{
+    struct galaxys2_ipc_transport_data *transport_data;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct galaxys2_ipc_transport_data *) data;
+
+    xmm6260_sec_modem_ipc_close(transport_data->fd);
+    transport_data->fd = -1;
+
+    return 0;
+}
+
+int galaxys2_ipc_read(void *data, void *buffer, unsigned int length)
+{
+    struct galaxys2_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct galaxys2_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_read(transport_data->fd, buffer, length);
+    return rc;
+}
+
+int galaxys2_ipc_write(void *data, void *buffer, unsigned int length)
+{
+    struct galaxys2_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct galaxys2_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_write(transport_data->fd, buffer, length);
+    return rc;
+}
+
+int galaxys2_ipc_poll(void *data, struct timeval *timeout)
+{
+    struct galaxys2_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct galaxys2_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_poll(transport_data->fd, timeout);
+    return rc;
+}
+
+int galaxys2_ipc_power_on(void *data)
+{
+    return 0;
+}
+
+int galaxys2_ipc_power_off(void *data)
+{
+    int fd;
+    int rc;
+
+    fd = open(XMM6260_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (fd < 0)
+        return -1;
+
+    rc = xmm6260_sec_modem_power(fd, 0);
+
+    close(fd);
+
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int galaxys2_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
+{
+    if (transport_data == NULL)
+        return -1;
+
+    *transport_data = (void *) malloc(sizeof(struct galaxys2_ipc_transport_data));
+    memset(*transport_data, 0, sizeof(struct galaxys2_ipc_transport_data));
+
+    return 0;
+}
+
+int galaxys2_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
+{
+    if (transport_data == NULL)
+        return -1;
+
+    free(transport_data);
+
+    return 0;
+}
+
+char *galaxys2_ipc_gprs_get_iface(int cid)
+{
+    return xmm6260_sec_modem_ipc_gprs_get_iface(cid);
+}
 
-#include "ipc.h"
 
-#include "xmm6260_ipc.h"
-#include "galaxys2_loader.h"
+int galaxys2_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
+{
+    return xmm6260_sec_modem_ipc_gprs_get_capabilities(capabilities);
+}
 
 struct ipc_ops galaxys2_ipc_fmt_ops = {
     .bootstrap = galaxys2_ipc_bootstrap,
-    .send = xmm6260_ipc_fmt_send,
-    .recv = xmm6260_ipc_fmt_recv,
+    .send = galaxys2_ipc_fmt_send,
+    .recv = galaxys2_ipc_fmt_recv,
 };
 
 struct ipc_ops galaxys2_ipc_rfs_ops = {
     .bootstrap = NULL,
-    .send = xmm6260_ipc_rfs_send,
-    .recv = xmm6260_ipc_rfs_recv,
+    .send = galaxys2_ipc_rfs_send,
+    .recv = galaxys2_ipc_rfs_recv,
 };
 
 struct ipc_handlers galaxys2_ipc_handlers = {
-    .open = xmm6260_ipc_open,
-    .close = xmm6260_ipc_close,
-    .read = xmm6260_ipc_read,
-    .write = xmm6260_ipc_write,
-    .poll = xmm6260_ipc_poll,
+    .read = galaxys2_ipc_read,
+    .write = galaxys2_ipc_write,
+    .open = galaxys2_ipc_open,
+    .close = galaxys2_ipc_close,
+    .poll = galaxys2_ipc_poll,
     .transport_data = NULL,
-    .power_on = xmm6260_ipc_power_on,
-    .power_off = xmm6260_ipc_power_off,
+    .power_on = galaxys2_ipc_power_on,
+    .power_off = galaxys2_ipc_power_off,
     .power_data = NULL,
     .gprs_activate = NULL,
     .gprs_deactivate = NULL,
     .gprs_data = NULL,
-    .data_create = xmm6260_ipc_data_create,
-    .data_destroy = xmm6260_ipc_data_destroy,
+    .data_create = galaxys2_ipc_data_create,
+    .data_destroy = galaxys2_ipc_data_destroy,
 };
 
 struct ipc_gprs_specs galaxys2_ipc_gprs_specs = {
-    .gprs_get_iface = xmm6260_ipc_gprs_get_iface,
-    .gprs_get_capabilities = xmm6260_ipc_gprs_get_capabilities,
+    .gprs_get_iface = galaxys2_ipc_gprs_get_iface,
+    .gprs_get_capabilities = galaxys2_ipc_gprs_get_capabilities,
 };
 
 // vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/galaxys2/galaxys2_ipc.h b/samsung-ipc/device/galaxys2/galaxys2_ipc.h
new file mode 100644 (file)
index 0000000..a7e17c2
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __GALAXYS2_IPC_H__
+#define __GALAXYS2_IPC_H__
+
+#define GALAXYS2_MODEM_IMAGE_SIZE                               0x1000000
+#define GALAXYS2_PSI_OFFSET                                     0
+#define GALAXYS2_PSI_SIZE                                       0xF000
+#define GALAXYS2_EBL_OFFSET                                     0xF000
+#define GALAXYS2_EBL_SIZE                                       0x19000
+#define GALAXYS2_SEC_START_OFFSET                               0x9FF800
+#define GALAXYS2_SEC_START_SIZE                                 0x800
+#define GALAXYS2_FIRMWARE_OFFSET                                0x28000
+#define GALAXYS2_FIRMWARE_SIZE                                  0x9D8000
+#define GALAXYS2_NV_DATA_OFFSET                                 0xA00000
+#define GALAXYS2_NV_DATA_SIZE                                   0x200000
+
+#define GALAXYS2_MODEM_IMAGE_DEVICE             "/dev/block/mmcblk0p8"
+
+struct galaxys2_ipc_transport_data {
+    int fd;
+};
+
+#endif
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/galaxys2/galaxys2_loader.c b/samsung-ipc/device/galaxys2/galaxys2_loader.c
deleted file mode 100644 (file)
index 03dca93..0000000
+++ /dev/null
@@ -1,765 +0,0 @@
-/*
- * Firmware loader for Samsung I9100 (galaxys2)
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <getopt.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-//for timeval
-#include <sys/time.h>
-
-//for mmap
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "ipc.h"
-
-#include "galaxys2_loader.h"
-#include "xmm6260_loader.h"
-#include "xmm6260_modemctl.h"
-#include "modem_prj.h"
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-
-/*
- * Locations of the firmware components in the Samsung firmware
- */
-
-struct xmm6260_radio_part galaxys2_radio_parts[] = {
-    [PSI] = {
-        .offset = 0,
-        .length = 0xf000,
-    },
-    [EBL] = {
-        .offset = 0xf000,
-        .length = 0x19000,
-    },
-    [SECURE_IMAGE] = {
-        .offset = 0x9ff800,
-        .length = 0x800,
-    },
-    [FIRMWARE] = {
-        .offset = 0x28000,
-        .length = 0x9d8000,
-    },
-    [NVDATA] = {
-        .offset = 0xa00000,
-        .length = 2 << 20,
-    }
-};
-
-struct galaxys2_boot_cmd_desc galaxys2_boot_cmd_desc[] = {
-    [SetPortConf] = {
-        .code = 0x86,
-        .data_size = 0x800,
-        .need_ack = 1,
-    },
-    [ReqSecStart] = {
-        .code = 0x204,
-        .data_size = 0x4000,
-        .need_ack = 1,
-    },
-    [ReqSecEnd] = {
-        .code = 0x205,
-        .data_size = 0x4000,
-        .need_ack = 1,
-    },
-    [ReqForceHwReset] = {
-        .code = 0x208,
-        .data_size = 0x4000,
-        .need_ack = 0,
-    },
-    [ReqFlashSetAddress] = {
-        .code = 0x802,
-        .data_size = 0x4000,
-        .need_ack = 1,
-    },
-    [ReqFlashWriteBlock] = {
-        .code = 0x804,
-        .data_size = 0x4000,
-        .need_ack = 0,
-    }
-};
-
-static int galaxys2_send_image(struct ipc_client *client,
-    struct modemctl_io_data *io_data, enum xmm6260_image type)
-{
-    int ret = -1;
-
-    if (type >= ARRAY_SIZE(galaxys2_radio_parts)) {
-        ipc_client_log(client, "Error: bad image type %x", type);
-        goto fail;
-    }
-    size_t length = galaxys2_radio_parts[type].length;
-    size_t offset = galaxys2_radio_parts[type].offset;
-
-    size_t start = offset;
-    size_t end = length + start;
-
-    //dump some image bytes
-    ipc_client_log(client, "image start");
-
-    while (start < end) {
-        ret = write(io_data->boot_fd, io_data->radio_data + start, end - start);
-        if (ret < 0) {
-            ipc_client_log(client, "failed to write image chunk");
-            goto fail;
-        }
-        start += ret;
-    }
-
-    unsigned char crc = xmm6260_crc_calculate(io_data->radio_data, offset, length);
-
-    if ((ret = write(io_data->boot_fd, &crc, 1)) < 1) {
-        ipc_client_log(client, "failed to write CRC");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "wrote CRC %x", crc);
-    }
-
-    return 0;
-
-fail:
-    return ret;
-}
-
-static int galaxys2_send_psi(struct ipc_client *client, struct modemctl_io_data *io_data)
-{
-    size_t length = galaxys2_radio_parts[PSI].length;
-
-    struct galaxys2_psi_header hdr = {
-        .magic = XMM_PSI_MAGIC,
-        .length = length,
-        .padding = 0xff,
-    };
-    int ret = -1;
-
-    if ((ret = write(io_data->boot_fd, &hdr, sizeof(hdr))) != sizeof(hdr)) {
-        ipc_client_log(client, "%s: failed to write header, ret %d", __func__, ret);
-        goto fail;
-    }
-
-    if ((ret = galaxys2_send_image(client, io_data, PSI)) < 0) {
-        ipc_client_log(client, "Error: failed to send PSI image");
-        goto fail;
-    }
-
-    int i;
-    for (i = 0; i < 22; i++) {
-        char ack;
-        if (expect_read(io_data->boot_fd, &ack, 1) < 1) {
-            ipc_client_log(client, "failed to read ACK byte %d", i);
-            goto fail;
-        }
-    }
-
-    if ((ret = expect_data(io_data->boot_fd, "\x1", 1)) < 0) {
-        ipc_client_log(client, "failed to wait for first ACK");
-        goto fail;
-    }
-
-    if ((ret = expect_data(io_data->boot_fd, "\x1", 1)) < 0) {
-        ipc_client_log(client, "failed to wait for second ACK");
-        goto fail;
-    }
-
-    if ((ret = expect_data(io_data->boot_fd, PSI_ACK_MAGIC, 2)) < 0) {
-        ipc_client_log(client, "Error: failed to receive PSI ACK");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "received PSI ACK");
-    }
-
-    return 0;
-
-fail:
-    return ret;
-}
-
-static int galaxys2_send_ebl(struct ipc_client *client, struct modemctl_io_data *io_data)
-{
-    int ret;
-    int fd = io_data->boot_fd;
-    unsigned length = galaxys2_radio_parts[EBL].length;
-
-    if ((ret = write(fd, &length, sizeof(length))) < 0) {
-        ipc_client_log(client, "Error: failed to write EBL length");
-        goto fail;
-    }
-
-    if ((ret = expect_data(fd, EBL_HDR_ACK_MAGIC, 2)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for EBL header ACK");
-        goto fail;
-    }
-
-    if ((ret = galaxys2_send_image(client, io_data, EBL)) < 0) {
-        ipc_client_log(client, "Error: failed to send EBL image");
-        goto fail;
-    }
-
-    if ((ret = expect_data(fd, EBL_IMG_ACK_MAGIC, 2)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for EBL image ACK");
-        goto fail;
-    }
-
-    return 0;
-
-fail:
-    return ret;
-}
-
-static int galaxys2_boot_cmd(struct ipc_client *client,
-    struct modemctl_io_data *io_data, enum xmm6260_boot_cmd cmd,
-    void *data, size_t data_size)
-{
-    int ret = 0;
-    char *cmd_data = 0;
-    if (cmd >= ARRAY_SIZE(galaxys2_boot_cmd_desc)) {
-        ipc_client_log(client, "Error: bad command %x\n", cmd);
-        goto done_or_fail;
-    }
-
-    unsigned cmd_code = galaxys2_boot_cmd_desc[cmd].code;
-
-    uint16_t magic = (data_size & 0xffff) + cmd_code;
-    unsigned char *ptr = (unsigned char*)data;
-    size_t i;
-    for (i = 0; i < data_size; i++) {
-        magic += ptr[i];
-    }
-
-    struct galaxys2_boot_cmd header = {
-        .check = magic,
-        .cmd = cmd_code,
-        .data_size = data_size,
-    };
-
-    size_t cmd_size = galaxys2_boot_cmd_desc[cmd].data_size;
-    size_t buf_size = cmd_size + sizeof(header);
-
-    cmd_data = (char*)malloc(buf_size);
-    if (!cmd_data) {
-        ipc_client_log(client, "Error: failed to allocate command buffer");
-        ret = -ENOMEM;
-        goto done_or_fail;
-    }
-    memset(cmd_data, 0, buf_size);
-    memcpy(cmd_data, &header, sizeof(header));
-    memcpy(cmd_data + sizeof(header), data, data_size);
-
-    if ((ret = write(io_data->boot_fd, cmd_data, buf_size)) < 0) {
-        ipc_client_log(client, "Error: failed to write command to socket");
-        goto done_or_fail;
-    }
-
-    if ((unsigned)ret != buf_size) {
-        ipc_client_log(client, "Error: written %d bytes of %d", ret, buf_size);
-        ret = -EINVAL;
-        goto done_or_fail;
-    }
-
-    if (!galaxys2_boot_cmd_desc[cmd].need_ack) {
-        ret = 0;
-        goto done_or_fail;
-    }
-
-    struct galaxys2_boot_cmd ack = {
-        .check = 0,
-    };
-    if ((ret = expect_read(io_data->boot_fd, &ack, sizeof(ack))) < 0) {
-        ipc_client_log(client, "Error: failed to receive ack for cmd %x", header.cmd);
-        goto done_or_fail;
-    }
-
-    if (ret != sizeof(ack)) {
-        ipc_client_log(client, "Error: received %x bytes of %x for ack", ret, sizeof(ack));
-        ret = -EINVAL;
-        goto done_or_fail;
-    }
-
-    if (ack.cmd != header.cmd) {
-        ipc_client_log(client, "Error: ack cmd %x does not match request %x", ack.cmd, header.cmd);
-        ret = -EINVAL;
-        goto done_or_fail;
-    }
-
-    if ((ret = expect_read(io_data->boot_fd, cmd_data, cmd_size)) < 0) {
-        ipc_client_log(client, "Error: failed to receive reply data");
-        goto done_or_fail;
-    }
-
-    if ((unsigned)ret != cmd_size) {
-        ipc_client_log(client, "Error: received %x bytes of %x for reply data", ret, cmd_size);
-        ret = -EINVAL;
-        goto done_or_fail;
-    }
-
-done_or_fail:
-
-    if (cmd_data) {
-        free(cmd_data);
-    }
-
-    return ret;
-}
-
-static int galaxys2_boot_info_ack(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret;
-    struct galaxys2_boot_info info;
-
-    if ((ret = expect_read(io_data->boot_fd, &info, sizeof(info))) != sizeof(info)) {
-        ipc_client_log(client, "Error: failed to receive Boot Info ret=%d", ret);
-        ret = -1;
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "received Boot Info");
-    }
-
-    if ((ret = galaxys2_boot_cmd(client, io_data, SetPortConf, &info, sizeof(info))) < 0) {
-        ipc_client_log(client, "Error: failed to send SetPortConf command");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent SetPortConf command");
-    }
-
-    return 0;
-
-fail:
-    return ret;
-}
-
-static int galaxys2_send_image_data(struct ipc_client *client,
-    struct modemctl_io_data *io_data, uint32_t addr,
-    void *data, int data_len)
-{
-    int ret = 0;
-    int count = 0;
-    char *data_p = (char *) data;
-
-    if ((ret = galaxys2_boot_cmd(client, io_data, ReqFlashSetAddress, &addr, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to send ReqFlashSetAddress");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqFlashSetAddress");
-    }
-
-    while (count < data_len) {
-        int rest = data_len - count;
-        int chunk = rest < SEC_DOWNLOAD_CHUNK ? rest : SEC_DOWNLOAD_CHUNK;
-
-        ret = galaxys2_boot_cmd(client, io_data, ReqFlashWriteBlock, data_p, chunk);
-        if (ret < 0) {
-            ipc_client_log(client, "Error: failed to send data chunk");
-            goto fail;
-        }
-
-        data_p += chunk;
-        count += chunk;
-    }
-
-    usleep(SEC_DOWNLOAD_DELAY_US);
-
-fail:
-    return ret;
-}
-
-static int galaxys2_send_image_addr(struct ipc_client *client,
-    struct modemctl_io_data *io_data, uint32_t addr, enum xmm6260_image type)
-{
-    uint32_t offset = galaxys2_radio_parts[type].offset;
-    uint32_t length = galaxys2_radio_parts[type].length;
-    char *start = io_data->radio_data + offset;
-    int ret = 0;
-
-    ret = galaxys2_send_image_data(client, io_data, addr, start, length);
-
-    return ret;
-}
-
-static int galaxys2_send_secure_images(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret = 0;
-
-    uint32_t sec_off = galaxys2_radio_parts[SECURE_IMAGE].offset;
-    uint32_t sec_len = galaxys2_radio_parts[SECURE_IMAGE].length;
-    void *sec_img = io_data->radio_data + sec_off;
-    void *nv_data = NULL;
-
-    if ((ret = galaxys2_boot_cmd(client, io_data, ReqSecStart, sec_img, sec_len)) < 0) {
-        ipc_client_log(client, "Error: failed to write ReqSecStart");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqSecStart");
-    }
-
-    if ((ret = galaxys2_send_image_addr(client, io_data, FW_LOAD_ADDR, FIRMWARE)) < 0) {
-        ipc_client_log(client, "Error: failed to send FIRMWARE image");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent FIRMWARE image");
-    }
-
-    if (nv_data_check(client) < 0)
-        goto fail;
-
-    if (nv_data_md5_check(client) < 0)
-        goto fail;
-
-    nv_data = ipc_client_file_read(client, nv_data_path(client), 2 << 20, 1024);
-    if (nv_data == NULL) {
-        ipc_client_log(client, "Error: failed to read NVDATA image");
-        goto fail;
-    }
-
-    if ((ret = galaxys2_send_image_data(client, io_data, NVDATA_LOAD_ADDR, nv_data, 2 << 20)) < 0) {
-        ipc_client_log(client, "Error: failed to send NVDATA image");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent NVDATA image");
-    }
-
-    free(nv_data);
-
-    if ((ret = galaxys2_boot_cmd(client, io_data, ReqSecEnd,
-        BL_END_MAGIC, BL_END_MAGIC_LEN)) < 0)
-    {
-        ipc_client_log(client, "Error: failed to write ReqSecEnd");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqSecEnd");
-    }
-
-    ret = galaxys2_boot_cmd(client, io_data, ReqForceHwReset,
-        BL_RESET_MAGIC, BL_RESET_MAGIC_LEN);
-    if (ret < 0) {
-        ipc_client_log(client, "Error: failed to write ReqForceHwReset");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqForceHwReset");
-    }
-
-fail:
-    return ret;
-}
-
-/*
- * i9200 (Galaxy S2) board-specific code
- */
-
-/*
- * Power management
- */
-static int galaxys2_ehci_setpower(struct ipc_client *client, bool enabled) {
-    int ret = -1;
-
-    ipc_client_log(client, "%s: enabled=%d", __func__, enabled);
-
-    int ehci_fd = open(I9100_EHCI_PATH, O_RDWR);
-    if (ehci_fd < 0) {
-        ipc_client_log(client, "Error: failed to open EHCI fd");
-        ret = -ENODEV;
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "opened EHCI %s: fd=%d", I9100_EHCI_PATH, ehci_fd);
-    }
-
-    ret = write(ehci_fd, enabled ? "1" : "0", 1);
-
-    //must write exactly one byte
-    if (ret <= 0) {
-        ipc_client_log(client, "Error: failed to set EHCI power");
-    }
-    else {
-        ipc_client_log(client, "set EHCI power");
-    }
-
-fail:
-    if (ehci_fd >= 0) {
-        close(ehci_fd);
-    }
-
-    return ret;
-}
-
-static int galaxys2_modem_reboot(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool hard) {
-    int ret;
-
-    //wait for link to become ready before redetection
-    if (!hard) {
-        if ((ret = modemctl_wait_link_ready(client, io_data)) < 0) {
-            ipc_client_log(client, "Error: failed to wait for link to get ready for redetection");
-            goto fail;
-        }
-        else {
-            ipc_client_log(client, "link ready for redetection");
-        }
-    }
-
-    /*
-     * Disable the hardware to ensure consistent state
-     */
-    if (hard) {
-        if ((ret = modemctl_modem_power(client, io_data, false)) < 0) {
-            ipc_client_log(client, "Error: failed to disable xmm6260 power");
-            goto fail;
-        }
-        else {
-            ipc_client_log(client, "disabled xmm6260 power");
-        }
-    }
-
-    if ((ret = modemctl_link_set_enabled(client, io_data, false)) < 0) {
-        ipc_client_log(client, "Error: failed to disable I9100 HSIC link");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "disabled I9100 HSIC link");
-    }
-
-    if ((ret = galaxys2_ehci_setpower(client, false)) < 0) {
-        ipc_client_log(client, "Error: failed to disable I9100 EHCI");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "disabled I9100 EHCI");
-    }
-
-    if ((ret = modemctl_link_set_active(client, io_data, false)) < 0) {
-        ipc_client_log(client, "Error: failed to deactivate I9100 HSIC link");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "deactivated I9100 HSIC link");
-    }
-
-    /*
-     * Now, initialize the hardware
-     */
-
-    if ((ret = modemctl_link_set_enabled(client, io_data, true)) < 0) {
-        ipc_client_log(client, "Error: failed to enable I9100 HSIC link");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "enabled I9100 HSIC link");
-    }
-
-    if ((ret = galaxys2_ehci_setpower(client, true)) < 0) {
-        ipc_client_log(client, "Error: failed to enable I9100 EHCI");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "enabled I9100 EHCI");
-    }
-
-    if ((ret = modemctl_link_set_active(client, io_data, true)) < 0) {
-        ipc_client_log(client, "Error: failed to activate I9100 HSIC link");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "activated I9100 HSIC link");
-    }
-
-    if (hard) {
-        if ((ret = modemctl_modem_power(client, io_data, true)) < 0) {
-            ipc_client_log(client, "Error: failed to enable xmm6260 power");
-            goto fail;
-        }
-        else {
-            ipc_client_log(client, "enabled xmm6260 power");
-        }
-    }
-
-    if ((ret = modemctl_wait_link_ready(client, io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for link to get ready");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "link ready");
-    }
-
-fail:
-    return ret;
-}
-
-int galaxys2_ipc_bootstrap(struct ipc_client *client) {
-    int ret = 0;
-    struct modemctl_io_data io_data;
-    memset(&io_data, 0, sizeof(client, io_data));
-
-    io_data.radio_fd = open(RADIO_IMAGE, O_RDONLY);
-    if (io_data.radio_fd < 0) {
-        ipc_client_log(client, "Error: failed to open radio firmware");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "opened radio image %s, fd=%d", RADIO_IMAGE, io_data.radio_fd);
-    }
-
-    if (fstat(io_data.radio_fd, &io_data.radio_stat) < 0) {
-        ipc_client_log(client, "Error: failed to stat radio image, error %s", strerror(errno));
-        goto fail;
-    }
-
-    io_data.radio_data = mmap(0, RADIO_MAP_SIZE, PROT_READ, MAP_SHARED,
-        io_data.radio_fd, 0);
-    if (io_data.radio_data == MAP_FAILED) {
-        ipc_client_log(client, "Error: failed to mmap radio image, error %s", strerror(errno));
-        goto fail;
-    }
-
-    io_data.boot_fd = open(BOOT_DEV, O_RDWR | O_NOCTTY | O_NONBLOCK);
-    if (io_data.boot_fd < 0) {
-        ipc_client_log(client, "Error: failed to open boot device");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "opened boot device %s, fd=%d", BOOT_DEV, io_data.boot_fd);
-    }
-
-    io_data.link_fd = open(LINK_PM, O_RDWR);
-    if (io_data.link_fd < 0) {
-        ipc_client_log(client, "Error: failed to open link device");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "opened link device %s, fd=%d", LINK_PM, io_data.link_fd);
-    }
-
-    if (galaxys2_modem_reboot(client, &io_data, true)) {
-        ipc_client_log(client, "Error: failed to hard reset modem");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "modem hard reset done");
-    }
-
-    /*
-     * Now, actually load the firmware
-     */
-    if (write(io_data.boot_fd, "ATAT", 4) != 4) {
-        ipc_client_log(client, "Error: failed to write ATAT to boot socket");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "written ATAT to boot socket, waiting for ACK");
-    }
-
-    char buf[2];
-    if (expect_read(io_data.boot_fd, buf, 1) < 0) {
-        ipc_client_log(client, "Error: failed to receive bootloader ACK");
-        goto fail;
-    }
-    if (expect_read(io_data.boot_fd, buf + 1, 1) < 0) {
-        ipc_client_log(client, "Error: failed to receive chip IP ACK");
-        goto fail;
-    }
-    ipc_client_log(client, "receive ID: [%02x %02x]", buf[0], buf[1]);
-
-    if ((ret = galaxys2_send_psi(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to upload PSI");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "PSI download complete");
-    }
-
-    if ((ret = galaxys2_send_ebl(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to upload EBL");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "EBL download complete");
-    }
-
-    if ((ret = galaxys2_boot_info_ack(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to receive Boot Info");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "Boot Info ACK done");
-    }
-
-    if ((ret = galaxys2_send_secure_images(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to upload Secure Image");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "Secure Image download complete");
-    }
-
-    usleep(POST_BOOT_TIMEOUT_US);
-
-    if ((ret = galaxys2_modem_reboot(client, &io_data, false))) {
-        ipc_client_log(client, "Error: failed to soft reset modem");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "modem soft reset done");
-    }
-
-    ipc_client_log(client, "Modem is online!");
-    ret = 0;
-
-fail:
-    if (io_data.radio_data != MAP_FAILED) {
-        munmap(io_data.radio_data, RADIO_MAP_SIZE);
-    }
-
-    if (io_data.link_fd >= 0) {
-        close(io_data.link_fd);
-    }
-
-    if (io_data.radio_fd >= 0) {
-        close(io_data.radio_fd);
-    }
-
-    if (io_data.boot_fd >= 0) {
-        close(io_data.boot_fd);
-    }
-
-    return ret;
-}
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/galaxys2/galaxys2_loader.h b/samsung-ipc/device/galaxys2/galaxys2_loader.h
deleted file mode 100644 (file)
index e300d70..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Firmware loader for Samsung I9100 (galaxys2)
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifndef __GALAXYS2_LOADER_H__
-#define __GALAXYS2_LOADER_H__
-
-#define RADIO_IMAGE "/dev/block/mmcblk0p8"
-#define I9100_EHCI_PATH "/sys/devices/platform/s5p-ehci/ehci_power"
-
-#define LINK_POLL_DELAY_US (50 * 1000)
-#define LINK_TIMEOUT_MS 2000
-
-#define XMM_PSI_MAGIC 0x30
-#define PSI_ACK_MAGIC "\x00\xaa"
-
-#define EBL_HDR_ACK_MAGIC "\xcc\xcc"
-#define EBL_IMG_ACK_MAGIC "\x51\xa5"
-
-#define BL_END_MAGIC "\x00\x00"
-#define BL_END_MAGIC_LEN 2
-
-#define BL_RESET_MAGIC "\x01\x10\x11\x00"
-#define BL_RESET_MAGIC_LEN 4
-
-#define SEC_DOWNLOAD_CHUNK 16384
-#define SEC_DOWNLOAD_DELAY_US (500 * 1000)
-
-#define POST_BOOT_TIMEOUT_US (600 * 1000)
-
-#define FW_LOAD_ADDR 0x60300000
-#define NVDATA_LOAD_ADDR 0x60e80000
-
-struct galaxys2_boot_cmd_desc {
-    unsigned code;
-    size_t data_size;
-    bool need_ack;
-};
-
-struct galaxys2_psi_header {
-    uint8_t magic;
-    uint16_t length;
-    uint8_t padding;
-} __attribute__((packed));
-
-struct galaxys2_boot_info {
-    uint8_t data[76];
-} __attribute__((packed));
-
-struct galaxys2_boot_cmd {
-    uint16_t check;
-    uint16_t cmd;
-    uint32_t data_size;
-} __attribute__((packed));
-
-int galaxys2_ipc_bootstrap(struct ipc_client *client);
-
-#endif
-
-// vim:ts=4:sw=4:expandtab
index f68e7e6..4774f08 100644 (file)
@@ -1,14 +1,8 @@
-/**
+/*
  * This file is part of libsamsung-ipc.
  *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
  * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on crespo IPC code which is:
- *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- *                    Joerie de Gram <j.de.gram@gmail.com>
- *                    Simon Busch <morphis@gravedo.de>
  *
  * libsamsung-ipc is free software: you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  */
 
 #include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include <samsung-ipc.h>
+#include <ipc.h>
+#include <util.h>
+
+#include "xmm6260.h"
+#include "xmm6260_mipi.h"
+#include "xmm6260_sec_modem.h"
+#include "maguro_ipc.h"
+
+int maguro_ipc_bootstrap(struct ipc_client *client)
+{
+    void *modem_image_data = NULL;
+    int modem_image_fd = -1;
+    int modem_boot_fd = -1;
+    void *mps_data = NULL;
+
+    unsigned char *p;
+    int rc;
+
+    if (client == NULL)
+        return -1;
+
+    ipc_client_log(client, "Starting maguro modem bootstrap");
+
+    modem_image_fd = open(MAGURO_MODEM_IMAGE_DEVICE, O_RDONLY);
+    if (modem_image_fd < 0) {
+        ipc_client_log(client, "Opening modem image device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem image device");
+
+    modem_image_data = mmap(0, MAGURO_MODEM_IMAGE_SIZE, PROT_READ, MAP_SHARED, modem_image_fd, 0);
+    if (modem_image_data == NULL || modem_image_data == (void *) 0xffffffff) {
+            ipc_client_log(client, "Mapping modem image data to memory failed");
+            goto error;
+    }
+    ipc_client_log(client, "Mapped modem image data to memory");
+
+    modem_boot_fd = open(XMM6260_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (modem_boot_fd < 0) {
+        ipc_client_log(client, "Opening modem boot device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem boot device");
+
+    rc = xmm6260_sec_modem_power(modem_boot_fd, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem off failed");
+        goto error;
+    }
+    ipc_client_log(client, "Turned the modem off");
+
+    rc = xmm6260_sec_modem_power(modem_boot_fd, 1);
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem on failed");
+        goto error;
+    }
+    ipc_client_log(client, "Turned the modem on");
+
+    p = (unsigned char *) modem_image_data + MAGURO_PSI_OFFSET;
+
+    rc = xmm6260_mipi_psi_send(client, modem_boot_fd, (void *) p, MAGURO_PSI_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI PSI failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI PSI");
+
+    close(modem_boot_fd);
+
+    modem_boot_fd = open(XMM6260_SEC_MODEM_BOOT1_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (modem_boot_fd < 0) {
+        ipc_client_log(client, "Opening modem boot device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem boot device");
+
+    p = (unsigned char *) modem_image_data + MAGURO_EBL_OFFSET;
+
+    rc = xmm6260_mipi_ebl_send(client, modem_boot_fd, (void *) p, MAGURO_EBL_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI EBL failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI EBL");
+
+    rc = xmm6260_mipi_port_config_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI port config failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI port config");
+
+    p = (unsigned char *) modem_image_data + MAGURO_SEC_START_OFFSET;
+
+    rc = xmm6260_mipi_sec_start_send(client, modem_boot_fd, (void *) p, MAGURO_SEC_START_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI SEC start failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI SEC start");
+
+    p = (unsigned char *) modem_image_data + MAGURO_FIRMWARE_OFFSET;
+
+    rc = xmm6260_mipi_firmware_send(client, modem_boot_fd, (void *) p, MAGURO_FIRMWARE_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI firmware failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI firmware");
+
+    rc = xmm6260_mipi_nv_data_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI nv_data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI nv_data");
+
+    mps_data = file_data_read(MAGURO_MPS_DATA_DEVICE, MAGURO_MPS_DATA_SIZE, MAGURO_MPS_DATA_SIZE);
+    if (mps_data == NULL) {
+        ipc_client_log(client, "Reading MPS data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read MPS data");
+
+    rc = xmm6260_mipi_mps_data_send(client, modem_boot_fd, mps_data, MAGURO_MPS_DATA_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI MPS data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI MPS data");
+
+    rc = xmm6260_mipi_sec_end_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI SEC end failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI SEC end");
+
+    rc = xmm6260_mipi_hw_reset_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI HW reset failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI HW reset");
+
+    rc = xmm6260_sec_modem_status_online_wait(modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Waiting for online status failed");
+        goto error;
+    }
+    ipc_client_log(client, "Waited for online status");
+
+    rc = xmm6260_sec_modem_boot_power(modem_boot_fd, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Turning modem boot off failed");
+        goto error;
+    }
+    ipc_client_log(client, "Turned modem boot off");
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (mps_data != NULL)
+        free(mps_data);
+
+    if (modem_image_data != NULL)
+        munmap(modem_image_data, MAGURO_MODEM_IMAGE_SIZE);
+
+    if (modem_image_fd >= 0)
+        close(modem_image_fd);
+
+    if (modem_boot_fd >= 0)
+        close(modem_boot_fd);
+
+    return rc;
+}
+
+
+int maguro_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    return xmm6260_sec_modem_ipc_fmt_send(client, request);
+}
+
+int maguro_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    return xmm6260_sec_modem_ipc_fmt_recv(client, response);
+}
+
+int maguro_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    return xmm6260_sec_modem_ipc_rfs_send(client, request);
+}
+
+int maguro_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    return xmm6260_sec_modem_ipc_rfs_recv(client, response);
+}
+
+int maguro_ipc_open(void *data, int type)
+{
+    struct maguro_ipc_transport_data *transport_data;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct maguro_ipc_transport_data *) data;
+
+    transport_data->fd = xmm6260_sec_modem_ipc_open(type);
+    if (transport_data->fd < 0)
+        return -1;
+
+    return 0;
+}
+
+int maguro_ipc_close(void *data)
+{
+    struct maguro_ipc_transport_data *transport_data;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct maguro_ipc_transport_data *) data;
+
+    xmm6260_sec_modem_ipc_close(transport_data->fd);
+    transport_data->fd = -1;
+
+    return 0;
+}
+
+int maguro_ipc_read(void *data, void *buffer, unsigned int length)
+{
+    struct maguro_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct maguro_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_read(transport_data->fd, buffer, length);
+    return rc;
+}
+
+int maguro_ipc_write(void *data, void *buffer, unsigned int length)
+{
+    struct maguro_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct maguro_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_write(transport_data->fd, buffer, length);
+    return rc;
+}
+
+int maguro_ipc_poll(void *data, struct timeval *timeout)
+{
+    struct maguro_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct maguro_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_poll(transport_data->fd, timeout);
+    return rc;
+}
+
+int maguro_ipc_power_on(void *data)
+{
+    return 0;
+}
+
+int maguro_ipc_power_off(void *data)
+{
+    int fd;
+    int rc;
+
+    fd = open(XMM6260_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (fd < 0)
+        return -1;
+
+    rc = xmm6260_sec_modem_power(fd, 0);
+
+    close(fd);
+
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int maguro_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
+{
+    if (transport_data == NULL)
+        return -1;
+
+    *transport_data = (void *) malloc(sizeof(struct maguro_ipc_transport_data));
+    memset(*transport_data, 0, sizeof(struct maguro_ipc_transport_data));
+
+    return 0;
+}
+
+int maguro_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
+{
+    if (transport_data == NULL)
+        return -1;
+
+    free(transport_data);
+
+    return 0;
+}
+
+char *maguro_ipc_gprs_get_iface(int cid)
+{
+    return xmm6260_sec_modem_ipc_gprs_get_iface(cid);
+}
 
-#include "ipc.h"
 
-#include "xmm6260_ipc.h"
-#include "maguro_loader.h"
+int maguro_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
+{
+    return xmm6260_sec_modem_ipc_gprs_get_capabilities(capabilities);
+}
 
 struct ipc_ops maguro_ipc_fmt_ops = {
     .bootstrap = maguro_ipc_bootstrap,
-    .send = xmm6260_ipc_fmt_send,
-    .recv = xmm6260_ipc_fmt_recv,
+    .send = maguro_ipc_fmt_send,
+    .recv = maguro_ipc_fmt_recv,
 };
 
 struct ipc_ops maguro_ipc_rfs_ops = {
     .bootstrap = NULL,
-    .send = xmm6260_ipc_rfs_send,
-    .recv = xmm6260_ipc_rfs_recv,
+    .send = maguro_ipc_rfs_send,
+    .recv = maguro_ipc_rfs_recv,
 };
 
 struct ipc_handlers maguro_ipc_handlers = {
-    .open = xmm6260_ipc_open,
-    .close = xmm6260_ipc_close,
-    .read = xmm6260_ipc_read,
-    .write = xmm6260_ipc_write,
-    .poll = xmm6260_ipc_poll,
+    .read = maguro_ipc_read,
+    .write = maguro_ipc_write,
+    .open = maguro_ipc_open,
+    .close = maguro_ipc_close,
+    .poll = maguro_ipc_poll,
     .transport_data = NULL,
-    .power_on = xmm6260_ipc_power_on,
-    .power_off = xmm6260_ipc_power_off,
+    .power_on = maguro_ipc_power_on,
+    .power_off = maguro_ipc_power_off,
     .power_data = NULL,
     .gprs_activate = NULL,
     .gprs_deactivate = NULL,
     .gprs_data = NULL,
-    .data_create = xmm6260_ipc_data_create,
-    .data_destroy = xmm6260_ipc_data_destroy,
+    .data_create = maguro_ipc_data_create,
+    .data_destroy = maguro_ipc_data_destroy,
 };
 
 struct ipc_gprs_specs maguro_ipc_gprs_specs = {
-    .gprs_get_iface = xmm6260_ipc_gprs_get_iface,
-    .gprs_get_capabilities = xmm6260_ipc_gprs_get_capabilities,
+    .gprs_get_iface = maguro_ipc_gprs_get_iface,
+    .gprs_get_capabilities = maguro_ipc_gprs_get_capabilities,
 };
 
 struct ipc_nv_data_specs maguro_ipc_nv_data_specs = {
-    .nv_data_path = "/factory/nv_data.bin",
-    .nv_data_md5_path = "/factory/nv_data.bin.md5",
-    .nv_state_path = "/factory/.nv_state",
-    .nv_data_bak_path = "/factory/.nv_data.bak",
-    .nv_data_md5_bak_path = "/factory/.nv_data.bak.md5",
+    .nv_data_path = MAGURO_NV_DATA_PATH,
+    .nv_data_md5_path = MAGURO_NV_DATA_MD5_PATH,
+    .nv_state_path = MAGURO_NV_STATE_PATH,
+    .nv_data_bak_path = MAGURO_NV_DATA_BAK_PATH,
+    .nv_data_md5_bak_path = MAGURO_NV_DATA_MD5_BAK_PATH,
 };
 
 // vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/maguro/maguro_ipc.h b/samsung-ipc/device/maguro/maguro_ipc.h
new file mode 100644 (file)
index 0000000..eb4b500
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __MAGURO_IPC_H__
+#define __MAGURO_IPC_H__
+
+#define MAGURO_MODEM_IMAGE_SIZE                                 0x1000000
+#define MAGURO_PSI_OFFSET                                       0
+#define MAGURO_PSI_SIZE                                         0xF000
+#define MAGURO_EBL_OFFSET                                       0xF000
+#define MAGURO_EBL_SIZE                                         0x19000
+#define MAGURO_SEC_START_OFFSET                                 0x9FF800
+#define MAGURO_SEC_START_SIZE                                   0x800
+#define MAGURO_FIRMWARE_OFFSET                                  0x28000
+#define MAGURO_FIRMWARE_SIZE                                    0x9D8000
+#define MAGURO_NV_DATA_OFFSET                                   0xA00000
+#define MAGURO_NV_DATA_SIZE                                     0x200000
+#define MAGURO_MPS_DATA_SIZE                                    3
+
+#define MAGURO_MODEM_IMAGE_DEVICE               "/dev/block/platform/omap/omap_hsmmc.0/by-name/radio"
+#define MAGURO_MPS_DATA_DEVICE                  "/factory/imei/mps_code.dat"
+
+#define MAGURO_NV_DATA_PATH                     "/factory/nv_data.bin"
+#define MAGURO_NV_DATA_MD5_PATH                 "/factory/nv_data.bin.md5"
+#define MAGURO_NV_STATE_PATH                    "/factory/.nv_state"
+#define MAGURO_NV_DATA_BAK_PATH                 "/factory/.nv_data.bak"
+#define MAGURO_NV_DATA_MD5_BAK_PATH             "/factory/.nv_data.bak.md5"
+
+struct maguro_ipc_transport_data {
+    int fd;
+};
+
+#endif
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/maguro/maguro_loader.c b/samsung-ipc/device/maguro/maguro_loader.c
deleted file mode 100644 (file)
index 785585f..0000000
+++ /dev/null
@@ -1,844 +0,0 @@
-/*
- * Firmware loader for Samsung I9250 (maguro)
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <getopt.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#include <sys/time.h>
-
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "ipc.h"
-
-#include "maguro_loader.h"
-#include "xmm6260_loader.h"
-#include "xmm6260_modemctl.h"
-#include "modem_prj.h"
-
-#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
-
-/*
- * Locations of the firmware components in the Samsung firmware
- */
-
-struct xmm6260_radio_part maguro_radio_parts[] = {
-    [PSI] = {
-        .offset = 0,
-        .length = 0xf000,
-    },
-    [EBL] = {
-        .offset = 0xf000,
-        .length = 0x19000,
-    },
-    [SECURE_IMAGE] = {
-        .offset = 0x9ff800,
-        .length = 0x800,
-    },
-    [FIRMWARE] = {
-        .offset = 0x28000,
-        .length = 0x9d8000,
-    },
-    [NVDATA] = {
-        .offset = 0xa00000,
-        .length = 2 << 20,
-    }
-};
-
-struct maguro_boot_cmd_desc maguro_boot_cmd_desc[] = {
-    [SetPortConf] = {
-        .code = 0x86,
-        .long_tail = 1,
-    },
-    [ReqSecStart] = {
-        .code = 0x204,
-        .long_tail = 1,
-    },
-    [ReqSecEnd] = {
-        .code = 0x205,
-    },
-    [ReqForceHwReset] = {
-        .code = 0x208,
-        .long_tail = 1,
-        .no_ack = 1,
-    },
-    [ReqFlashSetAddress] = {
-        .code = 0x802,
-        .long_tail = 1,
-    },
-    [ReqFlashWriteBlock] = {
-        .code = 0x804,
-    },
-};
-
-#define I9250_RADIO_IMAGE_PATHS_NUM 2
-
-const char *i9250_radio_image_paths[] = {
-    "/dev/block/platform/omap/omap_hsmmc.0/by-name/radio",
-    "/dev/mmcblk0p9"
-};
-
-static int maguro_send_image(struct ipc_client *client,
-    struct modemctl_io_data *io_data, enum xmm6260_image type)
-{
-    int ret = -1;
-
-    if (type >= ARRAY_SIZE(maguro_radio_parts)) {
-        ipc_client_log(client, "Error: bad image type %x", type);
-        goto fail;
-    }
-
-    size_t length = maguro_radio_parts[type].length;
-    size_t offset = maguro_radio_parts[type].offset;
-
-    size_t start = offset;
-    size_t end = length + start;
-
-    unsigned char crc = xmm6260_crc_calculate(io_data->radio_data, offset, length);
-
-    //dump some image bytes
-    ipc_client_log(client, "image start");
-
-    size_t chunk_size = 0xdfc;
-
-    while (start < end) {
-        size_t remaining = end - start;
-        size_t curr_chunk = chunk_size < remaining ? chunk_size : remaining;
-
-        ret = write(io_data->boot_fd, io_data->radio_data + start, curr_chunk);
-
-        if (ret < 0) {
-            ipc_client_log(client, "Error: failed to write image chunk");
-            goto fail;
-        }
-
-        start += ret;
-    }
-
-    ipc_client_log(client, "sent image type=%d", type);
-
-    if (type == EBL) {
-        if ((ret = write(io_data->boot_fd, &crc, 1)) < 1) {
-            ipc_client_log(client, "Error: failed to write EBL CRC");
-            goto fail;
-        }
-        else {
-            ipc_client_log(client, "wrote EBL CRC %02x", crc);
-        }
-
-        goto done;
-    }
-
-    uint32_t crc32 = (crc << 24) | 0xffffff;
-
-    if ((ret = write(io_data->boot_fd, &crc32, 4)) != 4) {
-        ipc_client_log(client, "Error: failed to write CRC");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "wrote CRC %x", crc);
-    }
-
-done:
-    ret = 0;
-
-fail:
-    return ret;
-}
-
-static int maguro_send_psi(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret = -1;
-
-    if ((ret = write(io_data->boot_fd, I9250_PSI_START_MAGIC, 4)) < 0) {
-        ipc_client_log(client, "%s: failed to write header, ret %d", __func__, ret);
-        goto fail;
-    }
-
-    if ((ret = maguro_send_image(client, io_data, PSI)) < 0) {
-        ipc_client_log(client, "Error: failed to send PSI image");
-        goto fail;
-    }
-
-    char expected_acks[4][4] = {
-        "\xff\xff\xff\x01",
-        "\xff\xff\xff\x01",
-        "\x02\x00\x00\x00",
-        "\x01\xdd\x00\x00",
-    };
-
-    unsigned i;
-    for (i = 0; i < ARRAY_SIZE(expected_acks); i++) {
-        ret = expect_data(io_data->boot_fd, expected_acks[i], 4);
-        if (ret < 0) {
-            ipc_client_log(client, "failed to wait for ack %d", i);
-            goto fail;
-        }
-    }
-    ipc_client_log(client, "received PSI ACK");
-
-    return 0;
-
-fail:
-    return ret;
-}
-
-static int maguro_send_ebl(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret;
-    int fd = io_data->boot_fd;
-    unsigned length = maguro_radio_parts[EBL].length;
-
-    if ((ret = write(fd, "\x04\x00\x00\x00", 4)) != 4) {
-        ipc_client_log(client, "Error: failed to write length of EBL length ('4') ");
-        goto fail;
-    }
-
-    if ((ret = write(fd, &length, sizeof(length))) != sizeof(length)) {
-        ipc_client_log(client, "Error: failed to write EBL length");
-        goto fail;
-    }
-
-    if ((ret = expect_data(fd, I9250_GENERAL_ACK, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for EBL length ACK");
-        goto fail;
-    }
-
-    if ((ret = expect_data(fd, I9250_EBL_HDR_ACK_MAGIC, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for EBL header ACK");
-        goto fail;
-    }
-
-    length++;
-    if ((ret = write(fd, &length, sizeof(length))) != sizeof(length)) {
-        ipc_client_log(client, "Error: failed to write EBL length + 1");
-        goto fail;
-    }
-
-    if ((ret = maguro_send_image(client, io_data, EBL)) < 0) {
-        ipc_client_log(client, "Error: failed to send EBL image");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent EBL image, waiting for ACK");
-    }
-
-    if ((ret = expect_data(fd, I9250_GENERAL_ACK, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for EBL image general ACK");
-        goto fail;
-    }
-
-    if ((ret = expect_data(fd, I9250_EBL_IMG_ACK_MAGIC, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for EBL image ACK");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "got EBL ACK");
-    }
-
-    return 0;
-
-fail:
-    return ret;
-}
-
-static int maguro_boot_cmd(struct ipc_client *client,
-    struct modemctl_io_data *io_data, enum xmm6260_boot_cmd cmd,
-    void *data, size_t data_size)
-{
-    int ret = 0;
-    char *cmd_data = 0;
-    uint32_t ack_length;
-
-    if (cmd >= ARRAY_SIZE(maguro_boot_cmd_desc)) {
-        ipc_client_log(client, "Error: bad command %x\n", cmd);
-        goto done_or_fail;
-    }
-
-    unsigned cmd_code = maguro_boot_cmd_desc[cmd].code;
-    uint16_t checksum = (data_size & 0xffff) + cmd_code;
-    unsigned char *ptr = (unsigned char*)data;
-    size_t i;
-
-    for (i = 0; i < data_size; i++) {
-        checksum += ptr[i];
-    }
-
-    DECLARE_BOOT_CMD_HEADER(header, cmd_code, data_size);
-    DECLARE_BOOT_TAIL_HEADER(tail, checksum);
-
-    size_t tail_size = sizeof(tail);
-    if (!maguro_boot_cmd_desc[cmd].long_tail) {
-        tail_size -= 2;
-    }
-
-    size_t cmd_buffer_size = data_size + sizeof(header) + tail_size;
-    ipc_client_log(client, "data_size %d [%d] checksum 0x%x", data_size, cmd_buffer_size, checksum);
-
-    cmd_data = (char*)malloc(cmd_buffer_size);
-
-    if (!cmd_data) {
-        ipc_client_log(client, "Error: failed to allocate command buffer");
-        ret = -ENOMEM;
-        goto done_or_fail;
-    }
-
-    memset(cmd_data, 0, cmd_buffer_size);
-    memcpy(cmd_data, &header, sizeof(header));
-    memcpy(cmd_data + sizeof(header), data, data_size);
-    memcpy(cmd_data + sizeof(header) + data_size, &tail, tail_size);
-
-    if ((ret = write(io_data->boot_fd, cmd_data, cmd_buffer_size)) < 0) {
-        ipc_client_log(client, "Error: failed to write command to socket");
-        goto done_or_fail;
-    }
-
-    if ((unsigned)ret < cmd_buffer_size) {
-        ipc_client_log(client, "Error: written %d bytes of %d", ret, cmd_buffer_size);
-        ret = -EINVAL;
-        goto done_or_fail;
-    }
-
-    if (maguro_boot_cmd_desc[cmd].no_ack) {
-        ipc_client_log(client, "not waiting for ACK");
-        goto done_or_fail;
-    }
-
-    if ((ret = expect_read(io_data->boot_fd, &ack_length, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to receive ack header length");
-        goto done_or_fail;
-    }
-
-    if (ack_length + 4 > cmd_buffer_size) {
-        free(cmd_data);
-
-        cmd_data = NULL;
-        cmd_data = malloc(ack_length + 4);
-
-        if (!cmd_data) {
-            ipc_client_log(client, "Error: failed to allocate the buffer for ack data");
-            goto done_or_fail;
-        }
-    }
-
-    memset(cmd_data, 0, ack_length);
-    memcpy(cmd_data, &ack_length, 4);
-
-    for (i = 0; i < (ack_length + 3) / 4; i++) {
-        if ((ret = expect_read(io_data->boot_fd, cmd_data + ((i + 1) << 2), 4)) < 0) {
-            ipc_client_log(client, "Error: failed to receive ack chunk");
-            goto done_or_fail;
-        }
-    }
-
-    ipc_client_log(client, "received ack");
-
-    struct maguro_boot_cmd_header *ack_hdr = (struct maguro_boot_cmd_header*)cmd_data;
-    struct maguro_boot_tail_header *ack_tail = (struct maguro_boot_tail_header*)
-        (cmd_data + ack_length + 4 - sizeof(struct maguro_boot_tail_header));
-
-    ipc_client_log(client, "ack code 0x%x checksum 0x%x", ack_hdr->cmd, ack_tail->checksum);
-    if (ack_hdr->cmd != header.cmd) {
-        ipc_client_log(client, "Error: request and ack command codes do not match");
-        ret = -1;
-        goto done_or_fail;
-    }
-
-    ret = 0;
-
-done_or_fail:
-    if (cmd_data)
-        free(cmd_data);
-
-    return ret;
-}
-
-static int maguro_boot_info_ack(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret = -1;
-    uint32_t boot_info_length;
-    char *boot_info = 0;
-
-
-    if ((ret = expect_read(io_data->boot_fd, &boot_info_length, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to receive boot info length");
-        goto fail;
-    }
-
-    ipc_client_log(client, "Boot Info length=0x%x", boot_info_length);
-
-    boot_info = (char*)malloc(boot_info_length);
-    if (!boot_info) {
-        ipc_client_log(client, "Error: failed to allocate memory for boot info");
-        goto fail;
-    }
-
-    memset(boot_info, 0, boot_info_length);
-
-    size_t boot_chunk = 4;
-    size_t boot_chunk_count = (boot_info_length + boot_chunk - 1) / boot_chunk;
-    unsigned i;
-    for (i = 0; i < boot_chunk_count; i++) {
-        ret = expect_read(io_data->boot_fd, boot_info + (i * boot_chunk), boot_chunk);
-        if (ret < 0) {
-            ipc_client_log(client, "Error: failed to receive Boot Info chunk %i ret=%d", i, ret);
-            goto fail;
-        }
-    }
-
-    ipc_client_log(client, "received Boot Info");
-
-    ret = maguro_boot_cmd(client, io_data, SetPortConf, boot_info, boot_info_length);
-    if (ret < 0) {
-        ipc_client_log(client, "Error: failed to send SetPortConf command");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent SetPortConf command");
-    }
-
-    ret = 0;
-
-fail:
-    if (boot_info)
-        free(boot_info);
-
-    return ret;
-}
-
-static int maguro_send_image_data(struct ipc_client *client,
-    struct modemctl_io_data *io_data, uint32_t addr,
-    void *data, int data_len)
-{
-    int ret = 0;
-    int count = 0;
-    char *data_p = (char *) data;
-
-    if ((ret = maguro_boot_cmd(client, io_data, ReqFlashSetAddress, &addr, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to send ReqFlashSetAddress");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqFlashSetAddress");
-    }
-
-    while (count < data_len) {
-        int rest = data_len - count;
-        int chunk = rest < SEC_DOWNLOAD_CHUNK ? rest : SEC_DOWNLOAD_CHUNK;
-
-        ret = maguro_boot_cmd(client, io_data, ReqFlashWriteBlock, data_p, chunk);
-        if (ret < 0) {
-            ipc_client_log(client, "Error: failed to send data chunk");
-            goto fail;
-        }
-
-        data_p += chunk;
-        count += chunk;
-    }
-
-    usleep(SEC_DOWNLOAD_DELAY_US);
-
-fail:
-    return ret;
-}
-
-static int maguro_send_image_addr(struct ipc_client *client,
-    struct modemctl_io_data *io_data, uint32_t addr, enum xmm6260_image type)
-{
-    uint32_t offset = maguro_radio_parts[type].offset;
-    uint32_t length = maguro_radio_parts[type].length;
-    char *start = io_data->radio_data + offset;
-    int ret = 0;
-
-    ret = maguro_send_image_data(client, io_data, addr, start, length);
-
-    return ret;
-}
-
-static int maguro_send_mps_data(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret = 0;
-    int mps_fd = -1;
-    char mps_data[I9250_MPS_LENGTH] = {};
-    uint32_t addr = I9250_MPS_LOAD_ADDR;
-
-    mps_fd = open(I9250_MPS_IMAGE_PATH, O_RDONLY);
-    if (mps_fd < 0) {
-        ipc_client_log(client, "Error: failed to open MPS data");
-        goto fail;
-    }
-    else {
-        ret = read(mps_fd, mps_data, I9250_MPS_LENGTH);
-        if (ret < 0) {
-            ipc_client_log(client, "Error: failed to read MPS data\n");
-            goto fail;
-        }
-    }
-
-    if ((ret = maguro_boot_cmd(client, io_data, ReqFlashSetAddress, &addr, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to send ReqFlashSetAddress");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqFlashSetAddress");
-    }
-
-    if ((ret = maguro_boot_cmd(client, io_data, ReqFlashWriteBlock,
-        mps_data, I9250_MPS_LENGTH)) < 0) {
-        ipc_client_log(client, "Error: failed to write MPS data to modem");
-        goto fail;
-    }
-
-
-fail:
-    if (mps_fd >= 0)
-        close(mps_fd);
-
-    return ret;
-}
-
-static int maguro_send_image_addrs(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret = 0;
-
-    uint32_t sec_off = maguro_radio_parts[SECURE_IMAGE].offset;
-    uint32_t sec_len = maguro_radio_parts[SECURE_IMAGE].length;
-    void *sec_img = io_data->radio_data + sec_off;
-    void *nv_data = NULL;
-
-    if ((ret = maguro_boot_cmd(client, io_data, ReqSecStart, sec_img, sec_len)) < 0) {
-        ipc_client_log(client, "Error: failed to write ReqSecStart");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqSecStart");
-    }
-
-    if ((ret = maguro_send_image_addr(client, io_data, FW_LOAD_ADDR, FIRMWARE)) < 0) {
-        ipc_client_log(client, "Error: failed to send FIRMWARE image");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent FIRMWARE image");
-    }
-
-    if (nv_data_check(client) < 0)
-        goto fail;
-
-    if (nv_data_md5_check(client) < 0)
-        goto fail;
-
-    nv_data = ipc_client_file_read(client, nv_data_path(client), 2 << 20, 1024);
-    if (nv_data == NULL) {
-        ipc_client_log(client, "Error: failed to read NVDATA image");
-        goto fail;
-    }
-
-    if ((ret = maguro_send_image_data(client, io_data, NVDATA_LOAD_ADDR, nv_data, 2 << 20)) < 0) {
-        ipc_client_log(client, "Error: failed to send NVDATA image");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent NVDATA image");
-    }
-
-    free(nv_data);
-
-    if ((ret = maguro_send_mps_data(client, io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to send MPS data");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent MPS data");
-    }
-
-    if ((ret = maguro_boot_cmd(client, io_data, ReqSecEnd,
-        BL_END_MAGIC, BL_END_MAGIC_LEN)) < 0)
-    {
-        ipc_client_log(client, "Error: failed to write ReqSecEnd");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqSecEnd");
-    }
-
-    ret = maguro_boot_cmd(client, io_data, ReqForceHwReset,
-        BL_RESET_MAGIC, BL_RESET_MAGIC_LEN);
-    if (ret < 0) {
-        ipc_client_log(client, "Error: failed to write ReqForceHwReset");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "sent ReqForceHwReset");
-    }
-
-fail:
-    return ret;
-}
-
-static int maguro_modem_reboot(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool hard)
-{
-    int ret;
-
-    if (!hard)
-        return 0;
-
-    /* Disable the hardware to ensure consistent state */
-    if ((ret = modemctl_modem_power(client, io_data, false)) < 0) {
-        ipc_client_log(client, "Error: failed to disable modem power");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "disabled modem power");
-    }
-
-    /* Now, initialize the hardware */
-    if ((ret = modemctl_modem_power(client, io_data, true)) < 0) {
-        ipc_client_log(client, "Error: failed to enable modem power");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "enabled modem power");
-    }
-
-fail:
-    return ret;
-}
-
-int maguro_ipc_power_off(void *io_data_unused) {
-    int ret = -1;
-    struct modemctl_io_data io_data;
-
-    io_data.boot_fd = open(BOOT_DEV, O_RDWR | O_NOCTTY | O_NONBLOCK);
-    if (io_data.boot_fd < 0) {
-        ret = io_data.boot_fd;
-        goto fail;
-    }
-
-    if ((ret = modemctl_modem_power(NULL, &io_data, false)) < 0)
-        goto fail_pwr;
-
-    ret = 0;
-
-fail_pwr:
-    close(io_data.boot_fd);
-fail:
-    return ret;
-}
-
-int maguro_ipc_bootstrap(struct ipc_client *client)
-{
-    int ret = -1, n = 0, fd = -1, i;
-    struct modemctl_io_data io_data;
-    memset(&io_data, 0, sizeof(client, io_data));
-
-    io_data.radio_fd = -1;
-    for (n = 0; n < I9250_RADIO_IMAGE_PATHS_NUM; n++) {
-        fd = open(i9250_radio_image_paths[n], O_RDONLY);
-        if (fd > 0) {
-            io_data.radio_fd = fd;
-            ipc_client_log(client, "opened radio image %s, fd=%d", i9250_radio_image_paths[n], io_data.radio_fd);
-            break;
-        }
-    }
-
-    if (io_data.radio_fd < 0) {
-        ipc_client_log(client, "Error: failed to open radio firmware");
-        goto fail;
-    }
-
-    if (fstat(io_data.radio_fd, &io_data.radio_stat) < 0) {
-        ipc_client_log(client, "Error: failed to stat radio image, error %s", strerror(errno));
-        goto fail;
-    }
-
-    io_data.radio_data = mmap(0, RADIO_MAP_SIZE, PROT_READ, MAP_SHARED,
-        io_data.radio_fd, 0);
-    if (io_data.radio_data == MAP_FAILED) {
-        ipc_client_log(client, "Error: failed to mmap radio image, error %s", strerror(errno));
-        goto fail;
-    }
-
-    io_data.boot_fd = open(BOOT_DEV, O_RDWR | O_NOCTTY | O_NONBLOCK);
-    if (io_data.boot_fd < 0) {
-        ipc_client_log(client, "Error: failed to open boot device");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "opened boot device %s, fd=%d", BOOT_DEV, io_data.boot_fd);
-    }
-
-    if (maguro_modem_reboot(client, &io_data, true) < 0) {
-        ipc_client_log(client, "Error: failed to hard reset modem");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "modem hard reset done");
-    }
-
-    /* Now, actually load the firmware */
-    for (i = 0; i < 2; i++) {
-        if (write(io_data.boot_fd, "ATAT", 4) != 4) {
-            ipc_client_log(client, "Error: failed to write ATAT to boot socket");
-            goto fail;
-        }
-        else {
-            ipc_client_log(client, "written ATAT to boot socket, waiting for ACK");
-        }
-
-        if (expect(io_data.boot_fd, 100) < 0) {
-            ipc_client_log(client, "failed to select before next ACK, ignoring");
-        }
-    }
-
-    /* FIXME: make sure it does not timeout or add the retry in the ril library */
-    if ((ret = expect(io_data.boot_fd, 100)) < 0) {
-        ipc_client_log(client, "Error: failed to wait for bootloader ready state");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "ready for PSI upload");
-    }
-
-    ret = -ETIMEDOUT;
-    for (i = 0; i < I9250_BOOT_REPLY_MAX; i++) {
-        uint32_t id_buf;
-        if ((ret = expect_read(io_data.boot_fd, (void*)&id_buf, 4)) != 4) {
-            ipc_client_log(client, "Error: failed receiving bootloader reply");
-            goto fail;
-        }
-        ipc_client_log(client, "got bootloader reply %08x", id_buf);
-        if ((id_buf & I9250_BOOT_LAST_MASK) == I9250_BOOT_LAST_MASK) {
-            ret = 0;
-            break;
-        }
-    }
-
-    if (ret < 0) {
-        ipc_client_log(client, "Error: bootloader id marker not received");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "got bootloader id marker");
-    }
-
-    if ((ret = maguro_send_psi(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to upload PSI");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "PSI download complete");
-    }
-
-    close(io_data.boot_fd);
-    io_data.boot_fd = open(I9250_SECOND_BOOT_DEV, O_RDWR | O_NOCTTY | O_NONBLOCK);
-    if (io_data.boot_fd < 0) {
-        ipc_client_log(client, "Error: failed to open " I9250_SECOND_BOOT_DEV " control device");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "opened second boot device %s, fd=%d", I9250_SECOND_BOOT_DEV, io_data.boot_fd);
-    }
-
-    if ((ret = write(io_data.boot_fd, I9250_PSI_CMD_EXEC, 4)) < 0) {
-        ipc_client_log(client, "Error: failed writing cmd_load_exe_EBL");
-        goto fail;
-    }
-
-    if ((ret = write(io_data.boot_fd, I9250_PSI_EXEC_DATA, 8)) < 0) {
-        ipc_client_log(client, "Error: failed writing 8 bytes to boot1");
-        goto fail;
-    }
-
-    if ((ret = expect_data(io_data.boot_fd, I9250_GENERAL_ACK, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to receive cmd_load_exe_EBL ack");
-        goto fail;
-    }
-
-    if ((ret = expect_data(io_data.boot_fd, I9250_PSI_READY_ACK, 4)) < 0) {
-        ipc_client_log(client, "Error: failed to receive PSI ready ack");
-        goto fail;
-    }
-
-    if ((ret = maguro_send_ebl(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to upload EBL");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "EBL download complete");
-    }
-
-    if ((ret = maguro_boot_info_ack(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to receive Boot Info");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "Boot Info ACK done");
-    }
-
-    if ((ret = maguro_send_image_addrs(client, &io_data)) < 0) {
-        ipc_client_log(client, "Error: failed to upload Secure Image");
-        goto fail;
-    }
-    else {
-        ipc_client_log(client, "Secure Image download complete");
-    }
-
-    if ((ret = modemctl_wait_modem_online(client, &io_data))) {
-        ipc_client_log(client, "Error: failed to wait for modem to become online");
-        goto fail;
-    }
-
-    /* This restores UART MUX to GPS */
-    modemctl_modem_boot_power(client, &io_data, false);
-
-    ipc_client_log(client, "Modem is online!");
-    ret = 0;
-
-fail:
-    if (io_data.radio_data != MAP_FAILED)
-        munmap(io_data.radio_data, RADIO_MAP_SIZE);
-
-    if (io_data.radio_fd >= 0)
-        close(io_data.radio_fd);
-
-    if (io_data.boot_fd >= 0)
-        close(io_data.boot_fd);
-
-    return ret;
-}
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/maguro/maguro_loader.h b/samsung-ipc/device/maguro/maguro_loader.h
deleted file mode 100644 (file)
index 2f97133..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Firmware loader for Samsung I9250 (maguro)
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifndef __MAGURO_LOADER_H__
-#define __MAGURO_LOADER_H__
-
-#define I9250_SECOND_BOOT_DEV "/dev/umts_boot1"
-
-#define I9250_BOOT_LAST_MASK 0x0000ffff
-#define I9250_BOOT_REPLY_MAX 20
-
-#define I9250_GENERAL_ACK "\x02\x00\x00\x00"
-
-#define I9250_PSI_START_MAGIC "\xff\xf0\x00\x30"
-#define I9250_PSI_CMD_EXEC "\x08\x00\x00\x00"
-#define I9250_PSI_EXEC_DATA "\x00\x00\x00\x00\x02\x00\x02\x00"
-#define I9250_PSI_READY_ACK "\x00\xaa\x00\x00"
-
-#define I9250_EBL_IMG_ACK_MAGIC "\x51\xa5\x00\x00"
-#define I9250_EBL_HDR_ACK_MAGIC "\xcc\xcc\x00\x00"
-
-#define I9250_MPS_IMAGE_PATH "/factory/imei/mps_code.dat"
-#define I9250_MPS_LOAD_ADDR 0x61080000
-#define I9250_MPS_LENGTH 3
-
-#define SEC_DOWNLOAD_CHUNK 0xdfc2
-#define SEC_DOWNLOAD_DELAY_US (500 * 1000)
-
-       #define FW_LOAD_ADDR 0x60300000
-#define NVDATA_LOAD_ADDR 0x60e80000
-
-#define BL_END_MAGIC "\x00\x00"
-#define BL_END_MAGIC_LEN 2
-
-#define BL_RESET_MAGIC "\x01\x10\x11\x00"
-#define BL_RESET_MAGIC_LEN 4
-
-/*
- * on I9250, all commands need ACK and we do not need to
- * allocate a fixed size buffer
- */
-struct maguro_boot_cmd_desc {
-    unsigned code;
-    bool long_tail;
-    bool no_ack;
-};
-
-struct maguro_boot_cmd_header {
-    uint32_t total_size;
-    uint16_t hdr_magic;
-    uint16_t cmd;
-    uint16_t data_size;
-} __attribute__((packed));
-
-#define DECLARE_BOOT_CMD_HEADER(name, code, size) \
-struct maguro_boot_cmd_header name = {\
-    .total_size = size + 10,\
-    .hdr_magic = 2,\
-    .cmd = code,\
-    .data_size = size,\
-}
-
-struct maguro_boot_tail_header {
-    uint16_t checksum;
-    uint16_t tail_magic;
-    uint8_t unknown[2];
-} __attribute__((packed));
-
-#define DECLARE_BOOT_TAIL_HEADER(name, checksum) \
-struct maguro_boot_tail_header name = {\
-    .checksum = checksum,\
-    .tail_magic = 3,\
-    .unknown = "\xea\xea",\
-}
-
-int maguro_ipc_bootstrap(struct ipc_client *client);
-int maguro_ipc_power_off(void *io_data);
-
-#endif
-
-// vim:ts=4:sw=4:expandtab
index 17b7133..5bdd0cd 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * This file is part of libsamsung-ipc.
  *
  * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
  */
 
 #include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/mman.h>
 
-#include "ipc.h"
+#include <samsung-ipc.h>
+#include <ipc.h>
 
-#include "xmm6260_ipc.h"
-#include "piranha_loader.h"
+#include "xmm6260.h"
+#include "xmm6260_mipi.h"
+#include "xmm6260_sec_modem.h"
+#include "piranha_ipc.h"
+
+int piranha_ipc_bootstrap(struct ipc_client *client)
+{
+    void *modem_image_data = NULL;
+    int modem_image_fd = -1;
+    int modem_boot_fd = -1;
+
+    unsigned char *p;
+    int rc;
+
+    if (client == NULL)
+        return -1;
+
+    ipc_client_log(client, "Starting piranha modem bootstrap");
+
+    modem_image_fd = open(PIRANHA_MODEM_IMAGE_DEVICE, O_RDONLY);
+    if (modem_image_fd < 0) {
+        ipc_client_log(client, "Opening modem image device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem image device");
+
+    modem_image_data = mmap(0, PIRANHA_MODEM_IMAGE_SIZE, PROT_READ, MAP_SHARED, modem_image_fd, 0);
+    if (modem_image_data == NULL || modem_image_data == (void *) 0xffffffff) {
+            ipc_client_log(client, "Mapping modem image data to memory failed");
+            goto error;
+    }
+    ipc_client_log(client, "Mapped modem image data to memory");
+
+    modem_boot_fd = open(XMM6260_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (modem_boot_fd < 0) {
+        ipc_client_log(client, "Opening modem boot device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem boot device");
+
+    rc = xmm6260_sec_modem_power(modem_boot_fd, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem off failed");
+        goto error;
+    }
+    ipc_client_log(client, "Turned the modem off");
+
+    rc = xmm6260_sec_modem_power(modem_boot_fd, 1);
+    if (rc < 0) {
+        ipc_client_log(client, "Turning the modem on failed");
+        goto error;
+    }
+    ipc_client_log(client, "Turned the modem on");
+
+    p = (unsigned char *) modem_image_data + PIRANHA_PSI_OFFSET;
+
+    rc = xmm6260_mipi_psi_send(client, modem_boot_fd, (void *) p, PIRANHA_PSI_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI PSI failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI PSI");
+
+    close(modem_boot_fd);
+
+    modem_boot_fd = open(XMM6260_SEC_MODEM_BOOT1_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (modem_boot_fd < 0) {
+        ipc_client_log(client, "Opening modem boot device failed");
+        goto error;
+    }
+    ipc_client_log(client, "Opened modem boot device");
+
+    p = (unsigned char *) modem_image_data + PIRANHA_EBL_OFFSET;
+
+    rc = xmm6260_mipi_ebl_send(client, modem_boot_fd, (void *) p, PIRANHA_EBL_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI EBL failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI EBL");
+
+    rc = xmm6260_mipi_port_config_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI port config failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI port config");
+
+    p = (unsigned char *) modem_image_data + PIRANHA_SEC_START_OFFSET;
+
+    rc = xmm6260_mipi_sec_start_send(client, modem_boot_fd, (void *) p, PIRANHA_SEC_START_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI SEC start failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI SEC start");
+
+    p = (unsigned char *) modem_image_data + PIRANHA_FIRMWARE_OFFSET;
+
+    rc = xmm6260_mipi_firmware_send(client, modem_boot_fd, (void *) p, PIRANHA_FIRMWARE_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI firmware failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI firmware");
+
+    rc = xmm6260_mipi_nv_data_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI nv_data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI nv_data");
+
+    rc = xmm6260_mipi_sec_end_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI SEC end failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI SEC end");
+
+    rc = xmm6260_mipi_hw_reset_send(client, modem_boot_fd);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6260 MIPI HW reset failed");
+        goto error;
+    }
+    ipc_client_log(client, "Sent XMM6260 MIPI HW reset");
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (modem_image_data != NULL)
+        munmap(modem_image_data, PIRANHA_MODEM_IMAGE_SIZE);
+
+    if (modem_image_fd >= 0)
+        close(modem_image_fd);
+
+    if (modem_boot_fd >= 0)
+        close(modem_boot_fd);
+
+    return rc;
+}
+
+int piranha_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    return xmm6260_sec_modem_ipc_fmt_send(client, request);
+}
+
+int piranha_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    return xmm6260_sec_modem_ipc_fmt_recv(client, response);
+}
+
+int piranha_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    return xmm6260_sec_modem_ipc_rfs_send(client, request);
+}
+
+int piranha_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    return xmm6260_sec_modem_ipc_rfs_recv(client, response);
+}
+
+int piranha_ipc_open(void *data, int type)
+{
+    struct piranha_ipc_transport_data *transport_data;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct piranha_ipc_transport_data *) data;
+
+    transport_data->fd = xmm6260_sec_modem_ipc_open(type);
+    if (transport_data->fd < 0)
+        return -1;
+
+    return 0;
+}
+
+int piranha_ipc_close(void *data)
+{
+    struct piranha_ipc_transport_data *transport_data;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct piranha_ipc_transport_data *) data;
+
+    xmm6260_sec_modem_ipc_close(transport_data->fd);
+    transport_data->fd = -1;
+
+    return 0;
+}
+
+int piranha_ipc_read(void *data, void *buffer, unsigned int length)
+{
+    struct piranha_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct piranha_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_read(transport_data->fd, buffer, length);
+    return rc;
+}
+
+int piranha_ipc_write(void *data, void *buffer, unsigned int length)
+{
+    struct piranha_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct piranha_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_write(transport_data->fd, buffer, length);
+    return rc;
+}
+
+int piranha_ipc_poll(void *data, struct timeval *timeout)
+{
+    struct piranha_ipc_transport_data *transport_data;
+    int rc;
+
+    if (data == NULL)
+        return -1;
+
+    transport_data = (struct piranha_ipc_transport_data *) data;
+
+    rc = xmm6260_sec_modem_ipc_poll(transport_data->fd, timeout);
+    return rc;
+}
+
+int piranha_ipc_power_on(void *data)
+{
+    return 0;
+}
+
+int piranha_ipc_power_off(void *data)
+{
+    int fd;
+    int rc;
+
+    fd = open(XMM6260_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+    if (fd < 0)
+        return -1;
+
+    rc = xmm6260_sec_modem_power(fd, 0);
+
+    close(fd);
+
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int piranha_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
+{
+    if (transport_data == NULL)
+        return -1;
+
+    *transport_data = (void *) malloc(sizeof(struct piranha_ipc_transport_data));
+    memset(*transport_data, 0, sizeof(struct piranha_ipc_transport_data));
+
+    return 0;
+}
+
+int piranha_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
+{
+    if (transport_data == NULL)
+        return -1;
+
+    free(transport_data);
+
+    return 0;
+}
+
+char *piranha_ipc_gprs_get_iface(int cid)
+{
+    return xmm6260_sec_modem_ipc_gprs_get_iface(cid);
+}
+
+
+int piranha_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
+{
+    return xmm6260_sec_modem_ipc_gprs_get_capabilities(capabilities);
+}
 
 struct ipc_ops piranha_ipc_fmt_ops = {
-    .bootstrap = piranha_modem_bootstrap,
-    .send = xmm6260_ipc_fmt_send,
-    .recv = xmm6260_ipc_fmt_recv,
+    .bootstrap = piranha_ipc_bootstrap,
+    .send = piranha_ipc_fmt_send,
+    .recv = piranha_ipc_fmt_recv,
 };
 
 struct ipc_ops piranha_ipc_rfs_ops = {
     .bootstrap = NULL,
-    .send = xmm6260_ipc_rfs_send,
-    .recv = xmm6260_ipc_rfs_recv,
+    .send = piranha_ipc_rfs_send,
+    .recv = piranha_ipc_rfs_recv,
 };
 
 struct ipc_handlers piranha_ipc_handlers = {
-    .read = xmm6260_ipc_read,
-    .write = xmm6260_ipc_write,
-    .open = xmm6260_ipc_open,
-    .close = xmm6260_ipc_close,
-    .poll = xmm6260_ipc_poll,
+    .read = piranha_ipc_read,
+    .write = piranha_ipc_write,
+    .open = piranha_ipc_open,
+    .close = piranha_ipc_close,
+    .poll = piranha_ipc_poll,
     .transport_data = NULL,
-    .power_on = xmm6260_ipc_power_on,
-    .power_off = xmm6260_ipc_power_off,
+    .power_on = piranha_ipc_power_on,
+    .power_off = piranha_ipc_power_off,
     .power_data = NULL,
     .gprs_activate = NULL,
     .gprs_deactivate = NULL,
     .gprs_data = NULL,
-    .data_create = xmm6260_ipc_data_create,
-    .data_destroy = xmm6260_ipc_data_destroy,
+    .data_create = piranha_ipc_data_create,
+    .data_destroy = piranha_ipc_data_destroy,
 };
 
 struct ipc_gprs_specs piranha_ipc_gprs_specs = {
-    .gprs_get_iface = xmm6260_ipc_gprs_get_iface,
-    .gprs_get_capabilities = xmm6260_ipc_gprs_get_capabilities,
+    .gprs_get_iface = piranha_ipc_gprs_get_iface,
+    .gprs_get_capabilities = piranha_ipc_gprs_get_capabilities,
 };
 
 // vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/piranha/piranha_ipc.h b/samsung-ipc/device/piranha/piranha_ipc.h
new file mode 100644 (file)
index 0000000..f915297
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __PIRANHA_IPC_H__
+#define __PIRANHA_IPC_H__
+
+#define PIRANHA_MODEM_IMAGE_SIZE                                0x1400000
+#define PIRANHA_PSI_OFFSET                                      0x1000
+#define PIRANHA_PSI_SIZE                                        0xE000
+#define PIRANHA_EBL_OFFSET                                      0xF000
+#define PIRANHA_EBL_SIZE                                        0x19000
+#define PIRANHA_SEC_START_OFFSET                                0x9FF800
+#define PIRANHA_SEC_START_SIZE                                  0x800
+#define PIRANHA_FIRMWARE_OFFSET                                 0x28000
+#define PIRANHA_FIRMWARE_SIZE                                   0x9D7800
+#define PIRANHA_NV_DATA_OFFSET                                  0xA00000
+#define PIRANHA_NV_DATA_SIZE                                    0x200000
+
+#define PIRANHA_MODEM_IMAGE_DEVICE              "/dev/block/mmcblk0p8"
+
+struct piranha_ipc_transport_data {
+    int fd;
+};
+
+#endif
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/piranha/piranha_loader.c b/samsung-ipc/device/piranha/piranha_loader.c
deleted file mode 100644 (file)
index d5b28ad..0000000
+++ /dev/null
@@ -1,764 +0,0 @@
-/*
- * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <getopt.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-//for timeval
-#include <sys/time.h>
-
-//for mmap
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "ipc.h"
-
-#include "xmm6260_loader.h"
-#include "xmm6260_modemctl.h"
-
-#include "piranha_loader.h"
-
-struct piranha_radio_part piranha_radio_parts[] = {
-    {
-        .id = PSI,
-        .offset = 0x1000,
-        .length = 0xe000,
-    },
-    {
-        .id = EBL,
-        .offset = 0xf000,
-        .length = 0x19000,
-    },
-    {
-        .id = SECURE_IMAGE,
-        .offset = 0x9ff800,
-        .length = 0x800,
-    },
-    {
-        .id = FIRMWARE,
-        .offset = 0x28000,
-        .length = 0x9d7800,
-    },
-    {
-        .id = NVDATA,
-        .offset = 0xa00000,
-        .length = 2 << 20,
-    },
-};
-
-int piranha_radio_parts_count = sizeof(piranha_radio_parts) / sizeof(struct piranha_radio_part);
-
-struct piranha_boot_cmd piranha_boot_cmds[] = {
-    {
-        .cmd = SetPortConf,
-        .code = 0x86,
-        .flags = PIRANHA_FLAG_NONE,
-    },
-    {
-        .cmd = ReqSecStart,
-        .code = 0x204,
-        .flags = PIRANHA_FLAG_NONE,
-    },
-    {
-        .cmd = ReqSecEnd,
-        .code = 0x205,
-        .flags = PIRANHA_FLAG_SHORT_TAIL,
-    },
-    {
-        .cmd = ReqForceHwReset,
-        .code = 0x208,
-        .flags = PIRANHA_FLAG_NO_ACK,
-    },
-    {
-        .cmd = ReqFlashSetAddress,
-        .code = 0x802,
-        .flags = PIRANHA_FLAG_NONE,
-    },
-    {
-        .cmd = ReqFlashWriteBlock,
-        .code = 0x804,
-        .flags = PIRANHA_FLAG_SHORT_TAIL,
-    },
-};
-
-int piranha_boot_cmds_count = sizeof(piranha_boot_cmds) / sizeof(struct piranha_boot_cmd);
-
-struct piranha_radio_part *piranha_radio_part_get(int id)
-{
-    int i;
-
-    for (i=0 ; i < piranha_radio_parts_count ; i++) {
-        if (piranha_radio_parts[i].id == id)
-            return &piranha_radio_parts[i];
-    }
-
-    return NULL;
-}
-
-struct piranha_boot_cmd *piranha_boot_cmd_get(int cmd)
-{
-    int i;
-
-    for (i=0 ; i < piranha_boot_cmds_count ; i++) {
-        if (piranha_boot_cmds[i].cmd == cmd)
-            return &piranha_boot_cmds[i];
-    }
-
-    return NULL;
-}
-
-int piranha_ack_read(struct ipc_client *client, int fd, int ack)
-{
-    int c, v;
-    int rc;
-
-    v = 0;
-    for (c=0 ; c < 10 ; c++) {
-        rc = expect_read(fd, &v, sizeof(v));
-        if ((v & 0xffff) == ack)
-            break;
-    }
-
-    if (rc <= 0 || (v & 0xffff) != ack)
-        return -1;
-
-    return 0;
-}
-
-void piranha_boot_cmd_header_fill(struct piranha_boot_cmd_header *header,
-    uint16_t code, int size)
-{
-    memset(header, 0, sizeof(struct piranha_boot_cmd_header));
-    header->size = size + sizeof(struct piranha_boot_cmd_header);
-    header->magic = PIRANHA_MAGIC_BOOT_CMD_HEADER;
-    header->code = code;
-    header->data_size = size;
-}
-
-void piranha_boot_cmd_tail_fill(struct piranha_boot_cmd_tail *tail,
-    uint16_t code, void *data, int size)
-{
-    unsigned char *p = NULL;
-    int i;
-
-    memset(tail, 0, sizeof(struct piranha_boot_cmd_tail));
-    tail->checksum = (size & 0xffff) + code;
-    tail->magic = PIRANHA_MAGIC_BOOT_CMD_TAIL;
-    tail->unknown = PIRANHA_MAGIC_BOOT_CMD_UNKNOWN;
-
-    p = data;
-
-    for (i=0 ; i < size ; i++)
-        tail->checksum += *p++;
-}
-
-int piranha_boot_cmd_send(struct ipc_client *client, struct modemctl_io_data *io_data,
-    int cmd, void *data, int size)
-{
-    struct piranha_boot_cmd *boot_cmd;
-    struct piranha_boot_cmd_header *header_p;
-    unsigned char *p;
-
-    struct piranha_boot_cmd_header header;
-    struct piranha_boot_cmd_tail tail;
-    int tail_length;
-
-    void *cmd_data = NULL;
-    int cmd_length = 0;
-
-    void *ack_data = NULL;
-    int ack_length = 0;
-
-    int count, length;
-    int chunk = 4;
-
-    int rc;
-
-    boot_cmd = piranha_boot_cmd_get(cmd);
-    if (boot_cmd == NULL)
-        goto fail;
-
-    piranha_boot_cmd_header_fill(&header, boot_cmd->code, size);
-    piranha_boot_cmd_tail_fill(&tail, boot_cmd->code, data, size);
-
-    tail_length = sizeof(tail);
-    if (boot_cmd->flags & PIRANHA_FLAG_SHORT_TAIL)
-        tail_length -= 2;
-
-    cmd_length = sizeof(header) + size + tail_length;
-    cmd_data = calloc(1, cmd_length);
-
-    p = (unsigned char *) cmd_data;
-    memcpy(p, &header, sizeof(header));
-    p += sizeof(header);
-    memcpy(p, data, size);
-    p += size;
-    memcpy(p, &tail, tail_length);
-
-    rc = write(io_data->boot_fd, cmd_data, cmd_length);
-    if (rc != cmd_length)
-        goto fail;
-
-    if (boot_cmd->flags & PIRANHA_FLAG_NO_ACK)
-        goto done;
-
-    rc = expect_read(io_data->boot_fd, &ack_length, sizeof(ack_length));
-    if (rc != sizeof(ack_length) || ack_length <= 0)
-        goto fail;
-
-    // Add short tail
-    ack_length += sizeof(tail) - 2;
-    if (ack_length % 4 != 0)
-        ack_length += ack_length % 4;
-    ack_data = calloc(1, ack_length);
-
-    p = (unsigned char *) ack_data;
-    memcpy(p, &ack_length, sizeof(ack_length));
-    p += sizeof(ack_length);
-
-    length = ack_length;
-    count = sizeof(ack_length);
-
-    while (count < length) {
-        rc = expect_read(io_data->boot_fd, p, chunk < length - count ? chunk : length - count);
-        if (rc < 0)
-            goto fail;
-
-        p += rc;
-        count += rc;
-    }
-
-    header_p = (struct piranha_boot_cmd_header *) ack_data;
-    if (header_p->code != boot_cmd->code)
-            goto fail;
-
-    rc = 0;
-    goto done;
-
-fail:
-    rc = -1;
-
-done:
-    if (cmd_data != NULL)
-        free(cmd_data);
-    if (ack_data != NULL)
-        free(ack_data);
-
-    return rc;
-}
-
-int piranha_boot_data_send(struct ipc_client *client, struct modemctl_io_data *io_data,
-    int address, void *data, int length)
-{
-    unsigned char *p = NULL;
-    int count;
-    int chunk = 0xdf2;
-    int rc;
-
-    rc = piranha_boot_cmd_send(client, io_data, ReqFlashSetAddress, &address, sizeof(address));
-    if (rc < 0)
-        goto fail;
-
-    p = (unsigned char *) data;
-    count = 0;
-
-    while (count < length) {
-        rc = piranha_boot_cmd_send(client, io_data, ReqFlashWriteBlock, p, chunk < length - count ? chunk : length - count);
-        if (rc < 0)
-            goto fail;
-
-        p += chunk;
-        count += chunk;
-    }
-
-    return 0;
-
-fail:
-    return -1;
-}
-
-int piranha_sec_send(struct ipc_client *client, struct modemctl_io_data *io_data)
-{
-    struct piranha_radio_part *radio_part;
-    void *nv_data = NULL;
-
-    uint16_t sec_end_data;
-    uint32_t hw_reset_data;
-
-    int length, offset;
-    void *data;
-    int start, end;
-    int rc;
-
-    // SEC start
-    ipc_client_log(client, "%s: Sending SEC start image", __func__);
-
-    radio_part = piranha_radio_part_get(SECURE_IMAGE);
-    if (radio_part == NULL)
-        goto fail;
-
-    length = radio_part->length;
-    offset = radio_part->offset;
-
-    data = io_data->radio_data + offset;
-
-    rc = piranha_boot_cmd_send(client, io_data, ReqSecStart, data, length);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send start SEC image", __func__);
-        goto fail;
-    }
-
-    // Firmware
-    ipc_client_log(client, "%s: Sending Firmware image", __func__);
-
-    radio_part = piranha_radio_part_get(FIRMWARE);
-    if (radio_part == NULL)
-        goto fail;
-
-    length = radio_part->length;
-    offset = radio_part->offset;
-
-    data = io_data->radio_data + offset;
-
-    rc = piranha_boot_data_send(client, io_data, PIRANHA_ADDRESS_FIRMWARE, data, length);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send Firmware image", __func__);
-        goto fail;
-    }
-
-    // NV Data
-    ipc_client_log(client, "%s: Sending NV Data image", __func__);
-
-    rc = nv_data_check(client);
-    if (rc < 0)
-        goto fail;
-
-    rc = nv_data_md5_check(client);
-    if (rc < 0)
-        goto fail;
-
-    nv_data = ipc_client_file_read(client, nv_data_path(client), 2 << 20, 1024);
-    if (nv_data == NULL) {
-        ipc_client_log(client, "%s: Failed to read NV Data image (%s)", __func__, nv_data_path(client));
-        goto fail;
-    }
-
-    rc = piranha_boot_data_send(client, io_data, PIRANHA_ADDRESS_NV_DATA, nv_data, 2 << 20);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send NV Data image", __func__);
-        goto fail;
-    }
-
-    // SEC end
-    ipc_client_log(client, "%s: Sending SEC end", __func__);
-
-    sec_end_data = PIRANHA_MAGIC_BOOT_CMD_SEC_END;
-    piranha_boot_cmd_send(client, io_data, ReqSecEnd, &sec_end_data, sizeof(sec_end_data));
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send SEC end", __func__);
-        goto fail;
-    }
-
-    // HW reset
-    ipc_client_log(client, "%s: Sending HW reset", __func__);
-
-    hw_reset_data = PIRANHA_MAGIC_BOOT_CMD_HW_RESET;
-    piranha_boot_cmd_send(client, io_data, ReqForceHwReset, &hw_reset_data, sizeof(hw_reset_data));
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send HW reset", __func__);
-        goto fail;
-    }
-
-    rc = 0;
-    goto done;
-
-fail:
-    rc = -1;
-
-done:
-    if (nv_data != NULL)
-        free(nv_data);
-
-    return rc;
-}
-
-int piranha_ebl_set(struct ipc_client *client, struct modemctl_io_data *io_data)
-{
-    unsigned char *data = NULL;
-    unsigned char *p = NULL;
-    int count, length;
-    int chunk = 4;
-    int rc;
-
-    rc = expect_read(io_data->boot_fd, &length, sizeof(length));
-    if (rc != sizeof(length)) {
-        ipc_client_log(client, "%s: Failed to read EBL set length", __func__);
-        goto fail;
-    }
-
-    data = calloc(1, length);
-    p = data;
-    count = 0;
-
-    while (count < length) {
-        rc = expect_read(io_data->boot_fd, p, chunk < length - count ? chunk : length - count);
-        if (rc < 0) {
-            ipc_client_log(client, "%s: Failed to read EBL set data", __func__);
-            goto fail;
-        }
-
-        p += rc;
-        count += rc;
-    }
-
-    rc = piranha_boot_cmd_send(client, io_data, SetPortConf, data, length);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send EBL set data", __func__);
-        goto fail;
-    }
-
-    return 0;
-
-fail:
-    if (data != NULL)
-        free(data);
-
-    return -1;
-}
-
-int piranha_ebl_send(struct ipc_client *client, struct modemctl_io_data *io_data)
-{
-    struct piranha_radio_part *radio_part;
-    int length, offset;
-    int chunk = 0xdfc;
-
-    int start, end;
-    unsigned char crc;
-
-    unsigned char *p;
-    int v;
-    int rc;
-
-    radio_part = piranha_radio_part_get(EBL);
-    if (radio_part == NULL)
-        goto fail;
-
-    length = radio_part->length;
-    offset = radio_part->offset;
-    start = offset;
-    end = start + length;
-
-    v = sizeof(length);
-    rc = write(io_data->boot_fd, &v, sizeof(v));
-    if (rc != sizeof(v)) {
-        ipc_client_log(client, "%s: Failed to write EBL length length", __func__);
-        goto fail;
-    }
-
-    rc = write(io_data->boot_fd, &length, sizeof(length));
-    if (rc != sizeof(length)) {
-        ipc_client_log(client, "%s: Failed to write EBL length (1)", __func__);
-        goto fail;
-    }
-
-    rc = piranha_ack_read(client, io_data->boot_fd, PIRANHA_ACK_EBL_LENGTH);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to read EBL length ACK", __func__);
-        goto fail;
-    }
-
-    v = length;
-     p = (unsigned char *) &v;
-    *p = 1;
-
-    rc = write(io_data->boot_fd, &v, sizeof(v));
-    if (rc != sizeof(v)) {
-        ipc_client_log(client, "%s: Failed to write EBL length (2)", __func__);
-        goto fail;
-    }
-
-    while (start < end) {
-        rc = write(io_data->boot_fd, io_data->radio_data + start, chunk < end - start ? chunk : end - start);
-        if (rc < 0) {
-            ipc_client_log(client, "%s: Failed to write EBL data", __func__);
-            goto fail;
-        }
-
-        start += rc;
-    }
-
-    crc = xmm6260_crc_calculate(io_data->radio_data, offset, length);
-
-    rc = write(io_data->boot_fd, &crc, sizeof(crc));
-    if (rc != sizeof(crc)) {
-        ipc_client_log(client, "%s: Failed to write EBL CRC (0x%x)", __func__, crc);
-        goto fail;
-    }
-
-    rc = piranha_ack_read(client, io_data->boot_fd, PIRANHA_ACK_EBL);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to read EBL ACK", __func__);
-        goto fail;
-    }
-
-    return 0;
-
-fail:
-    return -1;
-}
-
-int piranha_psi_send(struct ipc_client *client, struct modemctl_io_data *io_data)
-{
-    struct piranha_radio_part *radio_part;
-    int length, offset;
-    int chunk = 0xdfc;
-
-    int start, end;
-    unsigned char crc;
-    uint32_t crc32;
-
-    int v;
-    int rc;
-
-    radio_part = piranha_radio_part_get(PSI);
-    if (radio_part == NULL)
-        goto fail;
-
-    length = radio_part->length;
-    offset = radio_part->offset;
-    start = offset;
-    end = start + length;
-
-    struct piranha_psi_header header = {
-        .padding = 0xff,
-        .length[0] = (length >> 8) & 0xff,
-        .length[1] = length & 0xff,
-        .magic = PIRANHA_MAGIC_PSI,
-    };
-
-    rc = write(io_data->boot_fd, &header, sizeof(header));
-    if (rc != sizeof(header)) {
-        ipc_client_log(client, "%s: Failed to write PSI header", __func__);
-        goto fail;
-    }
-
-    while (start < end) {
-        rc = write(io_data->boot_fd, io_data->radio_data + start, chunk < end - start ? chunk : end - start);
-        if (rc < 0) {
-            ipc_client_log(client, "%s: Failed to write PSI data", __func__);
-            goto fail;
-        }
-
-        start += rc;
-    }
-
-    crc = xmm6260_crc_calculate(io_data->radio_data, offset, length);
-    crc32 = (crc << 24) | 0xffffff;
-
-    rc = write(io_data->boot_fd, &crc32, sizeof(crc32));
-    if (rc != sizeof(crc32)) {
-        ipc_client_log(client, "%s: Failed to write PSI CRC (0x%x)", __func__, crc);
-        goto fail;
-    }
-
-    rc = piranha_ack_read(client, io_data->boot_fd, PIRANHA_ACK_PSI);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to read PSI ACK", __func__);
-        goto fail;
-    }
-
-    return 0;
-
-fail:
-    return -1;
-}
-
-int piranha_modem_bootstrap(struct ipc_client *client)
-{
-    struct modemctl_io_data io_data;
-    unsigned short boot_magic[4];
-    int length;
-    int c;
-    int rc;
-
-    memset(&io_data, 0, sizeof(client, io_data));
-
-    ipc_client_log(client, "%s: Opening radio image (%s)", __func__, PIRANHA_RADIO_IMAGE);
-
-    io_data.radio_fd = open(PIRANHA_RADIO_IMAGE, O_RDONLY);
-    if (io_data.radio_fd < 0) {
-        ipc_client_log(client, "%s: Failed to open radio image (%s): %s", __func__, PIRANHA_RADIO_IMAGE, strerror(errno));
-        goto fail;
-    }
-
-    rc = fstat(io_data.radio_fd, &io_data.radio_stat);
-    if (rc < 0)
-        goto fail;
-
-    io_data.radio_data = mmap(0, RADIO_MAP_SIZE, PROT_READ, MAP_SHARED,
-        io_data.radio_fd, 0);
-    if (io_data.radio_data == MAP_FAILED) {
-        ipc_client_log(client, "%s: Failed to mmap radio image: %s", __func__, strerror(errno));
-        goto fail;
-    }
-
-    ipc_client_log(client, "%s: Opening boot device (%s)", __func__, PIRANHA_DEV_BOOT0);
-
-    io_data.boot_fd = open(PIRANHA_DEV_BOOT0, O_RDWR | O_NOCTTY | O_NONBLOCK);
-    if (io_data.boot_fd < 0) {
-        ipc_client_log(client, "%s: Failed to open boot device (%s): %s", __func__, PIRANHA_DEV_BOOT0, strerror(errno));
-        goto fail;
-    }
-
-    ipc_client_log(client, "%s: Setting power off", __func__);
-
-    rc = modemctl_modem_power(client, &io_data, false);
-    if (rc < 0)
-        goto fail;
-
-    ipc_client_log(client, "%s: Setting power on", __func__);
-
-    rc = modemctl_modem_power(client, &io_data, true);
-    if (rc < 0)
-        goto fail;
-
-    ipc_client_log(client, "%s: Writing ATAT on boot device", __func__);
-
-    // Boot 0
-    for (c=0 ; c < 10 ; c++) {
-        if (write(io_data.boot_fd, "ATAT", 4) != 4) {
-            rc = -1;
-            continue;
-        }
-
-        rc = piranha_ack_read(client, io_data.boot_fd, PIRANHA_ACK_BOOT0);
-        if (rc < 0)
-            continue;
-        else
-            break;
-    }
-
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to get boot ACK", __func__);
-        goto fail;
-    }
-
-    // PSI
-    ipc_client_log(client, "%s: Sending PSI", __func__);
-
-    rc = piranha_psi_send(client, &io_data);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send PSI", __func__);
-        goto fail;
-    }
-
-    close(io_data.boot_fd);
-
-    // Boot 1
-    ipc_client_log(client, "%s: Opening boot device (%s)", __func__, PIRANHA_DEV_BOOT1);
-
-    io_data.boot_fd = open(PIRANHA_DEV_BOOT1, O_RDWR | O_NOCTTY | O_NONBLOCK);
-    if (io_data.boot_fd < 0) {
-        ipc_client_log(client, "%s: Failed to open boot device (%s): %s", __func__, PIRANHA_DEV_BOOT1, strerror(errno));
-        goto fail;
-    }
-
-    boot_magic[0] = boot_magic[1] = 0;
-    boot_magic[2] = boot_magic[3] = PIRANHA_MAGIC_BOOT1;
-    length = sizeof(boot_magic);
-
-    rc = write(io_data.boot_fd, &length, sizeof(length));
-    if (rc != sizeof(length)) {
-        ipc_client_log(client, "%s: Failed to write boot magic length", __func__);
-        goto fail;
-    }
-
-    rc = write(io_data.boot_fd, &boot_magic, sizeof(boot_magic));
-    if (rc != sizeof(boot_magic)) {
-        ipc_client_log(client, "%s: Failed to write boot magic", __func__);
-        goto fail;
-    }
-
-    rc = piranha_ack_read(client, io_data.boot_fd, PIRANHA_ACK_BOOT1);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to read boot ACK", __func__);
-        goto fail;
-    }
-
-    // EBL
-    ipc_client_log(client, "%s: Sending EBL", __func__);
-
-    rc = piranha_ebl_send(client, &io_data);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send EBL", __func__);
-        goto fail;
-    }
-
-    rc = piranha_ebl_set(client, &io_data);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to set PSI", __func__);
-        goto fail;
-    }
-
-    // SEC images
-    ipc_client_log(client, "%s: Sending SEC images", __func__);
-
-    rc = piranha_sec_send(client, &io_data);
-    if (rc < 0) {
-        ipc_client_log(client, "%s: Failed to send SEC images", __func__);
-        goto fail;
-    }
-
-    rc = 0;
-    goto done;
-
-fail:
-    rc = -1;
-
-done:
-    if (io_data.radio_data != MAP_FAILED) {
-        munmap(io_data.radio_data, RADIO_MAP_SIZE);
-    }
-
-    if (io_data.link_fd >= 0) {
-        close(io_data.link_fd);
-    }
-
-    if (io_data.radio_fd >= 0) {
-        close(io_data.radio_fd);
-    }
-
-    if (io_data.boot_fd >= 0) {
-        close(io_data.boot_fd);
-    }
-
-    return rc;
-}
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/piranha/piranha_loader.h b/samsung-ipc/device/piranha/piranha_loader.h
deleted file mode 100644 (file)
index bf874f8..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Firmware loader for Samsung I9100 (galaxys2)
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdbool.h>
-#include <stdint.h>
-#include <stdlib.h>
-
-#ifndef __PIRANHA_LOADER_H__
-#define __PIRANHA_LOADER_H__
-
-#define PIRANHA_RADIO_IMAGE             "/dev/block/mmcblk0p8"
-#define PIRANHA_DEV_BOOT0               "/dev/umts_boot0"
-#define PIRANHA_DEV_BOOT1               "/dev/umts_boot1"
-
-#define PIRANHA_MAGIC_PSI               0x30
-#define PIRANHA_MAGIC_BOOT1             0x02
-#define PIRANHA_MAGIC_BOOT_CMD_HEADER   0x02
-#define PIRANHA_MAGIC_BOOT_CMD_TAIL     0x03
-#define PIRANHA_MAGIC_BOOT_CMD_UNKNOWN  0xeaea
-#define PIRANHA_MAGIC_BOOT_CMD_SEC_END  0x0000
-#define PIRANHA_MAGIC_BOOT_CMD_HW_RESET 0x00111001
-
-#define PIRANHA_ACK_BOOT0               0xffff
-#define PIRANHA_ACK_PSI                 0xdd01
-#define PIRANHA_ACK_BOOT1               0xaa00
-#define PIRANHA_ACK_EBL_LENGTH          0xcccc
-#define PIRANHA_ACK_EBL                 0xa551
-
-#define PIRANHA_ADDRESS_FIRMWARE        0x60300000
-#define PIRANHA_ADDRESS_NV_DATA         0x60e80000
-
-#define PIRANHA_FLAG_NONE               (0)
-#define PIRANHA_FLAG_SHORT_TAIL         (1 << 0)
-#define PIRANHA_FLAG_NO_ACK             (1 << 1)
-
-struct piranha_radio_part {
-    int id;
-    size_t offset;
-    size_t length;
-};
-
-struct piranha_boot_cmd {
-    int cmd;
-    uint16_t code;
-    int flags;
-};
-
-struct piranha_psi_header {
-    uint8_t padding;
-    uint8_t length[2];
-    uint8_t magic;
-} __attribute__((packed));
-
-struct piranha_boot_cmd_header {
-    uint32_t size;
-    uint16_t magic;
-    uint16_t code;
-    uint16_t data_size;
-} __attribute__((packed));
-
-struct piranha_boot_cmd_tail {
-    uint16_t checksum;
-    uint16_t magic;
-    uint16_t unknown;
-} __attribute__((packed));
-
-int piranha_modem_bootstrap(struct ipc_client *client);
-
-#endif
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/modem.h b/samsung-ipc/device/xmm6260/modem.h
new file mode 100644 (file)
index 0000000..5a456f5
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MODEM_IF_H__
+#define __MODEM_IF_H__
+
+enum modem_t {
+       IMC_XMM6260,
+       IMC_XMM6262,
+       VIA_CBP71,
+       VIA_CBP72,
+       SEC_CMC221,
+       QC_MDM6600,
+       DUMMY,
+};
+
+enum dev_format {
+       IPC_FMT,
+       IPC_RAW,
+       IPC_RFS,
+       IPC_CMD,
+       IPC_BOOT,
+       IPC_MULTI_RAW,
+       IPC_RAMDUMP,
+       MAX_DEV_FORMAT,
+};
+#define MAX_IPC_DEV    (IPC_RFS + 1)
+
+enum modem_io {
+       IODEV_MISC,
+       IODEV_NET,
+       IODEV_DUMMY,
+};
+
+enum modem_link {
+       LINKDEV_UNDEFINED,
+       LINKDEV_MIPI,
+       LINKDEV_DPRAM,
+       LINKDEV_SPI,
+       LINKDEV_USB,
+       LINKDEV_HSIC,
+       LINKDEV_C2C,
+       LINKDEV_MAX,
+};
+#define LINKTYPE(modem_link) (1u << (modem_link))
+
+enum modem_network {
+       UMTS_NETWORK,
+       CDMA_NETWORK,
+       LTE_NETWORK,
+};
+
+enum sipc_ver {
+       NO_SIPC_VER = 0,
+       SIPC_VER_40 = 40,
+       SIPC_VER_41 = 41,
+       SIPC_VER_42 = 42,
+       SIPC_VER_50 = 50,
+       MAX_SIPC_VER,
+};
+
+#endif
diff --git a/samsung-ipc/device/xmm6260/modem_link_device_hsic.h b/samsung-ipc/device/xmm6260/modem_link_device_hsic.h
new file mode 100755 (executable)
index 0000000..99e15cf
--- /dev/null
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2010 Samsung Electronics.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MODEM_LINK_DEVICE_USB_H__
+#define __MODEM_LINK_DEVICE_USB_H__
+
+
+enum {
+       IF_USB_BOOT_EP = 0,
+       IF_USB_FMT_EP = 0,
+       IF_USB_RAW_EP,
+       IF_USB_RFS_EP,
+       IF_USB_CMD_EP,
+       IF_USB_DEVNUM_MAX,
+};
+
+/* each pipe has 2 ep for in/out */
+#define LINKPM_DEV_NUM (IF_USB_DEVNUM_MAX * 2)
+/******************/
+/* xmm6260 specific */
+
+#define IOCTL_LINK_CONTROL_ENABLE      _IO('o', 0x30)
+#define IOCTL_LINK_CONTROL_ACTIVE      _IO('o', 0x31)
+#define IOCTL_LINK_GET_HOSTWAKE                _IO('o', 0x32)
+#define IOCTL_LINK_CONNECTED           _IO('o', 0x33)
+#define IOCTL_LINK_SET_BIAS_CLEAR      _IO('o', 0x34)
+
+/* VID,PID for IMC - XMM6260, XMM6262*/
+#define IMC_BOOT_VID           0x058b
+#define IMC_BOOT_PID           0x0041
+#define IMC_MAIN_VID           0x1519
+#define IMC_MAIN_PID           0x0020
+/* VID,PID for STE - M7400 */
+#define STE_BOOT_VID           0x04cc
+#define STE_BOOT_PID           0x7400
+#define STE_MAIN_VID           0x04cc
+#define STE_MAIN_PID           0x2333
+
+enum {
+       BOOT_DOWN = 0,
+       IPC_CHANNEL
+};
+
+enum ch_state {
+       STATE_SUSPENDED,
+       STATE_RESUMED,
+};
+
+#define HOSTWAKE_TRIGLEVEL     0
+
+#endif
index df4c37d..99f6087 100644 (file)
  *
  */
 
+#include <stdbool.h>
+#include <stdint.h>
+#include <linux/types.h>
+
+#define u8 uint8_t
+#define u16 uint16_t
+#define u32 uint32_t
+#define u64 uint64_t
+
 #ifndef __MODEM_PRJ_H__
 #define __MODEM_PRJ_H__
 
-#include <stdint.h>
+#define MAX_CPINFO_SIZE                512
 
 #define MAX_LINK_DEVTYPE       3
-#define MAX_RAW_DEVS           32
-#define MAX_NUM_IO_DEV         (MAX_RAW_DEVS + 4)
+
+#define MAX_FMT_DEVS   10
+#define MAX_RAW_DEVS   32
+#define MAX_RFS_DEVS   10
+#define MAX_NUM_IO_DEV (MAX_FMT_DEVS + MAX_RAW_DEVS + MAX_RFS_DEVS)
 
 #define IOCTL_MODEM_ON                 _IO('o', 0x19)
 #define IOCTL_MODEM_OFF                        _IO('o', 0x20)
@@ -33,7 +45,7 @@
 #define IOCTL_MODEM_PROTOCOL_RESUME    _IO('o', 0x26)
 
 #define IOCTL_MODEM_STATUS             _IO('o', 0x27)
-#define IOCTL_MODEM_GOTA_START         _IO('o', 0x28)
+#define IOCTL_MODEM_DL_START           _IO('o', 0x28)
 #define IOCTL_MODEM_FW_UPDATE          _IO('o', 0x29)
 
 #define IOCTL_MODEM_NET_SUSPEND                _IO('o', 0x30)
 #define PSD_DATA_CHID_BEGIN    0x2A
 #define PSD_DATA_CHID_END      0x38
 
+#define PS_DATA_CH_0   10
+#define PS_DATA_CH_LAST        24
+
 #define IP6VERSION             6
 
 #define SOURCE_MAC_ADDR                {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}
 
+/* Debugging features */
+#define MAX_MIF_LOG_PATH_LEN   128
+#define MAX_MIF_LOG_FILE_SIZE  0x800000        /* 8 MB */
+
+#define MAX_MIF_EVT_BUFF_SIZE  256
+#define MAX_MIF_TIME_LEN       32
+#define MAX_MIF_NAME_LEN       16
+#define MAX_MIF_STR_LEN                127
+#define MAX_MIF_LOG_LEN                128
+
+enum mif_event_id {
+       MIF_IRQ_EVT = 0,
+       MIF_LNK_RX_EVT,
+       MIF_MUX_RX_EVT,
+       MIF_IOD_RX_EVT,
+       MIF_IOD_TX_EVT,
+       MIF_MUX_TX_EVT,
+       MIF_LNK_TX_EVT,
+       MAX_MIF_EVT
+};
+
+struct dpram_queue_status {
+       unsigned in;
+       unsigned out;
+};
+
+struct dpram_queue_status_pair {
+       struct dpram_queue_status txq;
+       struct dpram_queue_status rxq;
+};
+
+struct dpram_irq_buff {
+       unsigned magic;
+       unsigned access;
+       struct dpram_queue_status_pair qsp[MAX_IPC_DEV];
+       unsigned int2ap;
+       unsigned int2cp;
+};
+
+struct mif_event_buff {
+       char time[MAX_MIF_TIME_LEN];
+
+       struct timeval tv;
+       enum mif_event_id evt;
+
+       char mc[MAX_MIF_NAME_LEN];
+
+       char iod[MAX_MIF_NAME_LEN];
+
+       char ld[MAX_MIF_NAME_LEN];
+       enum modem_link link_type;
+
+       unsigned rcvd;
+       unsigned len;
+       union {
+               u8 data[MAX_MIF_LOG_LEN];
+               struct dpram_irq_buff dpram_irqb;
+       };
+};
+
+#define MIF_LOG_DIR    "/sdcard"
+#define MIF_LOG_LV_FILE        "/data/.mif_log_level"
+
 /* Does modem ctl structure will use state ? or status defined below ?*/
 enum modem_state {
        STATE_OFFLINE,
@@ -85,6 +163,8 @@ enum modem_state {
        STATE_ONLINE,
        STATE_NV_REBUILDING, /* <= rebuilding start */
        STATE_LOADER_DONE,
+       STATE_SIM_ATTACH,
+       STATE_SIM_DETACH,
 };
 
 enum com_state {
@@ -95,6 +175,25 @@ enum com_state {
        COM_CRASH,
 };
 
+enum link_mode {
+       LINK_MODE_INVALID = 0,
+       LINK_MODE_IPC,
+       LINK_MODE_BOOT,
+       LINK_MODE_DLOAD,
+       LINK_MODE_ULOAD,
+};
+
+struct sim_state {
+       bool online;    /* SIM is online? */
+       bool changed;   /* online is changed? */
+};
+
+#define HDLC_START             0x7F
+#define HDLC_END               0x7E
+#define SIZE_OF_HDLC_START     1
+#define SIZE_OF_HDLC_END       1
+#define MAX_LINK_PADDING_SIZE  3
+
 struct header_data {
        char hdr[HDLC_HEADER_MAX_SIZE];
        unsigned len;
@@ -102,26 +201,30 @@ struct header_data {
        char start; /*hdlc start header 0x7F*/
 };
 
-struct sipc4_hdlc_fmt_hdr {
-       uint16_t len;
-       uint8_t  control;
+struct fmt_hdr {
+       u16 len;
+       u8 control;
 } __attribute__((packed));
 
-struct sipc4_fmt_hdr {
-       uint16_t len;
-       uint8_t  msg_seq;
-       uint8_t  ack_seq;
-       uint8_t  main_cmd;
-       uint8_t  sub_cmd;
-       uint8_t  cmd_type;
+struct raw_hdr {
+       u32 len;
+       u8 channel;
+       u8 control;
 } __attribute__((packed));
 
-//Link control
+struct rfs_hdr {
+       u32 len;
+       u8 cmd;
+       u8 id;
+} __attribute__((packed));
 
-#define IOCTL_LINK_CONTROL_ENABLE      _IO('o', 0x30)
-#define IOCTL_LINK_CONTROL_ACTIVE      _IO('o', 0x31)
-#define IOCTL_LINK_GET_HOSTWAKE                _IO('o', 0x32)
-#define IOCTL_LINK_CONNECTED           _IO('o', 0x33)
-#define IOCTL_LINK_SET_BIAS_CLEAR      _IO('o', 0x34)
+struct sipc_fmt_hdr {
+       u16 len;
+       u8  msg_seq;
+       u8  ack_seq;
+       u8  main_cmd;
+       u8  sub_cmd;
+       u8  cmd_type;
+} __attribute__((packed));
 
-#endif //__MODEM_PRJ_H__
+#endif
diff --git a/samsung-ipc/device/xmm6260/xmm6260.c b/samsung-ipc/device/xmm6260/xmm6260.c
new file mode 100644 (file)
index 0000000..a5c0779
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <sys/ioctl.h>
+
+#include "xmm6260.h"
+
+unsigned char xmm6260_crc_calculate(void *buffer, int length)
+{
+    unsigned char crc;
+    unsigned char *p;
+
+    if (buffer == NULL || length <= 0)
+        return 0;
+
+    p = (unsigned char *) buffer;
+
+    crc = 0;
+    while (length--)
+        crc ^= *p++;
+
+    return crc;
+}
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260.h b/samsung-ipc/device/xmm6260/xmm6260.h
new file mode 100644 (file)
index 0000000..d56ad1d
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __XMM6260_H__
+#define __XMM6260_H__
+
+#define XMM6260_AT                              "ATAT"
+#define XMM6260_PSI_PADDING                                     0xFF
+#define XMM6260_PSI_MAGIC                                       0x30
+#define XMM6260_SEC_END_MAGIC                                   0x0000
+#define XMM6260_HW_RESET_MAGIC                                  0x111001
+#define XMM6260_DATA_SIZE                                       0x1000
+
+#define XMM6260_COMMAND_SET_PORT_CONFIG                         0x86
+#define XMM6260_COMMAND_SEC_START                               0x204
+#define XMM6260_COMMAND_SEC_END                                 0x205
+#define XMM6260_COMMAND_HW_RESET                                0x208
+#define XMM6260_COMMAND_FLASH_SET_ADDRESS                       0x802
+#define XMM6260_COMMAND_FLASH_WRITE_BLOCK                       0x804
+
+#define XMM6260_FIRMWARE_ADDRESS                                0x60300000
+#define XMM6260_NV_DATA_ADDRESS                                 0x60E80000
+#define XMM6260_MPS_DATA_ADDRESS                                0x61080000
+
+unsigned char xmm6260_crc_calculate(void *buffer, int length);
+
+#endif
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_hsic.c b/samsung-ipc/device/xmm6260/xmm6260_hsic.c
new file mode 100644 (file)
index 0000000..263934b
--- /dev/null
@@ -0,0 +1,610 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ *
+ * Based on the incomplete C++ implementation which is:
+ * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/select.h>
+
+#include <samsung-ipc.h>
+#include <util.h>
+
+#include "xmm6260.h"
+#include "xmm6260_hsic.h"
+
+int xmm6260_hsic_ack_read(int device_fd, unsigned short ack)
+{
+    struct timeval timeout;
+    fd_set fds;
+
+    unsigned short value;
+    int rc;
+    int i;
+
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+
+    FD_ZERO(&fds);
+    FD_SET(device_fd, &fds);
+
+    for (i = 0; i < 50; i++) {
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0)
+            return -1;
+
+        value = 0;
+        rc = read(device_fd, &value, sizeof(value));
+        if (rc < (int) sizeof(value))
+            continue;
+
+        if (value == ack)
+            return 0;
+    }
+
+    return -1;
+}
+
+int xmm6260_hsic_psi_send(struct ipc_client *client, int device_fd,
+    void *psi_data, unsigned short psi_size)
+{
+    struct xmm6260_hsic_psi_header psi_header;
+    char at[] = XMM6260_AT;
+    unsigned char psi_ack;
+    unsigned char chip_id;
+    unsigned char psi_crc;
+
+    struct timeval timeout;
+    fd_set fds;
+    int wc;
+
+    unsigned char *p;
+    int length;
+    int rc;
+    int i;
+
+    if (client == NULL || device_fd < 0 || psi_data == NULL || psi_size == 0)
+        return -1;
+
+    FD_ZERO(&fds);
+
+    i = 0;
+    length = strlen(at);
+
+    do {
+        FD_SET(device_fd, &fds);
+
+        timeout.tv_sec = 0;
+        timeout.tv_usec = 100000;
+
+        rc = write(device_fd, at, length);
+        if (rc < length) {
+            ipc_client_log(client, "Writing ATAT in ASCII failed");
+            goto error;
+        }
+        ipc_client_log(client, "Wrote ATAT in ASCII");
+
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc < 0) {
+            ipc_client_log(client, "Waiting for bootup failed");
+            goto error;
+        }
+
+        if (i++ > 50) {
+            ipc_client_log(client, "Waiting for bootup failed");
+            goto error;
+        }
+    } while(rc == 0);
+
+    FD_SET(device_fd, &fds);
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 100000;
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0) {
+        ipc_client_log(client, "Reading chip id failed");
+        goto error;
+    }
+
+    psi_ack = 0;
+    rc = read(device_fd, &psi_ack, sizeof(psi_ack));
+    if (rc < 0 || psi_ack != XMM6260_HSIC_BOOT0_ACK) {
+        ipc_client_log(client, "Reading boot ACK failed");
+        goto error;
+    }
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0) {
+        ipc_client_log(client, "Reading chip id failed");
+        goto error;
+    }
+
+    chip_id = 0;
+    rc = read(device_fd, &chip_id, sizeof(chip_id));
+    if (rc < 0) {
+        ipc_client_log(client, "Reading chip id failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read chip id (0x%x)", chip_id);
+
+    psi_header.magic = XMM6260_PSI_MAGIC;
+    psi_header.length = psi_size;
+    psi_header.padding = XMM6260_PSI_PADDING;
+
+    rc = write(device_fd, &psi_header, sizeof(psi_header));
+    if (rc < (int) sizeof(psi_header)) {
+        ipc_client_log(client, "Writing PSI header failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote PSI header");
+
+    p = (unsigned char *) psi_data;
+
+    wc = 0;
+    while (wc < psi_size) {
+        rc = write(device_fd, (void *) p, psi_size - wc);
+        if (rc < 0) {
+            ipc_client_log(client, "Writing PSI failed");
+            goto error;
+        }
+
+        p += rc;
+        wc += rc;
+    }
+
+    psi_crc = xmm6260_crc_calculate(psi_data, psi_size);
+
+    ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc);
+
+    rc = write(device_fd, &psi_crc, sizeof(psi_crc));
+    if (rc < (int) sizeof(psi_crc)) {
+        ipc_client_log(client, "Writing PSI CRC failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote PSI CRC (0x%x)", psi_crc);
+
+    timeout.tv_sec = 0;
+    timeout.tv_usec = 100000;
+
+    for (i = 0; i < XMM6260_HSIC_PSI_UNKNOWN_COUNT; i++) {
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0) {
+            ipc_client_log(client, "Reading PSI unknown failed");
+            goto error;
+        }
+
+        rc = read(device_fd, &psi_ack, sizeof(psi_ack));
+        if (rc < (int) sizeof(psi_ack)) {
+            ipc_client_log(client, "Reading PSI unknown failed");
+            goto error;
+        }
+    }
+
+    for (i = 0; i < XMM6260_HSIC_PSI_CRC_ACK_COUNT ; i++) {
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0) {
+            ipc_client_log(client, "Reading PSI CRC ACK failed");
+            goto error;
+        }
+
+        rc = read(device_fd, &psi_ack, sizeof(psi_ack));
+        if (rc < (int) sizeof(psi_ack) || psi_ack != XMM6260_HSIC_PSI_CRC_ACK) {
+            ipc_client_log(client, "Reading PSI CRC ACK failed");
+            goto error;
+        }
+    }
+    ipc_client_log(client, "Read PSI CRC ACK");
+
+    rc = xmm6260_hsic_ack_read(device_fd, XMM6260_HSIC_PSI_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading PSI ACK failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read PSI ACK");
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6260_hsic_ebl_send(struct ipc_client *client, int device_fd,
+    void *ebl_data, int ebl_size)
+{
+    unsigned char ebl_crc;
+
+    int chunk;
+    int count;
+    int wc;
+
+    unsigned char *p;
+    int length;
+    int rc;
+
+    if (client == NULL || device_fd < 0 || ebl_data == NULL || ebl_size <= 0)
+        return -1;
+
+    length = sizeof(ebl_size);
+
+    rc = write(device_fd, &ebl_size, length);
+    if (rc < length) {
+        ipc_client_log(client, "Writing EBL size failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote EBL size");
+
+    rc = xmm6260_hsic_ack_read(device_fd, XMM6260_HSIC_EBL_SIZE_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading EBL size ACK failed");
+        goto error;
+    }
+
+    p = (unsigned char *) ebl_data;
+
+    chunk = XMM6260_HSIC_EBL_CHUNK;
+    wc = 0;
+    while (wc < ebl_size) {
+        count = chunk < ebl_size - wc ? chunk : ebl_size - wc;
+
+        rc = write(device_fd, (void *) p, count);
+        if (rc < 0) {
+            ipc_client_log(client, "Writing EBL failed");
+            goto error;
+        }
+
+        p += rc;
+        wc += rc;
+    }
+
+    ebl_crc = xmm6260_crc_calculate(ebl_data, ebl_size);
+
+    ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc);
+
+    rc = write(device_fd, &ebl_crc, sizeof(ebl_crc));
+    if (rc < (int) sizeof(ebl_crc)) {
+        ipc_client_log(client, "Writing EBL CRC failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc);
+
+    rc = xmm6260_hsic_ack_read(device_fd, XMM6260_HSIC_EBL_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading EBL ACK failed");
+        goto error;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6260_hsic_command_send(int device_fd, unsigned short code,
+    void *data, int size, int command_data_size, int ack)
+{
+    struct xmm6260_hsic_command_header header;
+    void *buffer = NULL;
+    int length;
+
+    struct timeval timeout;
+    fd_set fds;
+
+    unsigned char *p;
+    int rc;
+    int i;
+
+    if (device_fd < 0 || data == NULL || size <= 0 || command_data_size < size)
+        return -1;
+
+    header.checksum = (size & 0xffff) + code;
+    header.code = code;
+    header.data_size = size;
+
+    p = (unsigned char *) data;
+
+    for (i = 0; i < size; i++)
+        header.checksum += *p++;
+
+    length = command_data_size + sizeof(header);
+    buffer = malloc(length);
+
+    memset(buffer, 0, length);
+    p = (unsigned char *) buffer;
+    memcpy(p, &header, sizeof(header));
+    p += sizeof(header);
+    memcpy(p, data, size);
+
+    rc = write(device_fd, buffer, length);
+    if (rc < length)
+        goto error;
+
+    if (!ack) {
+        rc = 0;
+        goto complete;
+    }
+
+    memset(buffer, 0, length);
+
+    FD_ZERO(&fds);
+    FD_SET(device_fd, &fds);
+
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0)
+        goto error;
+
+    rc = read(device_fd, &header, sizeof(header));
+    if (rc < (int) sizeof(header))
+        goto error;
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0)
+        goto error;
+
+    rc = read(device_fd, buffer, command_data_size);
+    if (rc < command_data_size)
+        goto error;
+
+    if (header.code != code)
+        goto error;
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_hsic_modem_data_send(int device_fd, void *data, int size, int address)
+{
+    int chunk;
+    int count;
+    int c;
+
+    unsigned char *p;
+    int rc;
+
+    if (device_fd < 0 || data == NULL || size <= 0)
+        return -1;
+
+    rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_FLASH_SET_ADDRESS, &address, sizeof(address), XMM6260_HSIC_FLASH_SET_ADDRESS_SIZE, 1);
+    if (rc < 0)
+        goto error;
+
+    p = (unsigned char *) data;
+
+    chunk = XMM6260_HSIC_MODEM_DATA_CHUNK;
+    c = 0;
+    while (c < size) {
+        count = chunk < size - c ? chunk : size - c;
+
+        rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_FLASH_WRITE_BLOCK, p, count, XMM6260_HSIC_FLASH_WRITE_BLOCK_SIZE, 0);
+        if (rc < 0)
+            goto error;
+
+        p += count;
+        c += count;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6260_hsic_port_config_send(struct ipc_client *client, int device_fd)
+{
+    void *buffer = NULL;
+    int length;
+
+    struct timeval timeout;
+    fd_set fds;
+
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    FD_ZERO(&fds);
+    FD_SET(device_fd, &fds);
+
+    timeout.tv_sec = 2;
+    timeout.tv_usec = 0;
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0)
+        goto error;
+
+    length = XMM6260_HSIC_PORT_CONFIG_SIZE;
+    buffer = malloc(length);
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0)
+        goto error;
+
+    rc = read(device_fd, buffer, length);
+    if (rc < length) {
+        ipc_client_log(client, "Reading port config failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read port config");
+
+    rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_SET_PORT_CONFIG, buffer, length, XMM6260_HSIC_SET_PORT_CONFIG_SIZE, 1);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending port config command failed");
+        goto error;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_hsic_sec_start_send(struct ipc_client *client, int device_fd,
+    void *sec_data, int sec_size)
+{
+    int rc;
+
+    if (client == NULL || device_fd < 0 || sec_data == NULL || sec_size <= 0)
+        return -1;
+
+    rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_SEC_START, sec_data, sec_size, XMM6260_HSIC_SEC_START_SIZE, 1);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_hsic_sec_end_send(struct ipc_client *client, int device_fd)
+{
+    unsigned short sec_data;
+    int sec_size;
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    sec_data = XMM6260_SEC_END_MAGIC;
+    sec_size = sizeof(sec_data);
+
+    rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_SEC_END, &sec_data, sec_size, XMM6260_HSIC_SEC_END_SIZE, 1);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_hsic_firmware_send(struct ipc_client *client, int device_fd,
+    void *firmware_data, int firmware_size)
+{
+    int rc;
+
+    if (client == NULL || device_fd < 0 || firmware_data == NULL || firmware_size <= 0)
+        return -1;
+
+    rc = xmm6260_hsic_modem_data_send(device_fd, firmware_data, firmware_size, XMM6260_FIRMWARE_ADDRESS);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_hsic_nv_data_send(struct ipc_client *client, int device_fd)
+{
+    void *nv_data = NULL;
+    int nv_size;
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    rc = nv_data_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Checked nv_data");
+
+    rc = nv_data_md5_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data md5 failed");
+        goto error;
+    }
+    ipc_client_log(client, "Checked nv_data md5");
+
+    nv_data = file_data_read(nv_data_path(client), nv_data_size(client), nv_data_chunk_size(client));
+    if (nv_data == NULL) {
+        ipc_client_log(client, "Reading nv_data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read nv_data");
+
+    nv_size = nv_data_size(client);
+
+    rc = xmm6260_hsic_modem_data_send(device_fd, nv_data, nv_size, XMM6260_NV_DATA_ADDRESS);
+    if (rc < 0)
+        goto error;
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (nv_data != NULL)
+        free(nv_data);
+
+    return rc;
+}
+
+int xmm6260_hsic_hw_reset_send(struct ipc_client *client, int device_fd)
+{
+    unsigned int hw_reset_data;
+    int hw_reset_size;
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    hw_reset_data = XMM6260_HW_RESET_MAGIC;
+    hw_reset_size = sizeof(hw_reset_data);
+
+    rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_HW_RESET, &hw_reset_data, hw_reset_size, XMM6260_HSIC_HW_RESET_SIZE, 0);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_hsic.h b/samsung-ipc/device/xmm6260/xmm6260_hsic.h
new file mode 100644 (file)
index 0000000..5032e41
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __XMM6260_HSIC_H__
+#define __XMM6260_HSIC_H__
+
+#define XMM6260_HSIC_BOOT0_ACK                                  0xF0
+#define XMM6260_HSIC_PSI_UNKNOWN_COUNT                          22
+#define XMM6260_HSIC_PSI_CRC_ACK                                0x01
+#define XMM6260_HSIC_PSI_CRC_ACK_COUNT                          2
+#define XMM6260_HSIC_PSI_ACK                                    0xAA00
+#define XMM6260_HSIC_EBL_SIZE_ACK                               0xCCCC
+#define XMM6260_HSIC_EBL_ACK                                    0xA551
+#define XMM6260_HSIC_EBL_CHUNK                                  0x4000
+#define XMM6260_HSIC_PORT_CONFIG_SIZE                           0x4C
+#define XMM6260_HSIC_SET_PORT_CONFIG_SIZE                       0x800
+#define XMM6260_HSIC_SEC_START_SIZE                             0x4000
+#define XMM6260_HSIC_SEC_END_SIZE                               0x4000
+#define XMM6260_HSIC_HW_RESET_SIZE                              0x4000
+#define XMM6260_HSIC_FLASH_SET_ADDRESS_SIZE                     0x4000
+#define XMM6260_HSIC_FLASH_WRITE_BLOCK_SIZE                     0x4000
+#define XMM6260_HSIC_MODEM_DATA_CHUNK                           0x4000
+
+struct xmm6260_hsic_psi_header {
+    unsigned char magic;
+    unsigned short length;
+    unsigned char padding;
+} __attribute__((packed));
+
+struct xmm6260_hsic_command_header {
+    unsigned short checksum;
+    unsigned short code;
+    unsigned int data_size;
+} __attribute__((packed));
+
+int xmm6260_hsic_psi_send(struct ipc_client *client, int device_fd,
+    void *psi_data, unsigned short psi_size);
+int xmm6260_hsic_ebl_send(struct ipc_client *client, int device_fd,
+    void *ebl_data, int ebl_size);
+
+int xmm6260_hsic_port_config_send(struct ipc_client *client, int device_fd);
+int xmm6260_hsic_sec_start_send(struct ipc_client *client, int device_fd,
+    void *sec_data, int sec_size);
+int xmm6260_hsic_sec_end_send(struct ipc_client *client, int device_fd);
+int xmm6260_hsic_firmware_send(struct ipc_client *client, int device_fd,
+    void *firmware_data, int firmware_size);
+int xmm6260_hsic_nv_data_send(struct ipc_client *client, int device_fd);
+int xmm6260_hsic_hw_reset_send(struct ipc_client *client, int device_fd);
+
+#endif
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_ipc.c b/samsung-ipc/device/xmm6260/xmm6260_ipc.c
deleted file mode 100644 (file)
index b8c1f60..0000000
+++ /dev/null
@@ -1,399 +0,0 @@
-/**
- * This file is part of libsamsung-ipc.
- *
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- * based on crespo IPC code which is:
- *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- *                    Joerie de Gram <j.de.gram@gmail.com>
- *                    Simon Busch <morphis@gravedo.de>
- *
- * libsamsung-ipc is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * libsamsung-ipc is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdlib.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <termios.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <asm/types.h>
-#include <mtd/mtd-abi.h>
-#include <assert.h>
-
-#include <samsung-ipc.h>
-
-#include "ipc.h"
-
-#include "xmm6260_ipc.h"
-#include "xmm6260_loader.h"
-#include "xmm6260_modemctl.h"
-#include "modem_prj.h"
-
-int xmm6260_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
-{
-    struct ipc_header *hdr;
-    unsigned char *frame;
-    unsigned char *payload;
-    size_t frame_length;
-
-    /* Frame IPC header + payload length */
-    frame_length = (sizeof(*hdr) + request->length);
-
-    frame = (unsigned char*)malloc(frame_length);
-    hdr = (struct ipc_header*)frame;
-
-    /* IPC header */
-    hdr->length = frame_length;
-    hdr->mseq = request->mseq;
-    hdr->aseq = request->aseq;
-    hdr->group = request->group;
-    hdr->index = request->index;
-    hdr->type = request->type;
-
-    /* IPC payload */
-    payload = (frame + sizeof(*hdr));
-    memcpy(payload, request->data, request->length);
-
-    ipc_client_log_send(client, request, __func__);
-
-    client->handlers->write(client->handlers->transport_data, frame, frame_length);
-
-    free(frame);
-
-    return 0;
-}
-
-int xmm6260_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
-{
-    unsigned char buf[IPC_MAX_XFER] = {};
-    unsigned char *data;
-    unsigned short *frame_length;
-
-    struct ipc_header ipc = {
-        .length = 0,
-    };
-
-    int num_read = 0;
-    int left = 0;
-
-    if (!client || !response)
-        return -1;
-
-    num_read = client->handlers->read(client->handlers->transport_data, buf, IPC_MAX_XFER);
-
-    if (num_read <= 0) {
-        ipc_client_log(client, "read failed to read ipc length: %d", num_read);
-        response->data = 0;
-        response->length = 0;
-        goto done;
-    }
-
-    memcpy(&ipc, buf, sizeof(ipc));
-    left = ipc.length - num_read;
-
-    if (left > 0)
-        num_read = client->handlers->read(client->handlers->transport_data, buf + num_read, left);
-
-    memcpy(&ipc, buf, sizeof(ipc));
-
-    response->mseq = ipc.mseq;
-    response->aseq = ipc.aseq;
-    response->group = ipc.group;
-    response->index = ipc.index;
-    response->type = ipc.type;
-    response->cmd = IPC_COMMAND(response);
-    response->length = ipc.length - sizeof(ipc);
-    response->data = NULL;
-
-    if (response->length > 0) {
-        response->data = (unsigned char*)malloc(response->length);
-        memcpy(response->data, buf + sizeof(ipc), response->length);
-    }
-
-    ipc_client_log_recv(client, response, __func__);
-
-done:
-    return 0;
-}
-
-int xmm6260_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
-{
-    unsigned char buf[IPC_MAX_XFER] = {};
-    struct rfs_hdr header;
-    int header_recv = 0;
-    unsigned count=0;
-    int rc;
-    int ret = 0;
-
-    do {
-        rc = client->handlers->read(client->handlers->transport_data, buf, IPC_MAX_XFER);
-
-        if (rc < 0) {
-            ipc_client_log(client, "Failed to read RFS data.");
-            ret = -1;
-            goto done;
-        }
-
-        // We didn't recieve the header yet
-        if (!header_recv) {
-            if ((unsigned) rc < sizeof(struct rfs_hdr)) {
-                ipc_client_log(client, "Failed to read RFS data.");
-                ret = -1;
-                goto done;
-            }
-
-            memcpy((void *) &header, (void *) buf, sizeof(struct rfs_hdr));
-
-            if (header.size < sizeof(struct rfs_hdr)) {
-                ipc_client_log(client, "Invalid size in header");
-                ret = -1;
-                goto done;
-            }
-
-            response->mseq = 0;
-            response->aseq = header.id;
-            response->group = IPC_GROUP_RFS;
-            response->index = header.cmd;
-            response->type = 0;
-            response->length = header.size - sizeof(struct rfs_hdr);
-            response->data = NULL;
-
-            if (response->length > 0) {
-                response->data = malloc(response->length);
-                memcpy(response->data,
-                    (void *) (buf + sizeof(struct rfs_hdr)),
-                    rc - sizeof(struct rfs_hdr));
-            }
-
-            header_recv = 1;
-        } else {
-            // Still reading data, with no header
-            memcpy((void *) (response->data + count - sizeof(struct rfs_hdr)), buf, rc);
-        }
-
-        count += rc;
-    } while (count < header.size);
-
-    ipc_client_log_recv(client, response, __func__);
-
-done:
-    return ret;
-}
-
-int xmm6260_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
-{
-    struct rfs_hdr *header = NULL;
-    char *data = NULL;
-    int data_length;
-    int rc;
-
-    data_length = sizeof(struct rfs_hdr) + request->length;
-    data = malloc(data_length);
-    memset(data, 0, data_length);
-
-    header = (struct rfs_hdr *) data;
-    header->id = request->mseq;
-    header->cmd = request->index;
-    header->size = data_length;
-
-    memcpy((void *) (data + sizeof(struct rfs_hdr)), request->data, request->length);
-
-    ipc_client_log_send(client, request, __func__);
-
-    rc = client->handlers->write(client->handlers->transport_data, data, data_length);
-
-    return rc;
-}
-
-int xmm6260_ipc_open(void *transport_data, int type)
-{
-    struct xmm6260_ipc_transport_data *data;
-    int fd;
-
-    if (transport_data == NULL)
-        return -1;
-
-    data = (struct xmm6260_ipc_transport_data *) transport_data;
-
-    switch(type)
-    {
-        case IPC_CLIENT_TYPE_FMT:
-            fd = open("/dev/umts_ipc0", O_RDWR | O_NOCTTY | O_NONBLOCK);
-            break;
-        case IPC_CLIENT_TYPE_RFS:
-            fd = open("/dev/umts_rfs0", O_RDWR | O_NOCTTY | O_NONBLOCK);
-            break;
-        default:
-            break;
-    }
-
-    if(fd < 0)
-        return -1;
-
-    data->fd = fd;
-
-    return 0;
-}
-
-int xmm6260_ipc_close(void *transport_data)
-{
-    struct xmm6260_ipc_transport_data *data;
-    int fd;
-
-    if (transport_data == NULL)
-        return -1;
-
-    data = (struct xmm6260_ipc_transport_data *) transport_data;
-
-    fd = data->fd;
-    if (fd < 0)
-        return -1;
-
-    close(fd);
-
-    return 0;
-}
-
-int xmm6260_ipc_read(void *transport_data, void *buffer, unsigned int length)
-{
-    struct xmm6260_ipc_transport_data *data;
-    int fd;
-    int rc;
-
-    if (transport_data == NULL)
-        return -1;
-
-    data = (struct xmm6260_ipc_transport_data *) transport_data;
-
-    fd = data->fd;
-    if(fd < 0)
-        return -1;
-
-    rc = expect(fd, 100);
-    if (rc < 0)
-        return -1;
-
-    rc = read(fd, buffer, length);
-    if(rc < 0)
-        return -1;
-
-    return rc;
-}
-
-int xmm6260_ipc_write(void *transport_data, void *buffer, unsigned int length)
-{
-    struct xmm6260_ipc_transport_data *data;
-    int fd;
-    int rc;
-
-    if (transport_data == NULL)
-        return -1;
-
-    data = (struct xmm6260_ipc_transport_data *) transport_data;
-
-    fd = data->fd;
-    if(fd < 0)
-        return -1;
-
-    rc = write(fd, buffer, length);
-    if(rc < 0)
-        return -1;
-
-    return rc;
-}
-
-int xmm6260_ipc_poll(void *transport_data, struct timeval *timeout)
-{
-    struct xmm6260_ipc_transport_data *data;
-    fd_set fds;
-    int fd;
-    int rc;
-
-    if (transport_data == NULL)
-        return -1;
-
-    data = (struct xmm6260_ipc_transport_data *) transport_data;
-
-    fd = data->fd;
-    if (fd < 0)
-        return -1;
-
-    FD_ZERO(&fds);
-    FD_SET(fd, &fds);
-
-    rc = select(FD_SETSIZE, &fds, NULL, NULL, timeout);
-    return rc;
-}
-
-int xmm6260_ipc_power_on(void *power_data)
-{
-    return 0;
-}
-
-int xmm6260_ipc_power_off(void *power_data)
-{
-    return 0;
-}
-
-int xmm6260_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
-{
-    if (transport_data == NULL)
-        return -1;
-
-    *transport_data = (void *) malloc(sizeof(struct xmm6260_ipc_transport_data));
-    memset(*transport_data, 0, sizeof(struct xmm6260_ipc_transport_data));
-
-    return 0;
-}
-
-int xmm6260_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
-{
-    if (transport_data == NULL)
-        return -1;
-
-    free(transport_data);
-
-    return 0;
-}
-
-char *xmm6260_ipc_gprs_get_iface(int cid)
-{
-    char *iface = NULL;
-
-    if(cid > GPRS_IFACE_COUNT)
-        return NULL;
-
-    asprintf(&iface, "%s%d", GPRS_IFACE_PREFIX, cid - 1);
-
-    return iface;
-}
-
-int xmm6260_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
-{
-    if (capabilities == NULL)
-        return -1;
-
-    capabilities->port_list = 1;
-    capabilities->cid_max = GPRS_IFACE_COUNT;
-
-    return 0;
-}
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_ipc.h b/samsung-ipc/device/xmm6260/xmm6260_ipc.h
deleted file mode 100644 (file)
index 632c300..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * This file is part of libsamsung-ipc.
- *
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- * based on crespo IPC code which is:
- *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- *                    Joerie de Gram <j.de.gram@gmail.com>
- *                    Simon Busch <morphis@gravedo.de>
- *
- * libsamsung-ipc is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * libsamsung-ipc is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdint.h>
-
-#ifndef __XMM6260_IPC_H__
-#define __XMM6260_IPC_H__
-
-#define IPC_MAX_XFER        4096
-#define GPRS_IFACE_PREFIX   "rmnet"
-#define GPRS_IFACE_COUNT    3
-
-struct rfs_hdr {
-    uint32_t size;
-    uint8_t cmd;
-    uint8_t id;
-} __attribute__ ((packed));
-
-int xmm6260_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request);
-int xmm6260_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response);
-int xmm6260_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response);
-int xmm6260_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request);
-int xmm6260_ipc_open(void *transport_data, int type);
-int xmm6260_ipc_close(void *transport_data);
-int xmm6260_ipc_read(void *transport_data, void *buffer, unsigned int length);
-int xmm6260_ipc_write(void *transport_data, void *buffer, unsigned int length);
-int xmm6260_ipc_poll(void *transport_data, struct timeval *timeout);
-int xmm6260_ipc_power_on(void *power_data);
-int xmm6260_ipc_power_off(void *power_data);
-int xmm6260_ipc_data_create(void **transport_data, void **power_data, void **gprs_data);
-int xmm6260_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data);
-char* xmm6260_ipc_gprs_get_iface(int cid);
-int xmm6260_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities);
-
-struct xmm6260_ipc_transport_data {
-    int fd;
-};
-
-#endif
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_loader.c b/samsung-ipc/device/xmm6260/xmm6260_loader.c
deleted file mode 100644 (file)
index 0c077c6..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * XMM6260 Firmware loader functions
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <getopt.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#include <sys/time.h>
-
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "ipc.h"
-
-#include "xmm6260_loader.h"
-#include "xmm6260_modemctl.h"
-#include "modem_prj.h"
-
-unsigned char xmm6260_crc_calculate(void* data, size_t offset, size_t length)
-{
-    unsigned char crc = 0;
-    unsigned char *ptr = (unsigned char*) (data + offset);
-
-    while (length--)
-        crc ^= *ptr++;
-
-    return crc;
-}
-
-int expect(int fd, unsigned timeout)
-{
-    int ret = 0;
-
-    struct timeval tv = {
-        tv.tv_sec = timeout / 1000,
-        tv.tv_usec = 1000 * (timeout % 1000),
-    };
-
-    fd_set read_set;
-    FD_ZERO(&read_set);
-    FD_SET(fd, &read_set);
-
-    ret = select(fd + 1, &read_set, 0, 0, &tv);
-
-    if (ret < 0)
-        goto fail;
-
-    if (ret < 1 || !FD_ISSET(fd, &read_set))
-        goto fail;
-
-fail:
-    return ret;
-}
-
-int expect_read(int fd, void *buf, size_t size)
-{
-    int ret;
-
-    if ((ret = expect(fd, DEFAULT_TIMEOUT)) < 1)
-        return ret;
-
-    return read(fd, buf, size);
-}
-
-int expect_data(int fd, void *data, size_t size)
-{
-    int ret;
-    char buf[size];
-
-    if ((ret = expect_read(fd, buf, size)) != size) {
-        ret = -1;
-        return ret;
-    }
-
-    ret = memcmp(buf, data, size);
-
-    return ret;
-}
diff --git a/samsung-ipc/device/xmm6260/xmm6260_loader.h b/samsung-ipc/device/xmm6260/xmm6260_loader.h
deleted file mode 100644 (file)
index 9f19068..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * XMM6260 Firmware loader functions
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __XMM6260_LOADER_H__
-#define __XMM6260_LOADER_H__
-
-#define RADIO_MAP_SIZE (16 << 20)
-#define DEFAULT_TIMEOUT 50
-
-/*
- * Offset and length to describe a part of XMM6260 firmware
- */
-struct xmm6260_radio_part {
-    size_t offset;
-    size_t length;
-};
-
-/*
- * Components of the Samsung XMM6260 firmware
- */
-enum xmm6260_image {
-    PSI,
-    EBL,
-    SECURE_IMAGE,
-    FIRMWARE,
-    NVDATA,
-};
-
-/*
- * Bootloader control interface definitions
- */
-enum xmm6260_boot_cmd {
-    SetPortConf,
-
-    ReqSecStart,
-    ReqSecEnd,
-    ReqForceHwReset,
-
-    ReqFlashSetAddress,
-    ReqFlashWriteBlock,
-};
-
-/*
- * @brief Calculate the checksum for the XMM6260 bootloader protocol
- *
- * @param data [in] the data to calculate the checksum for
- * @param offset [in] number of bytes to skip
- * @param length [in] length of data in bytes
- * @return checksum value
- */
-unsigned char xmm6260_crc_calculate(void* data, size_t offset, size_t length);
-
-/* 
- * @brief Waits for fd to become available for reading
- *
- * @param fd [in] File descriptor of the socket
- * @param timeout [in] Timeout in milliseconds
- * @return Negative value indicating error code
- * @return Available socket number - 1, as select()
- */
-int expect(int fd, unsigned timeout);
-
-/* 
- * @brief Waits for data available and reads it to the buffer
- *
- * @param fd [in] File descriptor of the socket
- * @param buf Buffer to hold data
- * @param size [in] The number of bytes to read
- * @return Negative value indicating error code
- * @return The size of data received
- */
-int expect_read(int fd, void *buf, size_t size);
-
-/* 
- * @brief Receives data and compares with the pattern in memory
- *
- * @param fd [in] File descriptor of the socket
- * @param data [in] The pattern to compare to
- * @param size [in] The length of data to read in bytes
- * @return Negative value indicating error code
- * @return Available socket number - 1, as select()
- */
-int expect_data(int fd, void *data, size_t size);
-
-#endif
diff --git a/samsung-ipc/device/xmm6260/xmm6260_mipi.c b/samsung-ipc/device/xmm6260/xmm6260_mipi.c
new file mode 100644 (file)
index 0000000..902b7b9
--- /dev/null
@@ -0,0 +1,675 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ *
+ * Based on the incomplete C++ implementation which is:
+ * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/select.h>
+
+#include <samsung-ipc.h>
+#include <util.h>
+
+#include "xmm6260.h"
+#include "xmm6260_mipi.h"
+
+int xmm6260_mipi_crc_calculate(void *buffer, int length)
+{
+    unsigned char crc;
+    int mipi_crc;
+
+    crc = xmm6260_crc_calculate(buffer, length);
+    mipi_crc = (crc << 24) | 0xffffff;
+
+    return mipi_crc;
+}
+
+int xmm6260_mipi_ack_read(int device_fd, unsigned short ack)
+{
+    struct timeval timeout;
+    fd_set fds;
+
+    unsigned int value;
+    int rc;
+    int i;
+
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+
+    FD_ZERO(&fds);
+    FD_SET(device_fd, &fds);
+
+    for (i = 0; i < 50; i++) {
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0)
+            return -1;
+
+        value = 0;
+        rc = read(device_fd, &value, sizeof(value));
+        if (rc < (int) sizeof(value))
+            continue;
+
+        if ((value & 0xffff) == ack)
+            return 0;
+    }
+
+    return -1;
+}
+
+int xmm6260_mipi_psi_send(struct ipc_client *client, int device_fd,
+    void *psi_data, unsigned short psi_size)
+{
+    struct xmm6260_mipi_psi_header psi_header;
+    char at[] = XMM6260_AT;
+    int psi_crc;
+
+    struct timeval timeout;
+    fd_set fds;
+    int wc;
+
+    unsigned char *p;
+    int length;
+    int rc;
+    int i;
+
+    if (client == NULL || device_fd < 0 || psi_data == NULL || psi_size == 0)
+        return -1;
+
+    FD_ZERO(&fds);
+
+    i = 0;
+    length = strlen(at);
+
+    do {
+        FD_SET(device_fd, &fds);
+
+        timeout.tv_sec = 0;
+        timeout.tv_usec = 100000;
+
+        rc = write(device_fd, at, length);
+        if (rc < length) {
+            ipc_client_log(client, "Writing ATAT in ASCII failed");
+            goto error;
+        }
+        ipc_client_log(client, "Wrote ATAT in ASCII");
+
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc < 0) {
+            ipc_client_log(client, "Waiting for bootup failed");
+            goto error;
+        }
+
+        if (i++ > 50) {
+            ipc_client_log(client, "Waiting for bootup failed");
+            goto error;
+        }
+    } while(rc == 0);
+
+    rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_BOOT0_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading boot ACK failed");
+        goto error;
+    }
+
+    psi_header.padding = XMM6260_PSI_PADDING;
+    psi_header.length = ((psi_size >> 8) & 0xff) | ((psi_size & 0xff) << 8);
+    psi_header.magic = XMM6260_PSI_MAGIC;
+
+    rc = write(device_fd, &psi_header, sizeof(psi_header));
+    if (rc < (int) sizeof(psi_header)) {
+        ipc_client_log(client, "Writing PSI header failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote PSI header");
+
+    p = (unsigned char *) psi_data;
+
+    wc = 0;
+    while (wc < psi_size) {
+        rc = write(device_fd, (void *) p, psi_size - wc);
+        if (rc < 0) {
+            ipc_client_log(client, "Writing PSI failed");
+            goto error;
+        }
+
+        p += rc;
+        wc += rc;
+    }
+
+    psi_crc = xmm6260_mipi_crc_calculate(psi_data, psi_size);
+
+    ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc);
+
+    rc = write(device_fd, &psi_crc, sizeof(psi_crc));
+    if (rc < (int) sizeof(psi_crc)) {
+        ipc_client_log(client, "Writing PSI CRC failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote PSI CRC (0x%x)", psi_crc);
+
+    rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_PSI_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading PSI ACK failed");
+        goto error;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6260_mipi_ebl_send(struct ipc_client *client, int device_fd,
+    void *ebl_data, int ebl_size)
+{
+    unsigned short boot_magic[4];
+    unsigned char ebl_crc;
+
+    int chunk;
+    int count;
+    int wc;
+
+    unsigned char *p;
+    int length;
+    int rc;
+
+    if (client == NULL || device_fd < 0 || ebl_data == NULL || ebl_size <= 0)
+        return -1;
+
+    boot_magic[0] = 0;
+    boot_magic[1] = 0;
+    boot_magic[2] = XMM6260_MIPI_BOOT1_MAGIC;
+    boot_magic[3] = XMM6260_MIPI_BOOT1_MAGIC;
+
+    length = sizeof(boot_magic);
+
+    rc = write(device_fd, &length, sizeof(length));
+    if (rc < (int) sizeof(length)) {
+        ipc_client_log(client, "Writing boot magic length failed");
+        goto error;
+    }
+
+    rc = write(device_fd, &boot_magic, length);
+    if (rc < length) {
+        ipc_client_log(client, "Writing boot magic failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote boot magic");
+
+    rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_BOOT1_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading boot magic ACK failed");
+        goto error;
+    }
+
+    length = sizeof(ebl_size);
+
+    rc = write(device_fd, &length, sizeof(length));
+    if (rc < (int) sizeof(length)) {
+        ipc_client_log(client, "Writing EBL size length failed");
+        goto error;
+    }
+
+    rc = write(device_fd, &ebl_size, length);
+    if (rc < length) {
+        ipc_client_log(client, "Writing EBL size failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote EBL size");
+
+    rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_EBL_SIZE_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading EBL size ACK failed");
+        goto error;
+    }
+
+    ebl_size++;
+
+    rc = write(device_fd, &ebl_size, length);
+    if (rc < length) {
+        ipc_client_log(client, "Writing EBL size failed");
+        goto error;
+    }
+
+    ebl_size--;
+
+    p = (unsigned char *) ebl_data;
+
+    chunk = XMM6260_MIPI_EBL_CHUNK;
+    wc = 0;
+    while (wc < ebl_size) {
+        count = chunk < ebl_size - wc ? chunk : ebl_size - wc;
+
+        rc = write(device_fd, (void *) p, count);
+        if (rc < 0) {
+            ipc_client_log(client, "Writing EBL failed");
+            goto error;
+        }
+
+        p += rc;
+        wc += rc;
+    }
+
+    ebl_crc = xmm6260_crc_calculate(ebl_data, ebl_size);
+
+    ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc);
+
+    rc = write(device_fd, &ebl_crc, sizeof(ebl_crc));
+    if (rc < (int) sizeof(ebl_crc)) {
+        ipc_client_log(client, "Writing EBL CRC failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc);
+
+    rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_EBL_ACK);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading EBL ACK failed");
+        goto error;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6260_mipi_command_send(int device_fd, unsigned short code,
+    void *data, int size, int ack, int short_tail)
+{
+    struct xmm6260_mipi_command_header header;
+    struct xmm6260_mipi_command_tail tail;
+    int tail_size;
+    void *buffer = NULL;
+    int length;
+
+    struct timeval timeout;
+    fd_set fds;
+    int chunk;
+    int c;
+
+    unsigned char *p;
+    int rc;
+    int i;
+
+    if (device_fd < 0 || data == NULL || size <= 0)
+        return -1;
+
+    header.size = size + sizeof(header);
+    header.magic = XMM6260_MIPI_COMMAND_HEADER_MAGIC;
+    header.code = code;
+    header.data_size = size;
+
+    tail.checksum = (size & 0xffff) + code;
+    tail.magic = XMM6260_MIPI_COMMAND_TAIL_MAGIC;
+    tail.unknown = XMM6260_MIPI_COMMAND_TAIL_UNKNOWN;
+
+    p = (unsigned char *) data;
+
+    for (i = 0; i < size; i++)
+        tail.checksum += *p++;
+
+    tail_size = sizeof(tail);
+    if (short_tail)
+        tail_size -= sizeof(short);
+
+    length = sizeof(header) + size + tail_size;
+    buffer = malloc(length);
+
+    p = (unsigned char *) buffer;
+    memcpy(p, &header, sizeof(header));
+    p += sizeof(header);
+    memcpy(p, data, size);
+    p += size;
+    memcpy(p, &tail, tail_size);
+
+    rc = write(device_fd, buffer, length);
+    if (rc < length)
+        goto error;
+
+    free(buffer);
+    buffer = NULL;
+
+    if (!ack) {
+        rc = 0;
+        goto complete;
+    }
+
+    FD_ZERO(&fds);
+    FD_SET(device_fd, &fds);
+
+    timeout.tv_sec = 1;
+    timeout.tv_usec = 0;
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0)
+        goto error;
+
+    rc = read(device_fd, &length, sizeof(length));
+    if (rc < (int) sizeof(length) || length <= 0)
+        goto error;
+
+    length += sizeof(unsigned int);
+    if (length % 4 != 0)
+        length += length % 4;
+
+    if (length < (int) sizeof(buffer))
+        goto error;
+
+    buffer = malloc(length);
+
+    p = (unsigned char *) buffer;
+    memcpy(p, &length, sizeof(length));
+    p += sizeof(length);
+
+    chunk = 4;
+    c = sizeof(length);
+    while (c < length) {
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0)
+            goto error;
+
+        rc = read(device_fd, (void *) p, chunk);
+        if (rc < chunk)
+            goto error;
+
+        p += rc;
+        c += rc;
+    }
+
+    memcpy(&header, buffer, sizeof(header));
+    if (header.code != code)
+        goto error;
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_mipi_modem_data_send(int device_fd, void *data, int size, int address)
+{
+    int chunk;
+    int count;
+    int c;
+
+    unsigned char *p;
+    int rc;
+
+    if (device_fd < 0 || data == NULL || size <= 0)
+        return -1;
+
+    rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_FLASH_SET_ADDRESS, &address, sizeof(address), 1, 0);
+    if (rc < 0)
+        goto error;
+
+    p = (unsigned char *) data;
+
+    chunk = XMM6260_MIPI_MODEM_DATA_CHUNK;
+    c = 0;
+    while (c < size) {
+        count = chunk < size - c ? chunk : size - c;
+
+        rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_FLASH_WRITE_BLOCK, p, count, 1, 1);
+        if (rc < 0)
+            goto error;
+
+        p += count;
+        c += count;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6260_mipi_port_config_send(struct ipc_client *client, int device_fd)
+{
+    void *buffer = NULL;
+    int length;
+
+    struct timeval timeout;
+    fd_set fds;
+    int chunk;
+    int count;
+    int c;
+
+    unsigned char *p;
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    FD_ZERO(&fds);
+    FD_SET(device_fd, &fds);
+
+    timeout.tv_sec = 2;
+    timeout.tv_usec = 0;
+
+    rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+    if (rc <= 0)
+        goto error;
+
+    rc = read(device_fd, &length, sizeof(length));
+    if (rc < (int) sizeof(length) || length <= 0) {
+        ipc_client_log(client, "Reading port config length failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read port config length (0x%x)", length);
+
+    buffer = malloc(length);
+
+    p = (unsigned char *) buffer;
+
+    chunk = 4;
+    c = 0;
+    while (c < length) {
+        count = chunk < length - c ? chunk : length - c;
+
+        rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0)
+            goto error;
+
+        rc = read(device_fd, p, count);
+        if (rc < count) {
+            ipc_client_log(client, "Reading port config failed");
+            goto error;
+        }
+
+        p += count;
+        c += count;
+    }
+    ipc_client_log(client, "Read port config");
+
+    rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_SET_PORT_CONFIG, buffer, length, 1, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending port config command failed");
+        goto error;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_mipi_sec_start_send(struct ipc_client *client, int device_fd,
+    void *sec_data, int sec_size)
+{
+    int rc;
+
+    if (client == NULL || device_fd < 0 || sec_data == NULL || sec_size <= 0)
+        return -1;
+
+    rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_SEC_START, sec_data, sec_size, 1, 0);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_mipi_sec_end_send(struct ipc_client *client, int device_fd)
+{
+    unsigned short sec_data;
+    int sec_size;
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    sec_data = XMM6260_SEC_END_MAGIC;
+    sec_size = sizeof(sec_data);
+
+    rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_SEC_END, &sec_data, sec_size, 1, 1);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_mipi_firmware_send(struct ipc_client *client, int device_fd,
+    void *firmware_data, int firmware_size)
+{
+    int rc;
+
+    if (client == NULL || device_fd < 0 || firmware_data == NULL || firmware_size <= 0)
+        return -1;
+
+    rc = xmm6260_mipi_modem_data_send(device_fd, firmware_data, firmware_size, XMM6260_FIRMWARE_ADDRESS);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_mipi_nv_data_send(struct ipc_client *client, int device_fd)
+{
+    void *nv_data = NULL;
+    int nv_size;
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    rc = nv_data_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Checked nv_data");
+
+    rc = nv_data_md5_check(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Checking nv_data md5 failed");
+        goto error;
+    }
+    ipc_client_log(client, "Checked nv_data md5");
+
+    nv_data = file_data_read(nv_data_path(client), nv_data_size(client), nv_data_chunk_size(client));
+    if (nv_data == NULL) {
+        ipc_client_log(client, "Reading nv_data failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read nv_data");
+
+    nv_size = nv_data_size(client);
+
+    rc = xmm6260_mipi_modem_data_send(device_fd, nv_data, nv_size, XMM6260_NV_DATA_ADDRESS);
+    if (rc < 0)
+        goto error;
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (nv_data != NULL)
+        free(nv_data);
+
+    return rc;
+}
+
+int xmm6260_mipi_mps_data_send(struct ipc_client *client, int device_fd,
+    void *mps_data, int mps_size)
+{
+    int rc;
+
+    if (client == NULL || device_fd < 0 || mps_data == NULL || mps_size <= 0)
+        return -1;
+
+    rc = xmm6260_mipi_modem_data_send(device_fd, mps_data, mps_size, XMM6260_MPS_DATA_ADDRESS);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_mipi_hw_reset_send(struct ipc_client *client, int device_fd)
+{
+    unsigned int hw_reset_data;
+    int hw_reset_size;
+    int rc;
+
+    if (client == NULL || device_fd < 0)
+        return -1;
+
+    hw_reset_data = XMM6260_HW_RESET_MAGIC;
+    hw_reset_size = sizeof(hw_reset_data);
+
+    rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_HW_RESET, &hw_reset_data, hw_reset_size, 0, 1);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_mipi.h b/samsung-ipc/device/xmm6260/xmm6260_mipi.h
new file mode 100644 (file)
index 0000000..c8e7c73
--- /dev/null
@@ -0,0 +1,74 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __XMM6260_MIPI_H__
+#define __XMM6260_MIPI_H__
+
+#define XMM6260_MIPI_BOOT0_ACK                                  0xFFFF
+#define XMM6260_MIPI_BOOT1_MAGIC                                0x02
+#define XMM6260_MIPI_BOOT1_ACK                                  0xAA00
+#define XMM6260_MIPI_PSI_ACK                                    0xDD01
+#define XMM6260_MIPI_EBL_SIZE_ACK                               0xCCCC
+#define XMM6260_MIPI_EBL_ACK                                    0xA551
+#define XMM6260_MIPI_EBL_CHUNK                                  0xDFC
+#define XMM6260_MIPI_MODEM_DATA_CHUNK                           0xDF2
+#define XMM6260_MIPI_COMMAND_HEADER_MAGIC                       0x02
+#define XMM6260_MIPI_COMMAND_TAIL_MAGIC                         0x03
+#define XMM6260_MIPI_COMMAND_TAIL_UNKNOWN                       0xEAEA
+
+struct xmm6260_mipi_psi_header {
+    unsigned char padding;
+    unsigned short length;
+    unsigned char magic;
+} __attribute__((packed));
+
+struct xmm6260_mipi_command_header {
+    unsigned int size;
+    unsigned short magic;
+    unsigned short code;
+    unsigned short data_size;
+} __attribute__((packed));
+
+struct xmm6260_mipi_command_tail {
+    unsigned short checksum;
+    unsigned short magic;
+    unsigned short unknown;
+} __attribute__((packed));
+
+int xmm6260_mipi_psi_send(struct ipc_client *client, int device_fd,
+    void *psi_data, unsigned short psi_size);
+int xmm6260_mipi_ebl_send(struct ipc_client *client, int device_fd,
+    void *ebl_data, int ebl_size);
+
+int xmm6260_mipi_port_config_send(struct ipc_client *client, int device_fd);
+int xmm6260_mipi_sec_start_send(struct ipc_client *client, int device_fd,
+    void *sec_data, int sec_size);
+int xmm6260_mipi_sec_end_send(struct ipc_client *client, int device_fd);
+int xmm6260_mipi_firmware_send(struct ipc_client *client, int device_fd,
+    void *firmware_data, int firmware_size);
+int xmm6260_mipi_nv_data_send(struct ipc_client *client, int device_fd);
+int xmm6260_mipi_mps_data_send(struct ipc_client *client, int device_fd,
+    void *mps_data, int mps_size);
+int xmm6260_mipi_hw_reset_send(struct ipc_client *client, int device_fd);
+
+#endif
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_modemctl.c b/samsung-ipc/device/xmm6260/xmm6260_modemctl.c
deleted file mode 100644 (file)
index e0048e7..0000000
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * XMM6260 Modem Control functions
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <string.h>
-
-#include <getopt.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#include <sys/time.h>
-
-#include <sys/mman.h>
-#include <sys/stat.h>
-
-#include "ipc.h"
-
-#include "xmm6260_loader.h"
-#include "xmm6260_modemctl.h"
-#include "modem_prj.h"
-
-/*
- * modemctl generic functions
- */
-
-int modemctl_link_set_active(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled)
-{
-    unsigned status = enabled;
-    int ret;
-    unsigned long ioctl_code;
-
-    ioctl_code = IOCTL_LINK_CONTROL_ACTIVE;
-    ret = ioctl(io_data->link_fd, ioctl_code, &status);
-
-    if (ret < 0) {
-        ipc_client_log(client, "failed to set link active to %d", enabled);
-        goto fail;
-    }
-
-    return 0;
-
-fail:
-    return ret;
-}
-
-int modemctl_link_set_enabled(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled)
-{
-    unsigned status = enabled;
-    int ret;
-    unsigned long ioctl_code;
-
-    ioctl_code = IOCTL_LINK_CONTROL_ENABLE;
-    ret = ioctl(io_data->link_fd, ioctl_code, &status);
-
-    if (ret < 0) {
-        ipc_client_log(client, "failed to set link state to %d", enabled);
-        goto fail;
-    }
-
-    return 0;
-fail:
-    return ret;
-}
-
-int modemctl_wait_link_ready(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret;
-
-    struct timeval tv_start = {};
-    struct timeval tv_end = {};
-
-    gettimeofday(&tv_start, 0);;
-
-    /* link wakeup timeout in milliseconds */
-    long diff = 0;
-
-    do {
-        ret = ioctl(io_data->link_fd, IOCTL_LINK_CONNECTED, 0);
-
-        if (ret < 0)
-            goto fail;
-
-        if (ret == 1)
-            return 0;
-
-        usleep(LINK_POLL_DELAY_US);
-        gettimeofday(&tv_end, 0);;
-
-        diff = (tv_end.tv_sec - tv_start.tv_sec) * 1000;
-        diff += (tv_end.tv_usec - tv_start.tv_usec) / 1000;
-    } while (diff < LINK_TIMEOUT_MS);
-
-    ret = -ETIMEDOUT;
-
-fail:
-    return ret;
-}
-
-int modemctl_wait_modem_online(struct ipc_client *client,
-    struct modemctl_io_data *io_data)
-{
-    int ret;
-
-    struct timeval tv_start = {};
-    struct timeval tv_end = {};
-
-    gettimeofday(&tv_start, 0);;
-
-    /* link wakeup timeout in milliseconds */
-    long diff = 0;
-
-    do {
-        ret = ioctl(io_data->boot_fd, IOCTL_MODEM_STATUS, 0);
-        if (ret < 0)
-            goto fail;
-
-        if (ret == STATE_ONLINE)
-            return 0;
-
-        usleep(LINK_POLL_DELAY_US);
-        gettimeofday(&tv_end, 0);;
-
-        diff = (tv_end.tv_sec - tv_start.tv_sec) * 1000;
-        diff += (tv_end.tv_usec - tv_start.tv_usec) / 1000;
-    } while (diff < LINK_TIMEOUT_MS);
-
-    ret = -ETIMEDOUT;
-
-fail:
-    return ret;
-}
-
-int modemctl_modem_power(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled)
-{
-    if (enabled)
-        return ioctl(io_data->boot_fd, IOCTL_MODEM_ON, 0);
-    else
-        return ioctl(io_data->boot_fd, IOCTL_MODEM_OFF, 0);
-
-    return -1;
-}
-
-int modemctl_modem_boot_power(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled)
-{
-    if (enabled)
-        return ioctl(io_data->boot_fd, IOCTL_MODEM_BOOT_ON, 0);
-    else
-        return ioctl(io_data->boot_fd, IOCTL_MODEM_BOOT_OFF, 0);
-
-    return -1;
-}
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_modemctl.h b/samsung-ipc/device/xmm6260/xmm6260_modemctl.h
deleted file mode 100644 (file)
index aab2acb..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * XMM6260 Modem Control functions
- * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
- * Copyright (C) 2012 Paul Kocialkowski <contact@paulk.fr>
- *
- * based on the incomplete C++ implementation which is
- * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __XMM6260_MODEMCTL_H__
-#define __XMM6260_MODEMCTL_H__
-
-#include <samsung-ipc.h>
-
-#define MODEM_DEVICE(x) ("/dev/" #x)
-#define LINK_PM MODEM_DEVICE(link_pm)
-#define MODEM_DEV MODEM_DEVICE(modem_br)
-#define BOOT_DEV MODEM_DEVICE(umts_boot0)
-#define IPC_DEV MODEM_DEVICE(umts_ipc0)
-#define RFS_DEV MODEM_DEVICE(umts_rfs0)
-
-#define LINK_POLL_DELAY_US (50 * 1000)
-#define LINK_TIMEOUT_MS 2000
-
-struct modemctl_io_data {
-    int link_fd;
-    int boot_fd;
-
-    int radio_fd;
-    char *radio_data;
-    struct stat radio_stat;
-};
-
-/*
- * Function prototypes
- */
-
-/*
- * @brief Activates the modem <-> cpu link data transfer
- *
- * @param client [in] ipc client
- * @param io_data [in] modemctl-specific data
- * @param enabled [in] whether to enable or disable link data transport
- * @return Negative value indicating error code
- * @return ioctl call result
- */
-int modemctl_link_set_active(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled);
-
-/*
- * @brief Activates the modem <-> cpu link connection
- *
- * @param client [in] ipc client
- * @param io_data [in] modemctl-specific data
- * @param enabled [in] the state to set link to
- * @return Negative value indicating error code
- * @return ioctl call result
- */
-int modemctl_link_set_enabled(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled);
-
-/*
- * @brief Poll the link until it gets ready or times out
- *
- * @param client [in] ipc client
- * @param io_data [in] modemctl-specific data
- * @return Negative value indicating error code
- * @return ioctl call result
- */
-int modemctl_wait_link_ready(struct ipc_client *client,
-    struct modemctl_io_data *io_data);
-
-/*
- * @brief Poll the modem until it gets online or times out
- *
- * @param client [in] ipc client
- * @param io_data [in] modemctl-specific data
- * @return Negative value indicating error code
- * @return ioctl call result
- */
-int modemctl_wait_modem_online(struct ipc_client *client,
-    struct modemctl_io_data *io_data);
-
-/*
- * @brief Sets the modem power
- *
- * @param client [in] ipc client
- * @param io_data [in] modemctl-specific data
- * @param enabled [in] whether to enable or disable modem power
- * @return Negative value indicating error code
- * @return ioctl call result
- */
-int modemctl_modem_power(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled);
-
-/*
- * @brief Sets the modem bootloader power/UART configuration
- *
- * @param client [in] ipc client
- * @param io_data [in] modemctl-specific data
- * @param enabled [in] whether to enable or disable power
- * @return Negative value indicating error code
- * @return ioctl call result
- */
-int modemctl_modem_boot_power(struct ipc_client *client,
-    struct modemctl_io_data *io_data, bool enabled);
-
-#endif
-
-// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_sec_modem.c b/samsung-ipc/device/xmm6260/xmm6260_sec_modem.c
new file mode 100644 (file)
index 0000000..1a3629d
--- /dev/null
@@ -0,0 +1,500 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/select.h>
+
+#include <samsung-ipc.h>
+#include <ipc.h>
+#include <util.h>
+
+#include "modem.h"
+#include "modem_prj.h"
+#include "modem_link_device_hsic.h"
+
+#include "xmm6260.h"
+#include "xmm6260_sec_modem.h"
+
+int xmm6260_sec_modem_power(int device_fd, int power)
+{
+    int rc;
+
+    if (device_fd < 0)
+        return -1;
+
+    rc = ioctl(device_fd, power ? IOCTL_MODEM_ON : IOCTL_MODEM_OFF, 0);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_sec_modem_boot_power(int device_fd, int power)
+{
+    int rc;
+
+    if (device_fd < 0)
+        return -1;
+
+    rc = ioctl(device_fd, power ? IOCTL_MODEM_BOOT_ON : IOCTL_MODEM_BOOT_OFF, 0);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_sec_modem_status_online_wait(int device_fd)
+{
+    int status;
+    int i;
+
+    if (device_fd < 0)
+        return -1;
+
+    i = 0;
+    for (i = 0; i < 100; i++) {
+        status = ioctl(device_fd, IOCTL_MODEM_STATUS, 0);
+        if (status == STATE_ONLINE)
+            return 0;
+
+        usleep(50000);
+    }
+
+    return -1;
+}
+
+int xmm6260_sec_modem_hci_power(int power)
+{
+    int ehci_rc, ohci_rc;
+
+    ehci_rc = sysfs_value_write(XMM6260_SEC_MODEM_EHCI_POWER_SYSFS, !!power);
+    if (ehci_rc >= 0)
+        usleep(50000);
+
+    ohci_rc = sysfs_value_write(XMM6260_SEC_MODEM_OHCI_POWER_SYSFS, !!power);
+    if (ohci_rc >= 0)
+        usleep(50000);
+
+    if (ehci_rc < 0 && ohci_rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_sec_modem_link_control_enable(int device_fd, int enable)
+{
+    int rc;
+
+    if (device_fd < 0)
+        return -1;
+
+    rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ENABLE, &enable);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_sec_modem_link_control_active(int device_fd, int active)
+{
+    int rc;
+
+    if (device_fd < 0)
+        return -1;
+
+    rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ACTIVE, &active);
+    if (rc < 0)
+        return -1;
+
+    return 0;
+}
+
+int xmm6260_sec_modem_link_connected_wait(int device_fd)
+{
+    int status;
+    int i;
+
+    if (device_fd < 0)
+        return -1;
+
+    i = 0;
+    for (i = 0; i < 100; i++) {
+        status = ioctl(device_fd, IOCTL_LINK_CONNECTED, 0);
+        if (status)
+            return 0;
+
+        usleep(50000);
+    }
+
+    return -1;
+}
+
+int xmm6260_sec_modem_link_get_hostwake_wait(int device_fd)
+{
+    int status;
+    int i;
+
+    if (device_fd < 0)
+        return -1;
+
+    i = 0;
+    for (i = 0; i < 10; i++) {
+        status = ioctl(device_fd, IOCTL_LINK_GET_HOSTWAKE, 0);
+        if (status)
+            return 0;
+
+        usleep(50000);
+    }
+
+    return -1;
+}
+
+int xmm6260_sec_modem_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    struct ipc_header header;
+    void *buffer;
+    unsigned char *p;
+    int count;
+    int rc;
+
+    if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+        return -1;
+
+    ipc_header_fill(&header, request);
+
+    buffer = malloc(header.length);
+
+    memcpy(buffer, &header, sizeof(struct ipc_header));
+    if (request->data != NULL && request->length > 0)
+        memcpy((void *) ((unsigned char *) buffer + sizeof(struct ipc_header)), request->data, request->length);
+
+    ipc_client_log_send(client, request, __func__);
+
+    p = (unsigned char *) buffer;
+
+    count = 0;
+    while (count < header.length) {
+        rc = client->handlers->write(client->handlers->transport_data, p, header.length - count);
+        if (rc <= 0) {
+            ipc_client_log(client, "Writing FMT data to the modem failed");
+            goto error;
+        }
+
+        count += rc;
+        p += rc;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_sec_modem_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    struct ipc_header *header;
+    void *buffer = NULL;
+    unsigned char *p;
+    int length;
+    int count;
+    int rc;
+
+    if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
+        return -1;
+
+    length = XMM6260_DATA_SIZE;
+    buffer = malloc(length);
+
+    rc = client->handlers->read(client->handlers->transport_data, buffer, length);
+    if (rc < (int) sizeof(struct ipc_header)) {
+        ipc_client_log(client, "Reading FMT header from the modem failed");
+        goto error;
+    }
+
+    header = (struct ipc_header *) buffer;
+
+    ipc_message_info_fill(header, response);
+
+    if (header->length > sizeof(struct ipc_header)) {
+        response->length = header->length - sizeof(struct ipc_header);
+        response->data = malloc(response->length);
+
+        p = (unsigned char *) response->data;
+
+        count = rc - sizeof(struct ipc_header);
+        if (count > 0) {
+            memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct ipc_header)), count);
+            p += count;
+        }
+
+        while (count < (int) response->length) {
+            rc = client->handlers->read(client->handlers->transport_data, p, response->length - count);
+            if (rc <= 0) {
+                ipc_client_log(client, "Reading FMT data from the modem failed");
+                goto error;
+            }
+
+            count += rc;
+            p += rc;
+        }
+    }
+
+    ipc_client_log_recv(client, response, __func__);
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_sec_modem_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
+{
+    struct rfs_hdr header;
+    void *buffer;
+    unsigned char *p;
+    int count;
+    int rc;
+
+
+    if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+        return -1;
+
+    header.id = request->mseq;
+    header.cmd = request->index;
+    header.len = sizeof(struct rfs_hdr) + request->length;
+
+    buffer = malloc(header.len);
+
+    memcpy(buffer, &header, sizeof(struct rfs_hdr));
+    if (request->data != NULL && request->length > 0)
+        memcpy((void *) ((unsigned char *) buffer + sizeof(struct rfs_hdr)), request->data, request->length);
+
+    ipc_client_log_send(client, request, __func__);
+
+    p = (unsigned char *) buffer;
+
+    count = 0;
+    while (count < (int) header.len) {
+        rc = client->handlers->write(client->handlers->transport_data, p, header.len - count);
+        if (rc <= 0) {
+            ipc_client_log(client, "Writing RFS data to the modem failed");
+            goto error;
+        }
+
+        count += rc;
+        p += rc;
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_sec_modem_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
+{
+    struct rfs_hdr *header;
+    void *buffer = NULL;
+    unsigned char *p;
+    int length;
+    int count;
+    int rc;
+
+    if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
+        return -1;
+
+    length = XMM6260_DATA_SIZE;
+    buffer = malloc(length);
+
+    rc = client->handlers->read(client->handlers->transport_data, buffer, length);
+    if (rc < (int) sizeof(struct rfs_hdr)) {
+        ipc_client_log(client, "Reading RFS header from the modem failed");
+        goto error;
+    }
+
+    header = (struct rfs_hdr *) buffer;
+
+    memset(response, 0, sizeof(struct ipc_message_info));
+    response->aseq = header->id;
+    response->group = IPC_GROUP_RFS;
+    response->index = header->cmd;
+
+    if (header->len > sizeof(struct rfs_hdr)) {
+        response->length = header->len - sizeof(struct rfs_hdr);
+        response->data = malloc(response->length);
+
+        p = (unsigned char *) response->data;
+
+        count = rc - sizeof(struct rfs_hdr);
+        if (count > 0) {
+            memcpy(p, (void *) ((unsigned char *) buffer + sizeof(struct rfs_hdr)), count);
+            p += count;
+        }
+
+        while (count < (int) response->length) {
+            rc = client->handlers->read(client->handlers->transport_data, p, response->length - count);
+            if (rc <= 0) {
+                ipc_client_log(client, "Reading RFS data from the modem failed");
+                goto error;
+            }
+
+            count += rc;
+            p += rc;
+        }
+    }
+
+    ipc_client_log_recv(client, response, __func__);
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+}
+
+int xmm6260_sec_modem_ipc_open(int type)
+{
+    int fd;
+
+    switch (type) {
+        case IPC_CLIENT_TYPE_FMT:
+            fd = open(XMM6260_SEC_MODEM_IPC0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+            break;
+        case IPC_CLIENT_TYPE_RFS:
+            fd = open(XMM6260_SEC_MODEM_RFS0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
+            break;
+        default:
+            return -1;
+    }
+
+    return fd;
+}
+
+int xmm6260_sec_modem_ipc_close(int fd)
+{
+    if (fd < 0)
+        return -1;
+
+    close(fd);
+
+    return 0;
+}
+
+int xmm6260_sec_modem_ipc_read(int fd, void *buffer, unsigned int length)
+{
+    int rc;
+
+    if (fd < 0 || buffer == NULL || length <= 0)
+        return -1;
+
+    rc = read(fd, buffer, length);
+    return rc;
+}
+
+int xmm6260_sec_modem_ipc_write(int fd, void *buffer, unsigned int length)
+{
+    int rc;
+
+    if (fd < 0 || buffer == NULL || length <= 0)
+        return -1;
+
+    rc = write(fd, buffer, length);
+    return rc;
+}
+
+int xmm6260_sec_modem_ipc_poll(int fd, struct timeval *timeout)
+{
+    fd_set fds;
+    int rc;
+    int status;
+
+    if (fd < 0)
+        return -1;
+
+    FD_ZERO(&fds);
+    FD_SET(fd, &fds);
+
+    rc = select(fd + 1, &fds, NULL, NULL, timeout);
+    if (FD_ISSET(fd, &fds)) {
+        status = ioctl(fd, IOCTL_MODEM_STATUS, 0);
+        if (status != STATE_ONLINE && status != STATE_BOOTING)
+            return 0;
+    }
+
+    return rc;
+}
+
+char *xmm6260_sec_modem_ipc_gprs_get_iface(int cid)
+{
+    char *iface = NULL;
+
+    if (cid > XMM6260_SEC_MODEM_GPRS_IFACE_COUNT)
+        return NULL;
+
+    asprintf(&iface, "%s%d", XMM6260_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1);
+
+    return iface;
+}
+
+int xmm6260_sec_modem_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
+{
+    if (capabilities == NULL)
+        return -1;
+
+    capabilities->port_list = 0;
+    capabilities->cid_max = XMM6260_SEC_MODEM_GPRS_IFACE_COUNT;
+
+    return 0;
+}
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6260/xmm6260_sec_modem.h b/samsung-ipc/device/xmm6260/xmm6260_sec_modem.h
new file mode 100644 (file)
index 0000000..fc6082b
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
+ *
+ * libsamsung-ipc is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * libsamsung-ipc is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __XMM6260_SEC_MODEM_H__
+#define __XMM6260_SEC_MODEM_H__
+
+#define XMM6260_SEC_MODEM_BOOT0_DEVICE          "/dev/umts_boot0"
+#define XMM6260_SEC_MODEM_BOOT1_DEVICE          "/dev/umts_boot1"
+#define XMM6260_SEC_MODEM_IPC0_DEVICE           "/dev/umts_ipc0"
+#define XMM6260_SEC_MODEM_RFS0_DEVICE           "/dev/umts_rfs0"
+#define XMM6260_SEC_MODEM_LINK_PM_DEVICE        "/dev/link_pm"
+#define XMM6260_SEC_MODEM_EHCI_POWER_SYSFS      "/sys/devices/platform/s5p-ehci/ehci_power"
+#define XMM6260_SEC_MODEM_OHCI_POWER_SYSFS      "/sys/devices/platform/s5p-ehci/ohci_power"
+
+#define XMM6260_SEC_MODEM_GPRS_IFACE_PREFIX     "rmnet"
+#define XMM6260_SEC_MODEM_GPRS_IFACE_COUNT                      3
+
+int xmm6260_sec_modem_power(int device_fd, int power);
+int xmm6260_sec_modem_boot_power(int device_fd, int power);
+int xmm6260_sec_modem_status_online_wait(int device_fd);
+int xmm6260_sec_modem_hci_power(int power);
+int xmm6260_sec_modem_link_control_enable(int device_fd, int enable);
+int xmm6260_sec_modem_link_control_active(int device_fd, int active);
+int xmm6260_sec_modem_link_connected_wait(int device_fd);
+int xmm6260_sec_modem_link_get_hostwake_wait(int device_fd);
+
+int xmm6260_sec_modem_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request);
+int xmm6260_sec_modem_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response);
+int xmm6260_sec_modem_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request);
+int xmm6260_sec_modem_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response);
+
+int xmm6260_sec_modem_ipc_open(int type);
+int xmm6260_sec_modem_ipc_close(int fd);
+int xmm6260_sec_modem_ipc_read(int fd, void *buffer, unsigned int length);
+int xmm6260_sec_modem_ipc_write(int fd, void *buffer, unsigned int length);
+int xmm6260_sec_modem_ipc_poll(int fd, struct timeval *timeout);
+
+char *xmm6260_sec_modem_ipc_gprs_get_iface(int cid);
+int xmm6260_sec_modem_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities);
+
+#endif
+
+// vim:ts=4:sw=4:expandtab