From cf8ea3d14f425112990dcb94d0878fab9c767aa3 Mon Sep 17 00:00:00 2001 From: Denis 'GNUtoo' Carikli Date: Fri, 21 Feb 2020 05:24:36 +0100 Subject: Add a modem abstraction Some xmm626_kernel_smdk4412 functions are present for all devices: - open|close|read|write|poll - fmt/rfs - gprs - power Thses are not +----------+ | galaxys2 | | hci_power | link_control_enable | link_control_active | link_connected_wait | link_get_hostwake_wait | | | i9300 | | hci_power | link_control_enable | link_control_active | link_connected_wait | link_get_hostwake_wait | | | maguro | boot_power | | | | | | status_online_wait | | n5100 | | hci_power | link_control_enable | link_control_active | link_connected_wait | link_get_hostwake_wait | | | n7100 | | hci_power | link_control_enable | link_control_active | link_connected_wait | link_get_hostwake_wait | | | piranha | | | | | | | | +----------+ TODO: - don't add the python script to this commit or clean it up - cleanup style - Verify if we need to convert all boards in this commit - Look if i9300 changes should go in this commit Signed-off-by: Denis 'GNUtoo' Carikli --- Android.mk | 1 + samsung-ipc/Makefile.am | 15 +- samsung-ipc/devices/galaxys2/galaxys2.c | 2 +- samsung-ipc/devices/i9300/i9300.c | 2 +- samsung-ipc/devices/ipc_devices.h | 1 + samsung-ipc/devices/maguro/maguro.c | 2 +- samsung-ipc/devices/n5100/n5100.c | 2 +- samsung-ipc/devices/n7100/n7100.c | 2 +- samsung-ipc/devices/piranha/piranha.c | 2 +- samsung-ipc/ipc.c | 1 + samsung-ipc/ipc.h | 44 ++ samsung-ipc/modems/modem.c | 194 ++++++ samsung-ipc/modems/modem.h | 35 ++ samsung-ipc/modems/xmm626/firmware.c | 84 +++ samsung-ipc/modems/xmm626/hsic/hsic.c | 588 ++++++++++++++++++ samsung-ipc/modems/xmm626/hsic/hsic.h | 70 +++ .../modems/xmm626/hsic/xmm626_kernel_smdk4412.c | 634 +++++++++++++++++++ .../xmm626/hsic/xmm626_modem_link_device_hsic.h | 63 ++ samsung-ipc/modems/xmm626/kernel_smdk4412.c | 605 ++++++++++++++++++ samsung-ipc/modems/xmm626/mipi/mipi.c | 646 ++++++++++++++++++++ samsung-ipc/modems/xmm626/mipi/xmm626_mipi.h | 73 +++ samsung-ipc/modems/xmm626/xmm626_hsic.c | 612 ------------------- samsung-ipc/modems/xmm626/xmm626_hsic.h | 67 -- samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c | 604 ------------------ samsung-ipc/modems/xmm626/xmm626_mipi.c | 674 --------------------- samsung-ipc/modems/xmm626/xmm626_mipi.h | 71 --- .../modems/xmm626/xmm626_modem_link_device_hsic.h | 63 -- scripts/smdk4412_func_usage.py | 85 +++ 28 files changed, 3139 insertions(+), 2103 deletions(-) create mode 100644 samsung-ipc/modems/modem.c create mode 100644 samsung-ipc/modems/modem.h create mode 100644 samsung-ipc/modems/xmm626/firmware.c create mode 100644 samsung-ipc/modems/xmm626/hsic/hsic.c create mode 100644 samsung-ipc/modems/xmm626/hsic/hsic.h create mode 100644 samsung-ipc/modems/xmm626/hsic/xmm626_kernel_smdk4412.c create mode 100644 samsung-ipc/modems/xmm626/hsic/xmm626_modem_link_device_hsic.h create mode 100644 samsung-ipc/modems/xmm626/kernel_smdk4412.c create mode 100644 samsung-ipc/modems/xmm626/mipi/mipi.c create mode 100644 samsung-ipc/modems/xmm626/mipi/xmm626_mipi.h delete mode 100644 samsung-ipc/modems/xmm626/xmm626_hsic.c delete mode 100644 samsung-ipc/modems/xmm626/xmm626_hsic.h delete mode 100644 samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c delete mode 100644 samsung-ipc/modems/xmm626/xmm626_mipi.c delete mode 100644 samsung-ipc/modems/xmm626/xmm626_mipi.h delete mode 100644 samsung-ipc/modems/xmm626/xmm626_modem_link_device_hsic.h create mode 100755 scripts/smdk4412_func_usage.py diff --git a/Android.mk b/Android.mk index 63207e4..bb20dfa 100644 --- a/Android.mk +++ b/Android.mk @@ -52,6 +52,7 @@ endif libsamsung_ipc_local_src_files := \ samsung-ipc/ipc.c \ samsung-ipc/ipc_utils.c \ + samsung-ipc/modems/modem.c \ samsung-ipc/modems/xmm616/xmm616.c \ samsung-ipc/modems/xmm626/xmm626.c \ samsung-ipc/modems/xmm626/xmm626_hsic.c \ diff --git a/samsung-ipc/Makefile.am b/samsung-ipc/Makefile.am index f71e396..8c8e5bd 100644 --- a/samsung-ipc/Makefile.am +++ b/samsung-ipc/Makefile.am @@ -18,19 +18,22 @@ libsamsung_ipc_la_SOURCES = \ ipc.c \ ipc.h \ ipc_utils.c \ + modems/modem.c \ + modems/modem.h \ modems/xmm616/xmm616.c \ modems/xmm616/xmm616.h \ modems/xmm626/xmm626.c \ modems/xmm626/xmm626.h \ - modems/xmm626/xmm626_hsic.c \ - modems/xmm626/xmm626_hsic.h \ - modems/xmm626/xmm626_kernel_smdk4412.c \ - modems/xmm626/xmm626_kernel_smdk4412.h \ - modems/xmm626/xmm626_mipi.c \ - modems/xmm626/xmm626_mipi.h \ + modems/xmm626/firmware.c \ + modems/xmm626/kernel_smdk4412.c \ modems/xmm626/xmm626_modem.h \ modems/xmm626/xmm626_modem_link_device_hsic.h \ modems/xmm626/xmm626_modem_prj.h \ + modems/xmm626/xmm626_kernel_smdk4412.h \ + modems/xmm626/hsic/hsic.c \ + modems/xmm626/hsic/xmm626_hsic.h \ + modems/xmm626/mipi/mipi.c \ + modems/xmm626/mipi/xmm626_mipi.h \ devices/ipc_devices.c \ devices/ipc_devices.h \ devices/crespo/crespo.c \ diff --git a/samsung-ipc/devices/galaxys2/galaxys2.c b/samsung-ipc/devices/galaxys2/galaxys2.c index cdfe20c..296feac 100644 --- a/samsung-ipc/devices/galaxys2/galaxys2.c +++ b/samsung-ipc/devices/galaxys2/galaxys2.c @@ -28,7 +28,7 @@ #include "ipc.h" #include "devices/galaxys2/galaxys2.h" #include "modems/xmm626/xmm626.h" -#include "modems/xmm626/xmm626_hsic.h" +#include "modems/xmm626/hsic/hsic.h" #include "modems/xmm626/xmm626_kernel_smdk4412.h" int galaxys2_boot(struct ipc_client *client) diff --git a/samsung-ipc/devices/i9300/i9300.c b/samsung-ipc/devices/i9300/i9300.c index 85709a8..355ff62 100644 --- a/samsung-ipc/devices/i9300/i9300.c +++ b/samsung-ipc/devices/i9300/i9300.c @@ -28,7 +28,7 @@ #include "ipc.h" #include "devices/i9300/i9300.h" #include "modems/xmm626/xmm626.h" -#include "modems/xmm626/xmm626_hsic.h" +#include "modems/xmm626/hsic/hsic.h" #include "modems/xmm626/xmm626_kernel_smdk4412.h" int i9300_boot(struct ipc_client *client) diff --git a/samsung-ipc/devices/ipc_devices.h b/samsung-ipc/devices/ipc_devices.h index 176607c..17a40b8 100644 --- a/samsung-ipc/devices/ipc_devices.h +++ b/samsung-ipc/devices/ipc_devices.h @@ -42,6 +42,7 @@ struct ipc_device_desc { struct ipc_client_handlers *handlers; struct ipc_client_gprs_specs *gprs_specs; struct ipc_client_nv_data_specs *nv_data_specs; + struct ipc_client_modem_driver_ops *modem_driver_ops; }; extern struct ipc_device_desc ipc_devices[]; diff --git a/samsung-ipc/devices/maguro/maguro.c b/samsung-ipc/devices/maguro/maguro.c index a2db5fc..e6cd191 100644 --- a/samsung-ipc/devices/maguro/maguro.c +++ b/samsung-ipc/devices/maguro/maguro.c @@ -30,7 +30,7 @@ #include "devices/maguro/maguro.h" #include "modems/xmm626/xmm626.h" #include "modems/xmm626/xmm626_kernel_smdk4412.h" -#include "modems/xmm626/xmm626_mipi.h" +#include "modems/xmm626/mipi/xmm626_mipi.h" int maguro_boot(struct ipc_client *client) { diff --git a/samsung-ipc/devices/n5100/n5100.c b/samsung-ipc/devices/n5100/n5100.c index 0abe896..5489fb6 100644 --- a/samsung-ipc/devices/n5100/n5100.c +++ b/samsung-ipc/devices/n5100/n5100.c @@ -29,7 +29,7 @@ #include "ipc.h" #include "devices/n5100/n5100.h" #include "modems/xmm626/xmm626.h" -#include "modems/xmm626/xmm626_hsic.h" +#include "modems/xmm626/hsic/hsic.h" #include "modems/xmm626/xmm626_kernel_smdk4412.h" int n5100_boot(struct ipc_client *client) diff --git a/samsung-ipc/devices/n7100/n7100.c b/samsung-ipc/devices/n7100/n7100.c index d5091a2..4713e00 100644 --- a/samsung-ipc/devices/n7100/n7100.c +++ b/samsung-ipc/devices/n7100/n7100.c @@ -28,7 +28,7 @@ #include "ipc.h" #include "devices/n7100/n7100.h" #include "modems/xmm626/xmm626.h" -#include "modems/xmm626/xmm626_hsic.h" +#include "modems/xmm626/hsic/hsic.h" #include "modems/xmm626/xmm626_kernel_smdk4412.h" int n7100_boot(struct ipc_client *client) diff --git a/samsung-ipc/devices/piranha/piranha.c b/samsung-ipc/devices/piranha/piranha.c index 839b3ce..a98e1cb 100644 --- a/samsung-ipc/devices/piranha/piranha.c +++ b/samsung-ipc/devices/piranha/piranha.c @@ -29,7 +29,7 @@ #include "devices/piranha/piranha.h" #include "modems/xmm626/xmm626.h" #include "modems/xmm626/xmm626_kernel_smdk4412.h" -#include "modems/xmm626/xmm626_mipi.h" +#include "modems/xmm626/mipi/xmm626_mipi.h" int piranha_boot(struct ipc_client *client) { diff --git a/samsung-ipc/ipc.c b/samsung-ipc/ipc.c index c116fbb..efdd5d2 100644 --- a/samsung-ipc/ipc.c +++ b/samsung-ipc/ipc.c @@ -214,6 +214,7 @@ static struct ipc_client *ipc_transport_client_create(int type) client->gprs_specs = ipc_devices[device_index].gprs_specs; client->nv_data_specs = ipc_devices[device_index].nv_data_specs; + client->modem_driver_ops = ipc_devices[device_index].modem_driver_ops; /* Handlers can be modified */ client->handlers = (struct ipc_client_handlers *) calloc( diff --git a/samsung-ipc/ipc.h b/samsung-ipc/ipc.h index 1cfa757..dfeea11 100644 --- a/samsung-ipc/ipc.h +++ b/samsung-ipc/ipc.h @@ -78,6 +78,49 @@ struct ipc_client_gprs_specs { struct ipc_client_gprs_capabilities *capabilities); }; +struct ipc_client_modem_driver_ops { + int (*power)(struct ipc_client *client, int device_fd, int power); + int (*download_enable)(struct ipc_client *client, int device_fd, + int enable); + int (*bus_power)(struct ipc_client *client, int power); + int (*link_control_enable)(struct ipc_client *client, int device_fd, + int enable); + int (*link_control_active)(struct ipc_client *client, int device_fd, + int active); + int (*link_connected_wait)(struct ipc_client *client, int device_fd); + int (*link_get_hostwake_wait)(struct ipc_client *client, int device_fd); + int (*wait_status_online)( + __attribute__((unused)) struct ipc_client *client, + int device_fd); + int (*open)(struct ipc_client *client, int type); + int (*close)(struct ipc_client *client, int fd); + int (*read)(struct ipc_client *client, int fd, void *buffer, + size_t length); + int (*write)(struct ipc_client *client, int fd, const void *buffer, + size_t length); + int (*poll)(struct ipc_client *client, int fd, struct ipc_poll_fds *fds, + struct timeval *timeout); + + int (*fmt_send)(struct ipc_client *client, struct ipc_message *message); + int (*fmt_recv)(struct ipc_client *client, struct ipc_message *message); + int (*rfs_send)(struct ipc_client *client, struct ipc_message *message); + int (*rfs_recv)(struct ipc_client *client, struct ipc_message *message); + //TODO: find a better name not to conflict with fmt/rfs send + // like block-data send (used for firmware) + // what about firmware->MAIN + // and data_send firmware_send + // or send_partition + // or send_block + int (*data_send)(struct ipc_client *client, int device_fd, const void *data, + size_t size, int address); + + char * (*gprs_get_iface)(struct ipc_client *client, unsigned int cid); + int (*gprs_get_capabilities)( + struct ipc_client *client, + struct ipc_client_gprs_capabilities *capabilities); +}; + + struct ipc_client_nv_data_specs { char *nv_data_path; char *nv_data_md5_path; @@ -98,6 +141,7 @@ struct ipc_client { struct ipc_client_handlers *handlers; struct ipc_client_gprs_specs *gprs_specs; struct ipc_client_nv_data_specs *nv_data_specs; + struct ipc_client_modem_driver_ops *modem_driver_ops; }; /* diff --git a/samsung-ipc/modems/modem.c b/samsung-ipc/modems/modem.c new file mode 100644 index 0000000..82a6ca7 --- /dev/null +++ b/samsung-ipc/modems/modem.c @@ -0,0 +1,194 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2020 Denis 'GNUtoo' Carikli + * + * 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 . + */ + +#include + +/* Set the modem into download mode */ +int modem_download_enable(struct ipc_client *client, int device_fd, int enable) +{ + return client->modem_driver_ops->download_enable(client, device_fd, + enable); +} + +/* Power on/off the modem */ +int modem_power(struct ipc_client *client, int device_fd, int power) +{ + return client->modem_driver_ops->power(client, device_fd, power); +} + +/* Power on/off the modem bus (HSIC, MIPI, etc) */ +int modem_bus_power(struct ipc_client *client, int power) +{ + return client->modem_driver_ops->bus_power(client, power); +} + +// TODO +int modem_link_control_enable(struct ipc_client *client, int device_fd, + int enable) +{ + return client->modem_driver_ops->link_control_enable(client, device_fd, + enable); +} + +//TODO +//0: HSIC is low power +//1: HSIC is back +int modem_link_control_active(struct ipc_client *client, int device_fd, + int active) +{ + return client->modem_driver_ops->link_control_active(client, device_fd, + active); +} + +//TODO: +int modem_link_connected_wait(struct ipc_client *client, int device_fd) +{ + return client->modem_driver_ops->link_connected_wait(client, device_fd); +} + +// TODO +int modem_link_get_hostwake_wait(struct ipc_client *client, int device_fd) +{ + return client->modem_driver_ops->link_get_hostwake_wait(client, + device_fd); +} + +/* Wait for the modem driver to report the ONLINE status */ +int modem_wait_status_online(__attribute__((unused)) struct ipc_client *client, + int device_fd) +{ + return client->modem_driver_ops->wait_status_online(client, device_fd); +} + +int modem_open(struct ipc_client *client, int type) +{ + return client->modem_driver_ops->open(client, type); +} + +int modem_close(struct ipc_client *client, int fd) +{ + return client->modem_driver_ops->close(client, fd); +} + +int modem_read(struct ipc_client *client, int fd, void *buffer, size_t length) +{ + return client->modem_driver_ops->read(client, fd, buffer, length); +} + +int modem_write(struct ipc_client *client, int fd, const void *buffer, + size_t length) +{ + return client->modem_driver_ops->write(client, fd, buffer, length); +} + +int modem_poll(struct ipc_client *client, int fd, struct ipc_poll_fds *fds, + struct timeval *timeout) +{ + return client->modem_driver_ops->poll(client, fd, fds, timeout); +} + +int modem_fmt_send(struct ipc_client *client, struct ipc_message *message) +{ + return client->modem_driver_ops->fmt_send(client, message); +} + +int modem_fmt_recv(struct ipc_client *client, struct ipc_message *message) +{ + return client->modem_driver_ops->fmt_recv(client, message); +} + +int modem_rfs_send(struct ipc_client *client, struct ipc_message *message) +{ + return client->modem_driver_ops->rfs_send(client, message); +} + +int modem_rfs_recv(struct ipc_client *client, struct ipc_message *message) +{ + return client->modem_driver_ops->rfs_recv(client, message); +} + +// TODO +char *modem_gprs_get_iface(struct ipc_client *client, unsigned int cid) +{ + return client->modem_driver_ops->gprs_get_iface(client, cid); +} + +// TODO +int modem_gprs_get_capabilities(struct ipc_client *client, + struct ipc_client_gprs_capabilities *capabilities) +{ + return client->modem_driver_ops->gprs_get_capabilities(client, + capabilities); +} + +// TODO: make it more generic: +// - get rid of device_fd +// - we have many __send +// functions for partitions: +// | Function | Partition | +// | psi | PSIRAM | +// | ebl | EBL | +// | firmware | MAIN | +// | sec_start | SECPACK | +// | device specific | NV | + +// int modem_psi_send(struct ipc_client *client, int serial_fd, +// const void *psi_data, unsigned short psi_size); +// { +// /* TODO: get rid of serial_fd */ +// return client->modem_driver_ops->psi_send(client, serial_fd, psi_data, +// psi_size); +// } +// +// int modem_firmware_send(struct ipc_client *client, int device_fd, +// void *device_address, const void *firmware_data, +// size_t firmware_size) +// { +// /* TODO: get rid of device_fd */ +// return client->modem_driver_ops->firmware_send(client, device_fd, +// device_address, +// firmware_data, +// firmware_size); +// } +// +// int modem_nv_data_send(struct ipc_client *client, int device_fd, +// void *device_address) +// { +// /* TODO: get rid of device_fd */ +// return client->modem_driver_ops->firmware_send(client, device_fd, +// device_address); +// } +// +// +// int modem_psi_send(struct ipc_client *client, int serial_fd, +// const void *psi_data, unsigned short psi_size); +// { +// /* TODO: get rid of serial_fd */ +// return client->modem_driver_ops->psi_send(client, serial_fd, psi_data, +// psi_size); +// } +// + +// TODO: find a better name like block data (used for fimrware partitions) +int modem_data_send(struct ipc_client *client, int device_fd, const void *data, + size_t size, int address) +{ + return client->modem_driver_ops->data_send(client, device_fd, data, + size, address); +} diff --git a/samsung-ipc/modems/modem.h b/samsung-ipc/modems/modem.h new file mode 100644 index 0000000..b8119ce --- /dev/null +++ b/samsung-ipc/modems/modem.h @@ -0,0 +1,35 @@ +#ifndef __SAMSUNG_IPC_MODEM_H__ +#define __SAMSUNG_IPC_MODEM_H__ +int modem_download_enable(__attribute__((unused)) struct ipc_client *client, + int device_fd, int enable); +int modem_power(struct ipc_client *client, int device_fd, int power); +int modem_bus_power(struct ipc_client *client, int power); +int modem_link_control_enable(struct ipc_client *client, int device_fd, + int enable); +int modem_link_control_active(struct ipc_client *client, int device_fd, + int active); +int modem_link_connected_wait(struct ipc_client *client, int device_fd); +int modem_link_get_hostwake_wait(struct ipc_client *client, int device_fd); +int modem_wait_status(__attribute__((unused)) struct ipc_client *client, + int device_fd); +int modem_open(struct ipc_client *client, int type); +int modem_close(struct ipc_client *client, int fd); +int modem_read(struct ipc_client *client, int fd, void *buffer, size_t length); +int modem_write(struct ipc_client *client, int fd, const void *buffer, + size_t length); +int modem_poll(struct ipc_client *client, int fd, struct ipc_poll_fds *fds, + struct timeval *timeout); + +int modem_fmt_send(struct ipc_client *client, struct ipc_message *message); +int modem_fmt_recv(struct ipc_client *client, struct ipc_message *message); +int modem_rfs_send(struct ipc_client *client, struct ipc_message *message); +int modem_rfs_recv(struct ipc_client *client, struct ipc_message *message); +// TODO: find a better name like block data (used for fimrware partitions) +int modem_data_send(struct ipc_client *client, int device_fd, const void *data, + size_t size, int address); + +char *modem_gprs_get_iface(struct ipc_client *client, unsigned int cid); +int modem_gprs_get_capabilities(struct ipc_client *client, + struct ipc_client_gprs_capabilities *capabilities); + +#endif /* __SAMSUNG_IPC_MODEM_H__ */ diff --git a/samsung-ipc/modems/xmm626/firmware.c b/samsung-ipc/modems/xmm626/firmware.c new file mode 100644 index 0000000..a7d5f5c --- /dev/null +++ b/samsung-ipc/modems/xmm626/firmware.c @@ -0,0 +1,84 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2012 Alexander Tarasikov + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * Based on the incomplete C++ implementation which is: + * Copyright (C) 2012 Sergey Gridasov + * + * 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 . + */ + +#include + +#include "ipc.h" +#include "modems/modem.h" +#include "modems/xmm626/xmm626.h" + +int xmm626_firmware_send(struct ipc_client *client, int device_fd, + const void *firmware_data, size_t firmware_size) +{ + int rc; + + if (client == NULL || device_fd < 0 || firmware_data == NULL || + firmware_size == 0) { + return -1; + } + + rc = modem_data_send(client, device_fd, firmware_data, firmware_size, + XMM626_FIRMWARE_ADDRESS); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_nv_data_send(struct ipc_client *client, int device_fd) +{ + void *nv_data = NULL; + size_t nv_size; + int rc; + + if (client == NULL || device_fd < 0) + return -1; + + nv_size = ipc_client_nv_data_size(client); + if (nv_size == 0) + return -1; + + nv_data = ipc_nv_data_load(client); + if (nv_data == NULL) { + ipc_client_log(client, "Loading nv_data failed"); + goto error; + } + ipc_client_log(client, "Loaded nv_data"); + + rc = modem_data_send(client, device_fd, nv_data, nv_size, + XMM626_NV_DATA_ADDRESS); + if (rc < 0) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (nv_data != NULL) + free(nv_data); + + return rc; +} diff --git a/samsung-ipc/modems/xmm626/hsic/hsic.c b/samsung-ipc/modems/xmm626/hsic/hsic.c new file mode 100644 index 0000000..b195753 --- /dev/null +++ b/samsung-ipc/modems/xmm626/hsic/hsic.c @@ -0,0 +1,588 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2012 Alexander Tarasikov + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * Based on the incomplete C++ implementation which is: + * Copyright (C) 2012 Sergey Gridasov + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#include + +#include "ipc.h" +#include "modems/xmm626/xmm626.h" +#include "modems/xmm626/xmm626_kernel_smdk4412.h" +#include "modems/xmm626/hsic/hsic.h" + +int xmm626_hsic_ack_read(int device_fd, unsigned short ack) +{ + struct timeval timeout; + fd_set fds; + unsigned short value; + int rc; + int i; + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(device_fd, &fds); + + for (i = 0; i < 50; i++) { + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + return -1; + + value = 0; + rc = read(device_fd, &value, sizeof(value)); + if (rc < (int) sizeof(value)) + continue; + + if (value == ack) + return 0; + } + + return -1; +} + +int xmm626_hsic_psi_send(struct ipc_client *client, int device_fd, + const void *psi_data, unsigned short psi_size) +{ + struct xmm626_hsic_psi_header psi_header; + char at[] = XMM626_AT; + unsigned char psi_ack; + unsigned char chip_id; + unsigned char psi_crc; + struct timeval timeout; + fd_set fds; + size_t wc; + size_t length; + unsigned char *p; + int rc; + int i; + + if (client == NULL || device_fd < 0 || psi_data == NULL || + psi_size == 0) { + return -1; + } + + FD_ZERO(&fds); + + i = 0; + length = strlen(at); + + do { + FD_SET(device_fd, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + + rc = write(device_fd, at, length); + if (rc < (int) length) { + ipc_client_log(client, "Writing ATAT in ASCII failed"); + goto error; + } + ipc_client_log(client, "Wrote ATAT in ASCII"); + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc < 0) { + ipc_client_log(client, "Waiting for bootup failed"); + goto error; + } + + if (i++ > 50) { + ipc_client_log(client, "Waiting for bootup failed"); + goto error; + } + } while (rc == 0); + + FD_SET(device_fd, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) { + ipc_client_log(client, "Reading boot ACK failed"); + goto error; + } + + psi_ack = 0; + rc = read(device_fd, &psi_ack, sizeof(psi_ack)); + if (rc < (int) sizeof(psi_ack)) { + ipc_client_log(client, "Reading boot ACK failed"); + goto error; + } + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) { + ipc_client_log(client, "Reading chip id failed"); + goto error; + } + + chip_id = 0; + rc = read(device_fd, &chip_id, sizeof(chip_id)); + if (rc < (int) sizeof(chip_id)) { + ipc_client_log(client, "Reading chip id failed"); + goto error; + } + ipc_client_log(client, "Read chip id (0x%x)", chip_id); + + psi_header.magic = XMM626_PSI_MAGIC; + psi_header.length = psi_size; + psi_header.padding = XMM626_PSI_PADDING; + + rc = write(device_fd, &psi_header, sizeof(psi_header)); + if (rc < (int) sizeof(psi_header)) { + ipc_client_log(client, "Writing PSI header failed"); + goto error; + } + ipc_client_log(client, "Wrote PSI header"); + + p = (unsigned char *) psi_data; + + wc = 0; + while (wc < psi_size) { + rc = write(device_fd, (void *) p, psi_size - wc); + if (rc <= 0) { + ipc_client_log(client, "Writing PSI failed"); + goto error; + } + + p += rc; + wc += rc; + } + + psi_crc = xmm626_crc_calculate(psi_data, psi_size); + + ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc); + + rc = write(device_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 = 0; + timeout.tv_usec = 100000; + + for (i = 0; i < XMM626_HSIC_PSI_UNKNOWN_COUNT; i++) { + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) { + ipc_client_log(client, "Reading PSI unknown failed"); + goto error; + } + + rc = read(device_fd, &psi_ack, sizeof(psi_ack)); + if (rc < (int) sizeof(psi_ack)) { + ipc_client_log(client, "Reading PSI unknown failed"); + goto error; + } + } + + for (i = 0; i < XMM626_HSIC_PSI_CRC_ACK_COUNT ; i++) { + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) { + ipc_client_log(client, "Reading PSI CRC ACK failed"); + goto error; + } + + rc = read(device_fd, &psi_ack, sizeof(psi_ack)); + if (rc < (int) sizeof(psi_ack)) { + ipc_client_log(client, "Reading PSI CRC ACK failed"); + goto error; + } + } + ipc_client_log(client, "Read PSI CRC ACK"); + + rc = xmm626_hsic_ack_read(device_fd, XMM626_HSIC_PSI_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading PSI ACK failed"); + goto error; + } + ipc_client_log(client, "Read PSI ACK"); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int xmm626_hsic_ebl_send(struct ipc_client *client, int device_fd, + const void *ebl_data, size_t ebl_size) +{ + unsigned char ebl_crc; + size_t chunk; + size_t count; + size_t wc; + size_t size; + unsigned char *p; + int rc; + + if (client == NULL || device_fd < 0 || ebl_data == NULL || + ebl_size == 0) { + return -1; + } + + size = sizeof(ebl_size); + + rc = write(device_fd, &ebl_size, size); + if (rc < (int) size) { + ipc_client_log(client, "Writing EBL size failed"); + goto error; + } + ipc_client_log(client, "Wrote EBL size"); + + rc = xmm626_hsic_ack_read(device_fd, XMM626_HSIC_EBL_SIZE_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading EBL size ACK failed"); + goto error; + } + + p = (unsigned char *) ebl_data; + + chunk = XMM626_HSIC_EBL_CHUNK; + wc = 0; + while (wc < ebl_size) { + count = chunk < ebl_size - wc ? chunk : ebl_size - wc; + + rc = write(device_fd, (void *) p, count); + if (rc <= 0) { + ipc_client_log(client, "Writing EBL failed"); + goto error; + } + + p += rc; + wc += rc; + } + + ebl_crc = xmm626_crc_calculate(ebl_data, ebl_size); + + ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc); + + rc = write(device_fd, &ebl_crc, sizeof(ebl_crc)); + if (rc < (int) sizeof(ebl_crc)) { + ipc_client_log(client, "Writing EBL CRC failed"); + goto error; + } + ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc); + + rc = xmm626_hsic_ack_read(device_fd, XMM626_HSIC_EBL_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading EBL ACK failed"); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int xmm626_hsic_command_send(int device_fd, unsigned short code, + const void *data, size_t size, + size_t command_data_size, int ack) +{ + struct xmm626_hsic_command_header header; + void *buffer = NULL; + size_t length; + struct timeval timeout; + fd_set fds; + unsigned char *p; + int rc; + int i; + + if (device_fd < 0 || data == NULL || size == 0 || + command_data_size == 0 || command_data_size < size) { + return -1; + } + + header.checksum = (size & 0xffff) + code; + header.code = code; + header.data_size = size; + + p = (unsigned char *) data; + + for (i = 0; i < (int) size; i++) + header.checksum += *p++; + + length = command_data_size + sizeof(header); + buffer = calloc(1, length); + + memset(buffer, 0, length); + p = (unsigned char *) buffer; + memcpy(p, &header, sizeof(header)); + p += sizeof(header); + memcpy(p, data, size); + + rc = write(device_fd, buffer, length); + if (rc < (int) length) + goto error; + + if (!ack) { + rc = 0; + goto complete; + } + + memset(buffer, 0, length); + + FD_ZERO(&fds); + FD_SET(device_fd, &fds); + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + rc = read(device_fd, &header, sizeof(header)); + if (rc < (int) sizeof(header)) + goto error; + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + rc = read(device_fd, buffer, command_data_size); + if (rc < (int) command_data_size) + goto error; + + if (header.code != code) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_hsic_modem_data_send(struct ipc_client *client, int device_fd, + const void *data, size_t size, int address) +{ + size_t chunk; + size_t count; + size_t c; + unsigned char *p; + int rc; + + if (device_fd < 0 || data == NULL || size == 0) + return -1; + + rc = xmm626_hsic_command_send(device_fd, + XMM626_COMMAND_FLASH_SET_ADDRESS, + &address, sizeof(address), + XMM626_HSIC_FLASH_SET_ADDRESS_SIZE, 1); + if (rc < 0) + goto error; + + p = (unsigned char *) data; + + chunk = XMM626_HSIC_MODEM_DATA_CHUNK; + c = 0; + while (c < size) { + count = chunk < size - c ? chunk : size - c; + + rc = xmm626_hsic_command_send( + device_fd, XMM626_COMMAND_FLASH_WRITE_BLOCK, + p, count, XMM626_HSIC_FLASH_WRITE_BLOCK_SIZE, 0); + if (rc < 0) + goto error; + + p += count; + c += count; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int xmm626_hsic_port_config_send(struct ipc_client *client, int device_fd) +{ + void *buffer = NULL; + size_t length; + struct timeval timeout; + fd_set fds; + int rc; + + if (client == NULL || device_fd < 0) + return -1; + + FD_ZERO(&fds); + FD_SET(device_fd, &fds); + + timeout.tv_sec = 2; + timeout.tv_usec = 0; + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + length = XMM626_HSIC_PORT_CONFIG_SIZE; + buffer = calloc(1, length); + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + rc = read(device_fd, buffer, length); + if (rc < (int) length) { + ipc_client_log(client, "Reading port config failed"); + goto error; + } + ipc_client_log(client, "Read port config"); + + rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_SET_PORT_CONFIG, + buffer, length, + XMM626_HSIC_SET_PORT_CONFIG_SIZE, 1); + if (rc < 0) { + ipc_client_log(client, "Sending port config command failed"); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_hsic_sec_start_send(struct ipc_client *client, int device_fd, + const void *sec_data, size_t sec_size) +{ + int rc; + + if (client == NULL || device_fd < 0 || sec_data == NULL || + sec_size == 0) { + return -1; + } + + rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_SEC_START, + sec_data, sec_size, + XMM626_HSIC_SEC_START_SIZE, 1); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_hsic_sec_end_send(struct ipc_client *client, int device_fd) +{ + unsigned short sec_data; + size_t sec_size; + int rc; + + if (client == NULL || device_fd < 0) + return -1; + + sec_data = XMM626_SEC_END_MAGIC; + sec_size = sizeof(sec_data); + + rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_SEC_END, + &sec_data, sec_size, + XMM626_HSIC_SEC_END_SIZE, 1); + if (rc < 0) + return -1; + + return 0; +} + + +int xmm626_hsic_hw_reset_send(struct ipc_client *client, int device_fd) +{ + unsigned int hw_reset_data; + int hw_reset_size; + int rc; + + if (client == NULL || device_fd < 0) + return -1; + + hw_reset_data = XMM626_HW_RESET_MAGIC; + hw_reset_size = sizeof(hw_reset_data); + + rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_HW_RESET, + &hw_reset_data, hw_reset_size, + XMM626_HSIC_HW_RESET_SIZE, 0); + if (rc < 0) + return -1; + + return 0; +} + +struct ipc_client_modem_driver_ops smdk4412_xmm626_hsic_modem_driver_ops = { + .download_enable = xmm626_kernel_smdk4412_boot_power, + .power = xmm626_kernel_smdk4412_power, + .bus_power = xmm626_kernel_smdk4412_hci_power, + .link_control_enable = xmm626_kernel_smdk4412_link_control_enable, + .link_control_active = xmm626_kernel_smdk4412_link_control_active, + .link_connected_wait = xmm626_kernel_smdk4412_link_connected_wait, + .link_get_hostwake_wait = xmm626_kernel_smdk4412_link_get_hostwake_wait, + .wait_status_online = xmm626_kernel_smdk4412_status_online_wait, + + .open = xmm626_kernel_smdk4412_open, + .close = xmm626_kernel_smdk4412_close, + .read = xmm626_kernel_smdk4412_read, + .write = xmm626_kernel_smdk4412_write, + .poll = xmm626_kernel_smdk4412_poll, + + .fmt_send = xmm626_kernel_smdk4412_fmt_send, + .fmt_recv = xmm626_kernel_smdk4412_fmt_recv, + .rfs_send = xmm626_kernel_smdk4412_rfs_send, + .rfs_recv = xmm626_kernel_smdk4412_rfs_recv, + + // TODO: find a better name for data_send + .data_send = xmm626_hsic_modem_data_send, + + // TODO + // .gprs_get_iface = xmm626_kernel_smdk4412_gprs_get_iface, + // .modem_gprs_get_capabilities = xmm626_kernel_smdk4412_modem_gprs_get_capabilities, +}; + diff --git a/samsung-ipc/modems/xmm626/hsic/hsic.h b/samsung-ipc/modems/xmm626/hsic/hsic.h new file mode 100644 index 0000000..fc172d5 --- /dev/null +++ b/samsung-ipc/modems/xmm626/hsic/hsic.h @@ -0,0 +1,70 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2012 Alexander Tarasikov + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * 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 . + */ + +#ifndef __XMM626_HSIC_H__ +#define __XMM626_HSIC_H__ + +#define XMM626_HSIC_BOOT0_ACK 0xF0 +#define XMM626_HSIC_PSI_UNKNOWN_COUNT 22 +#define XMM626_HSIC_PSI_CRC_ACK 0x01 +#define XMM626_HSIC_PSI_CRC_ACK_COUNT 2 +#define XMM626_HSIC_PSI_ACK 0xAA00 +#define XMM626_HSIC_EBL_SIZE_ACK 0xCCCC +#define XMM626_HSIC_EBL_ACK 0xA551 +#define XMM626_HSIC_EBL_CHUNK 0x4000 +#define XMM626_HSIC_PORT_CONFIG_SIZE 0x4C +#define XMM626_HSIC_SET_PORT_CONFIG_SIZE 0x800 +#define XMM626_HSIC_SEC_START_SIZE 0x4000 +#define XMM626_HSIC_SEC_END_SIZE 0x4000 +#define XMM626_HSIC_HW_RESET_SIZE 0x4000 +#define XMM626_HSIC_FLASH_SET_ADDRESS_SIZE 0x4000 +#define XMM626_HSIC_FLASH_WRITE_BLOCK_SIZE 0x4000 +#define XMM626_HSIC_MODEM_DATA_CHUNK 0x4000 + +struct xmm626_hsic_psi_header { + unsigned char magic; + unsigned short length; + unsigned char padding; +} __attribute__((packed)); + +struct xmm626_hsic_command_header { + unsigned short checksum; + unsigned short code; + unsigned int data_size; +} __attribute__((packed)); + +int xmm626_hsic_psi_send(struct ipc_client *client, int device_fd, + const void *psi_data, unsigned short psi_size); +int xmm626_hsic_ebl_send(struct ipc_client *client, int device_fd, + const void *ebl_data, size_t ebl_size); + +int xmm626_hsic_port_config_send(struct ipc_client *client, int device_fd); +int xmm626_hsic_sec_start_send(struct ipc_client *client, int device_fd, + const void *sec_data, size_t sec_size); +int xmm626_hsic_sec_end_send(struct ipc_client *client, int device_fd); +int xmm626_hsic_firmware_send(struct ipc_client *client, int device_fd, + const void *firmware_data, size_t firmware_size); +int xmm626_hsic_nv_data_send(struct ipc_client *client, int device_fd); +int xmm626_hsic_hw_reset_send(struct ipc_client *client, int device_fd); +int xmm626_hsic_modem_data_send(struct ipc_client *client, int device_fd, + const void *data, size_t size, int address); + + +#endif /* __XMM626_HSIC_H__ */ diff --git a/samsung-ipc/modems/xmm626/hsic/xmm626_kernel_smdk4412.c b/samsung-ipc/modems/xmm626/hsic/xmm626_kernel_smdk4412.c new file mode 100644 index 0000000..ef8e975 --- /dev/null +++ b/samsung-ipc/modems/xmm626/hsic/xmm626_kernel_smdk4412.c @@ -0,0 +1,634 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2012 Alexander Tarasikov + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * 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 . + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "xmm626_modem_if.h" +#include "xmm626_modem_prj.h" +#include "xmm626_modem_link_device_hsic.h" + +#include "xmm626.h" +#include "xmm626_kernel_smdk4412.h" + +int xmm626_kernel_smdk4412_power( + __attribute__((unused)) struct ipc_client *client, int device_fd, + int power) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, power ? IOCTL_MODEM_ON : IOCTL_MODEM_OFF, 0); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_boot_power( + __attribute__((unused)) struct ipc_client *client, int device_fd, + int power) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, power ? + IOCTL_MODEM_BOOT_ON : IOCTL_MODEM_BOOT_OFF, + 0); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_status_online_wait( + __attribute__((unused)) struct ipc_client *client, int device_fd) +{ + int status; + int i; + + if (device_fd < 0) + return -1; + + i = 0; + for (i = 0; i < 100; i++) { + status = ioctl(device_fd, IOCTL_MODEM_STATUS, 0); + if (status == STATE_ONLINE) + return 0; + + usleep(50000); + } + + return -1; +} + +int xmm626_kernel_smdk4412_hci_power( + __attribute__((unused)) struct ipc_client *client, int power) +{ + int ehci_rc, ohci_rc; + + ehci_rc = sysfs_value_write(XMM626_SEC_MODEM_EHCI_POWER_SYSFS, !!power); + if (ehci_rc >= 0) + usleep(50000); + + ohci_rc = sysfs_value_write(XMM626_SEC_MODEM_OHCI_POWER_SYSFS, !!power); + if (ohci_rc >= 0) + usleep(50000); + + if (ehci_rc < 0 && ohci_rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_link_control_enable( + __attribute__((unused)) struct ipc_client *client, + int device_fd, int enable) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ENABLE, &enable); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_link_control_active( + __attribute__((unused)) struct ipc_client *client, int device_fd, + int active) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ACTIVE, &active); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_link_connected_wait( + __attribute__((unused)) struct ipc_client *client, int device_fd) +{ + int status; + int i; + + if (device_fd < 0) + return -1; + + i = 0; + for (i = 0; i < 100; i++) { + status = ioctl(device_fd, IOCTL_LINK_CONNECTED, 0); + if (status) + return 0; + + usleep(50000); + } + + return -1; +} + +int xmm626_kernel_smdk4412_link_get_hostwake_wait( + __attribute__((unused)) struct ipc_client *client, int device_fd) +{ + int status; + int i; + + if (device_fd < 0) + return -1; + + i = 0; + for (i = 0; i < 10; i++) { + status = ioctl(device_fd, IOCTL_LINK_GET_HOSTWAKE, 0); + if (status) + return 0; + + usleep(50000); + } + + return -1; +} + +int xmm626_kernel_smdk4412_fmt_send(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_fmt_header header; + void *buffer; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->write == NULL || message == NULL) { + return -1; + } + + ipc_fmt_header_setup(&header, message); + + length = header.length; + buffer = calloc(1, length); + + memcpy(buffer, &header, sizeof(struct ipc_fmt_header)); + if (message->data != NULL && message->size > 0) { + memcpy((void *) ((unsigned char *) buffer + + sizeof(struct ipc_fmt_header)), + message->data, message->size); + } + + ipc_client_log_send(client, message, __func__); + + p = (unsigned char *) buffer; + + count = 0; + while (count < length) { + rc = client->handlers->write(client, + client->handlers->transport_data, + p, length - count); + if (rc <= 0) { + ipc_client_log(client, "Writing FMT data failed"); + goto error; + } + + count += rc; + p += rc; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_fmt_recv(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_fmt_header *header; + void *buffer = NULL; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->read == NULL || message == NULL) { + return -1; + } + + length = XMM626_DATA_SIZE; + buffer = calloc(1, length); + + rc = client->handlers->read(client, client->handlers->transport_data, + buffer, length); + if (rc < (int) sizeof(struct ipc_fmt_header)) { + ipc_client_log(client, "Reading FMT header failed"); + goto error; + } + + header = (struct ipc_fmt_header *) buffer; + + ipc_fmt_message_setup(header, message); + + if (header->length > sizeof(struct ipc_fmt_header)) { + message->size = header->length - sizeof(struct ipc_fmt_header); + message->data = calloc(1, message->size); + + p = (unsigned char *) message->data; + + count = rc - sizeof(struct ipc_fmt_header); + if (count > 0) { + memcpy(p, + (void *) ((unsigned char *) buffer + + sizeof(struct ipc_fmt_header)), + count); + p += count; + } + + while (count < message->size) { + rc = client->handlers->read( + client, client->handlers->transport_data, p, + message->size - count); + if (rc <= 0) { + ipc_client_log(client, + "Reading FMT data failed"); + goto error; + } + + count += rc; + p += rc; + } + } + + ipc_client_log_recv(client, message, __func__); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_rfs_send(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_rfs_header header; + void *buffer; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->write == NULL || message == NULL) { + return -1; + } + + ipc_rfs_header_setup(&header, message); + + length = header.length; + buffer = calloc(1, length); + + memcpy(buffer, &header, sizeof(struct ipc_rfs_header)); + if (message->data != NULL && message->size > 0) { + memcpy((void *) ( + (unsigned char *) buffer + + sizeof(struct ipc_rfs_header)), + message->data, + message->size); + } + + ipc_client_log_send(client, message, __func__); + + p = (unsigned char *) buffer; + + count = 0; + while (count < length) { + rc = client->handlers->write(client, + client->handlers->transport_data, + p, length - count); + if (rc <= 0) { + ipc_client_log(client, "Writing RFS data failed"); + goto error; + } + + count += rc; + p += rc; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_rfs_recv(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_rfs_header *header; + void *buffer = NULL; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->read == NULL || message == NULL) { + return -1; + } + + length = XMM626_DATA_SIZE; + buffer = calloc(1, length); + + rc = client->handlers->read(client, client->handlers->transport_data, + buffer, length); + if (rc < (int) sizeof(struct ipc_rfs_header)) { + ipc_client_log(client, "Reading RFS header failed"); + goto error; + } + + header = (struct ipc_rfs_header *) buffer; + if (header->length > XMM626_DATA_SIZE_LIMIT) { + ipc_client_log(client, "Invalid RFS header length: %u", + header->length); + goto error; + } + + ipc_rfs_message_setup(header, message); + + if (header->length > sizeof(struct ipc_rfs_header)) { + message->size = header->length - sizeof(struct ipc_rfs_header); + message->data = calloc(1, message->size); + + p = (unsigned char *) message->data; + + count = rc - sizeof(struct ipc_rfs_header); + if (count > 0) { + memcpy(p, + (void *) ((unsigned char *) buffer + + sizeof(struct ipc_rfs_header)), + count); + p += count; + } + + while (count < message->size) { + rc = client->handlers->read( + client, client->handlers->transport_data, p, + message->size - count); + if (rc <= 0) { + ipc_client_log(client, + "Reading RFS data failed"); + goto error; + } + + count += rc; + p += rc; + } + } + + ipc_client_log_recv(client, message, __func__); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_open( + __attribute__((unused)) struct ipc_client *client, int type) +{ + int fd; + + switch (type) { + case IPC_CLIENT_TYPE_FMT: + fd = open(XMM626_SEC_MODEM_IPC0_DEVICE, + O_RDWR | O_NOCTTY | O_NONBLOCK); + break; + case IPC_CLIENT_TYPE_RFS: + fd = open(XMM626_SEC_MODEM_RFS0_DEVICE, + O_RDWR | O_NOCTTY | O_NONBLOCK); + break; + default: + return -1; + } + + return fd; +} + +int xmm626_kernel_smdk4412_close( + __attribute__((unused)) struct ipc_client *client, int fd) +{ + if (fd < 0) + return -1; + + close(fd); + + return 0; +} + +int xmm626_kernel_smdk4412_read( + __attribute__((unused)) struct ipc_client *client, int fd, void *buffer, + size_t length) +{ + int status; + int rc; + + if (fd < 0 || buffer == NULL || length <= 0) + return -1; + + status = ioctl(fd, IOCTL_MODEM_STATUS, 0); + if (status != STATE_ONLINE && status != STATE_BOOTING) + return -1; + + rc = read(fd, buffer, length); + + return rc; +} + +int xmm626_kernel_smdk4412_write( + __attribute__((unused)) struct ipc_client *client, int fd, + const void *buffer, size_t length) +{ + int status; + int rc; + + if (fd < 0 || buffer == NULL || length <= 0) + return -1; + + status = ioctl(fd, IOCTL_MODEM_STATUS, 0); + if (status != STATE_ONLINE && status != STATE_BOOTING) + return -1; + + rc = write(fd, buffer, length); + + return rc; +} + +int xmm626_kernel_smdk4412_poll( + __attribute__((unused)) struct ipc_client *client, + int fd, struct ipc_poll_fds *fds, struct timeval *timeout) +{ + int status; + fd_set set; + int fd_max; + unsigned int i; + unsigned int count; + int rc; + + if (fd < 0) + return -1; + + FD_ZERO(&set); + FD_SET(fd, &set); + + fd_max = fd; + + if (fds != NULL && fds->fds != NULL && fds->count > 0) { + for (i = 0; i < fds->count; i++) { + if (fds->fds[i] >= 0) { + FD_SET(fds->fds[i], &set); + + if (fds->fds[i] > fd_max) + fd_max = fds->fds[i]; + } + } + } + + rc = select(fd_max + 1, &set, NULL, NULL, timeout); + + if (FD_ISSET(fd, &set)) { + status = ioctl(fd, IOCTL_MODEM_STATUS, 0); + if (status != STATE_ONLINE && status != STATE_BOOTING) + return -1; + } + + if (fds != NULL && fds->fds != NULL && fds->count > 0) { + count = fds->count; + + for (i = 0; i < fds->count; i++) { + if (!FD_ISSET(fds->fds[i], &set)) { + fds->fds[i] = -1; + count--; + } + } + + fds->count = count; + } + + return rc; +} + +char *xmm626_kernel_smdk4412_gprs_get_iface( + __attribute__((unused)) struct ipc_client *client, unsigned int cid) +{ + char *iface = NULL; + + if (cid > XMM626_SEC_MODEM_GPRS_IFACE_COUNT) + return NULL; + + asprintf(&iface, "%s%d", XMM626_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1); + + return iface; +} + +int xmm626_kernel_smdk4412_gprs_get_capabilities( + __attribute__((unused)) struct ipc_client *client, + struct ipc_client_gprs_capabilities *capabilities) +{ + if (capabilities == NULL) + return -1; + + capabilities->cid_count = XMM626_SEC_MODEM_GPRS_IFACE_COUNT; + + return 0; +} + +struct ipc_client_modem_driver_ops smdk4412_xmm626_modem_driver_ops = { +#if 0 + .download_enable = xmm626_kernel_smdk4412_boot_power, + .power = xmm626_kernel_smdk4412_power, + .bus_power = xmm626_kernel_smdk4412_hci_power, + .link_control_enable = xmm626_kernel_smdk4412_link_control_enable, + .link_control_active = xmm626_kernel_smdk4412_link_control_active, + .link_connected_wait = xmm626_kernel_smdk4412_link_connected_wait, + .link_get_hostwake_wait = xmm626_kernel_smdk4412_link_get_hostwake_wait, + .wait_status_online = xmm626_kernel_smdk4412_status_online_wait, + + .open = xmm626_kernel_smdk4412_open, + .close = xmm626_kernel_smdk4412_close, + .read = xmm626_kernel_smdk4412_read, + .write = xmm626_kernel_smdk4412_write, + .poll = xmm626_kernel_smdk4412_poll, + + .fmt_send = xmm626_kernel_smdk4412_fmt_send, + .fmt_recv = xmm626_kernel_smdk4412_fmt_recv, + .rfs_send = xmm626_kernel_smdk4412_rfs_send, + .rfs_recv = xmm626_kernel_smdk4412_rfs_recv, + + // TODO + // .gprs_get_iface = xmm626_kernel_smdk4412_gprs_get_iface, + // .modem_gprs_get_capabilities = xmm626_kernel_smdk4412_modem_gprs_get_capabilities, +#endif +}; diff --git a/samsung-ipc/modems/xmm626/hsic/xmm626_modem_link_device_hsic.h b/samsung-ipc/modems/xmm626/hsic/xmm626_modem_link_device_hsic.h new file mode 100644 index 0000000..f2421e0 --- /dev/null +++ b/samsung-ipc/modems/xmm626/hsic/xmm626_modem_link_device_hsic.h @@ -0,0 +1,63 @@ +/* + * 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_LINK_DEVICE_USB_H__ +#define __MODEM_LINK_DEVICE_USB_H__ + + +enum { + IF_USB_BOOT_EP = 0, + IF_USB_FMT_EP = 0, + IF_USB_RAW_EP, + IF_USB_RFS_EP, + IF_USB_CMD_EP, + IF_USB_DEVNUM_MAX, +}; + +/* each pipe has 2 ep for in/out */ +#define LINKPM_DEV_NUM (IF_USB_DEVNUM_MAX * 2) +/*******************/ +/* xmm626 specific */ + +#define IOCTL_LINK_CONTROL_ENABLE _IO('o', 0x30) +#define IOCTL_LINK_CONTROL_ACTIVE _IO('o', 0x31) +#define IOCTL_LINK_GET_HOSTWAKE _IO('o', 0x32) +#define IOCTL_LINK_CONNECTED _IO('o', 0x33) +#define IOCTL_LINK_SET_BIAS_CLEAR _IO('o', 0x34) + +/* VID,PID for IMC - XMM626, XMM6262*/ +#define IMC_BOOT_VID 0x058b +#define IMC_BOOT_PID 0x0041 +#define IMC_MAIN_VID 0x1519 +#define IMC_MAIN_PID 0x0020 +/* VID,PID for STE - M7400 */ +#define STE_BOOT_VID 0x04cc +#define STE_BOOT_PID 0x7400 +#define STE_MAIN_VID 0x04cc +#define STE_MAIN_PID 0x2333 + +enum { + BOOT_DOWN = 0, + IPC_CHANNEL +}; + +enum ch_state { + STATE_SUSPENDED, + STATE_RESUMED, +}; + +#define HOSTWAKE_TRIGLEVEL 0 + +#endif /* __MODEM_LINK_DEVICE_USB_H__ */ diff --git a/samsung-ipc/modems/xmm626/kernel_smdk4412.c b/samsung-ipc/modems/xmm626/kernel_smdk4412.c new file mode 100644 index 0000000..d9c7620 --- /dev/null +++ b/samsung-ipc/modems/xmm626/kernel_smdk4412.c @@ -0,0 +1,605 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2012 Alexander Tarasikov + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * 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 . + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "ipc.h" +#include "modems/xmm626/xmm626.h" +#include "modems/xmm626/xmm626_kernel_smdk4412.h" +#include "modems/xmm626/hsic/xmm626_modem_link_device_hsic.h" +#include "modems/xmm626/xmm626_modem_prj.h" + +int xmm626_kernel_smdk4412_power( + __attribute__((unused)) struct ipc_client *client, int device_fd, + int power) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, power ? IOCTL_MODEM_ON : IOCTL_MODEM_OFF, 0); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_boot_power( + __attribute__((unused)) struct ipc_client *client, int device_fd, + int power) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, power ? + IOCTL_MODEM_BOOT_ON : IOCTL_MODEM_BOOT_OFF, + 0); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_status_online_wait( + __attribute__((unused)) struct ipc_client *client, int device_fd) +{ + int status; + int i; + + if (device_fd < 0) + return -1; + + i = 0; + for (i = 0; i < 100; i++) { + status = ioctl(device_fd, IOCTL_MODEM_STATUS, 0); + if (status == STATE_ONLINE) + return 0; + + usleep(50000); + } + + return -1; +} + +int xmm626_kernel_smdk4412_hci_power( + __attribute__((unused)) struct ipc_client *client, int power) +{ + int ehci_rc, ohci_rc; + + ehci_rc = sysfs_value_write(XMM626_SEC_MODEM_EHCI_POWER_SYSFS, !!power); + if (ehci_rc >= 0) + usleep(50000); + + ohci_rc = sysfs_value_write(XMM626_SEC_MODEM_OHCI_POWER_SYSFS, !!power); + if (ohci_rc >= 0) + usleep(50000); + + if (ehci_rc < 0 && ohci_rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_link_control_enable( + __attribute__((unused)) struct ipc_client *client, + int device_fd, int enable) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ENABLE, &enable); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_link_control_active( + __attribute__((unused)) struct ipc_client *client, int device_fd, + int active) +{ + int rc; + + if (device_fd < 0) + return -1; + + rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ACTIVE, &active); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_kernel_smdk4412_link_connected_wait( + __attribute__((unused)) struct ipc_client *client, int device_fd) +{ + int status; + int i; + + if (device_fd < 0) + return -1; + + i = 0; + for (i = 0; i < 100; i++) { + status = ioctl(device_fd, IOCTL_LINK_CONNECTED, 0); + if (status) + return 0; + + usleep(50000); + } + + return -1; +} + +int xmm626_kernel_smdk4412_link_get_hostwake_wait( + __attribute__((unused)) struct ipc_client *client, int device_fd) +{ + int status; + int i; + + if (device_fd < 0) + return -1; + + i = 0; + for (i = 0; i < 10; i++) { + status = ioctl(device_fd, IOCTL_LINK_GET_HOSTWAKE, 0); + if (status) + return 0; + + usleep(50000); + } + + return -1; +} + +int xmm626_kernel_smdk4412_fmt_send(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_fmt_header header; + void *buffer; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->write == NULL || message == NULL) { + return -1; + } + + ipc_fmt_header_setup(&header, message); + + length = header.length; + buffer = calloc(1, length); + + memcpy(buffer, &header, sizeof(struct ipc_fmt_header)); + if (message->data != NULL && message->size > 0) { + memcpy((void *) ((unsigned char *) buffer + + sizeof(struct ipc_fmt_header)), + message->data, message->size); + } + + ipc_client_log_send(client, message, __func__); + + p = (unsigned char *) buffer; + + count = 0; + while (count < length) { + rc = client->handlers->write(client, + client->handlers->transport_data, + p, length - count); + if (rc <= 0) { + ipc_client_log(client, "Writing FMT data failed"); + goto error; + } + + count += rc; + p += rc; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_fmt_recv(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_fmt_header *header; + void *buffer = NULL; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->read == NULL || message == NULL) { + return -1; + } + + length = XMM626_DATA_SIZE; + buffer = calloc(1, length); + + rc = client->handlers->read(client, client->handlers->transport_data, + buffer, length); + if (rc < (int) sizeof(struct ipc_fmt_header)) { + ipc_client_log(client, "Reading FMT header failed"); + goto error; + } + + header = (struct ipc_fmt_header *) buffer; + + ipc_fmt_message_setup(header, message); + + if (header->length > sizeof(struct ipc_fmt_header)) { + message->size = header->length - sizeof(struct ipc_fmt_header); + message->data = calloc(1, message->size); + + p = (unsigned char *) message->data; + + count = rc - sizeof(struct ipc_fmt_header); + if (count > 0) { + memcpy(p, + (void *) ((unsigned char *) buffer + + sizeof(struct ipc_fmt_header)), + count); + p += count; + } + + while (count < message->size) { + rc = client->handlers->read( + client, client->handlers->transport_data, p, + message->size - count); + if (rc <= 0) { + ipc_client_log(client, + "Reading FMT data failed"); + goto error; + } + + count += rc; + p += rc; + } + } + + ipc_client_log_recv(client, message, __func__); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_rfs_send(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_rfs_header header; + void *buffer; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->write == NULL || message == NULL) { + return -1; + } + + ipc_rfs_header_setup(&header, message); + + length = header.length; + buffer = calloc(1, length); + + memcpy(buffer, &header, sizeof(struct ipc_rfs_header)); + if (message->data != NULL && message->size > 0) { + memcpy((void *) ( + (unsigned char *) buffer + + sizeof(struct ipc_rfs_header)), + message->data, + message->size); + } + + ipc_client_log_send(client, message, __func__); + + p = (unsigned char *) buffer; + + count = 0; + while (count < length) { + rc = client->handlers->write(client, + client->handlers->transport_data, + p, length - count); + if (rc <= 0) { + ipc_client_log(client, "Writing RFS data failed"); + goto error; + } + + count += rc; + p += rc; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_rfs_recv(struct ipc_client *client, + struct ipc_message *message) +{ + struct ipc_rfs_header *header; + void *buffer = NULL; + size_t length; + size_t count; + unsigned char *p; + int rc; + + if (client == NULL || client->handlers == NULL || + client->handlers->read == NULL || message == NULL) { + return -1; + } + + length = XMM626_DATA_SIZE; + buffer = calloc(1, length); + + rc = client->handlers->read(client, client->handlers->transport_data, + buffer, length); + if (rc < (int) sizeof(struct ipc_rfs_header)) { + ipc_client_log(client, "Reading RFS header failed"); + goto error; + } + + header = (struct ipc_rfs_header *) buffer; + if (header->length > XMM626_DATA_SIZE_LIMIT) { + ipc_client_log(client, "Invalid RFS header length: %u", + header->length); + goto error; + } + + ipc_rfs_message_setup(header, message); + + if (header->length > sizeof(struct ipc_rfs_header)) { + message->size = header->length - sizeof(struct ipc_rfs_header); + message->data = calloc(1, message->size); + + p = (unsigned char *) message->data; + + count = rc - sizeof(struct ipc_rfs_header); + if (count > 0) { + memcpy(p, + (void *) ((unsigned char *) buffer + + sizeof(struct ipc_rfs_header)), + count); + p += count; + } + + while (count < message->size) { + rc = client->handlers->read( + client, client->handlers->transport_data, p, + message->size - count); + if (rc <= 0) { + ipc_client_log(client, + "Reading RFS data failed"); + goto error; + } + + count += rc; + p += rc; + } + } + + ipc_client_log_recv(client, message, __func__); + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_kernel_smdk4412_open( + __attribute__((unused)) struct ipc_client *client, int type) +{ + int fd; + + switch (type) { + case IPC_CLIENT_TYPE_FMT: + fd = open(XMM626_SEC_MODEM_IPC0_DEVICE, + O_RDWR | O_NOCTTY | O_NONBLOCK); + break; + case IPC_CLIENT_TYPE_RFS: + fd = open(XMM626_SEC_MODEM_RFS0_DEVICE, + O_RDWR | O_NOCTTY | O_NONBLOCK); + break; + default: + return -1; + } + + return fd; +} + +int xmm626_kernel_smdk4412_close( + __attribute__((unused)) struct ipc_client *client, int fd) +{ + if (fd < 0) + return -1; + + close(fd); + + return 0; +} + +int xmm626_kernel_smdk4412_read( + __attribute__((unused)) struct ipc_client *client, int fd, void *buffer, + size_t length) +{ + int status; + int rc; + + if (fd < 0 || buffer == NULL || length <= 0) + return -1; + + status = ioctl(fd, IOCTL_MODEM_STATUS, 0); + if (status != STATE_ONLINE && status != STATE_BOOTING) + return -1; + + rc = read(fd, buffer, length); + + return rc; +} + +int xmm626_kernel_smdk4412_write( + __attribute__((unused)) struct ipc_client *client, int fd, + const void *buffer, size_t length) +{ + int status; + int rc; + + if (fd < 0 || buffer == NULL || length <= 0) + return -1; + + status = ioctl(fd, IOCTL_MODEM_STATUS, 0); + if (status != STATE_ONLINE && status != STATE_BOOTING) + return -1; + + rc = write(fd, buffer, length); + + return rc; +} + +int xmm626_kernel_smdk4412_poll( + __attribute__((unused)) struct ipc_client *client, + int fd, struct ipc_poll_fds *fds, struct timeval *timeout) +{ + int status; + fd_set set; + int fd_max; + unsigned int i; + unsigned int count; + int rc; + + if (fd < 0) + return -1; + + FD_ZERO(&set); + FD_SET(fd, &set); + + fd_max = fd; + + if (fds != NULL && fds->fds != NULL && fds->count > 0) { + for (i = 0; i < fds->count; i++) { + if (fds->fds[i] >= 0) { + FD_SET(fds->fds[i], &set); + + if (fds->fds[i] > fd_max) + fd_max = fds->fds[i]; + } + } + } + + rc = select(fd_max + 1, &set, NULL, NULL, timeout); + + if (FD_ISSET(fd, &set)) { + status = ioctl(fd, IOCTL_MODEM_STATUS, 0); + if (status != STATE_ONLINE && status != STATE_BOOTING) + return -1; + } + + if (fds != NULL && fds->fds != NULL && fds->count > 0) { + count = fds->count; + + for (i = 0; i < fds->count; i++) { + if (!FD_ISSET(fds->fds[i], &set)) { + fds->fds[i] = -1; + count--; + } + } + + fds->count = count; + } + + return rc; +} + +char *xmm626_kernel_smdk4412_gprs_get_iface( + __attribute__((unused)) struct ipc_client *client, unsigned int cid) +{ + char *iface = NULL; + + if (cid > XMM626_SEC_MODEM_GPRS_IFACE_COUNT) + return NULL; + + asprintf(&iface, "%s%d", XMM626_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1); + + return iface; +} + +int xmm626_kernel_smdk4412_gprs_get_capabilities( + __attribute__((unused)) struct ipc_client *client, + struct ipc_client_gprs_capabilities *capabilities) +{ + if (capabilities == NULL) + return -1; + + capabilities->cid_count = XMM626_SEC_MODEM_GPRS_IFACE_COUNT; + + return 0; +} + diff --git a/samsung-ipc/modems/xmm626/mipi/mipi.c b/samsung-ipc/modems/xmm626/mipi/mipi.c new file mode 100644 index 0000000..c356d5a --- /dev/null +++ b/samsung-ipc/modems/xmm626/mipi/mipi.c @@ -0,0 +1,646 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2012 Alexander Tarasikov + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * Based on the incomplete C++ implementation which is: + * Copyright (C) 2012 Sergey Gridasov + * + * 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 . + */ + +#include +#include +#include +#include +#include + +#include + +#include "ipc.h" +#include "modems/xmm626/xmm626.h" +#include "modems/xmm626/xmm626_kernel_smdk4412.h" +#include "modems/xmm626/mipi/xmm626_mipi.h" + +int xmm626_mipi_crc_calculate(const void *data, size_t size) +{ + unsigned char crc; + int mipi_crc; + + crc = xmm626_crc_calculate(data, size); + mipi_crc = (crc << 24) | 0xffffff; + + return mipi_crc; +} + +int xmm626_mipi_ack_read(int device_fd, unsigned short ack) +{ + struct timeval timeout; + fd_set fds; + unsigned int value; + int rc; + int i; + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(device_fd, &fds); + + for (i = 0; i < 50; i++) { + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + return -1; + + value = 0; + rc = read(device_fd, &value, sizeof(value)); + if (rc < (int) sizeof(value)) + continue; + + if ((value & 0xffff) == ack) + return 0; + } + + return -1; +} + +int xmm626_mipi_psi_send(struct ipc_client *client, int device_fd, + const void *psi_data, unsigned short psi_size) +{ + struct xmm626_mipi_psi_header psi_header; + char at[] = XMM626_AT; + int psi_crc; + struct timeval timeout; + fd_set fds; + size_t wc; + size_t length; + unsigned char *p; + int rc; + int i; + + if (client == NULL || device_fd < 0 || psi_data == NULL || + psi_size == 0) { + return -1; + } + + FD_ZERO(&fds); + + i = 0; + length = strlen(at); + + do { + FD_SET(device_fd, &fds); + + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + + rc = write(device_fd, at, length); + if (rc < (int) length) { + ipc_client_log(client, "Writing ATAT in ASCII failed"); + goto error; + } + ipc_client_log(client, "Wrote ATAT in ASCII"); + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc < 0) { + ipc_client_log(client, "Waiting for bootup failed"); + goto error; + } + + if (i++ > 50) { + ipc_client_log(client, "Waiting for bootup failed"); + goto error; + } + } while (rc == 0); + + rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_BOOT0_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading boot ACK failed"); + goto error; + } + + psi_header.padding = XMM626_PSI_PADDING; + psi_header.length = ((psi_size >> 8) & 0xff) | ((psi_size & 0xff) << 8); + psi_header.magic = XMM626_PSI_MAGIC; + + rc = write(device_fd, &psi_header, sizeof(psi_header)); + if (rc < (int) sizeof(psi_header)) { + ipc_client_log(client, "Writing PSI header failed"); + goto error; + } + ipc_client_log(client, "Wrote PSI header"); + + p = (unsigned char *) psi_data; + + wc = 0; + while (wc < psi_size) { + rc = write(device_fd, (void *) p, psi_size - wc); + if (rc <= 0) { + ipc_client_log(client, "Writing PSI failed"); + goto error; + } + + p += rc; + wc += rc; + } + + psi_crc = xmm626_mipi_crc_calculate(psi_data, psi_size); + + ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc); + + rc = write(device_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); + + rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_PSI_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading PSI ACK failed"); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int xmm626_mipi_ebl_send(struct ipc_client *client, int device_fd, + const void *ebl_data, size_t ebl_size) +{ + unsigned short boot_magic[4]; + unsigned char ebl_crc; + size_t chunk; + size_t count; + size_t wc; + size_t size; + size_t length; + unsigned char *p; + int rc; + + if (client == NULL || device_fd < 0 || ebl_data == NULL || + ebl_size == 0) { + return -1; + } + + boot_magic[0] = 0; + boot_magic[1] = 0; + boot_magic[2] = XMM626_MIPI_BOOT1_MAGIC; + boot_magic[3] = XMM626_MIPI_BOOT1_MAGIC; + + length = sizeof(boot_magic); + + rc = write(device_fd, &length, sizeof(length)); + if (rc < (int) sizeof(length)) { + ipc_client_log(client, "Writing boot magic length failed"); + goto error; + } + + rc = write(device_fd, &boot_magic, length); + if (rc < (int) length) { + ipc_client_log(client, "Writing boot magic failed"); + goto error; + } + ipc_client_log(client, "Wrote boot magic"); + + rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_BOOT1_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading boot magic ACK failed"); + goto error; + } + + size = sizeof(ebl_size); + + rc = write(device_fd, &size, sizeof(size)); + if (rc < (int) sizeof(size)) { + ipc_client_log(client, "Writing EBL size length failed"); + goto error; + } + + rc = write(device_fd, &ebl_size, size); + if (rc < (int) size) { + ipc_client_log(client, "Writing EBL size failed"); + goto error; + } + ipc_client_log(client, "Wrote EBL size"); + + rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_EBL_SIZE_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading EBL size ACK failed"); + goto error; + } + + ebl_size++; + + rc = write(device_fd, &ebl_size, size); + if (rc < (int) size) { + ipc_client_log(client, "Writing EBL size failed"); + goto error; + } + + ebl_size--; + + p = (unsigned char *) ebl_data; + + chunk = XMM626_MIPI_EBL_CHUNK; + wc = 0; + while (wc < ebl_size) { + count = chunk < ebl_size - wc ? chunk : ebl_size - wc; + + rc = write(device_fd, (void *) p, count); + if (rc <= 0) { + ipc_client_log(client, "Writing EBL failed"); + goto error; + } + + p += rc; + wc += rc; + } + + ebl_crc = xmm626_crc_calculate(ebl_data, ebl_size); + + ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc); + + rc = write(device_fd, &ebl_crc, sizeof(ebl_crc)); + if (rc < (int) sizeof(ebl_crc)) { + ipc_client_log(client, "Writing EBL CRC failed"); + goto error; + } + ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc); + + rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_EBL_ACK); + if (rc < 0) { + ipc_client_log(client, "Reading EBL ACK failed"); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int xmm626_mipi_command_send(int device_fd, unsigned short code, + const void *data, size_t size, int ack, + int short_footer) +{ + struct xmm626_mipi_command_header header; + struct xmm626_mipi_command_footer footer; + void *buffer = NULL; + size_t length; + size_t footer_length; + struct timeval timeout; + fd_set fds; + size_t chunk; + size_t c; + unsigned char *p; + int rc; + int i; + + if (device_fd < 0 || data == NULL || size <= 0) + return -1; + + header.size = size + sizeof(header); + header.magic = XMM626_MIPI_COMMAND_HEADER_MAGIC; + header.code = code; + header.data_size = size; + + footer.checksum = (size & 0xffff) + code; + footer.magic = XMM626_MIPI_COMMAND_FOOTER_MAGIC; + footer.unknown = XMM626_MIPI_COMMAND_FOOTER_UNKNOWN; + + p = (unsigned char *) data; + + for (i = 0; i < (int) size; i++) + footer.checksum += *p++; + + footer_length = sizeof(footer); + if (short_footer) + footer_length -= sizeof(short); + + length = sizeof(header) + size + footer_length; + buffer = calloc(1, length); + + p = (unsigned char *) buffer; + memcpy(p, &header, sizeof(header)); + p += sizeof(header); + memcpy(p, data, size); + p += size; + memcpy(p, &footer, footer_length); + + rc = write(device_fd, buffer, length); + if (rc < (int) length) + goto error; + + free(buffer); + buffer = NULL; + + if (!ack) { + rc = 0; + goto complete; + } + + FD_ZERO(&fds); + FD_SET(device_fd, &fds); + + timeout.tv_sec = 1; + timeout.tv_usec = 0; + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + rc = read(device_fd, &length, sizeof(length)); + if (rc < (int) sizeof(length) || length <= 0) + goto error; + + length += sizeof(unsigned int); + if (length % 4 != 0) + length += length % 4; + + if (length < (int) sizeof(buffer)) + goto error; + + buffer = calloc(1, length); + + p = (unsigned char *) buffer; + memcpy(p, &length, sizeof(length)); + p += sizeof(length); + + chunk = 4; + c = sizeof(length); + while (c < length) { + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + rc = read(device_fd, (void *) p, chunk); + if (rc < (int) chunk) + goto error; + + p += rc; + c += rc; + } + + memcpy(&header, buffer, sizeof(header)); + if (header.code != code) + goto error; + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_mipi_modem_data_send(struct ipc_client *client, int device_fd, + const void *data, size_t size, int address) +{ + size_t chunk; + size_t count; + size_t c; + unsigned char *p; + int rc; + + if (device_fd < 0 || data == NULL || size == 0) + return -1; + + rc = xmm626_mipi_command_send(device_fd, + XMM626_COMMAND_FLASH_SET_ADDRESS, + &address, sizeof(address), 1, 0); + if (rc < 0) + goto error; + + p = (unsigned char *) data; + + chunk = XMM626_MIPI_MODEM_DATA_CHUNK; + c = 0; + while (c < size) { + count = chunk < size - c ? chunk : size - c; + + rc = xmm626_mipi_command_send(device_fd, + XMM626_COMMAND_FLASH_WRITE_BLOCK, + p, count, 1, 1); + if (rc < 0) + goto error; + + p += count; + c += count; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + return rc; +} + +int xmm626_mipi_port_config_send(struct ipc_client *client, int device_fd) +{ + void *buffer = NULL; + size_t length; + struct timeval timeout; + fd_set fds; + size_t chunk; + size_t count; + size_t c; + unsigned char *p; + int rc; + + if (client == NULL || device_fd < 0) + return -1; + + FD_ZERO(&fds); + FD_SET(device_fd, &fds); + + timeout.tv_sec = 2; + timeout.tv_usec = 0; + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + rc = read(device_fd, &length, sizeof(length)); + if (rc < (int) sizeof(length) || length == 0) { + ipc_client_log(client, "Reading port config length failed"); + goto error; + } + ipc_client_log(client, "Read port config length (0x%x)", length); + + buffer = calloc(1, length); + + p = (unsigned char *) buffer; + + chunk = 4; + c = 0; + while (c < length) { + count = chunk < length - c ? chunk : length - c; + + rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); + if (rc <= 0) + goto error; + + rc = read(device_fd, p, count); + if (rc < (int) count) { + ipc_client_log(client, "Reading port config failed"); + goto error; + } + + p += count; + c += count; + } + ipc_client_log(client, "Read port config"); + + rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_SET_PORT_CONFIG, + buffer, length, 1, 0); + if (rc < 0) { + ipc_client_log(client, "Sending port config command failed"); + goto error; + } + + rc = 0; + goto complete; + +error: + rc = -1; + +complete: + if (buffer != NULL) + free(buffer); + + return rc; +} + +int xmm626_mipi_sec_start_send(struct ipc_client *client, int device_fd, + const void *sec_data, size_t sec_size) +{ + int rc; + + if (client == NULL || device_fd < 0 || sec_data == NULL || + sec_size == 0) { + return -1; + } + + rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_SEC_START, + sec_data, sec_size, 1, 0); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_mipi_sec_end_send(struct ipc_client *client, int device_fd) +{ + unsigned short sec_data; + size_t sec_size; + int rc; + + if (client == NULL || device_fd < 0) + return -1; + + sec_data = XMM626_SEC_END_MAGIC; + sec_size = sizeof(sec_data); + + rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_SEC_END, + &sec_data, sec_size, 1, 1); + if (rc < 0) + return -1; + + return 0; +} + + +int xmm626_mipi_mps_data_send(struct ipc_client *client, int device_fd, + const void *mps_data, size_t mps_size) +{ + int rc; + + if (client == NULL || device_fd < 0 || mps_data == NULL || + mps_size == 0) { + return -1; + } + + rc = xmm626_mipi_modem_data_send(client, device_fd, mps_data, mps_size, + XMM626_MPS_DATA_ADDRESS); + if (rc < 0) + return -1; + + return 0; +} + +int xmm626_mipi_hw_reset_send(struct ipc_client *client, int device_fd) +{ + unsigned int hw_reset_data; + size_t hw_reset_size; + int rc; + + if (client == NULL || device_fd < 0) + return -1; + + hw_reset_data = XMM626_HW_RESET_MAGIC; + hw_reset_size = sizeof(hw_reset_data); + + rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_HW_RESET, + &hw_reset_data, hw_reset_size, 0, 1); + if (rc < 0) + return -1; + + return 0; +} + +struct ipc_client_modem_driver_ops smdk4412_xmm626_mipi_modem_driver_ops = { + .download_enable = xmm626_kernel_smdk4412_boot_power, //TODO + .power = xmm626_kernel_smdk4412_power, //TODO + .bus_power = xmm626_kernel_smdk4412_hci_power, //TODO + .link_control_enable = xmm626_kernel_smdk4412_link_control_enable, //TODO + .link_control_active = xmm626_kernel_smdk4412_link_control_active, //TODO + .link_connected_wait = xmm626_kernel_smdk4412_link_connected_wait, //TODO + .link_get_hostwake_wait = xmm626_kernel_smdk4412_link_get_hostwake_wait, //TODO + .wait_status_online = xmm626_kernel_smdk4412_status_online_wait, //TODO + + .open = xmm626_kernel_smdk4412_open, //TODO + .close = xmm626_kernel_smdk4412_close, //TODO + .read = xmm626_kernel_smdk4412_read, //TODO + .write = xmm626_kernel_smdk4412_write, //TODO + .poll = xmm626_kernel_smdk4412_poll, //TODO + + .fmt_send = xmm626_kernel_smdk4412_fmt_send, //TODO + .fmt_recv = xmm626_kernel_smdk4412_fmt_recv, //TODO + .rfs_send = xmm626_kernel_smdk4412_rfs_send, //TODO + .rfs_recv = xmm626_kernel_smdk4412_rfs_recv, //TODO + .data_send = xmm626_mipi_modem_data_send, + + // .gprs_get_iface = xmm626_kernel_smdk4412_gprs_get_iface, + // .modem_gprs_get_capabilities = xmm626_kernel_smdk4412_modem_gprs_get_capabilities, +}; diff --git a/samsung-ipc/modems/xmm626/mipi/xmm626_mipi.h b/samsung-ipc/modems/xmm626/mipi/xmm626_mipi.h new file mode 100644 index 0000000..67b35ba --- /dev/null +++ b/samsung-ipc/modems/xmm626/mipi/xmm626_mipi.h @@ -0,0 +1,73 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2012 Alexander Tarasikov + * Copyright (C) 2013-2014 Paul Kocialkowski + * + * 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 . + */ + +#ifndef __XMM626_MIPI_H__ +#define __XMM626_MIPI_H__ + +#define XMM626_MIPI_BOOT0_ACK 0xFFFF +#define XMM626_MIPI_BOOT1_MAGIC 0x02 +#define XMM626_MIPI_BOOT1_ACK 0xAA00 +#define XMM626_MIPI_PSI_ACK 0xDD01 +#define XMM626_MIPI_EBL_SIZE_ACK 0xCCCC +#define XMM626_MIPI_EBL_ACK 0xA551 +#define XMM626_MIPI_EBL_CHUNK 0xDFC +#define XMM626_MIPI_MODEM_DATA_CHUNK 0xDF2 +#define XMM626_MIPI_COMMAND_HEADER_MAGIC 0x02 +#define XMM626_MIPI_COMMAND_FOOTER_MAGIC 0x03 +#define XMM626_MIPI_COMMAND_FOOTER_UNKNOWN 0xEAEA + +struct xmm626_mipi_psi_header { + unsigned char padding; + unsigned short length; + unsigned char magic; +} __attribute__((packed)); + +struct xmm626_mipi_command_header { + unsigned int size; + unsigned short magic; + unsigned short code; + unsigned short data_size; +} __attribute__((packed)); + +struct xmm626_mipi_command_footer { + unsigned short checksum; + unsigned short magic; + unsigned short unknown; +} __attribute__((packed)); + +int xmm626_mipi_psi_send(struct ipc_client *client, int device_fd, + const void *psi_data, unsigned short psi_size); +int xmm626_mipi_ebl_send(struct ipc_client *client, int device_fd, + const void *ebl_data, size_t ebl_size); + +int xmm626_mipi_port_config_send(struct ipc_client *client, int device_fd); +int xmm626_mipi_sec_start_send(struct ipc_client *client, int device_fd, + const void *sec_data, size_t sec_size); +int xmm626_mipi_sec_end_send(struct ipc_client *client, int device_fd); +int xmm626_mipi_firmware_send(struct ipc_client *client, int device_fd, + const void *firmware_data, size_t firmware_size); +int xmm626_mipi_nv_data_send(struct ipc_client *client, int device_fd); +int xmm626_mipi_mps_data_send(struct ipc_client *client, int device_fd, + const void *mps_data, size_t mps_size); +int xmm626_mipi_hw_reset_send(struct ipc_client *client, int device_fd); +int xmm626_mipi_modem_data_send(struct ipc_client *client, int device_fd, + const void *data, size_t size, int address); + +#endif /* __XMM626_MIPI_H__ */ diff --git a/samsung-ipc/modems/xmm626/xmm626_hsic.c b/samsung-ipc/modems/xmm626/xmm626_hsic.c deleted file mode 100644 index 6e7126c..0000000 --- a/samsung-ipc/modems/xmm626/xmm626_hsic.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2012 Alexander Tarasikov - * Copyright (C) 2013-2014 Paul Kocialkowski - * - * Based on the incomplete C++ implementation which is: - * Copyright (C) 2012 Sergey Gridasov - * - * 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 . - */ - -#include -#include -#include -#include -#include - -#include - -#include "modems/xmm626/xmm626.h" -#include "modems/xmm626/xmm626_hsic.h" - -int xmm626_hsic_ack_read(int device_fd, unsigned short ack) -{ - struct timeval timeout; - fd_set fds; - unsigned short value; - int rc; - int i; - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - FD_ZERO(&fds); - FD_SET(device_fd, &fds); - - for (i = 0; i < 50; i++) { - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - return -1; - - value = 0; - rc = read(device_fd, &value, sizeof(value)); - if (rc < (int) sizeof(value)) - continue; - - if (value == ack) - return 0; - } - - return -1; -} - -int xmm626_hsic_psi_send(struct ipc_client *client, int device_fd, - const void *psi_data, unsigned short psi_size) -{ - struct xmm626_hsic_psi_header psi_header; - char at[] = XMM626_AT; - unsigned char psi_ack; - unsigned char chip_id; - unsigned char psi_crc; - struct timeval timeout; - fd_set fds; - size_t wc; - size_t length; - unsigned char *p; - int rc; - int i; - - if (client == NULL || device_fd < 0 || psi_data == NULL || - psi_size == 0) { - return -1; - } - - FD_ZERO(&fds); - - i = 0; - length = strlen(at); - - do { - FD_SET(device_fd, &fds); - - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - - rc = write(device_fd, at, length); - if (rc < (int) length) { - ipc_client_log(client, "Writing ATAT in ASCII failed"); - goto error; - } - ipc_client_log(client, "Wrote ATAT in ASCII"); - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc < 0) { - ipc_client_log(client, "Waiting for bootup failed"); - goto error; - } - - if (i++ > 50) { - ipc_client_log(client, "Waiting for bootup failed"); - goto error; - } - } while (rc == 0); - - FD_SET(device_fd, &fds); - - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) { - ipc_client_log(client, "Reading boot ACK failed"); - goto error; - } - - psi_ack = 0; - rc = read(device_fd, &psi_ack, sizeof(psi_ack)); - if (rc < (int) sizeof(psi_ack)) { - ipc_client_log(client, "Reading boot ACK failed"); - goto error; - } - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) { - ipc_client_log(client, "Reading chip id failed"); - goto error; - } - - chip_id = 0; - rc = read(device_fd, &chip_id, sizeof(chip_id)); - if (rc < (int) sizeof(chip_id)) { - ipc_client_log(client, "Reading chip id failed"); - goto error; - } - ipc_client_log(client, "Read chip id (0x%x)", chip_id); - - psi_header.magic = XMM626_PSI_MAGIC; - psi_header.length = psi_size; - psi_header.padding = XMM626_PSI_PADDING; - - rc = write(device_fd, &psi_header, sizeof(psi_header)); - if (rc < (int) sizeof(psi_header)) { - ipc_client_log(client, "Writing PSI header failed"); - goto error; - } - ipc_client_log(client, "Wrote PSI header"); - - p = (unsigned char *) psi_data; - - wc = 0; - while (wc < psi_size) { - rc = write(device_fd, (void *) p, psi_size - wc); - if (rc <= 0) { - ipc_client_log(client, "Writing PSI failed"); - goto error; - } - - p += rc; - wc += rc; - } - - psi_crc = xmm626_crc_calculate(psi_data, psi_size); - - ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc); - - rc = write(device_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 = 0; - timeout.tv_usec = 100000; - - for (i = 0; i < XMM626_HSIC_PSI_UNKNOWN_COUNT; i++) { - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) { - ipc_client_log(client, "Reading PSI unknown failed"); - goto error; - } - - rc = read(device_fd, &psi_ack, sizeof(psi_ack)); - if (rc < (int) sizeof(psi_ack)) { - ipc_client_log(client, "Reading PSI unknown failed"); - goto error; - } - } - - for (i = 0; i < XMM626_HSIC_PSI_CRC_ACK_COUNT ; i++) { - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) { - ipc_client_log(client, "Reading PSI CRC ACK failed"); - goto error; - } - - rc = read(device_fd, &psi_ack, sizeof(psi_ack)); - if (rc < (int) sizeof(psi_ack)) { - ipc_client_log(client, "Reading PSI CRC ACK failed"); - goto error; - } - } - ipc_client_log(client, "Read PSI CRC ACK"); - - rc = xmm626_hsic_ack_read(device_fd, XMM626_HSIC_PSI_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading PSI ACK failed"); - goto error; - } - ipc_client_log(client, "Read PSI ACK"); - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -int xmm626_hsic_ebl_send(struct ipc_client *client, int device_fd, - const void *ebl_data, size_t ebl_size) -{ - unsigned char ebl_crc; - size_t chunk; - size_t count; - size_t wc; - size_t size; - unsigned char *p; - int rc; - - if (client == NULL || device_fd < 0 || ebl_data == NULL || - ebl_size == 0) { - return -1; - } - - size = sizeof(ebl_size); - - rc = write(device_fd, &ebl_size, size); - if (rc < (int) size) { - ipc_client_log(client, "Writing EBL size failed"); - goto error; - } - ipc_client_log(client, "Wrote EBL size"); - - rc = xmm626_hsic_ack_read(device_fd, XMM626_HSIC_EBL_SIZE_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading EBL size ACK failed"); - goto error; - } - - p = (unsigned char *) ebl_data; - - chunk = XMM626_HSIC_EBL_CHUNK; - wc = 0; - while (wc < ebl_size) { - count = chunk < ebl_size - wc ? chunk : ebl_size - wc; - - rc = write(device_fd, (void *) p, count); - if (rc <= 0) { - ipc_client_log(client, "Writing EBL failed"); - goto error; - } - - p += rc; - wc += rc; - } - - ebl_crc = xmm626_crc_calculate(ebl_data, ebl_size); - - ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc); - - rc = write(device_fd, &ebl_crc, sizeof(ebl_crc)); - if (rc < (int) sizeof(ebl_crc)) { - ipc_client_log(client, "Writing EBL CRC failed"); - goto error; - } - ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc); - - rc = xmm626_hsic_ack_read(device_fd, XMM626_HSIC_EBL_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading EBL ACK failed"); - goto error; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -int xmm626_hsic_command_send(int device_fd, unsigned short code, - const void *data, size_t size, - size_t command_data_size, int ack) -{ - struct xmm626_hsic_command_header header; - void *buffer = NULL; - size_t length; - struct timeval timeout; - fd_set fds; - unsigned char *p; - int rc; - int i; - - if (device_fd < 0 || data == NULL || size == 0 || - command_data_size == 0 || command_data_size < size) { - return -1; - } - - header.checksum = (size & 0xffff) + code; - header.code = code; - header.data_size = size; - - p = (unsigned char *) data; - - for (i = 0; i < (int) size; i++) - header.checksum += *p++; - - length = command_data_size + sizeof(header); - buffer = calloc(1, length); - - memset(buffer, 0, length); - p = (unsigned char *) buffer; - memcpy(p, &header, sizeof(header)); - p += sizeof(header); - memcpy(p, data, size); - - rc = write(device_fd, buffer, length); - if (rc < (int) length) - goto error; - - if (!ack) { - rc = 0; - goto complete; - } - - memset(buffer, 0, length); - - FD_ZERO(&fds); - FD_SET(device_fd, &fds); - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - rc = read(device_fd, &header, sizeof(header)); - if (rc < (int) sizeof(header)) - goto error; - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - rc = read(device_fd, buffer, command_data_size); - if (rc < (int) command_data_size) - goto error; - - if (header.code != code) - goto error; - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_hsic_modem_data_send(int device_fd, const void *data, size_t size, - int address) -{ - size_t chunk; - size_t count; - size_t c; - unsigned char *p; - int rc; - - if (device_fd < 0 || data == NULL || size == 0) - return -1; - - rc = xmm626_hsic_command_send(device_fd, - XMM626_COMMAND_FLASH_SET_ADDRESS, - &address, sizeof(address), - XMM626_HSIC_FLASH_SET_ADDRESS_SIZE, 1); - if (rc < 0) - goto error; - - p = (unsigned char *) data; - - chunk = XMM626_HSIC_MODEM_DATA_CHUNK; - c = 0; - while (c < size) { - count = chunk < size - c ? chunk : size - c; - - rc = xmm626_hsic_command_send( - device_fd, XMM626_COMMAND_FLASH_WRITE_BLOCK, - p, count, XMM626_HSIC_FLASH_WRITE_BLOCK_SIZE, 0); - if (rc < 0) - goto error; - - p += count; - c += count; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -int xmm626_hsic_port_config_send(struct ipc_client *client, int device_fd) -{ - void *buffer = NULL; - size_t length; - struct timeval timeout; - fd_set fds; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - FD_ZERO(&fds); - FD_SET(device_fd, &fds); - - timeout.tv_sec = 2; - timeout.tv_usec = 0; - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - length = XMM626_HSIC_PORT_CONFIG_SIZE; - buffer = calloc(1, length); - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - rc = read(device_fd, buffer, length); - if (rc < (int) length) { - ipc_client_log(client, "Reading port config failed"); - goto error; - } - ipc_client_log(client, "Read port config"); - - rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_SET_PORT_CONFIG, - buffer, length, - XMM626_HSIC_SET_PORT_CONFIG_SIZE, 1); - if (rc < 0) { - ipc_client_log(client, "Sending port config command failed"); - goto error; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_hsic_sec_start_send(struct ipc_client *client, int device_fd, - const void *sec_data, size_t sec_size) -{ - int rc; - - if (client == NULL || device_fd < 0 || sec_data == NULL || - sec_size == 0) { - return -1; - } - - rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_SEC_START, - sec_data, sec_size, - XMM626_HSIC_SEC_START_SIZE, 1); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_hsic_sec_end_send(struct ipc_client *client, int device_fd) -{ - unsigned short sec_data; - size_t sec_size; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - sec_data = XMM626_SEC_END_MAGIC; - sec_size = sizeof(sec_data); - - rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_SEC_END, - &sec_data, sec_size, - XMM626_HSIC_SEC_END_SIZE, 1); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_hsic_firmware_send(struct ipc_client *client, int device_fd, - const void *firmware_data, size_t firmware_size) -{ - int rc; - - if (client == NULL || device_fd < 0 || firmware_data == NULL || - firmware_size == 0) { - return -1; - } - - rc = xmm626_hsic_modem_data_send(device_fd, firmware_data, - firmware_size, - XMM626_FIRMWARE_ADDRESS); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_hsic_nv_data_send(struct ipc_client *client, int device_fd) -{ - void *nv_data = NULL; - size_t nv_size; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - nv_size = ipc_client_nv_data_size(client); - if (nv_size == 0) - return -1; - - nv_data = ipc_nv_data_load(client); - if (nv_data == NULL) { - ipc_client_log(client, "Loading nv_data failed"); - goto error; - } - ipc_client_log(client, "Loaded nv_data"); - - rc = xmm626_hsic_modem_data_send(device_fd, nv_data, nv_size, - XMM626_NV_DATA_ADDRESS); - if (rc < 0) - goto error; - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (nv_data != NULL) - free(nv_data); - - return rc; -} - -int xmm626_hsic_hw_reset_send(struct ipc_client *client, int device_fd) -{ - unsigned int hw_reset_data; - int hw_reset_size; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - hw_reset_data = XMM626_HW_RESET_MAGIC; - hw_reset_size = sizeof(hw_reset_data); - - rc = xmm626_hsic_command_send(device_fd, XMM626_COMMAND_HW_RESET, - &hw_reset_data, hw_reset_size, - XMM626_HSIC_HW_RESET_SIZE, 0); - if (rc < 0) - return -1; - - return 0; -} diff --git a/samsung-ipc/modems/xmm626/xmm626_hsic.h b/samsung-ipc/modems/xmm626/xmm626_hsic.h deleted file mode 100644 index 6385cdc..0000000 --- a/samsung-ipc/modems/xmm626/xmm626_hsic.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2012 Alexander Tarasikov - * Copyright (C) 2013-2014 Paul Kocialkowski - * - * 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 . - */ - -#ifndef __XMM626_HSIC_H__ -#define __XMM626_HSIC_H__ - -#define XMM626_HSIC_BOOT0_ACK 0xF0 -#define XMM626_HSIC_PSI_UNKNOWN_COUNT 22 -#define XMM626_HSIC_PSI_CRC_ACK 0x01 -#define XMM626_HSIC_PSI_CRC_ACK_COUNT 2 -#define XMM626_HSIC_PSI_ACK 0xAA00 -#define XMM626_HSIC_EBL_SIZE_ACK 0xCCCC -#define XMM626_HSIC_EBL_ACK 0xA551 -#define XMM626_HSIC_EBL_CHUNK 0x4000 -#define XMM626_HSIC_PORT_CONFIG_SIZE 0x4C -#define XMM626_HSIC_SET_PORT_CONFIG_SIZE 0x800 -#define XMM626_HSIC_SEC_START_SIZE 0x4000 -#define XMM626_HSIC_SEC_END_SIZE 0x4000 -#define XMM626_HSIC_HW_RESET_SIZE 0x4000 -#define XMM626_HSIC_FLASH_SET_ADDRESS_SIZE 0x4000 -#define XMM626_HSIC_FLASH_WRITE_BLOCK_SIZE 0x4000 -#define XMM626_HSIC_MODEM_DATA_CHUNK 0x4000 - -struct xmm626_hsic_psi_header { - unsigned char magic; - unsigned short length; - unsigned char padding; -} __attribute__((packed)); - -struct xmm626_hsic_command_header { - unsigned short checksum; - unsigned short code; - unsigned int data_size; -} __attribute__((packed)); - -int xmm626_hsic_psi_send(struct ipc_client *client, int device_fd, - const void *psi_data, unsigned short psi_size); -int xmm626_hsic_ebl_send(struct ipc_client *client, int device_fd, - const void *ebl_data, size_t ebl_size); - -int xmm626_hsic_port_config_send(struct ipc_client *client, int device_fd); -int xmm626_hsic_sec_start_send(struct ipc_client *client, int device_fd, - const void *sec_data, size_t sec_size); -int xmm626_hsic_sec_end_send(struct ipc_client *client, int device_fd); -int xmm626_hsic_firmware_send(struct ipc_client *client, int device_fd, - const void *firmware_data, size_t firmware_size); -int xmm626_hsic_nv_data_send(struct ipc_client *client, int device_fd); -int xmm626_hsic_hw_reset_send(struct ipc_client *client, int device_fd); - -#endif /* __XMM626_HSIC_H__ */ diff --git a/samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c b/samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c deleted file mode 100644 index c6b1578..0000000 --- a/samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c +++ /dev/null @@ -1,604 +0,0 @@ -/* - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2012 Alexander Tarasikov - * Copyright (C) 2013-2014 Paul Kocialkowski - * - * 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 . - */ - -#define _GNU_SOURCE -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "ipc.h" -#include "modems/xmm626/xmm626.h" -#include "modems/xmm626/xmm626_kernel_smdk4412.h" -#include "modems/xmm626/xmm626_modem_link_device_hsic.h" -#include "modems/xmm626/xmm626_modem_prj.h" - -int xmm626_kernel_smdk4412_power( - __attribute__((unused)) struct ipc_client *client, int device_fd, - int power) -{ - int rc; - - if (device_fd < 0) - return -1; - - rc = ioctl(device_fd, power ? IOCTL_MODEM_ON : IOCTL_MODEM_OFF, 0); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_kernel_smdk4412_boot_power( - __attribute__((unused)) struct ipc_client *client, int device_fd, - int power) -{ - int rc; - - if (device_fd < 0) - return -1; - - rc = ioctl(device_fd, power ? - IOCTL_MODEM_BOOT_ON : IOCTL_MODEM_BOOT_OFF, - 0); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_kernel_smdk4412_status_online_wait( - __attribute__((unused)) struct ipc_client *client, int device_fd) -{ - int status; - int i; - - if (device_fd < 0) - return -1; - - i = 0; - for (i = 0; i < 100; i++) { - status = ioctl(device_fd, IOCTL_MODEM_STATUS, 0); - if (status == STATE_ONLINE) - return 0; - - usleep(50000); - } - - return -1; -} - -int xmm626_kernel_smdk4412_hci_power( - __attribute__((unused)) struct ipc_client *client, int power) -{ - int ehci_rc, ohci_rc; - - ehci_rc = sysfs_value_write(XMM626_SEC_MODEM_EHCI_POWER_SYSFS, !!power); - if (ehci_rc >= 0) - usleep(50000); - - ohci_rc = sysfs_value_write(XMM626_SEC_MODEM_OHCI_POWER_SYSFS, !!power); - if (ohci_rc >= 0) - usleep(50000); - - if (ehci_rc < 0 && ohci_rc < 0) - return -1; - - return 0; -} - -int xmm626_kernel_smdk4412_link_control_enable( - __attribute__((unused)) struct ipc_client *client, - int device_fd, int enable) -{ - int rc; - - if (device_fd < 0) - return -1; - - rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ENABLE, &enable); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_kernel_smdk4412_link_control_active( - __attribute__((unused)) struct ipc_client *client, int device_fd, - int active) -{ - int rc; - - if (device_fd < 0) - return -1; - - rc = ioctl(device_fd, IOCTL_LINK_CONTROL_ACTIVE, &active); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_kernel_smdk4412_link_connected_wait( - __attribute__((unused)) struct ipc_client *client, int device_fd) -{ - int status; - int i; - - if (device_fd < 0) - return -1; - - i = 0; - for (i = 0; i < 100; i++) { - status = ioctl(device_fd, IOCTL_LINK_CONNECTED, 0); - if (status) - return 0; - - usleep(50000); - } - - return -1; -} - -int xmm626_kernel_smdk4412_link_get_hostwake_wait( - __attribute__((unused)) struct ipc_client *client, int device_fd) -{ - int status; - int i; - - if (device_fd < 0) - return -1; - - i = 0; - for (i = 0; i < 10; i++) { - status = ioctl(device_fd, IOCTL_LINK_GET_HOSTWAKE, 0); - if (status) - return 0; - - usleep(50000); - } - - return -1; -} - -int xmm626_kernel_smdk4412_fmt_send(struct ipc_client *client, - struct ipc_message *message) -{ - struct ipc_fmt_header header; - void *buffer; - size_t length; - size_t count; - unsigned char *p; - int rc; - - if (client == NULL || client->handlers == NULL || - client->handlers->write == NULL || message == NULL) { - return -1; - } - - ipc_fmt_header_setup(&header, message); - - length = header.length; - buffer = calloc(1, length); - - memcpy(buffer, &header, sizeof(struct ipc_fmt_header)); - if (message->data != NULL && message->size > 0) { - memcpy((void *) ((unsigned char *) buffer + - sizeof(struct ipc_fmt_header)), - message->data, message->size); - } - - ipc_client_log_send(client, message, __func__); - - p = (unsigned char *) buffer; - - count = 0; - while (count < length) { - rc = client->handlers->write(client, - client->handlers->transport_data, - p, length - count); - if (rc <= 0) { - ipc_client_log(client, "Writing FMT data failed"); - goto error; - } - - count += rc; - p += rc; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_kernel_smdk4412_fmt_recv(struct ipc_client *client, - struct ipc_message *message) -{ - struct ipc_fmt_header *header; - void *buffer = NULL; - size_t length; - size_t count; - unsigned char *p; - int rc; - - if (client == NULL || client->handlers == NULL || - client->handlers->read == NULL || message == NULL) { - return -1; - } - - length = XMM626_DATA_SIZE; - buffer = calloc(1, length); - - rc = client->handlers->read(client, client->handlers->transport_data, - buffer, length); - if (rc < (int) sizeof(struct ipc_fmt_header)) { - ipc_client_log(client, "Reading FMT header failed"); - goto error; - } - - header = (struct ipc_fmt_header *) buffer; - - ipc_fmt_message_setup(header, message); - - if (header->length > sizeof(struct ipc_fmt_header)) { - message->size = header->length - sizeof(struct ipc_fmt_header); - message->data = calloc(1, message->size); - - p = (unsigned char *) message->data; - - count = rc - sizeof(struct ipc_fmt_header); - if (count > 0) { - memcpy(p, - (void *) ((unsigned char *) buffer + - sizeof(struct ipc_fmt_header)), - count); - p += count; - } - - while (count < message->size) { - rc = client->handlers->read( - client, client->handlers->transport_data, p, - message->size - count); - if (rc <= 0) { - ipc_client_log(client, - "Reading FMT data failed"); - goto error; - } - - count += rc; - p += rc; - } - } - - ipc_client_log_recv(client, message, __func__); - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_kernel_smdk4412_rfs_send(struct ipc_client *client, - struct ipc_message *message) -{ - struct ipc_rfs_header header; - void *buffer; - size_t length; - size_t count; - unsigned char *p; - int rc; - - if (client == NULL || client->handlers == NULL || - client->handlers->write == NULL || message == NULL) { - return -1; - } - - ipc_rfs_header_setup(&header, message); - - length = header.length; - buffer = calloc(1, length); - - memcpy(buffer, &header, sizeof(struct ipc_rfs_header)); - if (message->data != NULL && message->size > 0) { - memcpy((void *) ( - (unsigned char *) buffer + - sizeof(struct ipc_rfs_header)), - message->data, - message->size); - } - - ipc_client_log_send(client, message, __func__); - - p = (unsigned char *) buffer; - - count = 0; - while (count < length) { - rc = client->handlers->write(client, - client->handlers->transport_data, - p, length - count); - if (rc <= 0) { - ipc_client_log(client, "Writing RFS data failed"); - goto error; - } - - count += rc; - p += rc; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_kernel_smdk4412_rfs_recv(struct ipc_client *client, - struct ipc_message *message) -{ - struct ipc_rfs_header *header; - void *buffer = NULL; - size_t length; - size_t count; - unsigned char *p; - int rc; - - if (client == NULL || client->handlers == NULL || - client->handlers->read == NULL || message == NULL) { - return -1; - } - - length = XMM626_DATA_SIZE; - buffer = calloc(1, length); - - rc = client->handlers->read(client, client->handlers->transport_data, - buffer, length); - if (rc < (int) sizeof(struct ipc_rfs_header)) { - ipc_client_log(client, "Reading RFS header failed"); - goto error; - } - - header = (struct ipc_rfs_header *) buffer; - if (header->length > XMM626_DATA_SIZE_LIMIT) { - ipc_client_log(client, "Invalid RFS header length: %u", - header->length); - goto error; - } - - ipc_rfs_message_setup(header, message); - - if (header->length > sizeof(struct ipc_rfs_header)) { - message->size = header->length - sizeof(struct ipc_rfs_header); - message->data = calloc(1, message->size); - - p = (unsigned char *) message->data; - - count = rc - sizeof(struct ipc_rfs_header); - if (count > 0) { - memcpy(p, - (void *) ((unsigned char *) buffer + - sizeof(struct ipc_rfs_header)), - count); - p += count; - } - - while (count < message->size) { - rc = client->handlers->read( - client, client->handlers->transport_data, p, - message->size - count); - if (rc <= 0) { - ipc_client_log(client, - "Reading RFS data failed"); - goto error; - } - - count += rc; - p += rc; - } - } - - ipc_client_log_recv(client, message, __func__); - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_kernel_smdk4412_open( - __attribute__((unused)) struct ipc_client *client, int type) -{ - int fd; - - switch (type) { - case IPC_CLIENT_TYPE_FMT: - fd = open(XMM626_SEC_MODEM_IPC0_DEVICE, - O_RDWR | O_NOCTTY | O_NONBLOCK); - break; - case IPC_CLIENT_TYPE_RFS: - fd = open(XMM626_SEC_MODEM_RFS0_DEVICE, - O_RDWR | O_NOCTTY | O_NONBLOCK); - break; - default: - return -1; - } - - return fd; -} - -int xmm626_kernel_smdk4412_close( - __attribute__((unused)) struct ipc_client *client, int fd) -{ - if (fd < 0) - return -1; - - close(fd); - - return 0; -} - -int xmm626_kernel_smdk4412_read( - __attribute__((unused)) struct ipc_client *client, int fd, void *buffer, - size_t length) -{ - int status; - int rc; - - if (fd < 0 || buffer == NULL || length <= 0) - return -1; - - status = ioctl(fd, IOCTL_MODEM_STATUS, 0); - if (status != STATE_ONLINE && status != STATE_BOOTING) - return -1; - - rc = read(fd, buffer, length); - - return rc; -} - -int xmm626_kernel_smdk4412_write( - __attribute__((unused)) struct ipc_client *client, int fd, - const void *buffer, size_t length) -{ - int status; - int rc; - - if (fd < 0 || buffer == NULL || length <= 0) - return -1; - - status = ioctl(fd, IOCTL_MODEM_STATUS, 0); - if (status != STATE_ONLINE && status != STATE_BOOTING) - return -1; - - rc = write(fd, buffer, length); - - return rc; -} - -int xmm626_kernel_smdk4412_poll( - __attribute__((unused)) struct ipc_client *client, - int fd, struct ipc_poll_fds *fds, struct timeval *timeout) -{ - int status; - fd_set set; - int fd_max; - unsigned int i; - unsigned int count; - int rc; - - if (fd < 0) - return -1; - - FD_ZERO(&set); - FD_SET(fd, &set); - - fd_max = fd; - - if (fds != NULL && fds->fds != NULL && fds->count > 0) { - for (i = 0; i < fds->count; i++) { - if (fds->fds[i] >= 0) { - FD_SET(fds->fds[i], &set); - - if (fds->fds[i] > fd_max) - fd_max = fds->fds[i]; - } - } - } - - rc = select(fd_max + 1, &set, NULL, NULL, timeout); - - if (FD_ISSET(fd, &set)) { - status = ioctl(fd, IOCTL_MODEM_STATUS, 0); - if (status != STATE_ONLINE && status != STATE_BOOTING) - return -1; - } - - if (fds != NULL && fds->fds != NULL && fds->count > 0) { - count = fds->count; - - for (i = 0; i < fds->count; i++) { - if (!FD_ISSET(fds->fds[i], &set)) { - fds->fds[i] = -1; - count--; - } - } - - fds->count = count; - } - - return rc; -} - -char *xmm626_kernel_smdk4412_gprs_get_iface( - __attribute__((unused)) struct ipc_client *client, unsigned int cid) -{ - char *iface = NULL; - - if (cid > XMM626_SEC_MODEM_GPRS_IFACE_COUNT) - return NULL; - - asprintf(&iface, "%s%d", XMM626_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1); - - return iface; -} - -int xmm626_kernel_smdk4412_gprs_get_capabilities( - __attribute__((unused)) struct ipc_client *client, - struct ipc_client_gprs_capabilities *capabilities) -{ - if (capabilities == NULL) - return -1; - - capabilities->cid_count = XMM626_SEC_MODEM_GPRS_IFACE_COUNT; - - return 0; -} diff --git a/samsung-ipc/modems/xmm626/xmm626_mipi.c b/samsung-ipc/modems/xmm626/xmm626_mipi.c deleted file mode 100644 index 375ded0..0000000 --- a/samsung-ipc/modems/xmm626/xmm626_mipi.c +++ /dev/null @@ -1,674 +0,0 @@ -/* - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2012 Alexander Tarasikov - * Copyright (C) 2013-2014 Paul Kocialkowski - * - * Based on the incomplete C++ implementation which is: - * Copyright (C) 2012 Sergey Gridasov - * - * 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 . - */ - -#include -#include -#include -#include -#include - -#include - -#include "modems/xmm626/xmm626.h" -#include "modems/xmm626/xmm626_mipi.h" - -int xmm626_mipi_crc_calculate(const void *data, size_t size) -{ - unsigned char crc; - int mipi_crc; - - crc = xmm626_crc_calculate(data, size); - mipi_crc = (crc << 24) | 0xffffff; - - return mipi_crc; -} - -int xmm626_mipi_ack_read(int device_fd, unsigned short ack) -{ - struct timeval timeout; - fd_set fds; - unsigned int value; - int rc; - int i; - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - FD_ZERO(&fds); - FD_SET(device_fd, &fds); - - for (i = 0; i < 50; i++) { - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - return -1; - - value = 0; - rc = read(device_fd, &value, sizeof(value)); - if (rc < (int) sizeof(value)) - continue; - - if ((value & 0xffff) == ack) - return 0; - } - - return -1; -} - -int xmm626_mipi_psi_send(struct ipc_client *client, int device_fd, - const void *psi_data, unsigned short psi_size) -{ - struct xmm626_mipi_psi_header psi_header; - char at[] = XMM626_AT; - int psi_crc; - struct timeval timeout; - fd_set fds; - size_t wc; - size_t length; - unsigned char *p; - int rc; - int i; - - if (client == NULL || device_fd < 0 || psi_data == NULL || - psi_size == 0) { - return -1; - } - - FD_ZERO(&fds); - - i = 0; - length = strlen(at); - - do { - FD_SET(device_fd, &fds); - - timeout.tv_sec = 0; - timeout.tv_usec = 100000; - - rc = write(device_fd, at, length); - if (rc < (int) length) { - ipc_client_log(client, "Writing ATAT in ASCII failed"); - goto error; - } - ipc_client_log(client, "Wrote ATAT in ASCII"); - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc < 0) { - ipc_client_log(client, "Waiting for bootup failed"); - goto error; - } - - if (i++ > 50) { - ipc_client_log(client, "Waiting for bootup failed"); - goto error; - } - } while (rc == 0); - - rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_BOOT0_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading boot ACK failed"); - goto error; - } - - psi_header.padding = XMM626_PSI_PADDING; - psi_header.length = ((psi_size >> 8) & 0xff) | ((psi_size & 0xff) << 8); - psi_header.magic = XMM626_PSI_MAGIC; - - rc = write(device_fd, &psi_header, sizeof(psi_header)); - if (rc < (int) sizeof(psi_header)) { - ipc_client_log(client, "Writing PSI header failed"); - goto error; - } - ipc_client_log(client, "Wrote PSI header"); - - p = (unsigned char *) psi_data; - - wc = 0; - while (wc < psi_size) { - rc = write(device_fd, (void *) p, psi_size - wc); - if (rc <= 0) { - ipc_client_log(client, "Writing PSI failed"); - goto error; - } - - p += rc; - wc += rc; - } - - psi_crc = xmm626_mipi_crc_calculate(psi_data, psi_size); - - ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc); - - rc = write(device_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); - - rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_PSI_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading PSI ACK failed"); - goto error; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -int xmm626_mipi_ebl_send(struct ipc_client *client, int device_fd, - const void *ebl_data, size_t ebl_size) -{ - unsigned short boot_magic[4]; - unsigned char ebl_crc; - size_t chunk; - size_t count; - size_t wc; - size_t size; - size_t length; - unsigned char *p; - int rc; - - if (client == NULL || device_fd < 0 || ebl_data == NULL || - ebl_size == 0) { - return -1; - } - - boot_magic[0] = 0; - boot_magic[1] = 0; - boot_magic[2] = XMM626_MIPI_BOOT1_MAGIC; - boot_magic[3] = XMM626_MIPI_BOOT1_MAGIC; - - length = sizeof(boot_magic); - - rc = write(device_fd, &length, sizeof(length)); - if (rc < (int) sizeof(length)) { - ipc_client_log(client, "Writing boot magic length failed"); - goto error; - } - - rc = write(device_fd, &boot_magic, length); - if (rc < (int) length) { - ipc_client_log(client, "Writing boot magic failed"); - goto error; - } - ipc_client_log(client, "Wrote boot magic"); - - rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_BOOT1_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading boot magic ACK failed"); - goto error; - } - - size = sizeof(ebl_size); - - rc = write(device_fd, &size, sizeof(size)); - if (rc < (int) sizeof(size)) { - ipc_client_log(client, "Writing EBL size length failed"); - goto error; - } - - rc = write(device_fd, &ebl_size, size); - if (rc < (int) size) { - ipc_client_log(client, "Writing EBL size failed"); - goto error; - } - ipc_client_log(client, "Wrote EBL size"); - - rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_EBL_SIZE_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading EBL size ACK failed"); - goto error; - } - - ebl_size++; - - rc = write(device_fd, &ebl_size, size); - if (rc < (int) size) { - ipc_client_log(client, "Writing EBL size failed"); - goto error; - } - - ebl_size--; - - p = (unsigned char *) ebl_data; - - chunk = XMM626_MIPI_EBL_CHUNK; - wc = 0; - while (wc < ebl_size) { - count = chunk < ebl_size - wc ? chunk : ebl_size - wc; - - rc = write(device_fd, (void *) p, count); - if (rc <= 0) { - ipc_client_log(client, "Writing EBL failed"); - goto error; - } - - p += rc; - wc += rc; - } - - ebl_crc = xmm626_crc_calculate(ebl_data, ebl_size); - - ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc); - - rc = write(device_fd, &ebl_crc, sizeof(ebl_crc)); - if (rc < (int) sizeof(ebl_crc)) { - ipc_client_log(client, "Writing EBL CRC failed"); - goto error; - } - ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc); - - rc = xmm626_mipi_ack_read(device_fd, XMM626_MIPI_EBL_ACK); - if (rc < 0) { - ipc_client_log(client, "Reading EBL ACK failed"); - goto error; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -int xmm626_mipi_command_send(int device_fd, unsigned short code, - const void *data, size_t size, int ack, - int short_footer) -{ - struct xmm626_mipi_command_header header; - struct xmm626_mipi_command_footer footer; - void *buffer = NULL; - size_t length; - size_t footer_length; - struct timeval timeout; - fd_set fds; - size_t chunk; - size_t c; - unsigned char *p; - int rc; - int i; - - if (device_fd < 0 || data == NULL || size <= 0) - return -1; - - header.size = size + sizeof(header); - header.magic = XMM626_MIPI_COMMAND_HEADER_MAGIC; - header.code = code; - header.data_size = size; - - footer.checksum = (size & 0xffff) + code; - footer.magic = XMM626_MIPI_COMMAND_FOOTER_MAGIC; - footer.unknown = XMM626_MIPI_COMMAND_FOOTER_UNKNOWN; - - p = (unsigned char *) data; - - for (i = 0; i < (int) size; i++) - footer.checksum += *p++; - - footer_length = sizeof(footer); - if (short_footer) - footer_length -= sizeof(short); - - length = sizeof(header) + size + footer_length; - buffer = calloc(1, length); - - p = (unsigned char *) buffer; - memcpy(p, &header, sizeof(header)); - p += sizeof(header); - memcpy(p, data, size); - p += size; - memcpy(p, &footer, footer_length); - - rc = write(device_fd, buffer, length); - if (rc < (int) length) - goto error; - - free(buffer); - buffer = NULL; - - if (!ack) { - rc = 0; - goto complete; - } - - FD_ZERO(&fds); - FD_SET(device_fd, &fds); - - timeout.tv_sec = 1; - timeout.tv_usec = 0; - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - rc = read(device_fd, &length, sizeof(length)); - if (rc < (int) sizeof(length) || length <= 0) - goto error; - - length += sizeof(unsigned int); - if (length % 4 != 0) - length += length % 4; - - if (length < (int) sizeof(buffer)) - goto error; - - buffer = calloc(1, length); - - p = (unsigned char *) buffer; - memcpy(p, &length, sizeof(length)); - p += sizeof(length); - - chunk = 4; - c = sizeof(length); - while (c < length) { - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - rc = read(device_fd, (void *) p, chunk); - if (rc < (int) chunk) - goto error; - - p += rc; - c += rc; - } - - memcpy(&header, buffer, sizeof(header)); - if (header.code != code) - goto error; - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_mipi_modem_data_send(int device_fd, const void *data, size_t size, - int address) -{ - size_t chunk; - size_t count; - size_t c; - unsigned char *p; - int rc; - - if (device_fd < 0 || data == NULL || size == 0) - return -1; - - rc = xmm626_mipi_command_send(device_fd, - XMM626_COMMAND_FLASH_SET_ADDRESS, - &address, sizeof(address), 1, 0); - if (rc < 0) - goto error; - - p = (unsigned char *) data; - - chunk = XMM626_MIPI_MODEM_DATA_CHUNK; - c = 0; - while (c < size) { - count = chunk < size - c ? chunk : size - c; - - rc = xmm626_mipi_command_send(device_fd, - XMM626_COMMAND_FLASH_WRITE_BLOCK, - p, count, 1, 1); - if (rc < 0) - goto error; - - p += count; - c += count; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - return rc; -} - -int xmm626_mipi_port_config_send(struct ipc_client *client, int device_fd) -{ - void *buffer = NULL; - size_t length; - struct timeval timeout; - fd_set fds; - size_t chunk; - size_t count; - size_t c; - unsigned char *p; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - FD_ZERO(&fds); - FD_SET(device_fd, &fds); - - timeout.tv_sec = 2; - timeout.tv_usec = 0; - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - rc = read(device_fd, &length, sizeof(length)); - if (rc < (int) sizeof(length) || length == 0) { - ipc_client_log(client, "Reading port config length failed"); - goto error; - } - ipc_client_log(client, "Read port config length (0x%x)", length); - - buffer = calloc(1, length); - - p = (unsigned char *) buffer; - - chunk = 4; - c = 0; - while (c < length) { - count = chunk < length - c ? chunk : length - c; - - rc = select(device_fd + 1, &fds, NULL, NULL, &timeout); - if (rc <= 0) - goto error; - - rc = read(device_fd, p, count); - if (rc < (int) count) { - ipc_client_log(client, "Reading port config failed"); - goto error; - } - - p += count; - c += count; - } - ipc_client_log(client, "Read port config"); - - rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_SET_PORT_CONFIG, - buffer, length, 1, 0); - if (rc < 0) { - ipc_client_log(client, "Sending port config command failed"); - goto error; - } - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (buffer != NULL) - free(buffer); - - return rc; -} - -int xmm626_mipi_sec_start_send(struct ipc_client *client, int device_fd, - const void *sec_data, size_t sec_size) -{ - int rc; - - if (client == NULL || device_fd < 0 || sec_data == NULL || - sec_size == 0) { - return -1; - } - - rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_SEC_START, - sec_data, sec_size, 1, 0); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_mipi_sec_end_send(struct ipc_client *client, int device_fd) -{ - unsigned short sec_data; - size_t sec_size; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - sec_data = XMM626_SEC_END_MAGIC; - sec_size = sizeof(sec_data); - - rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_SEC_END, - &sec_data, sec_size, 1, 1); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_mipi_firmware_send(struct ipc_client *client, int device_fd, - const void *firmware_data, size_t firmware_size) -{ - int rc; - - if (client == NULL || device_fd < 0 || firmware_data == NULL || - firmware_size == 0) { - return -1; - } - - rc = xmm626_mipi_modem_data_send(device_fd, firmware_data, - firmware_size, - XMM626_FIRMWARE_ADDRESS); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_mipi_nv_data_send(struct ipc_client *client, int device_fd) -{ - void *nv_data = NULL; - size_t nv_size; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - nv_size = ipc_client_nv_data_size(client); - if (nv_size == 0) - return -1; - - nv_data = ipc_nv_data_load(client); - if (nv_data == NULL) { - ipc_client_log(client, "Loading nv_data failed"); - goto error; - } - ipc_client_log(client, "Loaded nv_data"); - - rc = xmm626_mipi_modem_data_send(device_fd, nv_data, nv_size, - XMM626_NV_DATA_ADDRESS); - if (rc < 0) - goto error; - - rc = 0; - goto complete; - -error: - rc = -1; - -complete: - if (nv_data != NULL) - free(nv_data); - - return rc; -} - -int xmm626_mipi_mps_data_send(struct ipc_client *client, int device_fd, - const void *mps_data, size_t mps_size) -{ - int rc; - - if (client == NULL || device_fd < 0 || mps_data == NULL || - mps_size == 0) { - return -1; - } - - rc = xmm626_mipi_modem_data_send(device_fd, mps_data, mps_size, - XMM626_MPS_DATA_ADDRESS); - if (rc < 0) - return -1; - - return 0; -} - -int xmm626_mipi_hw_reset_send(struct ipc_client *client, int device_fd) -{ - unsigned int hw_reset_data; - size_t hw_reset_size; - int rc; - - if (client == NULL || device_fd < 0) - return -1; - - hw_reset_data = XMM626_HW_RESET_MAGIC; - hw_reset_size = sizeof(hw_reset_data); - - rc = xmm626_mipi_command_send(device_fd, XMM626_COMMAND_HW_RESET, - &hw_reset_data, hw_reset_size, 0, 1); - if (rc < 0) - return -1; - - return 0; -} diff --git a/samsung-ipc/modems/xmm626/xmm626_mipi.h b/samsung-ipc/modems/xmm626/xmm626_mipi.h deleted file mode 100644 index 1545a3e..0000000 --- a/samsung-ipc/modems/xmm626/xmm626_mipi.h +++ /dev/null @@ -1,71 +0,0 @@ -/* - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2012 Alexander Tarasikov - * Copyright (C) 2013-2014 Paul Kocialkowski - * - * 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 . - */ - -#ifndef __XMM626_MIPI_H__ -#define __XMM626_MIPI_H__ - -#define XMM626_MIPI_BOOT0_ACK 0xFFFF -#define XMM626_MIPI_BOOT1_MAGIC 0x02 -#define XMM626_MIPI_BOOT1_ACK 0xAA00 -#define XMM626_MIPI_PSI_ACK 0xDD01 -#define XMM626_MIPI_EBL_SIZE_ACK 0xCCCC -#define XMM626_MIPI_EBL_ACK 0xA551 -#define XMM626_MIPI_EBL_CHUNK 0xDFC -#define XMM626_MIPI_MODEM_DATA_CHUNK 0xDF2 -#define XMM626_MIPI_COMMAND_HEADER_MAGIC 0x02 -#define XMM626_MIPI_COMMAND_FOOTER_MAGIC 0x03 -#define XMM626_MIPI_COMMAND_FOOTER_UNKNOWN 0xEAEA - -struct xmm626_mipi_psi_header { - unsigned char padding; - unsigned short length; - unsigned char magic; -} __attribute__((packed)); - -struct xmm626_mipi_command_header { - unsigned int size; - unsigned short magic; - unsigned short code; - unsigned short data_size; -} __attribute__((packed)); - -struct xmm626_mipi_command_footer { - unsigned short checksum; - unsigned short magic; - unsigned short unknown; -} __attribute__((packed)); - -int xmm626_mipi_psi_send(struct ipc_client *client, int device_fd, - const void *psi_data, unsigned short psi_size); -int xmm626_mipi_ebl_send(struct ipc_client *client, int device_fd, - const void *ebl_data, size_t ebl_size); - -int xmm626_mipi_port_config_send(struct ipc_client *client, int device_fd); -int xmm626_mipi_sec_start_send(struct ipc_client *client, int device_fd, - const void *sec_data, size_t sec_size); -int xmm626_mipi_sec_end_send(struct ipc_client *client, int device_fd); -int xmm626_mipi_firmware_send(struct ipc_client *client, int device_fd, - const void *firmware_data, size_t firmware_size); -int xmm626_mipi_nv_data_send(struct ipc_client *client, int device_fd); -int xmm626_mipi_mps_data_send(struct ipc_client *client, int device_fd, - const void *mps_data, size_t mps_size); -int xmm626_mipi_hw_reset_send(struct ipc_client *client, int device_fd); - -#endif /* __XMM626_MIPI_H__ */ diff --git a/samsung-ipc/modems/xmm626/xmm626_modem_link_device_hsic.h b/samsung-ipc/modems/xmm626/xmm626_modem_link_device_hsic.h deleted file mode 100644 index f2421e0..0000000 --- a/samsung-ipc/modems/xmm626/xmm626_modem_link_device_hsic.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * 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_LINK_DEVICE_USB_H__ -#define __MODEM_LINK_DEVICE_USB_H__ - - -enum { - IF_USB_BOOT_EP = 0, - IF_USB_FMT_EP = 0, - IF_USB_RAW_EP, - IF_USB_RFS_EP, - IF_USB_CMD_EP, - IF_USB_DEVNUM_MAX, -}; - -/* each pipe has 2 ep for in/out */ -#define LINKPM_DEV_NUM (IF_USB_DEVNUM_MAX * 2) -/*******************/ -/* xmm626 specific */ - -#define IOCTL_LINK_CONTROL_ENABLE _IO('o', 0x30) -#define IOCTL_LINK_CONTROL_ACTIVE _IO('o', 0x31) -#define IOCTL_LINK_GET_HOSTWAKE _IO('o', 0x32) -#define IOCTL_LINK_CONNECTED _IO('o', 0x33) -#define IOCTL_LINK_SET_BIAS_CLEAR _IO('o', 0x34) - -/* VID,PID for IMC - XMM626, XMM6262*/ -#define IMC_BOOT_VID 0x058b -#define IMC_BOOT_PID 0x0041 -#define IMC_MAIN_VID 0x1519 -#define IMC_MAIN_PID 0x0020 -/* VID,PID for STE - M7400 */ -#define STE_BOOT_VID 0x04cc -#define STE_BOOT_PID 0x7400 -#define STE_MAIN_VID 0x04cc -#define STE_MAIN_PID 0x2333 - -enum { - BOOT_DOWN = 0, - IPC_CHANNEL -}; - -enum ch_state { - STATE_SUSPENDED, - STATE_RESUMED, -}; - -#define HOSTWAKE_TRIGLEVEL 0 - -#endif /* __MODEM_LINK_DEVICE_USB_H__ */ diff --git a/scripts/smdk4412_func_usage.py b/scripts/smdk4412_func_usage.py new file mode 100755 index 0000000..fe54f66 --- /dev/null +++ b/scripts/smdk4412_func_usage.py @@ -0,0 +1,85 @@ +#!/bin/env python + +import os +import re +from sh import git + +funcs = [ + 'xmm626_kernel_smdk4412_power', + 'xmm626_kernel_smdk4412_boot_power', + 'xmm626_kernel_smdk4412_hci_power', + 'xmm626_kernel_smdk4412_link_control_enable', + 'xmm626_kernel_smdk4412_link_control_active', + 'xmm626_kernel_smdk4412_link_connected_wait', + 'xmm626_kernel_smdk4412_link_get_hostwake_wait', + 'xmm626_kernel_smdk4412_status_online_wait', + 'xmm626_kernel_smdk4412_open', + 'xmm626_kernel_smdk4412_close', + 'xmm626_kernel_smdk4412_read', + 'xmm626_kernel_smdk4412_write', + 'xmm626_kernel_smdk4412_poll', + 'xmm626_kernel_smdk4412_fmt_send', + 'xmm626_kernel_smdk4412_fmt_recv', + 'xmm626_kernel_smdk4412_rfs_send', + 'xmm626_kernel_smdk4412_rfs_recv', + 'xmm626_kernel_smdk4412_gprs_get_iface', + 'xmm626_kernel_smdk4412_gprs_get_capabilities', +] + +results = {} + +def func_usage(func): + output = "" + try: + output = git('--no-pager', 'grep', '--color=never', func) + except: + pass + + for line in output: + filepath = line.split(":")[0] + content = line.split(":")[1] + + device = None + if re.match('samsung-ipc/devices/.*/*\.c$', filepath): + device = re.sub('\.c', '', os.path.basename(filepath)) + if device not in results: + results[device] = {} + results[device][func] = True + +def print_func_group(device, device_data, device_maxlen, funcs, regex): + print ("| {}{} |".format(device, " " * (device_maxlen - len(device))), + end='') + for func in funcs: + if re.search(regex, func): + func_name = re.sub('xmm626_kernel_smdk4412_','', func) + if func in device_data: + print (" {} |".format(func_name), end='') + else: + print (" {} |".format(" " * len(func_name)), end='') + print() + +def report_results(results): + device_maxlen = 0 + for key in results.keys(): + if len(key) > device_maxlen: + device_maxlen = len(key) + + + print ("+{}+".format("-" * (device_maxlen + 2))) + for device, device_data in results.items(): + # All: + # print_func_group(device, device_data, device_maxlen, funcs, + # "open|close|read|write|poll") + # print_func_group(device, device_data, device_maxlen, funcs, "fmt|rfs") + # print_func_group(device, device_data, device_maxlen, funcs, "gprs") + + + print_func_group(device, device_data, device_maxlen, funcs, + "power|link|status") + + print ("+{}+".format("-" * (device_maxlen + 2))) + +for func in funcs: + func_usage(func) + +report_results(results) -- cgit v1.2.3