diff options
28 files changed, 752 insertions, 170 deletions
@@ -1,23 +1,33 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) -LOCAL_MODULE := ipc-modemctrl +LOCAL_MODULE := libsamsung-ipc LOCAL_MODULE_TAGS := optional samsung-ipc_files := \ samsung-ipc/ipc.c \ samsung-ipc/ipc_util.c \ - samsung-ipc/crespo_ipc.c \ - samsung-ipc/crespo_nv_data.c \ - samsung-ipc/util.c + samsung-ipc/util.c \ + samsung-ipc/gprs.c \ + samsung-ipc/misc.c \ + samsung-ipc/net.c \ + samsung-ipc/sec.c \ + samsung-ipc/device/$(TARGET_DEVICE)/$(TARGET_DEVICE)_ipc.c -modemctrl_files := tools/modemctrl.c +#modemctrl_files := tools/modemctrl.c + +ifeq ($(TARGET_DEVICE),crespo) + device_files := samsung-ipc/device/$(TARGET_DEVICE)/$(TARGET_DEVICE)_nv_data.c + LOCAL_CFLAGS += -Iexternal/openssl/include + LOCAL_LDFLAGS += -lcrypto +endif + +LOCAL_SRC_FILES := $(samsung-ipc_files) $(device_files) $(modemctrl_files) -LOCAL_SRC_FILES := $(samsung-ipc_files) $(modemctrl_files) LOCAL_SHARED_LIBRARIES := libutils -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include -LOCAL_CFLAGS += -Iexternal/openssl/include -LOCAL_LDFLAGS += -lcrypto +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include \ + $(LOCAL_PATH)/samsung-ipc + -#include $(BUILD_STATIC_LIBRARY) -include $(BUILD_EXECUTABLE) +include $(BUILD_STATIC_LIBRARY) +#include $(BUILD_EXECUTABLE) diff --git a/include/device/crespo/gen.h b/include/device/crespo/gen.h new file mode 100644 index 0000000..34f5ce9 --- /dev/null +++ b/include/device/crespo/gen.h @@ -0,0 +1,31 @@ +/** + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com> + * Copyright (C) 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef __DEVICE_CRESPO_GEN_H__ +#define __DEVICE_CRESPO_GEN_H__ + +struct ipc_gen_phone_res { + unsigned char group, type; + unsigned char unk; + unsigned short code; +} __attribute__((__packed__)); + +#endif diff --git a/include/device/crespo/net.h b/include/device/crespo/net.h new file mode 100644 index 0000000..b6a1750 --- /dev/null +++ b/include/device/crespo/net.h @@ -0,0 +1,41 @@ +/** + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com> + * Copyright (C) 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef __DEVICE_CRESPO_NET_H__ +#define __DEVICE_CRESPO_NET_H__ + +#define IPC_NET_ACCESS_TECHNOLOGY_UNKNOWN 0xff +#define IPC_NET_ACCESS_TECHNOLOGY_GSM 0x00 +#define IPC_NET_ACCESS_TECHNOLOGY_GSM2 0x01 +#define IPC_NET_ACCESS_TECHNOLOGY_GPRS 0x02 +#define IPC_NET_ACCESS_TECHNOLOGY_EDGE 0x03 +#define IPC_NET_ACCESS_TECHNOLOGY_UMTS 0x04 + +struct ipc_net_current_plmn { + char unk0; + unsigned char slevel; + char unk1; + unsigned char plmn[5]; + unsigned char type; // IPC_NET_SERVICE_TYPE_... ? + unsigned short lac; +} __attribute__((__packed__)); + +#endif diff --git a/include/device/h1/gen.h b/include/device/h1/gen.h new file mode 100644 index 0000000..f74ad55 --- /dev/null +++ b/include/device/h1/gen.h @@ -0,0 +1,31 @@ +/** + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com> + * Copyright (C) 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef __DEVICE_H1_GEN_H__ +#define __DEVICE_H1_GEN_H__ + +struct ipc_gen_phone_res { + unsigned char group, type; + unsigned short code; + unsigned char unk; +} __attribute__((__packed__)); + +#endif diff --git a/include/device/h1/net.h b/include/device/h1/net.h new file mode 100644 index 0000000..c2de8ec --- /dev/null +++ b/include/device/h1/net.h @@ -0,0 +1,39 @@ +/** + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com> + * Copyright (C) 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 + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#ifndef __DEVICE_H1_NET_H__ +#define __DEVICE_H1_NET_H__ + +#define IPC_NET_ACCESS_TECHNOLOGY_GSM 0x01 +#define IPC_NET_ACCESS_TECHNOLOGY_GSM2 0x02 +#define IPC_NET_ACCESS_TECHNOLOGY_GPRS 0x03 +#define IPC_NET_ACCESS_TECHNOLOGY_EDGE 0x04 +#define IPC_NET_ACCESS_TECHNOLOGY_UMTS 0x05 + +struct ipc_net_current_plmn { + char unk0; + unsigned char slevel; + unsigned char plmn[6]; + unsigned char type; + unsigned short lac; +} __attribute__((__packed__)); + +#endif diff --git a/include/gen.h b/include/gen.h index aae309b..e318168 100644 --- a/include/gen.h +++ b/include/gen.h @@ -21,13 +21,13 @@ #ifndef __GEN_H__ #define __GEN_H__ -#define IPC_GEN_PHONE_RES 0x8001 +#if defined(DEVICE_CRESPO) +#include "device/crespo/gen.h" +#elif defined(DEVICE_H1) +#include "device/h1/gen.h" +#endif -struct ipc_gen_phone_res { - unsigned char group, type; - unsigned char unk; - unsigned short code; -} __attribute__((__packed__)); +#define IPC_GEN_PHONE_RES 0x8001 #endif diff --git a/include/gprs.h b/include/gprs.h index 78aa299..b32b2de 100644 --- a/include/gprs.h +++ b/include/gprs.h @@ -25,17 +25,18 @@ #define IPC_GPRS_QOS 0x0D02 #define IPC_GPRS_PS 0x0D03 #define IPC_GPRS_PDP_CONTEXT 0x0D04 -#define IPC_GPRS_SHOW_PDP_ADDR 0x0D05 -#define IPC_GPRS_MS_CLASS 0x0D06 -#define IPC_GPRS_3G_QUAL_SERVICE_PROFILE 0x0D07 -#define IPC_GPRS_DEFINE_SEC_PDP_CONTEXT 0x0D08 +#define IPC_GPRS_ENTER_DATA 0x0D05 +#define IPC_GPRS_SHOW_PDP_ADDR 0x0D06 +#define IPC_GPRS_MS_CLASS 0x0D07 +#define IPC_GPRS_3G_QUAL_SERVICE_PROFILE 0x0D08 #define IPC_GPRS_IP_CONFIGURATION 0x0D09 -#define IPC_GPRS_TFT 0x0D0A -#define IPC_GPRS_HSDPA_STATUS 0x0D0B -#define IPC_GPRS_CURRENT_SESSION_DATA_COUNT 0x0D0C -#define IPC_GPRS_DATA_DORMANT 0x0D0D -#define IPC_GPRS_DUN_PIN_CTRL 0x0D0E -#define IPC_GPRS_CALL_STATUS 0x0D0F +#define IPC_GPRS_DEFINE_SEC_PDP_CONTEXT 0x0D0A +#define IPC_GPRS_TFT 0x0D0B +#define IPC_GPRS_HSDPA_STATUS 0x0D0C +#define IPC_GPRS_CURRENT_SESSION_DATA_COUNT 0x0D0D +#define IPC_GPRS_DATA_DORMANT 0x0D0E +#define IPC_GPRS_DUN_PIN_CTRL 0x0D0F +#define IPC_GPRS_CALL_STATUS 0x0D10 #define IPC_GPRS_CALL_STATUS_TYPE_ON 0x0 #define IPC_GPRS_CALL_STATUS_TYPE_OFF 0x3 diff --git a/include/misc.h b/include/misc.h index cc26c93..111fe7b 100644 --- a/include/misc.h +++ b/include/misc.h @@ -21,7 +21,7 @@ #ifndef __MISC_H__ #define __MISC_H__ -struct ipc_response; +struct ipc_message_info; #define IPC_MISC_ME_VERSION 0x0A01 #define IPC_MISC_ME_IMSI 0x0A02 @@ -43,7 +43,7 @@ struct ipc_misc_time_info { char plmn[6]; } __attribute__((__packed__)); -char* ipc_misc_me_imsi_response_get_imsi(struct ipc_response *response); +char* ipc_misc_me_imsi_response_get_imsi(struct ipc_message_info *response); #endif diff --git a/include/net.h b/include/net.h index 444d52b..fe6f328 100644 --- a/include/net.h +++ b/include/net.h @@ -21,6 +21,12 @@ #ifndef __NET_H__ #define __NET_H__ +#if defined(DEVICE_CRESPO) +#include "device/crespo/net.h" +#elif defined(DEVICE_H1) +#include "device/h1/net.h" +#endif + #define IPC_NET_PREF_PLMN 0x0801 #define IPC_NET_PLMN_SEL 0x0802 #define IPC_NET_CURRENT_PLMN 0x0803 @@ -42,13 +48,6 @@ #define IPC_NET_PLMN_SEL_MANUAL 0x00 #define IPC_NET_PLMN_SEL_AUTO 0x01 -#define IPC_NET_ACCESS_TECHNOLOGY_UNKNOWN 0xff -#define IPC_NET_ACCESS_TECHNOLOGY_GSM 0x00 -#define IPC_NET_ACCESS_TECHNOLOGY_GSM2 0x01 -#define IPC_NET_ACCESS_TECHNOLOGY_GPRS 0x02 -#define IPC_NET_ACCESS_TECHNOLOGY_EDGE 0x03 -#define IPC_NET_ACCESS_TECHNOLOGY_UMTS 0x04 - #define IPC_NET_REGISTRATION_STATE_NONE 0x01 #define IPC_NET_REGISTRATION_STATE_HOME 0x02 #define IPC_NET_REGISTRATION_STATE_SEARCHING 0x03 @@ -59,16 +58,7 @@ #define IPC_NET_SERVICE_DOMAIN_GSM 0x02 #define IPC_NET_SERVICE_DOMAIN_GPRS 0x03 -struct ipc_net_current_plmn { - char unk0; - unsigned char slevel; - char unk1; - unsigned char plmn[5]; - unsigned char type; // IPC_NET_SERVICE_TYPE_... ? - unsigned short lac; -} __attribute__((__packed__)); - -struct ipc_net_regist_set { +struct ipc_net_regist_get { unsigned char net; unsigned char domain; } __attribute__((__packed__)); @@ -95,5 +85,7 @@ struct ipc_net_plmn_entries { struct ipc_net_plmn_entry *data; }; +void ipc_net_regist_get(struct ipc_net_regist_get *message, int domain); + #endif diff --git a/include/radio.h b/include/radio.h index 988ba5f..d1c842e 100644 --- a/include/radio.h +++ b/include/radio.h @@ -26,9 +26,8 @@ #include "types.h" #include "util.h" -#define IPC_CLIENT_TYPE_CRESPO_FMT 1 -#define IPC_CLIENT_TYPE_CRESPO_RFS 2 -#define IPC_CLIENT_TYPE_H1 3 +#define IPC_CLIENT_TYPE_FMT 0 +#define IPC_CLIENT_TYPE_RFS 1 #define IPC_COMMAND(f) ((f->group << 8) | f->index) #define IPC_GROUP(m) (m >> 8) @@ -40,7 +39,7 @@ struct ipc_header { unsigned char group, index, type; } __attribute__((__packed__)); -struct ipc_request { +struct ipc_message_info { unsigned char mseq; unsigned char aseq; unsigned char group; @@ -50,30 +49,34 @@ struct ipc_request { unsigned char *data; }; -struct ipc_response { - unsigned char mseq, aseq; - unsigned short command; - unsigned char type; - unsigned int data_length; - unsigned char *data; -}; - struct ipc_client; +struct ipc_handlers; -typedef int (*ipc_client_transport_cb)(uint8_t *data, unsigned int size, void *user_data); -typedef int (*ipc_client_log_handler_cb)(const char *message, void *user_data); +typedef void (*ipc_client_log_handler_cb)(const char *message, void *user_data); + +typedef void *(*ipc_handler_data_cb)(void); +typedef int (*ipc_io_handler_cb)(void *data, unsigned int size, void *io_data); +typedef int (*ipc_handler_cb)(void *data); struct ipc_client *ipc_client_new(int client_type); -int ipc_client_set_log_handler(struct ipc_client *client, ipc_client_log_handler_cb log_handler_cb, void *user_data); -int ipc_client_set_delegates(struct ipc_client *client, ipc_client_transport_cb write, void *write_data, - ipc_client_transport_cb read, void *read_data); int ipc_client_free(struct ipc_client *client); +int ipc_client_set_log_handler(struct ipc_client *client, ipc_client_log_handler_cb log_handler_cb, void *user_data); + +int ipc_client_set_handlers(struct ipc_client *client, struct ipc_handlers *handlers); +int ipc_client_set_io_handlers(struct ipc_client *client, void *io_data, + ipc_io_handler_cb read, ipc_io_handler_cb write, + ipc_io_handler_cb open, ipc_io_handler_cb close); +void *ipc_client_get_handlers_io_data(struct ipc_client *client); +int ipc_client_set_handlers_io_data(struct ipc_client *client, void *io_data); + int ipc_client_bootstrap_modem(struct ipc_client *client); int ipc_client_open(struct ipc_client *client); int ipc_client_close(struct ipc_client *client); +int ipc_client_power_on(struct ipc_client *client); +int ipc_client_power_off(struct ipc_client *client); -int ipc_client_recv(struct ipc_client *client, struct ipc_response *response); +int ipc_client_recv(struct ipc_client *client, struct ipc_message_info *response); /* Convenience functions for ipc_send */ void ipc_client_send(struct ipc_client *client, const unsigned short command, const char type, unsigned char *data, diff --git a/include/sec.h b/include/sec.h index 3401a40..d5dee00 100644 --- a/include/sec.h +++ b/include/sec.h @@ -21,7 +21,7 @@ #ifndef __SEC_H__ #define __SEC_H__ -struct ipc_response; +struct ipc_message_info; #define IPC_SEC_PIN_STATUS 0x0501 #define IPC_SEC_PHONE_LOCK 0x0502 @@ -109,7 +109,7 @@ struct ipc_sec_lock_info_response { unsigned char attempts; } __attribute__((__packed__)); -char* ipc_sec_rsim_access_response_get_file_data(struct ipc_response *response); +char* ipc_sec_rsim_access_response_get_file_data(struct ipc_message_info *response); void ipc_sec_pin_status_set_setup(struct ipc_sec_pin_status_set *message, unsigned char pin_type, char *pin1, char *pin2); diff --git a/include/types.h b/include/types.h index e85d921..375d6d7 100644 --- a/include/types.h +++ b/include/types.h @@ -39,9 +39,9 @@ #define IPC_TYPE_EVENT 0x05 /* Baseband -> AP */ -#define IPC_TYPE_INDICATION 0x01 -#define IPC_TYPE_RESPONSE 0x02 -#define IPC_TYPE_NOTIFICATION 0x03 +#define IPC_TYPE_INDI 0x01 +#define IPC_TYPE_RESP 0x02 +#define IPC_TYPE_NOTI 0x03 /* Message groups */ #define IPC_GROUP_PWR 0x01 diff --git a/samsung-ipc/crespo_ipc.c b/samsung-ipc/device/crespo/crespo_ipc.c index 44bc676..8752ae0 100644 --- a/samsung-ipc/crespo_ipc.c +++ b/samsung-ipc/device/crespo/crespo_ipc.c @@ -274,6 +274,8 @@ boot_loop_start: free(nv_data_p); + close(modem_ctl_fd); + rc = 0; goto exit; @@ -292,7 +294,7 @@ exit: return rc; } -int crespo_ipc_client_send(struct ipc_client *client, struct ipc_request *request) +int crespo_ipc_client_send(struct ipc_client *client, struct ipc_message_info *request) { struct modem_io modem_data; struct ipc_header reqhdr; @@ -312,11 +314,11 @@ int crespo_ipc_client_send(struct ipc_client *client, struct ipc_request *reques modem_data.data = malloc(reqhdr.length); memcpy(modem_data.data, &reqhdr, sizeof(struct ipc_header)); - memcpy(modem_data.data + sizeof(struct ipc_header), request->data, request->length); + memcpy((unsigned char *)modem_data.data + sizeof(struct ipc_header), request->data, request->length); - assert(client->write != NULL); + assert(client->handlers->write != NULL); - rc = client->write((uint8_t*) &modem_data, sizeof(struct modem_io), client->write_data); + rc = client->handlers->write((uint8_t*) &modem_data, sizeof(struct modem_io), client->handlers->io_data); return rc; } @@ -342,7 +344,7 @@ int wake_unlock(char *lock_name, int size) return rc; } -int crespo_ipc_client_recv(struct ipc_client *client, struct ipc_response *response) +int crespo_ipc_client_recv(struct ipc_client *client, struct ipc_message_info *response) { struct modem_io modem_data; struct ipc_header *resphdr; @@ -352,13 +354,13 @@ int crespo_ipc_client_recv(struct ipc_client *client, struct ipc_response *respo 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_message_info)); wake_lock("secril_fmt-interface", sizeof("secril_fmt-interface") - 1); // FIXME sizeof("...") is ugly! - 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) + assert(client->handlers->read != NULL); + bread = client->handlers->read((uint8_t*) &modem_data, sizeof(struct modem_io) + MAX_MODEM_DATA_SIZE, client->handlers->io_data); + if (bread < 0) { ipc_client_log(client, "ERROR: crespo_ipc_client_recv: can't receive enough bytes from modem to process incoming response!"); return 1; @@ -372,22 +374,25 @@ int crespo_ipc_client_recv(struct ipc_client *client, struct ipc_response *respo return 1; } + /* You MUST send back modem_data */ + resphdr = (struct ipc_header *) modem_data.data; response->mseq = resphdr->mseq; response->aseq = resphdr->aseq; - response->command = IPC_COMMAND(resphdr); + response->group = resphdr->group; + response->index = resphdr->index; response->type = resphdr->type; - response->data_length = modem_data.size - sizeof(struct ipc_header); + response->length = modem_data.size - sizeof(struct ipc_header); response->data = NULL; - ipc_client_log(client, "INFO: crespo_ipc_client_recv: response: group = %d, index = %d, command = %04x", - resphdr->group, resphdr->index, response->command); + ipc_client_log(client, "INFO: crespo_ipc_client_recv: response: group = %d, index = %d", + resphdr->group, resphdr->index); - if(response->data_length > 0) + if(response->length > 0) { - response->data = malloc(response->data_length); - memcpy(response->data, (uint8_t *) modem_data.data + sizeof(struct ipc_header), response->data_length); + response->data = malloc(response->length); + memcpy(response->data, (uint8_t *) modem_data.data + sizeof(struct ipc_header), response->length); } free(modem_data.data); @@ -397,11 +402,175 @@ int crespo_ipc_client_recv(struct ipc_client *client, struct ipc_response *respo return 0; } -struct ipc_ops crespo_ipc_ops = { - .open = NULL, - .close = NULL, +int crespo_ipc_open(void *data, unsigned int size, void *io_data) +{ + int type = *((int *) data); + int fd = -1; + + switch(type) + { + case IPC_CLIENT_TYPE_FMT: + fd = open("/dev/modem_fmt", O_RDWR | O_NDELAY); + printf("crespo_ipc_open: opening /dev/modem_fmt\n"); + break; + case IPC_CLIENT_TYPE_RFS: + fd = open("/dev/modem_rfs", O_RDWR | O_NDELAY); + printf("crespo_ipc_open: opening /dev/modem_rfs\n"); + break; + default: + break; + } + + if(fd < 0) + return -1; + + if(io_data == NULL) + return -1; + + memcpy(io_data, &fd, sizeof(int)); + + return 0; +} + +int crespo_ipc_close(void *data, unsigned int size, void *io_data) +{ + int fd = -1; + + if(io_data == NULL) + return -1; + + fd = *((int *) io_data); + + if(fd < 0) + return -1; + + close(fd); + + return 0; +} + +int crespo_ipc_read(void *data, unsigned int size, void *io_data) +{ + int fd = -1; + int rc; + + if(io_data == NULL) + return -1; + + if(data == NULL) + return -1; + + fd = *((int *) io_data); + + if(fd < 0) + return -1; + + rc = ioctl(fd, IOCTL_MODEM_RECV, data); + + if(rc < 0) + return -1; + + return 0; +} + +int crespo_ipc_write(void *data, unsigned int size, void *io_data) +{ + int fd = -1; + int rc; + + if(io_data == NULL) + return -1; + + fd = *((int *) io_data); + + if(fd < 0) + return -1; + + rc = ioctl(fd, IOCTL_MODEM_SEND, data); + + if(rc < 0) + return -1; + + return 0; +} + +int crespo_ipc_power_on(void *data) +{ + int fd=open("/dev/modem_ctl", O_RDWR); + int rc; + +/* + fd = open("/sys/devices/platform/modemctl/power_mode", O_RDWR); + rc = write(fd, "1", 1); +*/ + + if(fd < 0) + return -1; + + rc = ioctl(fd, IOCTL_MODEM_START); + close(fd); + + if(rc < 0) + return -1; + + return 0; +} + +int crespo_ipc_power_off(void *data) +{ + int fd=open("/dev/modem_ctl", O_RDWR); + int rc; + +/* + fd = open("/sys/devices/platform/modemctl/power_mode", O_RDWR); + rc = write(fd, "0", 1); +*/ + + if(fd < 0) + return -1; + + rc = ioctl(fd, IOCTL_MODEM_OFF); + close(fd); + + if(rc < 0) + return -1; + + return 0; +} + +void *crespo_ipc_io_data_reg(void) +{ + void *data = NULL; + + data = malloc(sizeof(int)); + + return data; +} + +int crespo_ipc_io_data_unreg(void *data) +{ + if(data == NULL) + return -1; + + free(data); + + return 0; +} + +struct ipc_handlers ipc_default_handlers = { + .read = crespo_ipc_read, + .write = crespo_ipc_write, + .open = crespo_ipc_open, + .close = crespo_ipc_close, + .io_data_reg = crespo_ipc_io_data_reg, + .io_data_unreg = crespo_ipc_io_data_unreg, + .io_data = NULL, + .power_on = crespo_ipc_power_on, + .power_off = crespo_ipc_power_off, +}; + +struct ipc_ops ipc_ops = { .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/device/crespo/crespo_ipc.h index 7bf6abc..a6540b5 100644 --- a/samsung-ipc/crespo_ipc.h +++ b/samsung-ipc/device/crespo/crespo_ipc.h @@ -45,4 +45,6 @@ void *file_read(char *file_name, int size, int block_size); int wake_lock(char *lock_name, int size); int wake_unlock(char *lock_name, int size); +extern struct ipc_handlers crespo_ipc_default_handlers; + #endif diff --git a/samsung-ipc/crespo_modem_ctl.h b/samsung-ipc/device/crespo/crespo_modem_ctl.h index 7c23165..7c23165 100644 --- a/samsung-ipc/crespo_modem_ctl.h +++ b/samsung-ipc/device/crespo/crespo_modem_ctl.h diff --git a/samsung-ipc/crespo_nv_data.c b/samsung-ipc/device/crespo/crespo_nv_data.c index 58b034e..58b034e 100644 --- a/samsung-ipc/crespo_nv_data.c +++ b/samsung-ipc/device/crespo/crespo_nv_data.c diff --git a/samsung-ipc/crespo_nv_data.h b/samsung-ipc/device/crespo/crespo_nv_data.h index bc17416..bc17416 100644 --- a/samsung-ipc/crespo_nv_data.h +++ b/samsung-ipc/device/crespo/crespo_nv_data.h diff --git a/samsung-ipc/h1_ipc.c b/samsung-ipc/device/h1/h1_ipc.c index 65f48bb..601f67d 100644 --- a/samsung-ipc/h1_ipc.c +++ b/samsung-ipc/device/h1/h1_ipc.c @@ -25,6 +25,7 @@ #include "ipc_private.h" #include "h1_ipc.h" +/* FIXME: move to io_data */ static int fd = 0; int h1_ipc_open() @@ -50,28 +51,28 @@ int h1_ipc_close() return close(fd); } - return 1; -} - -int h1_ipc_fd_get() -{ - return fd; + return 0; } -void h1_ipc_power_on() +int h1_ipc_power_on() { ioctl(fd, IOCTL_PHONE_ON); + + return 0; } -void h1_ipc_power_off() +int h1_ipc_power_off() { ioctl(fd, IOCTL_PHONE_OFF); + + return 0; } -void h1_ipc_send(struct ipc_request *request) +int h1_ipc_send(struct ipc_client *client, struct ipc_message_info *request) { struct hdlc_header *hdlc; unsigned char *frame; + unsigned char *payload; int frame_length; /* Frame length: HDLC/IPC header + payload length + HDLC flags (2) */ @@ -87,7 +88,7 @@ void h1_ipc_send(struct ipc_request *request) hdlc->length = (sizeof(*hdlc) + request->length); hdlc->unknown = 0; - /* IPC data */ + /* IPC header */ hdlc->ipc.length = (sizeof(hdlc->ipc) + request->length); hdlc->ipc.mseq = request->mseq; hdlc->ipc.aseq = request->aseq; @@ -95,13 +96,24 @@ void h1_ipc_send(struct ipc_request *request) hdlc->ipc.index = request->index; hdlc->ipc.type = request->type; + /* IPC payload */ + payload = (frame + 1 + sizeof(*hdlc)); + memcpy(payload, request->data, request->length); + + ipc_client_log(client, "sending %s %s\n", + ipc_command_type_to_str(IPC_COMMAND(request)), + ipc_response_type_to_str(request->type)); + hex_dump(frame, frame_length); - write(fd, frame, frame_length); + + client->handlers->write(frame, frame_length, client->handlers->io_data); free(frame); + + return 0; } -int h1_ipc_recv(struct ipc_response *response) +int h1_ipc_recv(struct ipc_client *client, struct ipc_message_info *response) { unsigned char buf[4]; unsigned char *data; @@ -110,39 +122,64 @@ int h1_ipc_recv(struct ipc_response *response) int num_read; int left; - num_read = read(fd, buf, sizeof(buf)); + num_read = client->handlers->read((void*)buf, sizeof(buf), client->handlers->io_data); if(num_read == sizeof(buf) && *buf == FRAME_START) { frame_length = (unsigned short*)&buf[1]; left = (*frame_length - 3 + 1); data = (unsigned char*)malloc(left); - num_read = read(fd, data, left); + num_read = client->handlers->read((void*)data, left, client->handlers->io_data); if(num_read == left && data[left-1] == FRAME_END) { ipc = (struct ipc_header*)data; response->mseq = ipc->mseq; response->aseq = ipc->aseq; - response->command = IPC_COMMAND(ipc); + response->group = ipc->group; + response->index = ipc->index; response->type = ipc->type; - response->data_length = (ipc->length - sizeof(*ipc)); + response->length = (ipc->length - sizeof(*ipc)); + + response->data = (unsigned char*)malloc(response->length); + memcpy(response->data, (data + sizeof(*ipc)), response->length); + + ipc_client_log(client, "received %s %s\n", + ipc_command_type_to_str(IPC_COMMAND(response)), + ipc_response_type_to_str(response->type)); - response->data = (unsigned char*)malloc(response->data_length); - memcpy(response->data, (data + sizeof(*ipc)), response->data_length); + hex_dump(data, num_read-1); return 0; } } - return 1; + return 0; +} + +int h1_ipc_read(void *data, unsigned int size, void *io_data) +{ + return read(fd, data, size); +} + +int h1_ipc_write(void *data, unsigned int size, void *io_data) +{ + return write(fd, data, size); } -struct ipc_ops h1_ipc_ops = { +struct ipc_handlers ipc_default_handlers = { .open = h1_ipc_open, .close = h1_ipc_close, .power_on = h1_ipc_power_on, .power_off = h1_ipc_power_off, + .read = h1_ipc_read, + .write = h1_ipc_write, + .io_data_reg = NULL, + .io_data_unreg = NULL, + .io_data = NULL, +}; + +struct ipc_ops ipc_ops = { .send = h1_ipc_send, .recv = h1_ipc_recv, - .fd_get = h1_ipc_fd_get, + .bootstrap = NULL, }; diff --git a/samsung-ipc/h1_ipc.h b/samsung-ipc/device/h1/h1_ipc.h index 1bbc951..1bbc951 100644 --- a/samsung-ipc/h1_ipc.h +++ b/samsung-ipc/device/h1/h1_ipc.h diff --git a/samsung-ipc/gprs.c b/samsung-ipc/gprs.c index 7f656a6..da39ba6 100644 --- a/samsung-ipc/gprs.c +++ b/samsung-ipc/gprs.c @@ -29,7 +29,7 @@ void ipc_gprs_define_pdp_context_setup(struct ipc_gprs_define_pdp_context *messa message->unk0[0] = 0x1; message->unk0[1] = 0x1; message->unk0[2] = 0x2; - strncpy(message->apn, apn, 124); + strncpy((char*)message->apn, apn, 124); } void ipc_gprs_pdp_context_setup(struct ipc_gprs_pdp_context *message, char *username, char *password) @@ -39,6 +39,6 @@ void ipc_gprs_pdp_context_setup(struct ipc_gprs_pdp_context *message, char *user message->unk0[1] = 0x1; message->unk0[2] = 0x13; message->unk2 = 0x1; - strncpy(message->username, username, 32); - strncpy(message->password, password, 32); + strncpy((char*)message->username, username, 32); + strncpy((char*)message->password, password, 32); } diff --git a/samsung-ipc/ipc.c b/samsung-ipc/ipc.c index 9ef091c..97a0b18 100644 --- a/samsung-ipc/ipc.c +++ b/samsung-ipc/ipc.c @@ -29,9 +29,8 @@ #include "ipc_private.h" -extern struct ipc_ops crespo_ipc_ops; -// extern struct ipc_ops h1_ipc_ops; - +extern struct ipc_ops ipc_ops; +extern struct ipc_handlers ipc_default_handlers; void log_handler_default(const char *message, void *user_data) { @@ -54,31 +53,35 @@ void ipc_client_log(struct ipc_client *client, const char *message, ...) struct ipc_client* ipc_client_new(int client_type) { struct ipc_client *client; - struct ips_ops *ops = NULL; + struct ipc_ops *ops = NULL; switch (client_type) { - 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; + case IPC_CLIENT_TYPE_FMT: + case IPC_CLIENT_TYPE_RFS: + ops = &ipc_ops; break; default: - break; + return NULL; } client = (struct ipc_client*) malloc(sizeof(struct ipc_client)); client->type = client_type; client->ops = ops; + client->handlers = (struct ipc_handlers *) malloc(sizeof(struct ipc_handlers)); client->log_handler = log_handler_default; + /* Set default handlers */ + ipc_client_set_handlers(client, &ipc_default_handlers); + return client; } int ipc_client_free(struct ipc_client *client) { + if(client->handlers->io_data != NULL) + client->handlers->io_data_unreg(client->handlers->io_data); + free(client->handlers); free(client); client = NULL; return 0; @@ -86,7 +89,7 @@ int ipc_client_free(struct ipc_client *client) int ipc_client_set_log_handler(struct ipc_client *client, ipc_client_log_handler_cb log_handler_cb, void *user_data) { - if (client == NULL) + if(client == NULL) return -1; client->log_handler = log_handler_cb; @@ -95,18 +98,59 @@ int ipc_client_set_log_handler(struct ipc_client *client, ipc_client_log_handler return 0; } +int ipc_client_set_io_handlers(struct ipc_client *client, void *io_data, + ipc_io_handler_cb read, ipc_io_handler_cb write, + ipc_io_handler_cb open, ipc_io_handler_cb close) +{ + if(client == NULL) + return -1; -int ipc_client_set_delegates(struct ipc_client *client, - ipc_client_transport_cb write, void *write_data, - ipc_client_transport_cb read, void *read_data) + if(read != NULL) + client->handlers->read = read; + if(write != NULL) + client->handlers->write = write; + if(open != NULL) + client->handlers->open = open; + if(close != NULL) + client->handlers->close = close; + if(io_data != NULL) + { + client->handlers->io_data = io_data; + if(client->handlers->io_data_reg != NULL) + client->handlers->io_data = client->handlers->io_data_reg(); + } + + return 0; +} + +int ipc_client_set_handlers(struct ipc_client *client, struct ipc_handlers *handlers) { - if (client == NULL) + if(client == NULL) + return -1; + if(handlers == NULL) return -1; - client->read = read; - client->read_data = read_data; - client->write = write; - client->write_data = write_data; + memcpy(client->handlers, handlers, sizeof(struct ipc_handlers)); + + if(client->handlers->io_data_reg != NULL) + client->handlers->io_data = client->handlers->io_data_reg(); + + return 0; +} + +void *ipc_client_get_handlers_io_data(struct ipc_client *client) +{ + return client->handlers->io_data; +} + +int ipc_client_set_handlers_io_data(struct ipc_client *client, void *io_data) +{ + if(client == NULL) + return -1; + if(io_data == NULL) + return -1; + + client->handlers->io_data=io_data; return 0; } @@ -123,25 +167,50 @@ int ipc_client_bootstrap_modem(struct ipc_client *client) int ipc_client_open(struct ipc_client *client) { + int type; + int fd; + if (client == NULL || - client->ops == NULL || - client->ops->open == NULL) + client->handlers == NULL || + client->handlers->open == NULL) return -1; - return client->ops->open(client); + type = client->type; + + return client->handlers->open(&type, 0, client->handlers->io_data); } int ipc_client_close(struct ipc_client *client) { if (client == NULL || - client->ops == NULL || - client->ops->close == NULL) + client->handlers == NULL || + client->handlers->open == NULL) + return -1; + + return client->handlers->close(NULL, 0, client->handlers->io_data); +} + +int ipc_client_power_on(struct ipc_client *client) +{ + if (client == NULL || + client->handlers == NULL || + client->handlers->open == NULL) + return -1; + + return client->handlers->power_on(NULL); +} + +int ipc_client_power_off(struct ipc_client *client) +{ + if (client == NULL || + client->handlers == NULL || + client->handlers->open == NULL) return -1; - return client->ops->close(client); + return client->handlers->power_off(NULL); } -int _ipc_client_send(struct ipc_client *client, struct ipc_request *request) +int _ipc_client_send(struct ipc_client *client, struct ipc_message_info *request) { if (client == NULL || client->ops == NULL || @@ -165,7 +234,7 @@ inline void ipc_client_send_exec(struct ipc_client *client, const unsigned short /* Wrapper for ipc_send */ void ipc_client_send(struct ipc_client *client, const unsigned short command, const char type, unsigned char *data, const int length, unsigned char mseq) { - struct ipc_request request; + struct ipc_message_info request; request.mseq = mseq; request.aseq = 0xff; @@ -178,7 +247,7 @@ void ipc_client_send(struct ipc_client *client, const unsigned short command, co _ipc_client_send(client, &request); } -int ipc_client_recv(struct ipc_client *client, struct ipc_response *response) +int ipc_client_recv(struct ipc_client *client, struct ipc_message_info *response) { if (client == NULL || client->ops == NULL || diff --git a/samsung-ipc/ipc_private.h b/samsung-ipc/ipc_private.h index d724781..4e05119 100644 --- a/samsung-ipc/ipc_private.h +++ b/samsung-ipc/ipc_private.h @@ -21,31 +21,42 @@ #ifndef __IPC_PRIVATE_H__ #define __IPC_PRIVATE_H__ +#include <radio.h> + struct ipc_client; void ipc_client_log(struct ipc_client *client, const char *message, ...); struct ipc_ops { 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*); + int (*send)(struct ipc_client *client, struct ipc_message_info *); + int (*recv)(struct ipc_client *client, struct ipc_message_info *); +}; + +struct ipc_handlers { + /* Transport handlers/data */ + ipc_io_handler_cb read; + ipc_io_handler_cb write; + ipc_io_handler_cb open; + ipc_io_handler_cb close; + + ipc_handler_data_cb io_data_reg; + ipc_handler_cb io_data_unreg; + void *io_data; + + /* Power handlers */ + ipc_handler_cb power_on; + ipc_handler_cb power_off; }; 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; - ipc_client_log_handler_cb log_handler; void *log_data; struct ipc_ops *ops; + struct ipc_handlers *handlers; }; diff --git a/samsung-ipc/ipc_util.c b/samsung-ipc/ipc_util.c index 1f642ae..b1726e1 100644 --- a/samsung-ipc/ipc_util.c +++ b/samsung-ipc/ipc_util.c @@ -25,12 +25,12 @@ const char *ipc_response_type_to_str(int type) { switch(type) { - case IPC_TYPE_INDICATION: - return "INDICATION"; - case IPC_TYPE_RESPONSE: - return "RESPONSE"; - case IPC_TYPE_NOTIFICATION: - return "NOTIFICATION"; + case IPC_TYPE_INDI: + return "INDI"; + case IPC_TYPE_RESP: + return "RESP"; + case IPC_TYPE_NOTI: + return "NOTI"; default: return "UNKNOWN"; } diff --git a/samsung-ipc/misc.c b/samsung-ipc/misc.c index 609d7b8..c4f27ee 100644 --- a/samsung-ipc/misc.c +++ b/samsung-ipc/misc.c @@ -23,7 +23,7 @@ #define DEFAULT_IMSI_LENGTH 15 -char* ipc_misc_me_imsi_response_get_imsi(struct ipc_response *response) +char* ipc_misc_me_imsi_response_get_imsi(struct ipc_message_info *response) { if (response == NULL || response->data[0] != DEFAULT_IMSI_LENGTH) return NULL; diff --git a/samsung-ipc/net.c b/samsung-ipc/net.c new file mode 100644 index 0000000..9024e86 --- /dev/null +++ b/samsung-ipc/net.c @@ -0,0 +1,27 @@ +/** + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2010-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 + * the Free Software Foundation, either version 3 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 <radio.h> + +void ipc_net_regist_get(struct ipc_net_regist_get *message, int domain) +{ + message->net = 0xff; + message->domain = domain; +} diff --git a/samsung-ipc/sec.c b/samsung-ipc/sec.c index 9cef712..5d43a62 100644 --- a/samsung-ipc/sec.c +++ b/samsung-ipc/sec.c @@ -32,18 +32,18 @@ void ipc_sec_pin_status_set_setup(struct ipc_sec_pin_status_set *message, if (pin1 != NULL) { - strncpy(message->pin1, pin1, 8); + strncpy((char*)message->pin1, pin1, 8); message->length1 = strlen(pin1); } if (pin2 != NULL) { - strncpy(message->pin2, pin2, 8); + strncpy((char*)message->pin2, pin2, 8); message->length2 = strlen(pin2); } } -char* ipc_sec_rsim_access_response_get_file_data(struct ipc_response *response) +char* ipc_sec_rsim_access_response_get_file_data(struct ipc_message_info *response) { int n = 0; int offset = (int) sizeof(struct ipc_sec_rsim_access_response); diff --git a/tools/modemctrl.c b/tools/modemctrl.c index 14237eb..4109d9f 100644 --- a/tools/modemctrl.c +++ b/tools/modemctrl.c @@ -21,7 +21,20 @@ #include <stdlib.h> #include <stdio.h> #include <unistd.h> +#include <stdint.h> +#include <stdbool.h> +#include <termios.h> +#include <fcntl.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <pthread.h> + #include <radio.h> +#include <crespo_ipc.h> + +#define RC_CHECK printf("line %d, rc = %d\n", __LINE__, rc); void print_help() { @@ -32,23 +45,129 @@ void print_help() printf("\tpower-off power off the modem\n"); } +int crespo_read_loop(struct ipc_client *client) +{ + struct ipc_response resp; + void *io_data = NULL; + int fd = -1; + fd_set fds; + + io_data = ipc_client_get_handlers_io_data(client); + fd = *((int *) io_data); + + if(fd < 0) { + return -1; + } + + memset(&resp, 0, sizeof(resp)); + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + while(1) { + usleep(3000); + + select(fd + 1, &fds, NULL, NULL, NULL); + + if(FD_ISSET(fd, &fds)) + { + ipc_client_recv(client, &resp); + if(resp.data != NULL) + free(resp.data); + } + } +} + +int modem_start(struct ipc_client *client) +{ + int rc; + + ipc_client_set_handlers(client, &ipc_default_handlers); + ipc_client_bootstrap_modem(client); + + rc = ipc_client_power_on(client); + if(rc < 0) + return -1; + + rc = ipc_client_open(client); + if(rc < 0) + return -1; + + + return 0; +} + +int modem_stop(struct ipc_client *client) +{ + ipc_client_close(client); + ipc_client_power_off(client); + + return 0; +} + int main(int argc, char *argv[]) { - struct ipc_client *client; - int error; + struct ipc_client *crespo_fmt_client; + struct ipc_client *crespo_rfs_client; + int rc; if (argc != 2) { print_help(); exit(1); } - client = ipc_client_new(IPC_CLIENT_TYPE_CRESPO_FMT); + crespo_fmt_client = ipc_client_new(IPC_CLIENT_TYPE_FMT); + crespo_rfs_client = ipc_client_new(IPC_CLIENT_TYPE_RFS); + + if (!strncmp(argv[1], "power-on", sizeof("power-on"))) { + ipc_client_power_on(crespo_fmt_client); + } + + else if (!strncmp(argv[1], "power-off", sizeof("power-off"))) { + ipc_client_power_off(crespo_fmt_client); + } + + else if (!strncmp(argv[1], "stop-all", 8)) { + ipc_client_close(crespo_fmt_client); + ipc_client_close(crespo_rfs_client); + ipc_client_power_off(crespo_fmt_client); + } + + else if (!strncmp(argv[1], "start-fmt", 9)) { + printf("Starting modem on FMT client\n"); + rc = modem_start(crespo_fmt_client); + if(rc < 0) { + printf("Somethign went wrong\n"); + modem_stop(crespo_fmt_client); + return 1; + } + + printf("Starting crespo_read_loop on FMT client\n"); + crespo_read_loop(crespo_fmt_client); - if (!strncmp(argv[1], "bootstrap", 9)) { - ipc_client_bootstrap_modem(client); + modem_stop(crespo_fmt_client); + } + + else if (!strncmp(argv[1], "start-rfs", 9)) { + printf("Starting modem on RFS client\n"); + rc = modem_start(crespo_rfs_client); + if(rc < 0) { + printf("Somethign went wrong\n"); + modem_stop(crespo_rfs_client); + return 1; + } + + printf("Starting crespo_read_loop on RFS client\n"); + crespo_read_loop(crespo_rfs_client); + + modem_stop(crespo_rfs_client); + } + else { + printf("Unknown command!\n"); } - ipc_client_free(client); + ipc_client_free(crespo_fmt_client); + ipc_client_free(crespo_rfs_client); return 0; } diff --git a/vapi/samsung-ipc-1.0.vapi b/vapi/samsung-ipc-1.0.vapi index 053f151..57d55bd 100644 --- a/vapi/samsung-ipc-1.0.vapi +++ b/vapi/samsung-ipc-1.0.vapi @@ -527,7 +527,7 @@ namespace SamsungIpc } } - [CCode (cname = "struct ipc_net_regist_set", destroy_function = "")] + [CCode (cname = "struct ipc_net_regist_get", destroy_function = "")] public struct RegistrationSetMessage { public uint8 net; @@ -972,7 +972,7 @@ namespace SamsungIpc public uint8 type; } - [CCode (cname = "struct ipc_request", destroy_function = "", free_function = "")] + [CCode (cname = "struct ipc_message_info", destroy_function = "", free_function = "")] public struct Request { public uint8 mseq; |