diff options
author | Paul Kocialkowski <contact@paulk.fr> | 2014-02-08 14:29:15 +0100 |
---|---|---|
committer | Paul Kocialkowski <contact@paulk.fr> | 2014-02-08 14:29:15 +0100 |
commit | ffc71f0da11b322e5c28425200cbb8666cf441f9 (patch) | |
tree | 4287b6798313811b51faf200186624e6f85623e9 /samsung-ipc/devices/crespo | |
parent | 190984f13910b589b8909b1088bac863316cdc96 (diff) | |
download | external_libsamsung-ipc-ffc71f0da11b322e5c28425200cbb8666cf441f9.zip external_libsamsung-ipc-ffc71f0da11b322e5c28425200cbb8666cf441f9.tar.gz external_libsamsung-ipc-ffc71f0da11b322e5c28425200cbb8666cf441f9.tar.bz2 |
devices folder instead of device, for better consistency
Signed-off-by: Paul Kocialkowski <contact@paulk.fr>
Diffstat (limited to 'samsung-ipc/devices/crespo')
-rw-r--r-- | samsung-ipc/devices/crespo/crespo_ipc.c | 559 | ||||
-rw-r--r-- | samsung-ipc/devices/crespo/crespo_ipc.h | 49 | ||||
-rw-r--r-- | samsung-ipc/devices/crespo/crespo_modem_ctl.h | 44 |
3 files changed, 652 insertions, 0 deletions
diff --git a/samsung-ipc/devices/crespo/crespo_ipc.c b/samsung-ipc/devices/crespo/crespo_ipc.c new file mode 100644 index 0000000..457cd48 --- /dev/null +++ b/samsung-ipc/devices/crespo/crespo_ipc.c @@ -0,0 +1,559 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2011 Joerie de Gram <j.de.gram@gmail.com> + * Copyright (C) 2011 Simon Busch <morphis@gravedo.de> + * 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 <stdint.h> +#include <stdbool.h> +#include <string.h> +#include <fcntl.h> +#include <sys/ioctl.h> + +#include <samsung-ipc.h> +#include <ipc.h> +#include <util.h> + +#include "crespo_modem_ctl.h" + +#include "xmm6160.h" +#include "crespo_ipc.h" + +int crespo_ipc_bootstrap(struct ipc_client *client) +{ + void *modem_image_data = NULL; + + int modem_ctl_fd = -1; + int serial_fd = -1; + + unsigned char *p; + int rc; + + if (client == NULL) + return -1; + + ipc_client_log(client, "Starting crespo modem bootstrap"); + + modem_image_data = file_data_read(CRESPO_MODEM_IMAGE_DEVICE, CRESPO_MODEM_IMAGE_SIZE, 0x1000); + if (modem_image_data == NULL) { + ipc_client_log(client, "Reading modem image data failed"); + goto error; + } + ipc_client_log(client, "Read modem image data"); + + modem_ctl_fd = open(CRESPO_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"); + + rc = ioctl(modem_ctl_fd, IOCTL_MODEM_RESET); + if (rc < 0) { + ipc_client_log(client, "Resetting modem failed"); + goto error; + } + ipc_client_log(client, "Reset modem"); + + serial_fd = open(CRESPO_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"); + + usleep(100000); + + p = (unsigned char *) modem_image_data; + + rc = xmm6160_psi_send(client, serial_fd, (void *) p, CRESPO_PSI_SIZE); + if (rc < 0) { + ipc_client_log(client, "Sending XMM6160 PSI failed"); + goto error; + } + ipc_client_log(client, "Sent XMM6160 PSI"); + + p += CRESPO_PSI_SIZE; + + lseek(modem_ctl_fd, 0, SEEK_SET); + + rc = xmm6160_firmware_send(client, modem_ctl_fd, NULL, (void *) p, CRESPO_MODEM_IMAGE_SIZE - CRESPO_PSI_SIZE); + if (rc < 0) { + ipc_client_log(client, "Sending XMM6160 firmware failed"); + goto error; + } + ipc_client_log(client, "Sent XMM6160 firmware"); + + lseek(modem_ctl_fd, CRESPO_MODEM_CTL_NV_DATA_OFFSET, SEEK_SET); + + rc = xmm6160_nv_data_send(client, modem_ctl_fd, NULL); + if (rc < 0) { + ipc_client_log(client, "Sending XMM6160 nv_data failed"); + goto error; + } + ipc_client_log(client, "Sent XMM6160 nv_data"); + + rc = 0; + goto complete; + +error: + rc = -1; + +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 ipc_fmt_header header; + struct modem_io mio; + int rc; + + if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL) + return -1; + + ipc_fmt_header_fill(&header, request); + + memset(&mio, 0, sizeof(struct modem_io)); + mio.size = request->length + sizeof(struct ipc_fmt_header); + mio.data = malloc(mio.size); + + memcpy(mio.data, &header, sizeof(struct ipc_fmt_header)); + if (request->data != NULL && request->length > 0) + memcpy((void *) ((unsigned char *) mio.data + sizeof(struct ipc_fmt_header)), request->data, request->length); + + ipc_client_log_send(client, request, __func__); + + rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io)); + if (rc < 0) { + ipc_client_log(client, "Writing FMT data to the modem failed"); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (mio.data != NULL) + free(mio.data); + + return rc; +} + +int crespo_ipc_fmt_recv(struct ipc_client *client, struct ipc_message_info *response) +{ + struct ipc_fmt_header *header; + struct modem_io mio; + int rc; + + if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL) + return -1; + + memset(&mio, 0, sizeof(struct modem_io)); + mio.size = CRESPO_BUFFER_LENGTH; + 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 < sizeof(struct ipc_fmt_header)) { + ipc_client_log(client, "Reading FMT data from the modem failed"); + goto error; + } + + header = (struct ipc_fmt_header *) mio.data; + + ipc_fmt_message_fill(header, response); + + if (mio.size > sizeof(struct ipc_fmt_header)) { + response->length = mio.size - sizeof(struct ipc_fmt_header); + response->data = malloc(response->length); + + memcpy(response->data, (void *) ((unsigned char *) mio.data + sizeof(struct ipc_fmt_header)), response->length); + } + + ipc_client_log_recv(client, response, __func__); + + rc = 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 mio; + int rc; + + if (client == NULL || client->handlers == NULL || client->handlers->write == NULL || request == NULL) + return -1; + + 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); + } + + ipc_client_log_send(client, request, __func__); + + rc = client->handlers->write(client->handlers->transport_data, (void *) &mio, sizeof(struct modem_io)); + if (rc < 0) { + ipc_client_log(client, "Writing RFS data to the modem failed"); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (mio.data != NULL) + free(mio.data); + + return rc; +} + +int crespo_ipc_rfs_recv(struct ipc_client *client, struct ipc_message_info *response) +{ + struct modem_io mio; + int rc; + + if (client == NULL || client->handlers == NULL || client->handlers->read == NULL || response == NULL) + return -1; + + memset(&mio, 0, sizeof(struct modem_io)); + mio.size = CRESPO_BUFFER_LENGTH; + 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; + } + + memset(response, 0, sizeof(struct ipc_message_info)); + response->aseq = mio.id; + response->group = IPC_GROUP_RFS; + response->index = mio.cmd; + + if (mio.size > 0) { + response->length = mio.size; + response->data = malloc(response->length); + + memcpy(response->data, mio.data, response->length); + } + + ipc_client_log_recv(client, response, __func__); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (mio.data != NULL) + free(mio.data); + + return rc; +} + +int crespo_ipc_open(void *data, int type) +{ + struct crespo_ipc_transport_data *transport_data; + int fd; + + if (data == NULL) + return -1; + + transport_data = (struct crespo_ipc_transport_data *) data; + + switch (type) { + case IPC_CLIENT_TYPE_FMT: + fd = open(CRESPO_MODEM_FMT_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); + break; + case IPC_CLIENT_TYPE_RFS: + fd = open(CRESPO_MODEM_RFS_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK); + break; + default: + return -1; + } + + if (fd < 0) + return -1; + + transport_data->fd = fd; + + return 0; +} + +int crespo_ipc_close(void *data) +{ + struct crespo_ipc_transport_data *transport_data; + int fd; + + if (data == NULL) + return -1; + + transport_data = (struct crespo_ipc_transport_data *) data; + + fd = transport_data->fd; + if (fd < 0) + return -1; + + transport_data->fd = -1; + close(fd); + + return 0; +} + +int crespo_ipc_read(void *data, void *buffer, unsigned int length) +{ + struct crespo_ipc_transport_data *transport_data; + int fd; + int rc; + + if (data == NULL || buffer == NULL || length == 0) + return -1; + + transport_data = (struct crespo_ipc_transport_data *) data; + + fd = transport_data->fd; + if (fd < 0) + return -1; + + rc = ioctl(fd, IOCTL_MODEM_RECV, buffer); + if (rc < 0) + return -1; + + return 0; +} + +int crespo_ipc_write(void *data, void *buffer, unsigned int length) +{ + struct crespo_ipc_transport_data *transport_data; + int fd; + int rc; + + if (data == NULL || buffer == NULL || length == 0) + return -1; + + transport_data = (struct crespo_ipc_transport_data *) data; + + fd = transport_data->fd; + if (fd < 0) + return -1; + + rc = ioctl(fd, IOCTL_MODEM_SEND, buffer); + if (rc < 0) + return -1; + + return 0; +} + +int crespo_ipc_poll(void *data, struct timeval *timeout) +{ + struct crespo_ipc_transport_data *transport_data; + fd_set fds; + int fd; + int rc; + + if (data == NULL) + return -1; + + transport_data = (struct crespo_ipc_transport_data *) data; + + fd = transport_data->fd; + if (fd < 0) + return -1; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + rc = select(fd + 1, &fds, NULL, NULL, timeout); + return rc; +} + +int crespo_ipc_power_on(void *data) +{ + int fd; + int rc; + + fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR); + 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; + int rc; + + fd = open(CRESPO_MODEM_CTL_DEVICE, O_RDWR); + if (fd < 0) + return -1; + + rc = ioctl(fd, IOCTL_MODEM_OFF); + + close(fd); + + if (rc < 0) + return -1; + + return 0; +} + +int crespo_ipc_data_create(void **transport_data, void **power_data, void **gprs_data) +{ + if (transport_data == NULL) + return -1; + + *transport_data = (void *) malloc(sizeof(struct crespo_ipc_transport_data)); + memset(*transport_data, 0, sizeof(struct crespo_ipc_transport_data)); + + return 0; +} + +int crespo_ipc_data_destroy(void *transport_data, void *power_data, void *gprs_data) +{ + if (transport_data == NULL) + return -1; + + free(transport_data); + + return 0; +} + +char *crespo_ipc_gprs_get_iface_single(int cid) +{ + char *iface = NULL; + + asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, 0); + + return iface; +} + +int crespo_ipc_gprs_get_capabilities_single(struct ipc_client_gprs_capabilities *capabilities) +{ + if (capabilities == NULL) + return -1; + + capabilities->port_list = 0; + capabilities->cid_max = 1; + + return 0; +} + +char *crespo_ipc_gprs_get_iface(int cid) +{ + char *iface = NULL; + + if (cid > CRESPO_GPRS_IFACE_COUNT) + return NULL; + + asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, cid - 1); + + return iface; +} + +int crespo_ipc_gprs_get_capabilities(struct ipc_client_gprs_capabilities *capabilities) +{ + if (capabilities == NULL) + return -1; + + capabilities->port_list = 0; + capabilities->cid_max = CRESPO_GPRS_IFACE_COUNT; + + return 0; +} + +struct ipc_ops crespo_ipc_fmt_ops = { + .bootstrap = crespo_ipc_bootstrap, + .send = crespo_ipc_fmt_send, + .recv = crespo_ipc_fmt_recv, +}; + +struct ipc_ops crespo_ipc_rfs_ops = { + .bootstrap = NULL, + .send = crespo_ipc_rfs_send, + .recv = crespo_ipc_rfs_recv, +}; + +struct ipc_handlers crespo_ipc_handlers = { + .open = crespo_ipc_open, + .close = crespo_ipc_close, + .read = crespo_ipc_read, + .write = crespo_ipc_write, + .poll = crespo_ipc_poll, + .transport_data = NULL, + .power_on = crespo_ipc_power_on, + .power_off = crespo_ipc_power_off, + .power_data = NULL, + .gprs_activate = NULL, + .gprs_deactivate = NULL, + .gprs_data = NULL, + .data_create = crespo_ipc_data_create, + .data_destroy = crespo_ipc_data_destroy, +}; + +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_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/devices/crespo/crespo_ipc.h b/samsung-ipc/devices/crespo/crespo_ipc.h new file mode 100644 index 0000000..85bf21d --- /dev/null +++ b/samsung-ipc/devices/crespo/crespo_ipc.h @@ -0,0 +1,49 @@ +/* + * 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/>. + */ + +#ifndef __CRESPO_IPC_H__ +#define __CRESPO_IPC_H__ + +#define CRESPO_MODEM_IMAGE_SIZE 0xD80000 +#define CRESPO_PSI_SIZE 0x5000 +#define CRESPO_MODEM_CTL_NV_DATA_OFFSET 0xD80000 +#define CRESPO_BUFFER_LENGTH 0x50000 + +#define CRESPO_MODEM_IMAGE_DEVICE "/dev/mtd/mtd5ro" +#define CRESPO_MODEM_SERIAL_DEVICE "/dev/s3c2410_serial3" +#define CRESPO_MODEM_CTL_DEVICE "/dev/modem_ctl" +#define CRESPO_MODEM_FMT_DEVICE "/dev/modem_fmt" +#define CRESPO_MODEM_RFS_DEVICE "/dev/modem_rfs" + +#define CRESPO_GPRS_IFACE_PREFIX "rmnet" +#define CRESPO_GPRS_IFACE_COUNT 3 + +struct crespo_ipc_transport_data { + int fd; +}; + +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_ipc_gprs_specs_single; +extern struct ipc_gprs_specs crespo_ipc_gprs_specs; + +#endif + +// vim:ts=4:sw=4:expandtab diff --git a/samsung-ipc/devices/crespo/crespo_modem_ctl.h b/samsung-ipc/devices/crespo/crespo_modem_ctl.h new file mode 100644 index 0000000..7c23165 --- /dev/null +++ b/samsung-ipc/devices/crespo/crespo_modem_ctl.h @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2010 Google, Inc. + * Copyright (C) 2010 Samsung Electronics. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#ifndef __MODEM_CONTROL_H__ +#define __MODEM_CONTROL_H__ + +#define IOCTL_MODEM_RAMDUMP _IO('o', 0x19) +#define IOCTL_MODEM_RESET _IO('o', 0x20) +#define IOCTL_MODEM_START _IO('o', 0x21) +#define IOCTL_MODEM_OFF _IO('o', 0x22) + +#define IOCTL_MODEM_SEND _IO('o', 0x23) +#define IOCTL_MODEM_RECV _IO('o', 0x24) + +struct modem_io { + uint32_t size; + uint32_t id; + uint32_t cmd; + void *data; +}; + +/* platform data */ +struct modemctl_data { + const char *name; + unsigned gpio_phone_active; + unsigned gpio_pda_active; + unsigned gpio_cp_reset; + unsigned gpio_phone_on; + bool is_cdma_modem; /* 1:CDMA Modem */ +}; + +#endif |