diff options
author | Simon Busch <morphis@gravedo.de> | 2011-10-09 18:43:28 +0200 |
---|---|---|
committer | Simon Busch <morphis@gravedo.de> | 2011-10-10 08:23:23 +0200 |
commit | 743ede5407a6e8b8baeb9c5b10cfc80d428ae847 (patch) | |
tree | 3d7d5eb9b849528c3db1f8969c775c74199287d6 /samsung-ipc | |
parent | 1cec835e06ddbf9d5229ff0a080e0e36106d64f3 (diff) | |
download | external_libsamsung-ipc-743ede5407a6e8b8baeb9c5b10cfc80d428ae847.zip external_libsamsung-ipc-743ede5407a6e8b8baeb9c5b10cfc80d428ae847.tar.gz external_libsamsung-ipc-743ede5407a6e8b8baeb9c5b10cfc80d428ae847.tar.bz2 |
Rework API of this library to integrate better with other environments than Android
* send/recv is now done outside this library; the user has to provide callbacks for send
and recv
* it's now possible to create more than one ipc client as every ipc API method needs an
object of type ipc_client (which is the context it operates in)
* there are now two different client types for the crespo machine: RFS and FMT
* disabled h1 client for now
* removed power on/off functionality; should be done by another userland component with
handling the correct sysfs nodes rather than dealing with ioctls for this.
* updated vala interface description file to reflect API changes
* various source code cleanups
Signed-off-by: Simon Busch <morphis@gravedo.de>
Diffstat (limited to 'samsung-ipc')
-rw-r--r-- | samsung-ipc/Makefile.am | 1 | ||||
-rw-r--r-- | samsung-ipc/crespo_ipc.c | 683 | ||||
-rw-r--r-- | samsung-ipc/crespo_ipc.h | 23 | ||||
-rw-r--r-- | samsung-ipc/ipc.c | 119 | ||||
-rw-r--r-- | samsung-ipc/ipc_private.h | 30 | ||||
-rw-r--r-- | samsung-ipc/util.c | 140 |
6 files changed, 495 insertions, 501 deletions
diff --git a/samsung-ipc/Makefile.am b/samsung-ipc/Makefile.am index eeb9c62..ec03933 100644 --- a/samsung-ipc/Makefile.am +++ b/samsung-ipc/Makefile.am @@ -13,7 +13,6 @@ lib_LTLIBRARIES = \ libsamsung_ipc_la_SOURCES = \ crespo_ipc.c \ crespo_nv_data.c \ - h1_ipc.c \ ipc.c \ ipc_util.c \ util.c \ diff --git a/samsung-ipc/crespo_ipc.c b/samsung-ipc/crespo_ipc.c index feb4964..be97609 100644 --- a/samsung-ipc/crespo_ipc.c +++ b/samsung-ipc/crespo_ipc.c @@ -2,7 +2,8 @@ * This file is part of libsamsung-ipc. * * Copyright (C) 2011 Paul Kocialkowski <contact@paulk.fr> - * Copyright (C) 2011 Joerie de Gram <j.de.gram@gmail.com> + * Joerie de Gram <j.de.gram@gmail.com> + * Simon Busch <morphis@gravedo.de> * * libsamsung-ipc is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +17,6 @@ * * 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 <stdio.h> @@ -32,6 +32,7 @@ #include <sys/types.h> #include <asm/types.h> #include <mtd/mtd-abi.h> +#include <assert.h> #include <radio.h> @@ -40,507 +41,361 @@ #include "crespo_ipc.h" #include "ipc_private.h" -int s3c2410_serial3_fd= -1; -int modem_ctl_fd= -1; -int modem_fmt_fd= -1; -int modem_rfs_fd= -1; -int wake_lock_fd= -1; -int wake_unlock_fd= -1; +int wake_lock_fd= -1; +int wake_unlock_fd= -1; -void *mtd_read(char *mtd_name, int size, int block_size) +int crespo_modem_bootstrap(struct ipc_client *client) { - void *mtd_p=NULL; - uint8_t *data_p=NULL; - - loff_t offs; - int fd; - int i; - - if(mtd_name == NULL || size <= 0 || block_size <= 0) - goto error; - - printf("mtd_read: reading 0x%x bytes from %s with 0x%x bytes block size\n", size, mtd_name, block_size); - - mtd_p=malloc(size); - if(mtd_p == NULL) - goto error; - - memset(mtd_p, 0, size); - - data_p=(uint8_t *) mtd_p; - - fd=open(mtd_name, O_RDONLY); - if(fd < 0) - goto error; - - for(i=0 ; i < size / block_size ; i++) - { - offs=i * block_size; - if(ioctl(fd, MEMGETBADBLOCK, &offs) == 1) - { - printf("mtd_read: warning: bad block at offset %lld\n", offs); - data_p+=block_size; - continue; - } - - read(fd, data_p, block_size); - data_p+=block_size; - } - - close(fd); - - return mtd_p; - -error: - printf("%s: something went wrong\n", __func__); - return NULL; -} - -void *file_read(char *file_name, int size, int block_size) -{ - void *file_p=NULL; - uint8_t *data_p=NULL; - - int fd; - int i; - - if(file_name == NULL || size <= 0 || block_size <= 0) - goto error; - - printf("file_read: reading 0x%x bytes from %s with 0x%x bytes block size\n", size, file_name, block_size); - - file_p=malloc(size); - if(file_p == NULL) - goto error; - - memset(file_p, 0, size); - - data_p=(uint8_t *) file_p; - - fd=open(file_name, O_RDONLY); - if(fd < 0) - goto error; - - for(i=0 ; i < size / block_size ; i++) - { - read(fd, data_p, block_size); - data_p+=block_size; - } - - close(fd); - - return file_p; + int s3c2410_serial3_fd= -1; + int modem_ctl_fd= -1; -error: - printf("%s: something went wrong\n", __func__); - return NULL; -} - -int crespo_ipc_bootstrap(void) -{ - /* Control variables. */ - int boot_tries_count=0; - int rc=0; + /* Control variables. */ + int boot_tries_count=0; + 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; + /* 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; + /* s3c2410 serial setup variables. */ + struct termios termios; + int serial; - /* fds maniplation variables */ - struct timeval timeout; - fd_set fds; + /* fds maniplation variables */ + struct timeval timeout; + fd_set fds; - /* nv_data variables */ - void *nv_data_p; + /* nv_data variables */ + void *nv_data_p; - /* General purpose variables. */ - uint8_t data; - uint16_t data_16; - uint8_t *data_p; - int i; + /* General purpose variables. */ + uint8_t data; + uint16_t data_16; + uint8_t *data_p; + int i; - printf("crespo_ipc_bootstrap: enter\n"); + printf("crespo_ipc_bootstrap: enter\n"); boot_loop_start: - if(boot_tries_count > 5) - { - printf("crespo_ipc_bootstrap: boot has failed too many times.\n"); - goto error; - } + if(boot_tries_count > 5) + { + printf("crespo_ipc_bootstrap: boot has failed too many times.\n"); + goto error; + } - /* Read the radio.img image. */ - printf("crespo_ipc_bootstrap: reading radio image\n"); - radio_img_p=mtd_read("/dev/mtd/mtd5ro", RADIO_IMG_SIZE, 0x1000); - printf("crespo_ipc_bootstrap: radio image read\n"); - - printf("crespo_ipc_bootstrap: open modem_ctl\n"); - modem_ctl_fd=open("/dev/modem_ctl", O_RDWR | O_NDELAY); - if(modem_ctl_fd < 0) - goto error_loop; + /* Read the radio.img image. */ + printf("crespo_ipc_bootstrap: reading radio image\n"); + radio_img_p=mtd_read("/dev/mtd/mtd5ro", RADIO_IMG_SIZE, 0x1000); + printf("crespo_ipc_bootstrap: radio image read\n"); + + printf("crespo_ipc_bootstrap: open modem_ctl\n"); + modem_ctl_fd=open("/dev/modem_ctl", O_RDWR | O_NDELAY); + if(modem_ctl_fd < 0) + goto error_loop; - /* Reset the modem before init to send the first part of modem.img. */ - ioctl(modem_ctl_fd, IOCTL_MODEM_RESET); - usleep(400000); - - printf("crespo_ipc_bootstrap: open s3c2410_serial3\n"); - s3c2410_serial3_fd=open("/dev/s3c2410_serial3", O_RDWR | O_NDELAY); - if(s3c2410_serial3_fd < 0) - goto error_loop; - - /* Setup the s3c2410 serial. */ - printf("crespo_ipc_bootstrap: setup s3c2410_serial3\n"); - tcgetattr(s3c2410_serial3_fd, &termios); - - cfmakeraw(&termios); - cfsetispeed(&termios, B115200); - cfsetospeed(&termios, B115200); - - tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios); - - ioctl(s3c2410_serial3_fd, TIOCMGET, &serial); //FIXME - ioctl(s3c2410_serial3_fd, TIOCMSET, &serial); //FIXME - - tcgetattr(s3c2410_serial3_fd, &termios); //FIXME - tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios); //FIXME - - /* Send 'AT' in ASCII. */ - printf("crespo_ipc_bootstrap: sending AT in ASCII\n"); - for(i=0 ; i < 20 ; i++) - { - write(s3c2410_serial3_fd, "AT", 2); - usleep(50000); - } - printf("crespo_ipc_bootstrap: sending AT in ASCII done\n"); + /* Reset the modem before init to send the first part of modem.img. */ + ioctl(modem_ctl_fd, IOCTL_MODEM_RESET); + usleep(400000); + + printf("crespo_ipc_bootstrap: open s3c2410_serial3\n"); + s3c2410_serial3_fd=open("/dev/s3c2410_serial3", O_RDWR | O_NDELAY); + if(s3c2410_serial3_fd < 0) + goto error_loop; + + /* Setup the s3c2410 serial. */ + printf("crespo_ipc_bootstrap: setup s3c2410_serial3\n"); + tcgetattr(s3c2410_serial3_fd, &termios); + + cfmakeraw(&termios); + cfsetispeed(&termios, B115200); + cfsetospeed(&termios, B115200); + + tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios); + + ioctl(s3c2410_serial3_fd, TIOCMGET, &serial); //FIXME + ioctl(s3c2410_serial3_fd, TIOCMSET, &serial); //FIXME + + tcgetattr(s3c2410_serial3_fd, &termios); //FIXME + tcsetattr(s3c2410_serial3_fd, TCSANOW, &termios); //FIXME + + /* Send 'AT' in ASCII. */ + printf("crespo_ipc_bootstrap: sending AT in ASCII\n"); + for(i=0 ; i < 20 ; i++) + { + rc = write(s3c2410_serial3_fd, "AT", 2); + usleep(50000); + } + printf("crespo_ipc_bootstrap: sending AT in ASCII done\n"); - usleep(50000); //FIXME - - /* Get and check bootcore version. */ - read(s3c2410_serial3_fd, &bootcore_version, sizeof(bootcore_version)); - printf("crespo_ipc_bootstrap: got bootcore version: 0x%x\n", bootcore_version); - - if(bootcore_version != BOOTCORE_VERSION) - goto error_loop; - - /* Get info_size. */ - read(s3c2410_serial3_fd, &info_size, sizeof(info_size)); - printf("crespo_ipc_bootstrap: got info_size: 0x%x\n", info_size); + usleep(50000); //FIXME + + /* Get and check bootcore version. */ + read(s3c2410_serial3_fd, &bootcore_version, sizeof(bootcore_version)); + printf("crespo_ipc_bootstrap: got bootcore version: 0x%x\n", bootcore_version); + + if(bootcore_version != BOOTCORE_VERSION) + goto error_loop; + + /* Get info_size. */ + read(s3c2410_serial3_fd, &info_size, sizeof(info_size)); + printf("crespo_ipc_bootstrap: got info_size: 0x%x\n", info_size); - /* Send PSI magic. */ - data=PSI_MAGIC; - write(s3c2410_serial3_fd, &data, sizeof(data)); - printf("crespo_ipc_bootstrap: sent PSI_MAGIC (0x%x)\n", PSI_MAGIC); + /* Send PSI magic. */ + data=PSI_MAGIC; + write(s3c2410_serial3_fd, &data, sizeof(data)); + printf("crespo_ipc_bootstrap: sent PSI_MAGIC (0x%x)\n", PSI_MAGIC); - /* Send PSI data len. */ - data_16=PSI_DATA_LEN; - data_p=(uint8_t *)&data_16; + /* Send PSI data len. */ + data_16=PSI_DATA_LEN; + data_p=(uint8_t *)&data_16; - for(i=0 ; i < 2 ; i++) - { - write(s3c2410_serial3_fd, data_p, 1); - data_p++; - } - printf("crespo_ipc_bootstrap: sent PSI_DATA_LEN (0x%x)\n", PSI_DATA_LEN); + for(i=0 ; i < 2 ; i++) + { + write(s3c2410_serial3_fd, data_p, 1); + data_p++; + } + printf("crespo_ipc_bootstrap: sent PSI_DATA_LEN (0x%x)\n", PSI_DATA_LEN); - /* Write the first part of modem.img. */ - FD_ZERO(&fds); - FD_SET(s3c2410_serial3_fd, &fds); + /* Write the first part of modem.img. */ + FD_ZERO(&fds); + FD_SET(s3c2410_serial3_fd, &fds); - timeout.tv_sec=4; - timeout.tv_usec=0; + timeout.tv_sec=4; + timeout.tv_usec=0; - data_p=radio_img_p; + data_p=radio_img_p; - printf("crespo_ipc_bootstrap: sending the first part of radio.img\n"); + printf("crespo_ipc_bootstrap: sending the first part of radio.img\n"); - for(i=0 ; i < PSI_DATA_LEN ; i++) - { - if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) - { - printf("crespo_ipc_bootstrap: select timeout passed\n"); - goto error_loop; - } + for(i=0 ; i < PSI_DATA_LEN ; i++) + { + if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) + { + printf("crespo_ipc_bootstrap: select timeout passed\n"); + goto error_loop; + } - write(s3c2410_serial3_fd, data_p, 1); - crc_byte=crc_byte ^ *data_p; + write(s3c2410_serial3_fd, data_p, 1); + crc_byte=crc_byte ^ *data_p; - data_p++; - } + data_p++; + } - printf("crespo_ipc_bootstrap: first part of radio.img sent; crc_byte is 0x%x\n", crc_byte); + printf("crespo_ipc_bootstrap: first part of radio.img sent; crc_byte is 0x%x\n", crc_byte); - if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) - { - printf("crespo_ipc_bootstrap: select timeout passed\n"); - goto error_loop; - } + if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) + { + printf("crespo_ipc_bootstrap: select timeout passed\n"); + goto error_loop; + } - write(s3c2410_serial3_fd, &crc_byte, sizeof(crc_byte)); + write(s3c2410_serial3_fd, &crc_byte, sizeof(crc_byte)); - printf("crespo_ipc_bootstrap: crc_byte sent\n"); + printf("crespo_ipc_bootstrap: crc_byte sent\n"); - data=0; - for(i=0 ; data != 0x01 ; i++) - { - if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) - { - printf("crespo_ipc_bootstrap: select timeout passed\n"); - goto error_loop; - } + data = 0; + for(i = 0 ; data != 0x01 ; i++) + { + if(select(FD_SETSIZE, &fds, NULL, NULL, &timeout) == 0) + { + printf("crespo_ipc_bootstrap: select timeout passed\n"); + goto error_loop; + } - read(s3c2410_serial3_fd, &data, sizeof(data)); + read(s3c2410_serial3_fd, &data, sizeof(data)); - if(i > 50) - { - printf("crespo_ipc_bootstrap: fairly too much attempts to get ACK\n"); - goto error_loop; - } - } + if(i > 50) + { + printf("crespo_ipc_bootstrap: fairly too much attempts to get ACK\n"); + goto error_loop; + } + } - printf("crespo_ipc_bootstrap: close s3c2410_serial3\n"); - close(s3c2410_serial3_fd); + printf("crespo_ipc_bootstrap: close s3c2410_serial3\n"); + close(s3c2410_serial3_fd); - printf("crespo_ipc_bootstrap: writing the rest of radio.img to modem_ctl.\n"); - /* Seek to the begining of modem_ctl_fd (should already be so). */ - lseek(modem_ctl_fd, 0, SEEK_SET); + printf("crespo_ipc_bootstrap: writing the rest of radio.img to modem_ctl.\n"); + /* 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; + /* 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); + FD_ZERO(&fds); + FD_SET(modem_ctl_fd, &fds); - block_size=0x100000; + 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) - { - printf("crespo_ipc_bootstrap: select timeout passed\n"); - goto error_loop; - } + for(i=0 ; i < (RADIO_IMG_SIZE - PSI_DATA_LEN) / block_size ; i++) + { + if(select(FD_SETSIZE, NULL, &fds, NULL, &timeout) == 0) + { + printf("crespo_ipc_bootstrap: select timeout passed\n"); + goto error_loop; + } - write(modem_ctl_fd, data_p, block_size); - data_p+=block_size; - } + write(modem_ctl_fd, data_p, block_size); + data_p += block_size; + } - free(radio_img_p); + free(radio_img_p); - /* nv_data part. */ + /* nv_data part. */ - /* Check if all the nv_data files are ok. */ - nv_data_check(); + /* Check if all the nv_data files are ok. */ + nv_data_check(); - /* Check if the MD5 is ok. */ - nv_data_md5_check(); + /* Check if the MD5 is ok. */ + nv_data_md5_check(); - /* Write nv_data.bin to modem_ctl. */ - printf("crespo_ipc_bootstrap: write nv_data to modem_ctl\n"); + /* Write nv_data.bin to modem_ctl. */ + printf("crespo_ipc_bootstrap: write nv_data to modem_ctl\n"); - nv_data_p=file_read("/efs/nv_data.bin", NV_DATA_SIZE, 1024); - data_p=nv_data_p; + nv_data_p = file_read("/efs/nv_data.bin", NV_DATA_SIZE, 1024); + data_p = nv_data_p; - lseek(modem_ctl_fd, RADIO_IMG_SIZE, SEEK_SET); + lseek(modem_ctl_fd, RADIO_IMG_SIZE, SEEK_SET); - for(i=0 ; i < 2 ; i++) - { - write(modem_ctl_fd, data_p, NV_DATA_SIZE / 2); - data_p+=NV_DATA_SIZE / 2; - } + for(i=0 ; i < 2 ; i++) + { + write(modem_ctl_fd, data_p, NV_DATA_SIZE / 2); + data_p += NV_DATA_SIZE / 2; + } - free(nv_data_p); + free(nv_data_p); - rc=0; - goto exit; + rc = 0; + goto exit; error_loop: - printf("%s: something went wrong\n", __func__); - boot_tries_count++; - sleep(2); + printf("%s: something went wrong\n", __func__); + boot_tries_count++; + sleep(2); - goto boot_loop_start; + goto boot_loop_start; error: - printf("%s: something went wrong\n", __func__); - rc=1; + printf("%s: something went wrong\n", __func__); + rc = 1; exit: - printf("crespo_ipc_bootstrap: exit\n"); - return rc; + printf("crespo_ipc_bootstrap: exit\n"); + return rc; } -int crespo_ipc_open(void) +int crespo_ipc_client_send(struct ipc_client *client, struct ipc_request *request) { - modem_fmt_fd = open("/dev/modem_fmt", O_RDWR | O_NDELAY); -#if 0 - modem_rfs_fd=open("/dev/modem_rfs", O_RDWR | O_NDELAY); -#endif - return modem_fmt_fd > 0 ? 0 : -1; -} + struct modem_io modem_data; + struct ipc_header reqhdr; + int rc = 0; -void crespo_ipc_fd_set(int fd) -{ - modem_fmt_fd = fd; -} + memset(&modem_data, 0, sizeof(struct modem_io)); + modem_data.data = malloc(MAX_MODEM_DATA_SIZE); + modem_data.size = request->length + sizeof(struct ipc_header); -int crespo_ipc_close(void) -{ - close(modem_fmt_fd); -#if 0 - close(modem_rfs_fd); -#endif - close(modem_ctl_fd); + 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)); - return 0; -} + modem_data.data = malloc(reqhdr.length); -void crespo_ipc_power_on(void) -{ - ioctl(modem_ctl_fd, IOCTL_MODEM_START); -} + memcpy(modem_data.data, &reqhdr, sizeof(struct ipc_header)); + // modem_data.data += sizeof(struct ipc_header); + memcpy(modem_data.data + sizeof(struct ipc_header), request->data, request->length); -void crespo_ipc_power_off(void) -{ - ioctl(modem_ctl_fd, IOCTL_MODEM_OFF); -} + assert(client->write != NULL); -int crespo_ipc_fd_get(void) -{ - return modem_fmt_fd; + rc = client->write((uint8_t*) &modem_data, sizeof(struct modem_io), client->write_data); + return rc; } -void crespo_ipc_send(struct ipc_request *request) +int wake_lock(char *lock_name, int size) { - struct modem_io modem_data; - struct ipc_header hdlc_data; - uint8_t *data_p; + int rc = 0; - memset(&modem_data, 0, sizeof(struct modem_io)); - modem_data.data=malloc(0x1000); - modem_data.size=request->length + sizeof(struct ipc_header); + wake_lock_fd = open("/sys/power/wake_lock", O_RDWR); + rc = write(wake_lock_fd, lock_name, size); + close(wake_lock_fd); - hdlc_data.mseq=request->mseq; - hdlc_data.aseq=request->aseq; - hdlc_data.group=request->group; - hdlc_data.index=request->index; - hdlc_data.type=request->type; - hdlc_data.length=(uint16_t) (request->length + sizeof(struct ipc_header)); - - modem_data.data=malloc(hdlc_data.length); - data_p=modem_data.data; - - memcpy(data_p, &hdlc_data, sizeof(struct ipc_header)); - data_p+=sizeof(struct ipc_header); - memcpy(data_p, request->data, request->length); - - ioctl(modem_fmt_fd, IOCTL_MODEM_SEND, &modem_data); + return rc; } -void wake_lock(char *lock_name, int size) +int wake_unlock(char *lock_name, int size) { - if(wake_lock_fd < 0) - wake_lock_fd=open("/sys/power/wake_lock", O_RDWR); + int rc = 0; - write(wake_lock_fd, lock_name, size); -} + wake_lock_fd = open("/sys/power/wake_unlock", O_RDWR); + rc = write(wake_unlock_fd, lock_name, size); + close(wake_unlock_fd); -void wake_unlock(char *lock_name, int size) -{ - if(wake_unlock_fd < 0) - wake_lock_fd=open("/sys/power/wake_unlock", O_RDWR); - - write(wake_unlock_fd, lock_name, size); + return rc; } -int crespo_ipc_recv(struct ipc_response *response) +int crespo_ipc_client_recv(struct ipc_client *client, struct ipc_response *response) { - struct modem_io modem_data; - struct ipc_header *hdlc_data; - - fd_set fds; + struct modem_io modem_data; + struct ipc_header *resphdr; + int bread = 0; -recv_loop_start: - memset(&modem_data, 0, sizeof(struct modem_io)); - modem_data.data=malloc(0x1000); - modem_data.size=0x1000; + 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_response)); + memset(response, 0, sizeof(struct ipc_response)); - /* TODO: Should be with the wakelocks. */ + wake_lock("secril_fmt-interface", sizeof("secril_fmt-interface") - 1); // FIXME sizeof("...") is ugly! - wake_lock("secril_fmt-interface", sizeof("secril_fmt-interface") - 1); + assert(client->read != NULL); + bread = client->read((uint8_t*) &modem_data, sizeof(struct modem_io) + MAX_MODEM_DATA_SIZE, client->read_data); + if (bread <= 0) + { + printf("ERROR: crespo_ipc_client_recv: can't receive enough bytes from modem to process incoming response!\n"); + return 1; + } - FD_ZERO(&fds); - FD_SET(modem_fmt_fd, &fds); + printf("ERROR: crespo_ipc_client_recv: Modem RECV FMT (id=%d cmd=%d size=%d)!\n", modem_data.id, modem_data.cmd, modem_data.size); -#if 0 - FD_SET(modem_rfs_fd, &fds); + if(modem_data.size <= 0 || modem_data.size >= 0x1000 || modem_data.data == NULL) + { + printf("ERROR: crespo_ipc_client_recv: we retrieve less bytes from the modem than we exepected!\n"); + return 1; + } - select(FD_SETSIZE, &fds, NULL, NULL, NULL); + resphdr = (struct ipc_header *) modem_data.data; - if(FD_ISSET(modem_rfs_fd, &fds)) - { - ioctl(modem_rfs_fd, IOCTL_MODEM_RECV, &modem_data); - printf("ipc_recv: Modem RECV RFS (id=%d cmd=%d size=%d)!\n", modem_data.id, modem_data.cmd, modem_data.size); - free(modem_data.data); - wake_unlock("secril_fmt-interface", sizeof("secril_fmt-interface") - 1); + response->mseq = resphdr->mseq; + response->aseq = resphdr->aseq; + response->command = IPC_COMMAND(resphdr); + response->type = resphdr->type; + response->data_length = modem_data.size - sizeof(struct ipc_header); - goto recv_loop_start; - return 0; - } -#endif + if(response->data_length > 0) + { + response->data = malloc(response->data_length); + memcpy(response->data, (uint8_t *) modem_data.data + sizeof(struct ipc_header), response->data_length); + } + else + { + response->data = NULL; + } - if(FD_ISSET(modem_fmt_fd, &fds)) - { - ioctl(modem_fmt_fd, IOCTL_MODEM_RECV, &modem_data); - printf("ipc_recv: Modem RECV FMT (id=%d cmd=%d size=%d)!\n", modem_data.id, modem_data.cmd, modem_data.size); + free(modem_data.data); - if(modem_data.size <= 0 || modem_data.size >= 0x1000 || modem_data.data == NULL) - { - printf("ipc_recv: Something is wrong with the received message\n"); - return 1; - } + wake_unlock("secril_fmt-interface", sizeof("secril_fmt-interface") - 1); // FIXME sizeof("...") is ugly! - hdlc_data=(struct ipc_header *) modem_data.data; - - response->mseq=hdlc_data->mseq; - response->aseq=hdlc_data->aseq; - response->command=IPC_COMMAND(hdlc_data); - response->type=hdlc_data->type; - response->data_length=modem_data.size - sizeof(struct ipc_header); - - if(response->data_length > 0) - { - response->data=malloc(response->data_length); - memcpy(response->data, (uint8_t *)modem_data.data + sizeof(struct ipc_header), response->data_length); - } - else - { - response->data=NULL; - } - - free(modem_data.data); - - wake_unlock("secril_fmt-interface", sizeof("secril_fmt-interface") - 1); - return 0; - } - - return 1; + return 0; } struct ipc_ops crespo_ipc_ops = { - .open = crespo_ipc_open, - .bootstrap = crespo_ipc_bootstrap, - .close = crespo_ipc_close, - .power_on = crespo_ipc_power_on, - .power_off = crespo_ipc_power_off, - .send = crespo_ipc_send, - .recv = crespo_ipc_recv, - .fd_set = crespo_ipc_fd_set, - .fd_get = crespo_ipc_fd_get, + .open = NULL, + .close = NULL, + .send = crespo_ipc_client_send, + .recv = crespo_ipc_client_recv, + .bootstrap = crespo_modem_bootstrap, }; + diff --git a/samsung-ipc/crespo_ipc.h b/samsung-ipc/crespo_ipc.h index 7001d2a..7bf6abc 100644 --- a/samsung-ipc/crespo_ipc.h +++ b/samsung-ipc/crespo_ipc.h @@ -21,25 +21,28 @@ #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 BOOTCORE_VERSION 0xf0 +#define PSI_MAGIC 0x30 +#define PSI_DATA_LEN 0x5000 +#define RADIO_IMG_SIZE 0xd80000 + +#define MAX_MODEM_DATA_SIZE 0x1000 struct samsung_rfs_msg { - uint32_t offset; - uint32_t size; + uint32_t offset; + uint32_t size; }; struct samsung_rfs_cfrm { - uint8_t confirmation; - struct samsung_rfs_msg msg; + uint8_t confirmation; + struct samsung_rfs_msg msg; }; void *mtd_read(char *mtd_name, int size, int block_size); void *file_read(char *file_name, int size, int block_size); -void wake_lock(char *lock_name, int size); -void wake_unlock(char *lock_name, int size); +int wake_lock(char *lock_name, int size); +int wake_unlock(char *lock_name, int size); + #endif diff --git a/samsung-ipc/ipc.c b/samsung-ipc/ipc.c index 0d5c359..7f8d7ab 100644 --- a/samsung-ipc/ipc.c +++ b/samsung-ipc/ipc.c @@ -2,6 +2,7 @@ * This file is part of libsamsung-ipc. * * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com> + * 2011 Simon Busch <morphis@gravedo.de> * * libsamsung-ipc is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,100 +27,126 @@ #include "ipc_private.h" -struct ipc_ops *ops = NULL; - extern struct ipc_ops crespo_ipc_ops; -extern struct ipc_ops h1_ipc_ops; +// extern struct ipc_ops h1_ipc_ops; + -int ipc_init(int client_type) +struct ipc_client* ipc_client_new(int client_type) { - int rc = 0; + struct ipc_client *client; + struct ips_ops *ops = NULL; switch (client_type) { - case IPC_CLIENT_TYPE_CRESPO: + case IPC_CLIENT_TYPE_CRESPO_FMT: + case IPC_CLIENT_TYPE_CRESPO_RFS: ops = &crespo_ipc_ops; break; case IPC_CLIENT_TYPE_H1: - ops = &h1_ipc_ops; + // ops = &h1_ipc_ops; break; default: - rc = -1; break; } - return rc; -} + client = (struct ipc_client*) malloc(sizeof(struct ipc_client)); + client->type = client_type; + client->ops = ops; -int ipc_bootstrap(void) -{ - return ops != NULL && ops->bootstrap != NULL ? ops->bootstrap() : -1; + return client; } -int ipc_open(void) +int ipc_client_free(struct ipc_client *client) { - return ops != NULL && ops->open != NULL ? ops->open() : -1; + free(client); + client = NULL; + return 0; } -int ipc_close(void) +int ipc_client_transport_callback_set(struct ipc_client *client, + ipc_client_transport_cb write, void *write_data, + ipc_client_transport_cb read, void *read_data) { - return ops != NULL && ops->close != NULL ? ops->close() : -1; + if (client == NULL) + return -1; + + client->read = read; + client->read_data = read_data; + client->write = write; + client->write_data = write_data; + + return 0; } -void ipc_power_on(void) +int ipc_client_bootstrap_modem(struct ipc_client *client) { - if (ops != NULL && ops->power_on != NULL) - ops->power_on(); + if (client == NULL || + client->ops == NULL || + client->ops->bootstrap == NULL) + return -1; + + return client->ops->bootstrap(client); } -void ipc_power_off(void) +int ipc_client_open(struct ipc_client *client) { - if (ops != NULL && ops->power_off != NULL) - ops->power_off(); + if (client == NULL || + client->ops == NULL || + client->ops->open == NULL) + return -1; + + return client->ops->open(client); } -void ipc_send(struct ipc_request *request) +int ipc_client_close(struct ipc_client *client) { - if (ops != NULL && ops->send != NULL) - ops->send(request); + if (client == NULL || + client->ops == NULL || + client->ops->close == NULL) + return -1; + + return client->ops->close(client); } -int ipc_fd_get() +int _ipc_client_send(struct ipc_client *client, struct ipc_request *request) { - if (ops != NULL && ops->fd_get != NULL) - return ops->fd_get(); - return -1; + if (client == NULL || + client->ops == NULL || + client->ops->send == NULL) + return -1; + + return client->ops->send(client, request); } /* Convenience functions for ipc_send */ -inline void ipc_msg_send_get(const int command, unsigned char aseq) +inline void ipc_client_send_get(struct ipc_client *client, const int command, unsigned char aseq) { - ipc_msg_send(command, IPC_TYPE_GET, 0, 0, aseq); + ipc_client_send(client, command, IPC_TYPE_GET, 0, 0, aseq); } -inline void ipc_msg_send_exec(const int command, unsigned char aseq) +inline void ipc_client_send_exec(struct ipc_client *client, const int command, unsigned char aseq) { - ipc_msg_send(command, IPC_TYPE_EXEC, 0, 0, aseq); + ipc_client_send(client, command, IPC_TYPE_EXEC, 0, 0, aseq); } /* Wrapper for ipc_send */ -void ipc_msg_send(const int command, const int type, unsigned char *data, const int length, unsigned char mseq) +void ipc_client_send(struct ipc_client *client, const int command, const int type, unsigned char *data, const int length, unsigned char mseq) { - struct ipc_request request; + struct ipc_request request; - request.mseq = mseq; - request.aseq = 0xff; - request.group = IPC_GROUP(command); - request.index = IPC_INDEX(command); - request.type = type; - request.length = length; - request.data = data; + request.mseq = mseq; + request.aseq = 0xff; + request.group = IPC_GROUP(command); + request.index = IPC_INDEX(command); + request.type = type; + request.length = length; + request.data = data; - ipc_send(&request); + _ipc_client_send(client, &request); } -int ipc_recv(struct ipc_response *response) +int ipc_client_recv(struct ipc_client *client, struct ipc_response *response) { - return ops != NULL && ops->recv != NULL ? ops->recv(response) : -1; + return -1; } diff --git a/samsung-ipc/ipc_private.h b/samsung-ipc/ipc_private.h index bf7d00f..1efcd26 100644 --- a/samsung-ipc/ipc_private.h +++ b/samsung-ipc/ipc_private.h @@ -21,16 +21,28 @@ #ifndef __IPC_PRIVATE_H__ #define __IPC_PRIVATE_H__ +struct ipc_client; + struct ipc_ops { - int (*bootstrap)(void); - int (*open)(void); - void (*fd_set)(int); - int (*close)(void); - void (*power_on)(void); - void (*power_off)(void); - int (*send)(struct ipc_request*); - int (*recv)(struct ipc_response*); - int (*fd_get)(void); + int (*bootstrap)(struct ipc_client *client); + int (*open)(struct ipc_client *client); + int (*close)(struct ipc_client *client); + int (*send)(struct ipc_client *client, struct ipc_request*); + int (*recv)(struct ipc_client *client, struct ipc_response*); }; +struct ipc_client { + int type; + + /* callbacks for transport handling */ + ipc_client_transport_cb read; + void *read_data; + ipc_client_transport_cb write; + void *write_data; + + struct ipc_ops *ops; +}; + + + #endif diff --git a/samsung-ipc/util.c b/samsung-ipc/util.c index c6dce60..8d943a1 100644 --- a/samsung-ipc/util.c +++ b/samsung-ipc/util.c @@ -21,6 +21,14 @@ #include <stdio.h> #include <string.h> #include <ctype.h> +#include <mtd/mtd-abi.h> +#include <fcntl.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <asm/types.h> +#include <stdint.h> #if defined(ANDROID) && !defined(LOG_STDOUT) @@ -86,33 +94,123 @@ void hex_dump(void *data, int size) const char *plmn_lookup(const char *plmn) { - unsigned int mcc, mnc; - sscanf(plmn, "%3u%2u", &mcc, &mnc); - - switch(mcc) { - case 204: - switch(mnc) { - case 1: return "VastMobiel"; - case 2: return "Tele2"; - case 4: return "Vodafone"; - case 8: case 10: return "KPN"; - case 12: return "Telfort"; - case 16: case 20: return "T-Mobile"; - } - } - - return NULL; + unsigned int mcc, mnc; + sscanf(plmn, "%3u%2u", &mcc, &mnc); + + switch(mcc) { + case 204: + switch(mnc) { + case 1: return "VastMobiel"; + case 2: return "Tele2"; + case 4: return "Vodafone"; + case 8: case 10: return "KPN"; + case 12: return "Telfort"; + case 16: case 20: return "T-Mobile"; + } + } + + return NULL; } char *plmn_string(const char *plmn) { - int length = (plmn[5] == '#') ? 6 : 7; + int length = (plmn[5] == '#') ? 6 : 7; + + char *plmn_str = (char*)malloc(length); + + memcpy(plmn_str, plmn, length); + plmn_str[length-1] = '\0'; + + return plmn_str; +} + +void *mtd_read(char *mtd_name, int size, int block_size) +{ + void *mtd_p=NULL; + uint8_t *data_p=NULL; + + loff_t offs; + int fd; + int i; + + if(mtd_name == NULL || size <= 0 || block_size <= 0) + goto error; + + printf("mtd_read: reading 0x%x bytes from %s with 0x%x bytes block size\n", size, mtd_name, block_size); + + mtd_p=malloc(size); + if(mtd_p == NULL) + goto error; + + memset(mtd_p, 0, size); + + data_p=(uint8_t *) mtd_p; + + fd=open(mtd_name, O_RDONLY); + if(fd < 0) + goto error; + + for(i=0 ; i < size / block_size ; i++) + { + offs = i * block_size; + if(ioctl(fd, MEMGETBADBLOCK, &offs) == 1) + { + printf("mtd_read: warning: bad block at offset %lld\n", (long long int) offs); + data_p+=block_size; + continue; + } + + read(fd, data_p, block_size); + data_p+=block_size; + } + + close(fd); + + return mtd_p; + +error: + printf("%s: something went wrong\n", __func__); + return NULL; +} + +void *file_read(char *file_name, int size, int block_size) +{ + void *file_p=NULL; + uint8_t *data_p=NULL; + + int fd; + int i; - char *plmn_str = (char*)malloc(length); + if(file_name == NULL || size <= 0 || block_size <= 0) + goto error; - memcpy(plmn_str, plmn, length); - plmn_str[length-1] = '\0'; + printf("file_read: reading 0x%x bytes from %s with 0x%x bytes block size\n", size, file_name, block_size); - return plmn_str; + file_p=malloc(size); + if(file_p == NULL) + goto error; + + memset(file_p, 0, size); + + data_p=(uint8_t *) file_p; + + fd=open(file_name, O_RDONLY); + if(fd < 0) + goto error; + + for(i=0 ; i < size / block_size ; i++) + { + read(fd, data_p, block_size); + data_p+=block_size; + } + + close(fd); + + return file_p; + +error: + printf("%s: something went wrong\n", __func__); + return NULL; } + |