Split aries and crespo common code to xmm6160, along with major code rework
authorPaul Kocialkowski <contact@paulk.fr>
Sun, 30 Jun 2013 08:40:11 +0000 (10:40 +0200)
committerPaul Kocialkowski <contact@paulk.fr>
Sun, 30 Jun 2013 08:40:11 +0000 (10:40 +0200)
Change-Id: Id78c7ce62bf5b9b875b6bc3dd53e6bf21fa36c95
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Android.mk
samsung-ipc/Makefile.am
samsung-ipc/device/aries/aries_ipc.c
samsung-ipc/device/aries/aries_ipc.h
samsung-ipc/device/crespo/crespo_ipc.c
samsung-ipc/device/crespo/crespo_ipc.h
samsung-ipc/device/xmm6160/xmm6160.c [new file with mode: 0644]
samsung-ipc/device/xmm6160/xmm6160.h [new file with mode: 0644]
samsung-ipc/device/xmm6260/xmm6260_ipc.h
samsung-ipc/ipc_devices.c
samsung-ipc/ipc_devices.h

index e1f635e..1e47081 100644 (file)
@@ -8,7 +8,6 @@ LOCAL_MODULE := libsamsung-ipc
 LOCAL_MODULE_TAGS := optional
 
 LOCAL_C_INCLUDES := external/openssl/include
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/samsung-ipc/device/xmm6260/
 LOCAL_LDFLAGS += -lcrypto
 
 ifeq ($(TARGET_DEVICE),crespo)
@@ -63,6 +62,7 @@ samsung-ipc_files := \
        samsung-ipc/util.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 \
@@ -77,8 +77,11 @@ LOCAL_SRC_FILES := $(samsung-ipc_files)
 LOCAL_CFLAGS += -DIPC_BOARD_NAME_EXPLICIT=\"$(board_name)\"
 
 LOCAL_SHARED_LIBRARIES := libutils
-LOCAL_C_INCLUDES += $(LOCAL_PATH)/include \
-       $(LOCAL_PATH)/samsung-ipc
+LOCAL_C_INCLUDES += \
+       $(LOCAL_PATH)/include \
+       $(LOCAL_PATH)/samsung-ipc \
+       $(LOCAL_PATH)/samsung-ipc/device/xmm6160/ \
+       $(LOCAL_PATH)/samsung-ipc/device/xmm6260/
 
 include $(BUILD_STATIC_LIBRARY)
 
index 25d730f..154bb70 100644 (file)
@@ -3,6 +3,7 @@ NULL =
 AM_CFLAGS = \
        -I$(top_srcdir)/include \
        -I$(top_srcdir)/samsung-ipc \
+       -I$(top_srcdir)/samsung-ipc/device/xmm6160 \
        -I$(top_srcdir)/samsung-ipc/device/xmm6260 \
        $(OPENSSL_CFLAGS) \
        $(NULL)
@@ -39,6 +40,8 @@ libsamsung_ipc_la_SOURCES = \
        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 \
index 2986321..4e3d273 100644 (file)
  */
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <stdint.h>
-#include <unistd.h>
 #include <stdbool.h>
-#include <termios.h>
-#include <fcntl.h>
 #include <string.h>
-#include <sys/mman.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+#include <fcntl.h>
 #include <sys/ioctl.h>
-#include <linux/netlink.h>
+#include <sys/mman.h>
 #include <net/if.h>
-#include <asm/types.h>
-#include <mtd/mtd-abi.h>
-#include <assert.h>
-#include <string.h>
 
 #include <samsung-ipc.h>
+#include <ipc.h>
+#include <util.h>
 
-#include "aries_ipc.h"
-#include "ipc.h"
 #include "sipc4.h"
 #include "onedram.h"
 #include "phonet.h"
 
-int phonet_iface_ifdown(void)
-{
-    struct ifreq ifr;
-    int fd;
-    int rc;
-
-    memset(&ifr, 0, sizeof(ifr));
-    strncpy(ifr.ifr_name, PHONET_IFACE, IFNAMSIZ);
-
-    fd = socket(AF_PHONET, SOCK_DGRAM, 0);
-
-    rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
-    if(rc < 0)
-        return -1;
-
-    ifr.ifr_flags = (ifr.ifr_flags & (~IFF_UP));
-
-    rc = ioctl(fd, SIOCSIFFLAGS, &ifr);
-    if(rc < 0)
-        return -1;
-
-    close(fd);
-
-    return 0;
-}
-
-int phonet_iface_ifup(void)
-{
-    struct ifreq ifr;
-    int fd;
-    int rc;
-
-    memset(&ifr, 0, sizeof(ifr));
-    strncpy(ifr.ifr_name, PHONET_IFACE, IFNAMSIZ);
-
-    fd = socket(AF_PHONET, SOCK_DGRAM, 0);
-
-    rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
-    if(rc < 0)
-        return -1;
-
-    ifr.ifr_flags |= IFF_UP;
-
-    rc = ioctl(fd, SIOCSIFFLAGS, &ifr);
-    if(rc < 0)
-        return -1;
-
-    close(fd);
-
-    return 0;
-}
+#include "xmm6160.h"
+#include "aries_ipc.h"
 
 int aries_ipc_bootstrap(struct ipc_client *client)
 {
-    int s3c2410_serial3_fd = -1;
-    int onedram_fd = -1;
-
-    /* Control variables. */
-    int rc = 0;
+    void *modem_image_data = NULL;
+    void *onedram_address = NULL;
+    unsigned int onedram_init;
+    unsigned int onedram_magic;
+    unsigned int onedram_deinit;
 
-    /* Boot variables */
-    uint8_t *radio_img_p = NULL;
-    uint32_t onedram_data = 0;
-    uint8_t bootcore_version = 0;
-    uint8_t info_size = 0;
-    uint8_t crc_byte = 0;
-    int block_size = 0;
-
-    /* s3c2410 serial setup variables. */
-    struct termios termios;
-    int serial;
+    int onedram_fd = -1;
+    int serial_fd = -1;
 
-    /* fds maniplation variables */
     struct timeval timeout;
     fd_set fds;
 
-    /* nv_data variables */
-    void *nv_data_p;
-    void *onedram_p;
-
-    /* General purpose variables. */
-    uint8_t data;
-    uint16_t data_16;
-    uint8_t *data_p;
+    int rc;
     int i;
 
-    ipc_client_log(client, "aries_ipc_bootstrap: enter");
-
-    /* Read the radio.img image. */
-    ipc_client_log(client, "aries_ipc_bootstrap: reading radio image");
-    radio_img_p = ipc_client_mtd_read(client, "/dev/block/bml12", RADIO_IMG_READ_SIZE, RADIO_IMG_READ_SIZE);
-    ipc_client_log(client, "aries_ipc_bootstrap: radio image read");
+    ipc_client_log(client, "Starting aries modem bootstrap");
 
-    ipc_client_log(client, "aries_ipc_bootstrap: open onedram");
-    onedram_fd=open("/dev/onedram", O_RDWR);
-    if(onedram_fd < 0)
+    modem_image_data = file_data_read(MODEM_IMAGE_DEVICE, MODEM_IMAGE_SIZE, 0x1000);
+    if (modem_image_data == NULL) {
+        ipc_client_log(client, "Reading modem image data failed");
         goto error;
-
-    /* Reset the modem before init to send the first part of modem.img. */
-    ipc_client_log(client, "aries_ipc_bootstrap: turning %s iface down", PHONET_IFACE);
-    rc = phonet_iface_ifdown();
-    if(rc < 0)
-        goto error;
-
-    ipc_client_power_off(client);
-    ipc_client_log(client, "aries_ipc_bootstrap: sent PHONE \"off\" command");
-    usleep(1000);
-
-    ipc_client_power_on(client);
-    ipc_client_log(client, "aries_ipc_bootstrap: sent PHONE \"on\" command");
-    usleep(200000);
-
-    ipc_client_log(client, "aries_ipc_bootstrap: open s3c2410_serial3");
-    s3c2410_serial3_fd=open("/dev/s3c2410_serial3", O_RDWR);
-    if(s3c2410_serial3_fd < 0)
-        goto error;
-
-    /* Setup the s3c2410 serial. */
-    ipc_client_log(client, "aries_ipc_bootstrap: setup s3c2410_serial3");
-    tcgetattr(s3c2410_serial3_fd, &termios);
-
-    cfmakeraw(&termios);
-    cfsetispeed(&termios, B115200);
-    cfsetospeed(&termios, B115200);
-
-    tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios);
-
-    /* Send 'AT' in ASCII. */
-    ipc_client_log(client, "aries_ipc_bootstrap: sending AT in ASCII");
-    for(i=0 ; i < 20 ; i++)
-    {
-        rc = write(s3c2410_serial3_fd, "AT", 2);
-        usleep(50000);
     }
-    ipc_client_log(client, "aries_ipc_bootstrap: sending AT in ASCII done");
-
-    /* Write the first part of modem.img. */
-    FD_ZERO(&fds);
-    FD_SET(s3c2410_serial3_fd, &fds);
+    ipc_client_log(client, "Read modem image data");
 
-    timeout.tv_sec=5;
-    timeout.tv_usec=0;
-
-    if(select(s3c2410_serial3_fd + 1, &fds, NULL, NULL, &timeout) == 0)
-    {
-        ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed");
+    onedram_fd = open(ONEDRAM_DEVICE, O_RDWR);
+    if (onedram_fd < 0) {
+        ipc_client_log(client, "Opening onedram failed");
         goto error;
     }
+    ipc_client_log(client, "Opened onedram");
 
-    /* Get and check bootcore version. */
-    read(s3c2410_serial3_fd, &bootcore_version, sizeof(bootcore_version));
-    ipc_client_log(client, "aries_ipc_bootstrap: got bootcore version: 0x%x", bootcore_version);
-
-    if(bootcore_version != BOOTCORE_VERSION)
+    rc = network_iface_down(MODEM_NETWORK_IFACE, AF_PHONET, SOCK_DGRAM);
+    if (rc < 0) {
+        ipc_client_log(client, "Turning modem network iface down failed");
         goto error;
+    }
+    ipc_client_log(client, "Turned modem network iface down");
 
-    FD_ZERO(&fds);
-    FD_SET(s3c2410_serial3_fd, &fds);
-
-    timeout.tv_sec=5;
-    timeout.tv_usec=0;
-
-    if(select(s3c2410_serial3_fd + 1, &fds, NULL, NULL, &timeout) == 0)
-    {
-        ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed");
+    rc = ipc_client_power_off(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Powering the modem off failed");
         goto error;
     }
+    ipc_client_log(client, "Powered the modem off");
 
-    /* Get info_size. */
-    read(s3c2410_serial3_fd, &info_size, sizeof(info_size));
-    ipc_client_log(client, "aries_ipc_bootstrap: got info_size: 0x%x", info_size);
-
-    /* Send PSI magic. */
-    data=PSI_MAGIC;
-    write(s3c2410_serial3_fd, &data, sizeof(uint8_t));
-    ipc_client_log(client, "aries_ipc_bootstrap: sent PSI_MAGIC (0x%x)", PSI_MAGIC);
-
-    /* Send PSI data len. */
-    data_16=PSI_DATA_LEN;
-    data_p=(uint8_t *)&data_16;
+    usleep(1000);
 
-    for(i=0 ; i < 2 ; i++)
-    {
-        write(s3c2410_serial3_fd, data_p, sizeof(uint8_t));
-        data_p++;
+    rc = ipc_client_power_on(client);
+    if (rc < 0) {
+        ipc_client_log(client, "Powering the modem on failed");
+        goto error;
     }
-    ipc_client_log(client, "aries_ipc_bootstrap: sent PSI_DATA_LEN (0x%x)", PSI_DATA_LEN);
-
-    timeout.tv_sec=5;
-    timeout.tv_usec=0;
+    ipc_client_log(client, "Powered the modem on");
 
-    data_p=radio_img_p;
-
-    ipc_client_log(client, "aries_ipc_bootstrap: sending the first part of radio.img");
-
-    for(i=0 ; i < PSI_DATA_LEN ; i++)
-    {
-        FD_ZERO(&fds);
-        FD_SET(s3c2410_serial3_fd, &fds);
-
-        if(select(s3c2410_serial3_fd + 1, NULL, &fds, NULL, &timeout) == 0)
-        {
-            ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed");
-            goto error;
-        }
-
-        write(s3c2410_serial3_fd, data_p, 1);
-        crc_byte=crc_byte ^ *data_p;
-
-        data_p++;
+    serial_fd = open(MODEM_SERIAL_DEVICE, O_RDWR | O_NDELAY);
+    if (serial_fd < 0) {
+        ipc_client_log(client, "Opening serial failed");
+        goto error;
     }
+    ipc_client_log(client, "Opened serial");
 
-    ipc_client_log(client, "aries_ipc_bootstrap: first part of radio.img sent; crc_byte is 0x%x", crc_byte);
+    usleep(100000);
 
-    FD_ZERO(&fds);
-    FD_SET(s3c2410_serial3_fd, &fds);
-
-    if(select(s3c2410_serial3_fd + 1, NULL, &fds, NULL, &timeout) == 0)
-    {
-        ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed");
+    rc = xmm6160_psi_send(client, serial_fd, modem_image_data, MODEM_IMAGE_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6160 PSI failed");
         goto error;
     }
+    ipc_client_log(client, "Sent XMM6160 PSI");
 
-    write(s3c2410_serial3_fd, &crc_byte, sizeof(crc_byte));
-
-    ipc_client_log(client, "aries_ipc_bootstrap: crc_byte sent");
+    onedram_init = 0;
 
-    timeout.tv_sec=5;
-    timeout.tv_usec=0;
+    FD_ZERO(&fds);
+    FD_SET(onedram_fd, &fds);
 
-    data = 0;
-    for(i = 0 ; data != 0x01 ; i++)
-    {
-        FD_ZERO(&fds);
-        FD_SET(s3c2410_serial3_fd, &fds);
+    timeout.tv_sec = 4;
+    timeout.tv_usec = 0;
 
-        if(select(s3c2410_serial3_fd + 1, &fds, NULL, NULL, &timeout) == 0)
-        {
-            ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed");
+    i = 0;
+    do {
+        rc = select(onedram_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0) {
+            ipc_client_log(client, "Reading onedram init failed");
             goto error;
         }
 
-        read(s3c2410_serial3_fd, &data, sizeof(data));
-
-        if(i > 50)
-        {
-            ipc_client_log(client, "aries_ipc_bootstrap: fairly too much attempts to get ACK");
+        rc = read(onedram_fd, &onedram_init, sizeof(onedram_init));
+        if (rc < (int) sizeof(onedram_init)) {
+            ipc_client_log(client, "Reading onedram init failed");
             goto error;
         }
-    }
 
-    ipc_client_log(client, "aries_ipc_bootstrap: close s3c2410_serial3");
-    close(s3c2410_serial3_fd);
-
-    timeout.tv_sec=3;
-    timeout.tv_usec=0;
-
-    ipc_client_log(client, "aries_ipc_bootstrap: wait for 0x%04x from onedram", ONEDRAM_INIT_READ);
-
-    onedram_data = 0;
-    while(onedram_data != ONEDRAM_INIT_READ) {
-        FD_ZERO(&fds);
-        FD_SET(onedram_fd, &fds);
-
-        if(select(onedram_fd + 1, &fds, NULL, NULL, &timeout) == 0)
-        {
-            ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed");
+        if (i++ > 50) {
+            ipc_client_log(client, "Reading onedram init failed");
             goto error;
         }
+    } while (onedram_init != ONEDRAM_INIT);
+    ipc_client_log(client, "Read onedram init (0x%x)", onedram_init);
 
-        read(onedram_fd, &onedram_data, sizeof(onedram_data));
-
-        ipc_client_log(client, "aries_ipc_bootstrap: read 0x%04x from onedram", onedram_data);
+    onedram_address = mmap(NULL, ONEDRAM_MEMORY_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, onedram_fd, 0);
+    if (onedram_address == NULL || onedram_address == (void *) 0xffffffff) {
+            ipc_client_log(client, "Mapping onedram to memory failed");
+            goto error;
     }
+    ipc_client_log(client, "Mapped onedram to memory");
 
-    ipc_client_log(client, "aries_ipc_bootstrap: writing the rest of modem.img to onedram.");
-
-    /* Pointer to the remaining part of radio.img. */
-    data_p=radio_img_p + PSI_DATA_LEN;
-
-    onedram_p = mmap(NULL, ONENAND_MAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, onedram_fd, 0);
-
-    if(onedram_p == NULL || onedram_p < 0 || onedram_p == 0xffffffff)
-    {
-        ipc_client_log(client, "aries_ipc_bootstrap: could not map onedram to memory");
+    rc = xmm6160_modem_image_send(client, -1, onedram_address, modem_image_data, MODEM_IMAGE_SIZE, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6160 modem image failed");
         goto error;
     }
+    ipc_client_log(client, "Sent XMM6160 modem image");
 
-    ipc_client_log(client, "aries_ipc_bootstrap: mapped onedram to 0x%x", onedram_p);
-
-    memcpy(onedram_p, data_p, RADIO_IMG_READ_SIZE - PSI_DATA_LEN);
-
-    free(radio_img_p);
-
-    /* nv_data part. */
-
-    /* Check if all the nv_data files are ok. */
-    if (nv_data_check(client) < 0)
-        goto error;
-
-    /* Check if the MD5 is ok. */
-    if (nv_data_md5_check(client) < 0)
+    rc = xmm6160_nv_data_send(client, -1, onedram_address, NV_DATA_OFFSET);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6160 nv_data failed");
         goto error;
+    }
+    ipc_client_log(client, "Sent XMM6160 nv_data");
 
-    /* Write nv_data.bin to modem_ctl. */
-    ipc_client_log(client, "aries_ipc_bootstrap: write nv_data to onedram");
+    munmap(onedram_address, ONEDRAM_MEMORY_SIZE);
+    onedram_address = NULL;
 
-    nv_data_p = ipc_client_file_read(client, nv_data_path(client), nv_data_size(client), nv_data_chunk_size(client));
-    if (nv_data_p == NULL)
+    rc = ioctl(onedram_fd, ONEDRAM_REL_SEM);
+    if (rc < 0)
         goto error;
-    data_p = nv_data_p;
-
-    memcpy(onedram_p + RADIO_IMG_MAX_SIZE, data_p, nv_data_size(client));
-
-    free(nv_data_p);
-
-    munmap(onedram_p, ONENAND_MAP_SIZE);
 
-    if(ioctl(onedram_fd, ONEDRAM_REL_SEM) < 0)
-    {
-        ipc_client_log(client, "aries_ipc_bootstrap: ONEDRAM_REL_SEM ioctl on onedram failed");
+    onedram_magic = ONEDRAM_MAGIC;
+    rc = write(onedram_fd, &onedram_magic, sizeof(onedram_magic));
+    if (rc < (int) sizeof(onedram_magic)) {
+        ipc_client_log(client, "Writing onedram magic failed");
         goto error;
     }
+    ipc_client_log(client, "Wrote onedram magic");
 
-    onedram_data = ONEDRAM_DEINIT_CMD;
-
-    ipc_client_log(client, "aries_ipc_bootstrap: send 0x%04x", onedram_data);
-    write(onedram_fd, &onedram_data, sizeof(onedram_data));
-
-    timeout.tv_sec=3;
-    timeout.tv_usec=0;
-
-    ipc_client_log(client, "aries_ipc_bootstrap: wait for 0x%04x from onedram", ONEDRAM_DEINIT_READ);
+    FD_ZERO(&fds);
+    FD_SET(onedram_fd, &fds);
 
-    onedram_data = 0;
-    while(onedram_data != ONEDRAM_DEINIT_READ) {
-        FD_ZERO(&fds);
-        FD_SET(onedram_fd, &fds);
+    timeout.tv_sec = 4;
+    timeout.tv_usec = 0;
 
-        if(select(onedram_fd + 1, &fds, NULL, NULL, &timeout) == 0)
-        {
-            ipc_client_log(client, "aries_ipc_bootstrap: select timeout passed");
+    i = 0;
+    do {
+        rc = select(onedram_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0) {
+            ipc_client_log(client, "Reading onedram deinit failed");
             goto error;
         }
 
-        read(onedram_fd, &onedram_data, sizeof(onedram_data));
-
-        ipc_client_log(client, "aries_ipc_bootstrap: read 0x%04x from onedram", onedram_data);
-    }
+        rc = read(onedram_fd, &onedram_deinit, sizeof(onedram_deinit));
+        if (rc < (int) sizeof(onedram_deinit)) {
+            ipc_client_log(client, "Reading onedram deinit failed");
+            goto error;
+        }
 
-    close(onedram_fd);
+        if (i++ > 50) {
+            ipc_client_log(client, "Reading onedram deinit failed");
+            goto error;
+        }
+    } while (onedram_deinit != ONEDRAM_DEINIT);
+    ipc_client_log(client, "Read onedram deinit (0x%x)", onedram_deinit);
 
     rc = 0;
-    goto exit;
+    goto complete;
 
 error:
-    ipc_client_log(client, "aries_ipc_bootstrap: something went wrong");
     rc = -1;
 
-exit:
-    ipc_client_log(client, "aries_ipc_bootstrap: exit");
+complete:
+    if (modem_image_data != NULL)
+        free(modem_image_data);
+
+    if (serial_fd >= 0)
+        close(serial_fd);
+
+    if (onedram_address != NULL)
+        munmap(onedram_address, ONEDRAM_MEMORY_SIZE);
+
+    if (onedram_fd >= 0)
+        close(onedram_fd);
+
     return rc;
 }
 
 int aries_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
 {
-    struct ipc_header reqhdr;
-    void *data;
-    int rc = 0;
-
-    reqhdr.mseq = request->mseq;
-    reqhdr.aseq = request->aseq;
-    reqhdr.group = request->group;
-    reqhdr.index = request->index;
-    reqhdr.type = request->type;
-    reqhdr.length = (uint16_t) (request->length + sizeof(struct ipc_header));
+    struct ipc_header header;
+    void *buffer;
+    int rc;
 
-    data = malloc(reqhdr.length);
+    if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+        return -1;
 
-    memcpy(data, &reqhdr, sizeof(struct ipc_header));
-    memcpy((unsigned char *) (data + sizeof(struct ipc_header)), request->data, request->length);
+    ipc_header_fill(&header, request);
 
-    assert(client->handlers->write != NULL);
+    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__);
 
-    rc = client->handlers->write(client->handlers->transport_data, data, reqhdr.length);
+    rc = client->handlers->write(client->handlers->transport_data, buffer, header.length);
+
+    free(buffer);
+
     return rc;
 }
 
 int aries_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
 {
-    struct ipc_header *resphdr;
-    void *data;
-    int bread = 0;
-
-    data = malloc(MAX_MODEM_DATA_SIZE);
-    memset(data, 0, MAX_MODEM_DATA_SIZE);
-
-    memset(response, 0, sizeof(struct ipc_message_info));
-
-    assert(client->handlers->read != NULL);
-    bread = client->handlers->read(client->handlers->transport_data, (uint8_t*) data, MAX_MODEM_DATA_SIZE);
+    struct ipc_header *header;
+    void *buffer = NULL;
+    int rc;
 
-    if (bread < 0)
-    {
-        ipc_client_log(client, "aries_ipc_fmt_client_recv: can't receive enough bytes from modem to process incoming response!");
+    if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
         return -1;
-    }
 
-    if(data == NULL)
-    {
-        ipc_client_log(client, "aries_ipc_fmt_client_recv: we retrieve less (or fairly too much) bytes from the modem than we exepected!");
-        return -1;
+    buffer = malloc(MODEM_DATA_SIZE);
+
+    rc = client->handlers->read(client->handlers->transport_data, buffer, MODEM_DATA_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading FMT data from the modem failed");
+        goto error;
     }
 
-    resphdr = (struct ipc_header *) data;
+    header = (struct ipc_header *) buffer;
 
-    response->mseq = resphdr->mseq;
-    response->aseq = resphdr->aseq;
-    response->group = resphdr->group;
-    response->index = resphdr->index;
-    response->type = resphdr->type;
-    response->cmd = IPC_COMMAND(response);
-    response->length = resphdr->length - sizeof(struct ipc_header);
-    response->data = NULL;
+    ipc_message_info_fill(header, response);
 
-    if(response->length > 0)
-    {
+    if (header->length > sizeof(struct ipc_header)) {
+        response->length = header->length - sizeof(struct ipc_header);
         response->data = malloc(response->length);
-        memcpy(response->data, (uint8_t *) data + sizeof(struct ipc_header), response->length);
+        memcpy(response->data, (void *) ((unsigned char *) buffer + sizeof(struct ipc_header)), response->length);
     }
 
-    free(data);
-
     ipc_client_log_recv(client, response, __func__);
 
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
+
     return 0;
 }
 
 int aries_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
 {
-    struct rfs_hdr *rfs_hdr;
-    void *data;
-    int rc = 0;
-
-    data = malloc(request->length + sizeof(struct rfs_hdr));
-    memset(data, 0, request->length + sizeof(struct rfs_hdr));
+    struct rfs_hdr *header;
+    void *buffer;
+    int length;
+    int rc;
 
-    rfs_hdr = (struct rfs_hdr *) data;
+    if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+        return -1;
 
-    rfs_hdr->id = request->mseq;
-    rfs_hdr->cmd = request->index;
-    rfs_hdr->len = request->length + sizeof(struct rfs_hdr);
+    length = sizeof(struct rfs_hdr) + request->length;
+    buffer = malloc(length);
 
-    memcpy((void *) (data + sizeof(struct rfs_hdr)), request->data, request->length);
+    header = (struct rfs_hdr *) buffer;
+    header->id = request->mseq;
+    header->cmd = request->index;
+    header->len = length;
 
-    assert(client->handlers->write != NULL);
+    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__);
 
-    rc = client->handlers->write(client->handlers->transport_data, (uint8_t*) data, rfs_hdr->len);
+    rc = client->handlers->write(client->handlers->transport_data, buffer, length);
+
+    free(buffer);
+
     return rc;
 }
 
 int aries_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
 {
-    void *data;
-    int bread = 0;
-    struct rfs_hdr *rfs_hdr;
-
-    data = malloc(MAX_MODEM_DATA_SIZE);
-    memset(data, 0, MAX_MODEM_DATA_SIZE);
-
-    memset(response, 0, sizeof(struct ipc_message_info));
+    struct rfs_hdr *header;
+    void *buffer = NULL;
+    int length;
+    int rc;
 
-    assert(client->handlers->read != NULL);
-    bread = client->handlers->read(client->handlers->transport_data, (uint8_t*) data, MAX_MODEM_DATA_SIZE);
-    if (bread < 0)
-    {
-        ipc_client_log(client, "aries_ipc_rfs_client_recv: can't receive enough bytes from modem to process incoming response!");
+    if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
         return -1;
-    }
 
-    rfs_hdr = (struct rfs_hdr *) data;
+    length = MODEM_DATA_SIZE;
+    buffer = malloc(length);
 
-    if(rfs_hdr->len <= 0 || rfs_hdr->len >= MAX_MODEM_DATA_SIZE || data == NULL)
-    {
-        ipc_client_log(client, "aries_ipc_rfs_client_recv: we retrieve less (or fairly too much) bytes from the modem than we exepected!");
-        return -1;
+    rc = client->handlers->read(client->handlers->transport_data, buffer, length);
+    if (rc < 0) {
+        ipc_client_log(client, "Reading RFS data from the modem failed");
+        goto error;
     }
 
-    response->mseq = 0;
-    response->aseq = rfs_hdr->id;
+    header = (struct rfs_hdr *) buffer;
+
+    memset(response, 0, sizeof(struct ipc_message_info));
+    response->aseq = header->id;
     response->group = IPC_GROUP_RFS;
-    response->index = rfs_hdr->cmd;
-    response->type = 0;
-    response->length = rfs_hdr->len - sizeof(struct rfs_hdr);
-    response->data = NULL;
+    response->index = header->cmd;
 
-    if(response->length > 0)
-    {
+    if (header->len > sizeof(struct rfs_hdr)) {
+        response->length = header->len - sizeof(struct rfs_hdr);
         response->data = malloc(response->length);
-        memcpy(response->data, (uint8_t *) (data + sizeof(struct rfs_hdr)), response->length);
+        memcpy(response->data, (void *) ((unsigned char *) buffer + sizeof(struct rfs_hdr)), response->length);
     }
 
-    free(data);
-
     ipc_client_log_recv(client, response, __func__);
 
-    return 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (buffer != NULL)
+        free(buffer);
+
+    return rc;
 }
 
 int aries_ipc_open(void *transport_data, int type)
@@ -583,29 +393,29 @@ int aries_ipc_open(void *transport_data, int type)
     spn = &data->spn;
 
     memset(&ifr, 0, sizeof(ifr));
-    strncpy(ifr.ifr_name, PHONET_IFACE, IFNAMSIZ);
+    strncpy(ifr.ifr_name, MODEM_NETWORK_IFACE, IFNAMSIZ);
 
     spn->spn_family = AF_PHONET;
     spn->spn_dev = 0;
 
-    switch(type)
+    switch (type)
     {
         case IPC_CLIENT_TYPE_FMT:
-            spn->spn_resource = PHONET_SPN_RES_FMT;
+            spn->spn_resource = MODEM_FMT_SPN_RESSOURCE;
             break;
         case IPC_CLIENT_TYPE_RFS:
-            spn->spn_resource = PHONET_SPN_RES_RFS;
+            spn->spn_resource = MODEM_RFS_SPN_RESSOURCE;
             break;
         default:
             break;
     }
 
     fd = socket(AF_PHONET, SOCK_DGRAM, 0);
-    if(fd < 0)
+    if (fd < 0)
         return -1;
 
     rc = setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifr.ifr_name, IFNAMSIZ);
-    if(rc < 0)
+    if (rc < 0)
         return -1;
 
     rc = ioctl(fd, SIOCGIFINDEX, &ifr);
@@ -614,25 +424,25 @@ int aries_ipc_open(void *transport_data, int type)
 
     reuse = 1;
     rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse));
-    if(rc < 0)
+    if (rc < 0)
         return -1;
 
-    rc = bind(fd, spn, sizeof(struct sockaddr_pn));
-    if(rc < 0)
+    rc = bind(fd, (const struct sockaddr *) spn, sizeof(struct sockaddr_pn));
+    if (rc < 0)
         return -1;
 
     data->fd = fd;
 
-    if(type == IPC_CLIENT_TYPE_RFS)
+    if (type == IPC_CLIENT_TYPE_RFS)
     {
-        socket_rfs_magic = SOCKET_RFS_MAGIC;
-        rc = setsockopt(fd, SOL_SOCKET, SO_RFSMAGIC, &socket_rfs_magic, sizeof(socket_rfs_magic));
-        if(rc < 0)
+        socket_rfs_magic = MODEM_SOCKET_RFS_MAGIC;
+        rc = setsockopt(fd, SOL_SOCKET, SO_IPC_RFS, &socket_rfs_magic, sizeof(socket_rfs_magic));
+        if (rc < 0)
             return -1;
     }
 
-    rc = phonet_iface_ifup();
-    if(rc < 0)
+    rc = network_iface_up(MODEM_NETWORK_IFACE, AF_PHONET, SOCK_DGRAM);
+    if (rc < 0)
         return -1;
 
     return 0;
@@ -664,7 +474,7 @@ int aries_ipc_read(void *transport_data, void *buffer, unsigned int length)
     int fd;
     int rc;
 
-    if (transport_data == NULL || buffer == NULL)
+    if (transport_data == NULL || buffer == NULL || length == 0)
         return -1;
 
     data = (struct aries_ipc_transport_data *) transport_data;
@@ -675,7 +485,7 @@ int aries_ipc_read(void *transport_data, void *buffer, unsigned int length)
 
     spn_size = sizeof(struct sockaddr_pn);
 
-    rc = recvfrom(fd, buffer, length, 0, &data->spn, &spn_size);
+    rc = recvfrom(fd, buffer, length, 0, (const struct sockaddr *) &data->spn, &spn_size);
     if (rc < 0)
         return -1;
 
@@ -689,7 +499,7 @@ int aries_ipc_write(void *transport_data, void *buffer, unsigned int length)
     int fd;
     int rc;
 
-    if (transport_data == NULL || buffer == NULL)
+    if (transport_data == NULL || buffer == NULL || length == 0)
         return -1;
 
     data = (struct aries_ipc_transport_data *) transport_data;
@@ -700,7 +510,7 @@ int aries_ipc_write(void *transport_data, void *buffer, unsigned int length)
 
     spn_size = sizeof(struct sockaddr_pn);
 
-    rc = sendto(fd, buffer, length, 0, &data->spn, spn_size);
+    rc = sendto(fd, buffer, length, 0, (const struct sockaddr *) &data->spn, spn_size);
     if (rc < 0)
         return -1;
 
@@ -732,34 +542,20 @@ int aries_ipc_poll(void *transport_data, struct timeval *timeout)
 
 int aries_ipc_power_on(void *power_data)
 {
-    int fd = open("/sys/class/modemctl/xmm/status", O_RDONLY);
-    char status[1] = { 0 };
-    char data[4] = "on";
+    char buffer[] = "on\n";
+    int value;
     int rc;
 
-    if(fd < 0)
-        return -1;
-
-    rc = read(fd, status, 1);
-
-    close(fd);
-
-    if(rc < 0)
+    value = sysfs_value_read(MODEMCTL_STATUS_SYSFS);
+    if (value < 0)
         return -1;
 
-    // it's already on
-    if(status[0] == '1')
+    /* The modem is already on */
+    if (value == 1)
         return 0;
 
-    fd = open("/sys/class/modemctl/xmm/control", O_RDWR);
-    if(fd < 0)
-        return -1;
-
-    rc = write(fd, data, 2);
-
-    close(fd);
-
-    if(rc < 0)
+    rc = sysfs_string_write(MODEMCTL_CONTROL_SYSFS, (char *) &buffer, strlen(buffer));
+    if (rc < 0)
         return -1;
 
     return 0;
@@ -767,105 +563,64 @@ int aries_ipc_power_on(void *power_data)
 
 int aries_ipc_power_off(void *power_data)
 {
-    int fd = open("/sys/class/modemctl/xmm/status", O_RDONLY);
-    char status[1] = { 0 };
-    char data[5] = "off";
+    char buffer[] = "off\n";
+    int value;
     int rc;
 
-    if(fd < 0)
+    value = sysfs_value_read(MODEMCTL_STATUS_SYSFS);
+    if (value < 0)
         return -1;
 
-    rc = read(fd, status, 1);
-
-    close(fd);
-
-    if(rc < 0)
-        return -1;
-
-    // it's already off
-    if(status[0] == '0')
+    /* The modem is already off */
+    if (value == 0)
         return 0;
 
-    fd = open("/sys/class/modemctl/xmm/control", O_RDWR);
-    if(fd < 0)
-        return -1;
-
-    rc = write(fd, data, 3);
-
-    close(fd);
-
-    if(rc < 0)
+    rc = sysfs_string_write(MODEMCTL_CONTROL_SYSFS, (char *) &buffer, strlen(buffer));
+    if (rc < 0)
         return -1;
 
     return 0;
 }
 
-int aries_ipc_gprs_activate(void *gprs_data, int cid)
+int aries_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
 {
-    int fd = open("/sys/class/net/svnet0/pdp/activate", O_RDWR);
-    char *activate_data = NULL;
-    int rc;
-
-    if(fd < 0)
-        return -1;
-
-    asprintf(&activate_data, "%d\n", cid);
-    if(activate_data == NULL)
+    if (transport_data == NULL)
         return -1;
 
-    rc = write(fd, activate_data, strlen(activate_data));
-
-    free(activate_data);
-    close(fd);
-
-    if(rc < 0)
-        return -1;
+    *transport_data = (void *) malloc(sizeof(struct aries_ipc_transport_data));
+    memset(*transport_data, 0, sizeof(struct aries_ipc_transport_data));
 
     return 0;
-
 }
 
-int aries_ipc_gprs_deactivate(void *gprs_data, int cid)
+int aries_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
 {
-    int fd = open("/sys/class/net/svnet0/pdp/deactivate", O_RDWR);
-    char *deactivate_data = NULL;
-    int rc;
-
-    if(fd < 0)
-        return -1;
-
-    asprintf(&deactivate_data, "%d\n", cid);
-    if(deactivate_data == NULL)
+    if (transport_data == NULL)
         return -1;
 
-    rc = write(fd, deactivate_data, strlen(deactivate_data));
-
-    free(deactivate_data);
-    close(fd);
-
-    if(rc < 0)
-        return -1;
+    free(transport_data);
 
     return 0;
 }
 
-int aries_ipc_data_create(void **transport_data, void **power_data, void **gprs_data)
+int aries_ipc_gprs_activate(void *gprs_data, int cid)
 {
-    if (transport_data == NULL)
-        return -1;
+    int rc;
 
-    *transport_data = (void *) malloc(sizeof(struct aries_ipc_transport_data));
-    memset(*transport_data, 0, sizeof(struct aries_ipc_transport_data));
+    rc = sysfs_value_write(MODEM_PDP_ACTIVATE_SYSFS, cid);
+    if (rc < 0)
+        return -1;
 
     return 0;
 }
 
-int aries_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data)
+int aries_ipc_gprs_deactivate(void *gprs_data, int cid)
 {
-    if (transport_data == NULL)
-        return -1;
+    int rc;
 
-    free(transport_data);
+    rc = sysfs_value_write(MODEM_PDP_DEACTIVATE_SYSFS, cid);
+    if (rc < 0)
+        return -1;
 
     return 0;
 }
@@ -881,9 +636,10 @@ char *aries_ipc_gprs_get_iface(int cid)
     memset(&ifr, 0, sizeof(ifr));
 
     fd = socket(AF_PHONET, SOCK_DGRAM, 0);
+    if (fd < 0)
+        return NULL;
 
-
-    for(i=GPRS_IFACE_COUNT-1 ; i >= 0 ; i--) {
+    for(i = (GPRS_IFACE_COUNT - 1); i >= 0; i--) {
         sprintf(ifr.ifr_name, "%s%d", GPRS_IFACE_PREFIX, i);
         rc = ioctl(fd, SIOCGIFFLAGS, &ifr);
         if(rc < 0 || ifr.ifr_flags & IFF_UP) {
index 056fdfb..3e6aedc 100644 (file)
@@ -1,8 +1,8 @@
-/**
+/*
  * This file is part of libsamsung-ipc.
  *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- *                    Igor Almeida <igor.contato@gmail.com>
+ * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011 Igor Almeida <igor.contato@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
  *
  */
 
+#include "phonet.h"
+
 #ifndef __ARIES_IPC_H__
 #define __ARIES_IPC_H__
 
-#include "phonet.h"
-
-#define BOOTCORE_VERSION        0xf0
-#define PSI_MAGIC               0x30
-#define PSI_DATA_LEN            0x5000
-#define RADIO_IMG_MAX_SIZE      0xd80000
-#define RADIO_IMG_READ_SIZE     0xa00000
-#define ONENAND_MAP_SIZE        0xFFF000
-#define ONEDRAM_INIT_READ       0x12341234
-#define ONEDRAM_DEINIT_CMD      0x45674567
-#define ONEDRAM_DEINIT_READ     0xabcdabcd
-#define SO_RFSMAGIC             0x21
-#define SOCKET_RFS_MAGIC        0x80000
-#define PHONET_IFACE            "svnet0"
-#define PHONET_SPN_RES_FMT      0x01
-#define PHONET_SPN_RES_RFS      0x41
-
-#define MAX_MODEM_DATA_SIZE     0x1000
-
-#define GPRS_IFACE_PREFIX       "pdp"
-#define GPRS_IFACE_COUNT        3
-
-int phonet_iface_ifdown(void);
-int phonet_iface_ifup(void);
+#define MODEM_IMAGE_SIZE                                        0xA00000
+#define NV_DATA_OFFSET                                          0xD80000
+#define ONEDRAM_MEMORY_SIZE                                     0xFFF000
+#define ONEDRAM_INIT                                            0x12341234
+#define ONEDRAM_MAGIC                                           0x45674567
+#define ONEDRAM_DEINIT                                          0xABCDABCD
+#define MODEM_DATA_SIZE                                         0x50000
+#define MODEM_SOCKET_RFS_MAGIC                                  0x80000
+
+#define SO_IPC_RFS                                              0x21
+#define MODEM_FMT_SPN_RESSOURCE                                 0x01
+#define MODEM_RFS_SPN_RESSOURCE                                 0x41
+
+#define MODEM_IMAGE_DEVICE                      "/dev/block/bml12"
+#define MODEM_SERIAL_DEVICE                     "/dev/s3c2410_serial3"
+#define ONEDRAM_DEVICE                          "/dev/onedram"
+#define MODEMCTL_STATUS_SYSFS                   "/sys/class/modemctl/xmm/status"
+#define MODEMCTL_CONTROL_SYSFS                  "/sys/class/modemctl/xmm/control"
+#define MODEM_NETWORK_IFACE                     "svnet0"
+#define MODEM_PDP_ACTIVATE_SYSFS                "/sys/class/net/svnet0/pdp/activate"
+#define MODEM_PDP_DEACTIVATE_SYSFS              "/sys/class/net/svnet0/pdp/deactivate"
+
+#define GPRS_IFACE_PREFIX                       "pdp"
+#define GPRS_IFACE_COUNT                                        3
 
 struct aries_ipc_transport_data {
     struct sockaddr_pn spn;
index eae60d7..790b09c 100644 (file)
@@ -1,9 +1,9 @@
-/**
+/*
  * This file is part of libsamsung-ipc.
  *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
- *                    Joerie de Gram <j.de.gram@gmail.com>
- *                    Simon Busch <morphis@gravedo.de>
+ * Copyright (C) 2011-2013 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011 Simon Busch <morphis@gravedo.de>
+ * Copyright (C) 2011 Joerie de Gram <j.de.gram@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
  *
  * 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 <stdint.h>
-#include <unistd.h>
 #include <stdbool.h>
-#include <termios.h>
-#include <fcntl.h>
 #include <string.h>
+#include <fcntl.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 <util.h>
 
 #include "crespo_modem_ctl.h"
+
+#include "xmm6160.h"
 #include "crespo_ipc.h"
-#include "ipc.h"
 
 int crespo_ipc_bootstrap(struct ipc_client *client)
 {
-    int s3c2410_serial3_fd = -1;
-    int modem_ctl_fd = -1;
+    void *modem_image_data = NULL;
 
-    /* Control variables. */
-    int rc = 0;
-
-    /* Boot variables */
-    uint8_t *radio_img_p = NULL;
-    uint8_t bootcore_version = 0;
-    uint8_t info_size = 0;
-    uint8_t crc_byte = 0;
-    int block_size = 0;
-
-    /* s3c2410 serial setup variables. */
-    struct termios termios;
-    int serial;
-
-    /* fds maniplation variables */
-    struct timeval timeout;
-    fd_set fds;
+    int modem_ctl_fd = -1;
+    int serial_fd = -1;
 
-    /* nv_data variables */
-    void *nv_data_p;
+    int rc;
 
-    /* General purpose variables. */
-    uint8_t data;
-    uint16_t data_16;
-    uint8_t *data_p;
-    int i;
+    if (client == NULL)
+        return -1;
 
-    ipc_client_log(client, "crespo_ipc_bootstrap: enter");
+    ipc_client_log(client, "Starting crespo modem bootstrap");
 
-    /* Read the radio.img image. */
-    ipc_client_log(client, "crespo_ipc_bootstrap: reading radio image");
-    radio_img_p = ipc_client_mtd_read(client, "/dev/mtd/mtd5ro", RADIO_IMG_SIZE, 0x1000);
-    if (radio_img_p == NULL) {
-        radio_img_p = ipc_client_mtd_read(client, "/dev/mtd5ro", RADIO_IMG_SIZE, 0x1000);
-        if (radio_img_p == NULL)
-            goto error;
+    modem_image_data = file_data_read(MODEM_IMAGE_DEVICE, MODEM_IMAGE_SIZE, 0x1000);
+    if (modem_image_data == NULL) {
+        ipc_client_log(client, "Reading modem image data failed");
+        goto error;
     }
-    ipc_client_log(client, "crespo_ipc_bootstrap: radio image read");
+    ipc_client_log(client, "Read modem image data");
 
-    ipc_client_log(client, "crespo_ipc_bootstrap: open modem_ctl");
-    modem_ctl_fd=open("/dev/modem_ctl", O_RDWR | O_NDELAY);
-    if(modem_ctl_fd < 0)
+    modem_ctl_fd = open(MODEM_CTL_DEVICE, O_RDWR | O_NDELAY);
+    if (modem_ctl_fd < 0) {
+        ipc_client_log(client, "Opening modem ctl failed");
         goto error;
+    }
+    ipc_client_log(client, "Opened modem ctl");
 
-    /* Reset the modem before init to send the first part of modem.img. */
     rc = ioctl(modem_ctl_fd, IOCTL_MODEM_RESET);
-    if (rc < 0)
+    if (rc < 0) {
+        ipc_client_log(client, "Resetting modem failed");
         goto error;
-
-    usleep(400000);
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: open s3c2410_serial3");
-    s3c2410_serial3_fd=open("/dev/s3c2410_serial3", O_RDWR | O_NDELAY);
-    if(s3c2410_serial3_fd < 0)
-        goto error;
-
-    /* Setup the s3c2410 serial. */
-    ipc_client_log(client, "crespo_ipc_bootstrap: setup s3c2410_serial3");
-    tcgetattr(s3c2410_serial3_fd, &termios);
-
-    cfmakeraw(&termios);
-    cfsetispeed(&termios, B115200);
-    cfsetospeed(&termios, B115200);
-
-    tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios);
-
-    /* Send 'AT' in ASCII. */
-    ipc_client_log(client, "crespo_ipc_bootstrap: sending AT in ASCII");
-    for(i=0 ; i < 20 ; i++)
-    {
-        rc = write(s3c2410_serial3_fd, "AT", 2);
-        usleep(50000);
     }
-    ipc_client_log(client, "crespo_ipc_bootstrap: sending AT in ASCII done");
-
-    usleep(50000); //FIXME
+    ipc_client_log(client, "Reset modem");
 
-    /* Get and check bootcore version. */
-    rc = read(s3c2410_serial3_fd, &bootcore_version, sizeof(bootcore_version));
-    if (rc < 0)
+    serial_fd = open(MODEM_SERIAL_DEVICE, O_RDWR | O_NDELAY);
+    if (serial_fd < 0) {
+        ipc_client_log(client, "Opening serial failed");
         goto error;
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: got bootcore version: 0x%x", bootcore_version);
-
-    if(bootcore_version != BOOTCORE_VERSION)
-        goto error;
-
-    /* Get info_size. */
-    rc = read(s3c2410_serial3_fd, &info_size, sizeof(info_size));
-    if (rc < 0)
-        goto error;
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: got info_size: 0x%x", info_size);
-
-    /* Send PSI magic. */
-    data = PSI_MAGIC;
-    rc = write(s3c2410_serial3_fd, &data, sizeof(data));
-    if (rc < 0)
-        goto error;
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: sent PSI_MAGIC (0x%x)", PSI_MAGIC);
-
-    /* Send PSI data len. */
-    data_16 = PSI_DATA_LEN;
-    data_p = (uint8_t *)&data_16;
-
-    for(i=0 ; i < 2 ; i++)
-    {
-        rc = write(s3c2410_serial3_fd, data_p, 1);
-        if (rc < 0)
-            goto error;
-
-        data_p++;
     }
-    ipc_client_log(client, "crespo_ipc_bootstrap: sent PSI_DATA_LEN (0x%x)", PSI_DATA_LEN);
-
-    /* Write the first part of modem.img. */
-    FD_ZERO(&fds);
-    FD_SET(s3c2410_serial3_fd, &fds);
+    ipc_client_log(client, "Opened serial");
 
-    timeout.tv_sec = 4;
-    timeout.tv_usec = 0;
+    usleep(100000);
 
-    data_p = radio_img_p;
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: sending the first part of radio.img");
-
-    for (i=0 ; i < PSI_DATA_LEN ; i++)
-    {
-        if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0)
-        {
-            ipc_client_log(client, "crespo_ipc_bootstrap: select timeout passed");
-            goto error;
-        }
-
-        rc = write(s3c2410_serial3_fd, data_p, 1);
-        if (rc < 0)
-            goto error;
-
-        crc_byte = crc_byte ^ *data_p;
-        data_p++;
-    }
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: first part of radio.img sent; crc_byte is 0x%x", crc_byte);
-
-    if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0)
-    {
-        ipc_client_log(client, "crespo_ipc_bootstrap: select timeout passed");
+    rc = xmm6160_psi_send(client, serial_fd, modem_image_data, MODEM_IMAGE_SIZE);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6160 PSI failed");
         goto error;
     }
+    ipc_client_log(client, "Sent XMM6160 PSI");
 
-    rc = write(s3c2410_serial3_fd, &crc_byte, sizeof(crc_byte));
-    if (rc < 0)
+    rc = xmm6160_modem_image_send(client, modem_ctl_fd, NULL, modem_image_data, MODEM_IMAGE_SIZE, 0);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6160 modem image failed");
         goto error;
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: crc_byte sent");
-
-    data = 0;
-    for (i = 0 ; data != 0x01 ; i++)
-    {
-        if (select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0)
-        {
-            ipc_client_log(client, "crespo_ipc_bootstrap: select timeout passed");
-            goto error;
-        }
-
-        rc = read(s3c2410_serial3_fd, &data, sizeof(data));
-        if (rc < 0)
-            goto error;
-
-        if(i > 50)
-        {
-            ipc_client_log(client, "crespo_ipc_bootstrap: fairly too much attempts to get ACK");
-            goto error;
-        }
-    }
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: close s3c2410_serial3");
-    close(s3c2410_serial3_fd);
-
-    ipc_client_log(client, "crespo_ipc_bootstrap: writing the rest of radio.img to modem_ctl.");
-    /* Seek to the begining of modem_ctl_fd (should already be so). */
-    lseek(modem_ctl_fd, 0, SEEK_SET);
-
-    /* Pointer to the remaining part of radio.img. */
-    data_p = radio_img_p + PSI_DATA_LEN;
-
-    FD_ZERO(&fds);
-    FD_SET(modem_ctl_fd, &fds);
-
-    block_size = 0x100000;
-
-    for (i=0 ; i < (RADIO_IMG_SIZE - PSI_DATA_LEN) / block_size ; i++)
-    {
-        if (select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0)
-        {
-            ipc_client_log(client, "crespo_ipc_bootstrap: select timeout passed");
-            goto error;
-        }
-
-        rc = write(modem_ctl_fd, data_p, block_size);
-        if (rc < 0)
-            goto error;
-
-        data_p += block_size;
     }
+    ipc_client_log(client, "Sent XMM6160 modem image");
 
-    free(radio_img_p);
-
-    /* nv_data part. */
-
-    /* Check if all the nv_data files are ok. */
-    if (nv_data_check(client) < 0)
+    rc = xmm6160_nv_data_send(client, modem_ctl_fd, NULL, NV_DATA_OFFSET);
+    if (rc < 0) {
+        ipc_client_log(client, "Sending XMM6160 nv_data failed");
         goto error;
-
-    /* Check if the MD5 is ok. */
-    if (nv_data_md5_check(client) < 0)
-        goto error;
-
-    /* Write nv_data.bin to modem_ctl. */
-    ipc_client_log(client, "crespo_ipc_bootstrap: write nv_data to modem_ctl");
-
-    nv_data_p = ipc_client_file_read(client, nv_data_path(client), nv_data_size(client), nv_data_chunk_size(client));
-    if (nv_data_p == NULL)
-        goto error;
-
-    data_p = nv_data_p;
-    lseek(modem_ctl_fd, RADIO_IMG_SIZE, SEEK_SET);
-
-    for(i=0 ; i < 2 ; i++)
-    {
-        rc = write(modem_ctl_fd, data_p, nv_data_size(client) / 2);
-        if (rc < 0)
-            goto error;
-
-        data_p += nv_data_size(client) / 2;
     }
-
-    free(nv_data_p);
-    close(modem_ctl_fd);
+    ipc_client_log(client, "Sent XMM6160 nv_data");
 
     rc = 0;
-    goto exit;
+    goto complete;
 
 error:
-    ipc_client_log(client, "%s: something went wrong", __func__);
     rc = -1;
 
-exit:
-    ipc_client_log(client, "crespo_ipc_bootstrap: exit");
+complete:
+    if (modem_image_data != NULL)
+        free(modem_image_data);
+
+    if (serial_fd >= 0)
+        close(serial_fd);
+
+    if (modem_ctl_fd >= 0)
+        close(modem_ctl_fd);
+
     return rc;
 }
 
 int crespo_ipc_fmt_send(struct ipc_client *client, struct ipc_message_info *request)
 {
-    struct modem_io modem_data;
-    struct ipc_header reqhdr;
-    int rc = 0;
+    struct ipc_header header;
+    struct modem_io mio;
+    int rc;
 
-    memset(&modem_data, 0, sizeof(struct modem_io));
-    modem_data.size = request->length + sizeof(struct ipc_header);
+    if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+        return -1;
 
-    reqhdr.mseq = request->mseq;
-    reqhdr.aseq = request->aseq;
-    reqhdr.group = request->group;
-    reqhdr.index = request->index;
-    reqhdr.type = request->type;
-    reqhdr.length = (uint16_t) (request->length + sizeof(struct ipc_header));
+    ipc_header_fill(&header, request);
 
-    modem_data.data = malloc(reqhdr.length);
+    memset(&mio, 0, sizeof(struct modem_io));
+    mio.size = request->length + sizeof(struct ipc_header);
+    mio.data = malloc(mio.size);
+    memcpy(mio.data, &header, sizeof(struct ipc_header));
+    if (request->data != NULL && request->length > 0)
+        memcpy((void *) ((unsigned char *) mio.data + sizeof(struct ipc_header)), request->data, request->length);
 
-    memcpy(modem_data.data, &reqhdr, sizeof(struct ipc_header));
-    memcpy((unsigned char *) (modem_data.data + sizeof(struct ipc_header)), request->data, request->length);
+    ipc_client_log_send(client, request, __func__);
 
-    assert(client->handlers->write != NULL);
+    rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
 
-    ipc_client_log_send(client, request, __func__);
+    free(mio.data);
 
-    rc = client->handlers->write(client->handlers->transport_data, (uint8_t*) &modem_data, sizeof(struct modem_io));
     return rc;
 }
 
 int crespo_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response)
 {
-    struct modem_io modem_data;
-    struct ipc_header *resphdr;
-    int bread = 0;
-
-    memset(&modem_data, 0, sizeof(struct modem_io));
-    modem_data.data = malloc(MAX_MODEM_DATA_SIZE);
-    modem_data.size = MAX_MODEM_DATA_SIZE;
-
-    memset(response, 0, sizeof(struct ipc_message_info));
+    struct ipc_header *header;
+    struct modem_io mio;
+    int rc;
 
-    assert(client->handlers->read != NULL);
-    bread = client->handlers->read(client->handlers->transport_data, (uint8_t*) &modem_data, sizeof(struct modem_io) + MAX_MODEM_DATA_SIZE);
-    if (bread < 0)
-    {
-        ipc_client_log(client, "crespo_ipc_fmt_client_recv: can't receive enough bytes from modem to process incoming response!");
+    if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
         return -1;
-    }
 
-    if(modem_data.size <= 0 || modem_data.size >= MAX_MODEM_DATA_SIZE || modem_data.data == NULL)
-    {
-        ipc_client_log(client, "crespo_ipc_fmt_client_recv: we retrieve less (or fairly too much) bytes from the modem than we exepected!");
-        return -1;
-    }
+    memset(&mio, 0, sizeof(struct modem_io));
+    mio.size = MODEM_DATA_SIZE;
+    mio.data = malloc(mio.size);
 
-    resphdr = (struct ipc_header *) modem_data.data;
+    rc = client->handlers->read(client->handlers->transport_data, &mio, sizeof(struct modem_io) + mio.size);
+    if (rc < 0 || mio.data == NULL || mio.size < sizeof(struct ipc_header)) {
+        ipc_client_log(client, "Reading FMT data from the modem failed");
+        goto error;
+    }
 
-    response->mseq = resphdr->mseq;
-    response->aseq = resphdr->aseq;
-    response->group = resphdr->group;
-    response->index = resphdr->index;
-    response->type = resphdr->type;
-    response->cmd = IPC_COMMAND(response);
-    response->length = modem_data.size - sizeof(struct ipc_header);
-    response->data = NULL;
+    header = (struct ipc_header *) mio.data;
+    ipc_message_info_fill(header, response);
 
-    if(response->length > 0)
-    {
+    if (mio.size > sizeof(struct ipc_header)) {
+        response->length = mio.size - sizeof(struct ipc_header);
         response->data = malloc(response->length);
-        memcpy(response->data, (uint8_t *) modem_data.data + sizeof(struct ipc_header), response->length);
+        memcpy(response->data, (void *) ((unsigned char *) mio.data + sizeof(struct ipc_header)), response->length);
     }
 
-    free(modem_data.data);
-
     ipc_client_log_recv(client, response, __func__);
 
-    return 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (mio.data != NULL)
+        free(mio.data);
+
+    return rc;
 }
 
 int crespo_ipc_rfs_send(struct ipc_client *client, struct ipc_message_info *request)
 {
-    struct modem_io modem_data;
-    int rc = 0;
-
-    memset(&modem_data, 0, sizeof(struct modem_io));
+    struct modem_io mio;
+    int rc;
 
-    modem_data.id = request->mseq;
-    modem_data.cmd = request->index;
+    if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL)
+        return -1;
 
-    modem_data.size = request->length;
-    modem_data.data = malloc(request->length);
+    memset(&mio, 0, sizeof(struct modem_io));
+    mio.id = request->mseq;
+    mio.cmd = request->index;
+    mio.size = request->length;
+    if (request->data != NULL && request->length > 0) {
+        mio.data = malloc(mio.size);
+        memcpy(mio.data, request->data, request->length);
+    }
 
-    memcpy(modem_data.data, request->data, request->length);
+    ipc_client_log_send(client, request, __func__);
 
-    assert(client->handlers->write != NULL);
+    rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io));
 
-    ipc_client_log_send(client, request, __func__);
+    if (mio.data != NULL)
+        free(mio.data);
 
-    rc = client->handlers->write(client->handlers->transport_data, (uint8_t*) &modem_data, sizeof(struct modem_io));
     return rc;
 }
 
 int crespo_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response)
 {
-    struct modem_io modem_data;
-    int bread = 0;
-
-    memset(&modem_data, 0, sizeof(struct modem_io));
-    modem_data.data = malloc(MAX_MODEM_DATA_SIZE);
-    modem_data.size = MAX_MODEM_DATA_SIZE;
-
-    memset(response, 0, sizeof(struct ipc_message_info));
+    struct modem_io mio;
+    int rc;
 
-    assert(client->handlers->read != NULL);
-    bread = client->handlers->read(client->handlers->transport_data, (uint8_t*) &modem_data, sizeof(struct modem_io) + MAX_MODEM_DATA_SIZE);
-    if (bread < 0)
-    {
-        ipc_client_log(client, "crespo_ipc_rfs_client_recv: can't receive enough bytes from modem to process incoming response!");
+    if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL)
         return -1;
-    }
 
-    if(modem_data.size <= 0 || modem_data.size >= MAX_MODEM_DATA_SIZE || modem_data.data == NULL)
-    {
-        ipc_client_log(client, "crespo_ipc_rfs_client_recv: we retrieve less (or fairly too much) bytes from the modem than we exepected!");
-        return -1;
+    memset(&mio, 0, sizeof(struct modem_io));
+    mio.size = MODEM_DATA_SIZE;
+    mio.data = malloc(mio.size);
+
+    rc = client->handlers->read(client->handlers->transport_data, &mio, sizeof(struct modem_io) + mio.size);
+    if (rc < 0 || mio.data == NULL || mio.size <= 0) {
+        ipc_client_log(client, "Reading RFS data from the modem failed");
+        goto error;
     }
 
-    response->mseq = 0;
-    response->aseq = modem_data.id;
+    memset(response, 0, sizeof(struct ipc_message_info));
+    response->aseq = mio.id;
     response->group = IPC_GROUP_RFS;
-    response->index = modem_data.cmd;
-    response->type = 0;
-    response->length = modem_data.size;
-    response->data = NULL;
+    response->index = mio.cmd;
 
-    if(response->length > 0)
-    {
+    if (mio.size > 0) {
+        response->length = mio.size;
         response->data = malloc(response->length);
-        memcpy(response->data, (uint8_t *) modem_data.data, response->length);
+        memcpy(response->data, mio.data, response->length);
     }
 
-    free(modem_data.data);
-
     ipc_client_log_recv(client, response, __func__);
 
-    return 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (mio.data != NULL)
+        free(mio.data);
+
+    return rc;
 }
 
 int crespo_ipc_open(void *transport_data, int type)
@@ -458,10 +273,10 @@ int crespo_ipc_open(void *transport_data, int type)
     switch(type)
     {
         case IPC_CLIENT_TYPE_FMT:
-            fd = open("/dev/modem_fmt", O_RDWR | O_NOCTTY | O_NONBLOCK);
+            fd = open(MODEM_FMT_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
             break;
         case IPC_CLIENT_TYPE_RFS:
-            fd = open("/dev/modem_rfs", O_RDWR | O_NOCTTY | O_NONBLOCK);
+            fd = open(MODEM_RFS_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
             break;
         default:
             return -1;
@@ -489,6 +304,7 @@ int crespo_ipc_close(void *transport_data)
     if (fd < 0)
         return -1;
 
+    data->fd = -1;
     close(fd);
 
     return 0;
@@ -500,7 +316,7 @@ int crespo_ipc_read(void *transport_data, void *buffer, unsigned int length)
     int fd;
     int rc;
 
-    if (transport_data == NULL)
+    if (transport_data == NULL || buffer == NULL || length == 0)
         return -1;
 
     data = (struct crespo_ipc_transport_data *) transport_data;
@@ -522,7 +338,7 @@ int crespo_ipc_write(void *transport_data, void *buffer, unsigned int length)
     int fd;
     int rc;
 
-    if (transport_data == NULL)
+    if (transport_data == NULL || buffer == NULL || length == 0)
         return -1;
 
     data = (struct crespo_ipc_transport_data *) transport_data;
@@ -532,7 +348,7 @@ int crespo_ipc_write(void *transport_data, void *buffer, unsigned int length)
         return -1;
 
     rc = ioctl(fd, IOCTL_MODEM_SEND, buffer);
-    if(rc < 0)
+    if (rc < 0)
         return -1;
 
     return 0;
@@ -563,21 +379,18 @@ int crespo_ipc_poll(void *transport_data, struct timeval *timeout)
 
 int crespo_ipc_power_on(void *power_data)
 {
-    int fd=open("/dev/modem_ctl", O_RDWR);
+    int fd;
     int rc;
 
-/*
-    fd = open("/sys/devices/platform/modemctl/power_mode", O_RDWR);
-    rc = write(fd, "1", 1);
-*/
-
-    if(fd < 0)
+    fd = open(MODEM_CTL_DEVICE, O_RDWR);
+    if (fd < 0)
         return -1;
 
     rc = ioctl(fd, IOCTL_MODEM_START);
+
     close(fd);
 
-    if(rc < 0)
+    if (rc < 0)
         return -1;
 
     return 0;
@@ -585,21 +398,18 @@ int crespo_ipc_power_on(void *power_data)
 
 int crespo_ipc_power_off(void *power_data)
 {
-    int fd=open("/dev/modem_ctl", O_RDWR);
+    int fd;
     int rc;
 
-/*
-    fd = open("/sys/devices/platform/modemctl/power_mode", O_RDWR);
-    rc = write(fd, "0", 1);
-*/
-
-    if(fd < 0)
+    fd = open(MODEM_CTL_DEVICE, O_RDWR);
+    if (fd < 0)
         return -1;
 
     rc = ioctl(fd, IOCTL_MODEM_OFF);
+
     close(fd);
 
-    if(rc < 0)
+    if (rc < 0)
         return -1;
 
     return 0;
@@ -626,7 +436,7 @@ int crespo_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_d
     return 0;
 }
 
-char *crespo_2_6_35_ipc_gprs_get_iface(int cid)
+char *crespo_ipc_gprs_get_iface_single(int cid)
 {
     char *iface = NULL;
 
@@ -635,19 +445,7 @@ char *crespo_2_6_35_ipc_gprs_get_iface(int cid)
     return iface;
 }
 
-char *crespo_3_0_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 crespo_2_6_35_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
+int crespo_ipc_gprs_get_capabilities_single(struct ipc_client_gprs_capabilities *capabilities)
 {
     if (capabilities == NULL)
         return -1;
@@ -658,7 +456,19 @@ int crespo_2_6_35_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities
     return 0;
 }
 
-int crespo_3_0_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
+char *crespo_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 crespo_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities)
 {
     if (capabilities == NULL)
         return -1;
@@ -698,14 +508,14 @@ struct ipc_handlers crespo_ipc_handlers = {
     .data_destroy = crespo_ipc_data_destroy,
 };
 
-struct ipc_gprs_specs crespo_2_6_35_ipc_gprs_specs = {
-    .gprs_get_iface = crespo_2_6_35_ipc_gprs_get_iface,
-    .gprs_get_capabilities = crespo_2_6_35_ipc_gprs_get_capabilities,
+struct ipc_gprs_specs crespo_ipc_gprs_specs_single = {
+    .gprs_get_iface = crespo_ipc_gprs_get_iface_single,
+    .gprs_get_capabilities = crespo_ipc_gprs_get_capabilities_single,
 };
 
-struct ipc_gprs_specs crespo_3_0_ipc_gprs_specs = {
-    .gprs_get_iface = crespo_3_0_ipc_gprs_get_iface,
-    .gprs_get_capabilities = crespo_3_0_ipc_gprs_get_capabilities,
+struct ipc_gprs_specs crespo_ipc_gprs_specs = {
+    .gprs_get_iface = crespo_ipc_gprs_get_iface,
+    .gprs_get_capabilities = crespo_ipc_gprs_get_capabilities,
 };
 
 // vim:ts=4:sw=4:expandtab
index f633d1b..1750d97 100644 (file)
@@ -1,7 +1,7 @@
-/**
+/*
  * This file is part of libsamsung-ipc.
  *
- * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr>
+ * Copyright (C) 2011-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
 #ifndef __CRESPO_IPC_H__
 #define __CRESPO_IPC_H__
 
-#define BOOTCORE_VERSION        0xf0
-#define PSI_MAGIC               0x30
-#define PSI_DATA_LEN            0x5000
-#define RADIO_IMG_SIZE          0xd80000
+#define MODEM_IMAGE_SIZE                                        0xD80000
+#define NV_DATA_OFFSET                                          0xD80000
+#define MODEM_DATA_SIZE                                         0x50000
 
-#define MAX_MODEM_DATA_SIZE     0x50000
+#define MODEM_IMAGE_DEVICE                      "/dev/mtd/mtd5ro"
+#define MODEM_SERIAL_DEVICE                     "/dev/s3c2410_serial3"
+#define MODEM_CTL_DEVICE                        "/dev/modem_ctl"
+#define MODEM_FMT_DEVICE                        "/dev/modem_fmt"
+#define MODEM_RFS_DEVICE                        "/dev/modem_rfs"
 
-#define GPRS_IFACE_PREFIX       "rmnet"
-#define GPRS_IFACE_COUNT        3
+#define GPRS_IFACE_PREFIX                       "rmnet"
+#define GPRS_IFACE_COUNT                                        3
 
 struct crespo_ipc_transport_data {
     int fd;
diff --git a/samsung-ipc/device/xmm6160/xmm6160.c b/samsung-ipc/device/xmm6160/xmm6160.c
new file mode 100644 (file)
index 0000000..11e3ec5
--- /dev/null
@@ -0,0 +1,304 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2011-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/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <string.h>
+#include <termios.h>
+#include <sys/select.h>
+
+#include <samsung-ipc.h>
+#include <util.h>
+
+#include "xmm6160.h"
+
+int xmm6160_psi_send(struct ipc_client *client, int serial_fd,
+    void *modem_image_data, int modem_image_size)
+{
+    char modem_at[] = MODEM_AT;
+    unsigned char version;
+    unsigned char info;
+    unsigned char psi_magic;
+    unsigned short psi_size;
+    unsigned char psi_crc;
+    unsigned char psi_ack;
+
+    struct termios termios;
+    struct timeval timeout;
+    fd_set fds;
+
+    unsigned char *p;
+    int length;
+    int rc;
+    int i;
+
+    if (client == NULL || serial_fd < 0 || modem_image_data == NULL || modem_image_size < MODEM_PSI_SIZE)
+        return -1;
+
+    tcgetattr(serial_fd, &termios);
+
+    cfmakeraw(&termios);
+    cfsetispeed(&termios, B115200);
+    cfsetospeed(&termios, B115200);
+
+    tcsetattr(serial_fd, TCSANOW, &termios);
+
+    length = strlen(modem_at);
+    for (i=0; i < MODEM_AT_COUNT; i++) {
+        rc = write(serial_fd, modem_at, length);
+        if (rc < length) {
+            ipc_client_log(client, "Writing AT in ASCII failed");
+            goto error;
+        }
+
+        usleep(50000);
+    }
+    ipc_client_log(client, "Wrote AT in ASCII");
+
+    usleep(50000);
+
+    version = 0;
+
+    rc = read(serial_fd, &version, sizeof(version));
+    if (rc < (int) sizeof(version)) {
+        ipc_client_log(client, "Reading bootcore version failed");
+        goto error;
+    }
+
+    if (version != MODEM_BOOTCORE_VERSION) {
+        ipc_client_log(client, "Read wrong bootcore version (0x%x)", version);
+        goto error;
+    }
+
+    ipc_client_log(client, "Read bootcore version (0x%x)", version);
+
+    rc = read(serial_fd, &info, sizeof(info));
+    if (rc < (int) sizeof(info)) {
+        ipc_client_log(client, "Reading info size failed");
+        goto error;
+    }
+    ipc_client_log(client, "Read info size (0x%x)", info);
+
+    psi_magic = MODEM_PSI_MAGIC;
+
+    rc = write(serial_fd, &psi_magic, sizeof(psi_magic));
+    if (rc < (int) sizeof(psi_magic)) {
+        ipc_client_log(client, "Writing PSI magic failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote PSI magic (0x%x)", psi_magic);
+
+    psi_size = MODEM_PSI_SIZE;
+
+    rc = write(serial_fd, &psi_size, sizeof(psi_size));
+    if (rc < (int) sizeof(psi_size)) {
+        ipc_client_log(client, "Writing PSI size failed");
+        goto error;
+    }
+    ipc_client_log(client, "Wrote PSI size (0x%x)", psi_size);
+
+    FD_ZERO(&fds);
+    FD_SET(serial_fd, &fds);
+
+    timeout.tv_sec = 4;
+    timeout.tv_usec = 0;
+
+    p = (unsigned char *) modem_image_data;
+    psi_crc = 0;
+
+    for (i=0; i < MODEM_PSI_SIZE; i++) {
+        rc = select(serial_fd + 1, NULL, &fds, NULL, &timeout);
+        if (rc <= 0) {
+            ipc_client_log(client, "Writing PSI failed");
+            goto error;
+        }
+
+        rc = write(serial_fd, p, 1);
+        if (rc < 1) {
+            ipc_client_log(client, "Writing PSI failed");
+            goto error;
+        }
+
+        psi_crc ^= *p++;
+    }
+    ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc);
+
+    rc = select(serial_fd + 1, NULL, &fds, NULL, &timeout);
+    if (rc <= 0) {
+        ipc_client_log(client, "Writing PSI crc failed");
+        goto error;
+    }
+
+    rc = write(serial_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 = 4;
+    timeout.tv_usec = 0;
+
+    i = 0;
+    do {
+        rc = select(serial_fd + 1, &fds, NULL, NULL, &timeout);
+        if (rc <= 0) {
+            ipc_client_log(client, "Reading PSI ACK failed");
+            goto error;
+        }
+
+        rc = read(serial_fd, &psi_ack, sizeof(psi_ack));
+        if (rc < (int) sizeof(psi_ack)) {
+            ipc_client_log(client, "Reading PSI ACK failed");
+            goto error;
+        }
+
+        if (i++ > 50) {
+            ipc_client_log(client, "Reading PSI ACK failed");
+            goto error;
+        }
+    } while (psi_ack != MODEM_PSI_ACK);
+    ipc_client_log(client, "Read PSI ACK (0x%x)", psi_ack);
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6160_modem_image_send(struct ipc_client *client, int device_fd,
+    void *device_address, void *modem_image_data, int modem_image_size, int modem_image_offset)
+{
+    int wc;
+
+    unsigned char *p;
+    int length;
+    int rc;
+    int i;
+
+    if (client == NULL || (device_fd < 0 && device_address == NULL) || modem_image_data == NULL || modem_image_size <= MODEM_PSI_SIZE)
+        return -1;
+
+    p = (unsigned char *) modem_image_data + MODEM_PSI_SIZE;
+    length = modem_image_size - MODEM_PSI_SIZE;
+
+    if (device_address != NULL) {
+        memcpy((void *) ((unsigned char *) device_address + modem_image_offset), p, length);
+    } else {
+        lseek(device_fd, modem_image_offset, SEEK_SET);
+
+        wc = 0;
+        while (wc < length) {
+            rc = write(device_fd, p, length - wc);
+            if (rc < 0) {
+                ipc_client_log(client, "Writing modem image failed");
+                goto error;
+            }
+
+            p += rc;
+            wc += rc;
+        }
+    }
+    ipc_client_log(client, "Wrote modem image");
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    return rc;
+}
+
+int xmm6160_nv_data_send(struct ipc_client *client, int device_fd,
+    void *device_address, int modem_image_offset)
+{
+    void *nv_data = NULL;
+    int wc;
+
+    unsigned char *p;
+    int length;
+    int rc;
+
+    if (client == NULL || (device_fd < 0 && device_address == NULL))
+        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");
+
+    p = (unsigned char *) nv_data;
+    length = nv_data_size(client);
+
+    if (device_address != NULL) {
+        memcpy((void *) ((unsigned char *) device_address + modem_image_offset), p, length);
+    } else {
+        lseek(device_fd, modem_image_offset, SEEK_SET);
+
+        wc = 0;
+        while (wc < length) {
+            rc = write(device_fd, p, length - wc);
+            if (rc < 0) {
+                ipc_client_log(client, "Writing modem image failed");
+                goto error;
+            }
+
+            p += rc;
+            wc += rc;
+        }
+    }
+
+    rc = 0;
+    goto complete;
+
+error:
+    rc = -1;
+
+complete:
+    if (nv_data != NULL)
+        free(nv_data);
+
+    return rc;
+}
+
+// vim:ts=4:sw=4:expandtab
diff --git a/samsung-ipc/device/xmm6160/xmm6160.h b/samsung-ipc/device/xmm6160/xmm6160.h
new file mode 100644 (file)
index 0000000..e48323d
--- /dev/null
@@ -0,0 +1,42 @@
+/*
+ * This file is part of libsamsung-ipc.
+ *
+ * Copyright (C) 2011-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/>.
+ *
+ */
+
+#include <samsung-ipc.h>
+
+#ifndef __XMM6160_H__
+#define __XMM6160_H__
+
+#define MODEM_AT                                "AT"
+#define MODEM_AT_COUNT                                          20
+#define MODEM_PSI_SIZE                                          0x5000
+#define MODEM_PSI_MAGIC                                         0x30
+#define MODEM_PSI_ACK                                           0x01
+#define MODEM_BOOTCORE_VERSION                                  0xF0
+
+int xmm6160_psi_send(struct ipc_client *client, int serial_fd,
+    void *modem_image_data, int modem_image_size);
+int xmm6160_modem_image_send(struct ipc_client *client, int device_fd,
+    void *device_address, void *modem_image_data, int modem_image_size,int modem_image_offset);
+int xmm6160_nv_data_send(struct ipc_client *client, int device_fd,
+    void *device_address, int modem_image_offset);
+
+#endif
+
+// vim:ts=4:sw=4:expandtab
index 588469d..632c300 100644 (file)
@@ -23,6 +23,8 @@
  * along with libsamsung-ipc.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <stdint.h>
+
 #ifndef __XMM6260_IPC_H__
 #define __XMM6260_IPC_H__
 
index 77b58dd..2bd436e 100644 (file)
@@ -32,7 +32,7 @@ struct ipc_device_desc ipc_devices[] = {
         .fmt_ops = &crespo_ipc_fmt_ops,
         .rfs_ops = &crespo_ipc_rfs_ops,
         .handlers = &crespo_ipc_handlers,
-        .gprs_specs = &crespo_2_6_35_ipc_gprs_specs,
+        .gprs_specs = &crespo_ipc_gprs_specs_single,
         .nv_data_specs = NULL,
     },
     {
@@ -42,7 +42,7 @@ struct ipc_device_desc ipc_devices[] = {
         .fmt_ops = &crespo_ipc_fmt_ops,
         .rfs_ops = &crespo_ipc_rfs_ops,
         .handlers = &crespo_ipc_handlers,
-        .gprs_specs = &crespo_3_0_ipc_gprs_specs,
+        .gprs_specs = &crespo_ipc_gprs_specs,
         .nv_data_specs = NULL,
     },
     {
index 17c16f1..b8f4007 100644 (file)
@@ -42,8 +42,8 @@ extern int ipc_devices_count;
 extern struct ipc_ops crespo_ipc_fmt_ops;
 extern struct ipc_ops crespo_ipc_rfs_ops;
 extern struct ipc_handlers crespo_ipc_handlers;
-extern struct ipc_gprs_specs crespo_2_6_35_ipc_gprs_specs;
-extern struct ipc_gprs_specs crespo_3_0_ipc_gprs_specs;
+extern struct ipc_gprs_specs crespo_ipc_gprs_specs_single;
+extern struct ipc_gprs_specs crespo_ipc_gprs_specs;
 
 /* aries */
 extern struct ipc_ops aries_ipc_fmt_ops;