diff options
author | Paul Kocialkowski <contact@paulk.fr> | 2013-06-30 10:40:11 +0200 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2013-06-30 10:40:11 +0200 |
commit | c79aeafe5a44717d04fe4d14edf0ed71e7052783 (patch) | |
tree | 568ce66450634065a0619dbc25f3c17c524260df | |
parent | 1edc56a5fcb62dfea78fc27e29d7d87eda8c5662 (diff) | |
download | external_libsamsung-ipc-c79aeafe5a44717d04fe4d14edf0ed71e7052783.zip external_libsamsung-ipc-c79aeafe5a44717d04fe4d14edf0ed71e7052783.tar.gz external_libsamsung-ipc-c79aeafe5a44717d04fe4d14edf0ed71e7052783.tar.bz2 |
Split aries and crespo common code to xmm6160, along with major code rework
Change-Id: Id78c7ce62bf5b9b875b6bc3dd53e6bf21fa36c95
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
-rw-r--r-- | Android.mk | 9 | ||||
-rw-r--r-- | samsung-ipc/Makefile.am | 3 | ||||
-rw-r--r-- | samsung-ipc/device/aries/aries_ipc.c | 774 | ||||
-rw-r--r-- | samsung-ipc/device/aries/aries_ipc.h | 56 | ||||
-rw-r--r-- | samsung-ipc/device/crespo/crespo_ipc.c | 552 | ||||
-rw-r--r-- | samsung-ipc/device/crespo/crespo_ipc.h | 21 | ||||
-rw-r--r-- | samsung-ipc/device/xmm6160/xmm6160.c | 304 | ||||
-rw-r--r-- | samsung-ipc/device/xmm6160/xmm6160.h | 42 | ||||
-rw-r--r-- | samsung-ipc/device/xmm6260/xmm6260_ipc.h | 2 | ||||
-rw-r--r-- | samsung-ipc/ipc_devices.c | 4 | ||||
-rw-r--r-- | samsung-ipc/ipc_devices.h | 4 |
11 files changed, 848 insertions, 923 deletions
@@ -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) diff --git a/samsung-ipc/Makefile.am b/samsung-ipc/Makefile.am index 25d730f..154bb70 100644 --- a/samsung-ipc/Makefile.am +++ b/samsung-ipc/Makefile.am @@ -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 \ diff --git a/samsung-ipc/device/aries/aries_ipc.c b/samsung-ipc/device/aries/aries_ipc.c index 2986321..4e3d273 100644 --- a/samsung-ipc/device/aries/aries_ipc.c +++ b/samsung-ipc/device/aries/aries_ipc.c @@ -22,544 +22,354 @@ */ #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) { diff --git a/samsung-ipc/device/aries/aries_ipc.h b/samsung-ipc/device/aries/aries_ipc.h index 056fdfb..3e6aedc 100644 --- a/samsung-ipc/device/aries/aries_ipc.h +++ b/samsung-ipc/device/aries/aries_ipc.h @@ -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 @@ -19,33 +19,35 @@ * */ +#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; diff --git a/samsung-ipc/device/crespo/crespo_ipc.c b/samsung-ipc/device/crespo/crespo_ipc.c index eae60d7..790b09c 100644 --- a/samsung-ipc/device/crespo/crespo_ipc.c +++ b/samsung-ipc/device/crespo/crespo_ipc.c @@ -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 @@ -17,432 +17,247 @@ * * 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 diff --git a/samsung-ipc/device/crespo/crespo_ipc.h b/samsung-ipc/device/crespo/crespo_ipc.h index f633d1b..1750d97 100644 --- a/samsung-ipc/device/crespo/crespo_ipc.h +++ b/samsung-ipc/device/crespo/crespo_ipc.h @@ -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 @@ -21,15 +21,18 @@ #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 index 0000000..11e3ec5 --- /dev/null +++ b/samsung-ipc/device/xmm6160/xmm6160.c @@ -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 index 0000000..e48323d --- /dev/null +++ b/samsung-ipc/device/xmm6160/xmm6160.h @@ -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 diff --git a/samsung-ipc/device/xmm6260/xmm6260_ipc.h b/samsung-ipc/device/xmm6260/xmm6260_ipc.h index 588469d..632c300 100644 --- a/samsung-ipc/device/xmm6260/xmm6260_ipc.h +++ b/samsung-ipc/device/xmm6260/xmm6260_ipc.h @@ -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__ diff --git a/samsung-ipc/ipc_devices.c b/samsung-ipc/ipc_devices.c index 77b58dd..2bd436e 100644 --- a/samsung-ipc/ipc_devices.c +++ b/samsung-ipc/ipc_devices.c @@ -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, }, { diff --git a/samsung-ipc/ipc_devices.h b/samsung-ipc/ipc_devices.h index 17c16f1..b8f4007 100644 --- a/samsung-ipc/ipc_devices.h +++ b/samsung-ipc/ipc_devices.h @@ -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; |