2 * This file is part of libsamsung-ipc.
4 * Copyright (C) 2013-2014 Paul Kocialkowski <contact@paulk.fr>
6 * libsamsung-ipc is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 2 of the License, or
9 * (at your option) any later version.
11 * libsamsung-ipc is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>.
26 #include <samsung-ipc.h>
30 #include "xmm626_hsic.h"
31 #include "xmm626_sec_modem.h"
34 int i9300_boot(struct ipc_client *client)
36 void *modem_image_data = NULL;
37 int modem_image_fd = -1;
38 int modem_boot_fd = -1;
39 int modem_link_fd = -1;
46 ipc_client_log(client, "Starting i9300 modem boot");
48 modem_image_fd = open(I9300_MODEM_IMAGE_DEVICE, O_RDONLY);
49 if (modem_image_fd < 0) {
50 ipc_client_log(client, "Opening modem image device failed");
53 ipc_client_log(client, "Opened modem image device");
55 modem_image_data = mmap(0, I9300_MODEM_IMAGE_SIZE, PROT_READ, MAP_SHARED, modem_image_fd, 0);
56 if (modem_image_data == NULL || modem_image_data == (void *) 0xffffffff) {
57 ipc_client_log(client, "Mapping modem image data to memory failed");
60 ipc_client_log(client, "Mapped modem image data to memory");
62 modem_boot_fd = open(XMM626_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
63 if (modem_boot_fd < 0) {
64 ipc_client_log(client, "Opening modem boot device failed");
67 ipc_client_log(client, "Opened modem boot device");
69 modem_link_fd = open(XMM626_SEC_MODEM_LINK_PM_DEVICE, O_RDWR);
70 if (modem_link_fd < 0) {
71 ipc_client_log(client, "Opening modem link device failed");
74 ipc_client_log(client, "Opened modem link device");
76 rc = xmm626_sec_modem_hci_power(0);
78 ipc_client_log(client, "Turning the modem off failed");
81 ipc_client_log(client, "Turned the modem off");
83 rc = xmm626_sec_modem_power(modem_boot_fd, 1);
84 rc |= xmm626_sec_modem_hci_power(1);
87 ipc_client_log(client, "Turning the modem on failed");
90 ipc_client_log(client, "Turned the modem on");
92 rc = xmm626_sec_modem_link_connected_wait(modem_link_fd);
94 ipc_client_log(client, "Waiting for link connected failed");
97 ipc_client_log(client, "Waited for link connected");
99 p = (unsigned char *) modem_image_data + I9300_PSI_OFFSET;
101 rc = xmm626_hsic_psi_send(client, modem_boot_fd, (void *) p, I9300_PSI_SIZE);
103 ipc_client_log(client, "Sending XMM626 HSIC PSI failed");
106 ipc_client_log(client, "Sent XMM626 HSIC PSI");
108 p = (unsigned char *) modem_image_data + I9300_EBL_OFFSET;
110 rc = xmm626_hsic_ebl_send(client, modem_boot_fd, (void *) p, I9300_EBL_SIZE);
112 ipc_client_log(client, "Sending XMM626 HSIC EBL failed");
115 ipc_client_log(client, "Sent XMM626 HSIC EBL");
117 rc = xmm626_hsic_port_config_send(client, modem_boot_fd);
119 ipc_client_log(client, "Sending XMM626 HSIC port config failed");
122 ipc_client_log(client, "Sent XMM626 HSIC port config");
124 p = (unsigned char *) modem_image_data + I9300_SEC_START_OFFSET;
126 rc = xmm626_hsic_sec_start_send(client, modem_boot_fd, (void *) p, I9300_SEC_START_SIZE);
128 ipc_client_log(client, "Sending XMM626 HSIC SEC start failed");
131 ipc_client_log(client, "Sent XMM626 HSIC SEC start");
133 p = (unsigned char *) modem_image_data + I9300_FIRMWARE_OFFSET;
135 rc = xmm626_hsic_firmware_send(client, modem_boot_fd, (void *) p, I9300_FIRMWARE_SIZE);
137 ipc_client_log(client, "Sending XMM626 HSIC firmware failed");
140 ipc_client_log(client, "Sent XMM626 HSIC firmware");
142 rc = xmm626_hsic_nv_data_send(client, modem_boot_fd);
144 ipc_client_log(client, "Sending XMM626 HSIC nv_data failed");
147 ipc_client_log(client, "Sent XMM626 HSIC nv_data");
149 rc = xmm626_hsic_sec_end_send(client, modem_boot_fd);
151 ipc_client_log(client, "Sending XMM626 HSIC SEC end failed");
154 ipc_client_log(client, "Sent XMM626 HSIC SEC end");
156 rc = xmm626_hsic_hw_reset_send(client, modem_boot_fd);
158 ipc_client_log(client, "Sending XMM626 HSIC HW reset failed");
161 ipc_client_log(client, "Sent XMM626 HSIC HW reset");
165 rc = xmm626_sec_modem_link_get_hostwake_wait(modem_link_fd);
167 ipc_client_log(client, "Waiting for host wake failed");
170 rc = xmm626_sec_modem_link_control_enable(modem_link_fd, 0);
171 rc |= xmm626_sec_modem_hci_power(0);
172 rc |= xmm626_sec_modem_link_control_active(modem_link_fd, 0);
175 ipc_client_log(client, "Turning the modem off failed");
179 rc = xmm626_sec_modem_link_get_hostwake_wait(modem_link_fd);
181 ipc_client_log(client, "Waiting for host wake failed");
184 ipc_client_log(client, "Waited for host wake");
186 rc = xmm626_sec_modem_link_control_enable(modem_link_fd, 1);
187 rc |= xmm626_sec_modem_hci_power(1);
188 rc |= xmm626_sec_modem_link_control_active(modem_link_fd, 1);
191 ipc_client_log(client, "Turning the modem on failed");
195 rc = xmm626_sec_modem_link_connected_wait(modem_link_fd);
197 ipc_client_log(client, "Waiting for link connected failed");
200 ipc_client_log(client, "Waited for link connected");
211 if (modem_image_data != NULL)
212 munmap(modem_image_data, I9300_MODEM_IMAGE_SIZE);
214 if (modem_image_fd >= 0)
215 close(modem_image_fd);
217 if (modem_boot_fd >= 0)
218 close(modem_boot_fd);
220 if (modem_link_fd >= 0)
221 close(modem_link_fd);
226 int i9300_open(void *data, int type)
228 struct i9300_transport_data *transport_data;
233 transport_data = (struct i9300_transport_data *) data;
235 transport_data->fd = xmm626_sec_modem_open(type);
236 if (transport_data->fd < 0)
242 int i9300_close(void *data)
244 struct i9300_transport_data *transport_data;
249 transport_data = (struct i9300_transport_data *) data;
251 xmm626_sec_modem_close(transport_data->fd);
252 transport_data->fd = -1;
257 int i9300_read(void *data, void *buffer, size_t length)
259 struct i9300_transport_data *transport_data;
265 transport_data = (struct i9300_transport_data *) data;
267 rc = xmm626_sec_modem_read(transport_data->fd, buffer, length);
272 int i9300_write(void *data, const void *buffer, size_t length)
274 struct i9300_transport_data *transport_data;
280 transport_data = (struct i9300_transport_data *) data;
282 rc = xmm626_sec_modem_write(transport_data->fd, buffer, length);
287 int i9300_poll(void *data, struct timeval *timeout)
289 struct i9300_transport_data *transport_data;
295 transport_data = (struct i9300_transport_data *) data;
297 rc = xmm626_sec_modem_poll(transport_data->fd, timeout);
302 int i9300_power_on(void *data)
307 int i9300_power_off(void *data)
312 fd = open(XMM626_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
316 rc = xmm626_sec_modem_power(fd, 0);
326 int i9300_gprs_activate(void *data, unsigned int cid)
331 int i9300_gprs_deactivate(void *data, unsigned int cid)
336 int i9300_data_create(void **transport_data, void **power_data,
339 if (transport_data == NULL)
342 *transport_data = calloc(1, sizeof(struct i9300_transport_data));
347 int i9300_data_destroy(void *transport_data, void *power_data, void *gprs_data)
349 if (transport_data == NULL)
352 free(transport_data);
357 struct ipc_client_ops i9300_fmt_ops = {
359 .send = xmm626_sec_modem_fmt_send,
360 .recv = xmm626_sec_modem_fmt_recv,
363 struct ipc_client_ops i9300_rfs_ops = {
365 .send = xmm626_sec_modem_rfs_send,
366 .recv = xmm626_sec_modem_rfs_recv,
369 struct ipc_client_handlers i9300_handlers = {
371 .write = i9300_write,
373 .close = i9300_close,
375 .transport_data = NULL,
376 .power_on = i9300_power_on,
377 .power_off = i9300_power_off,
379 .gprs_activate = i9300_gprs_activate,
380 .gprs_deactivate = i9300_gprs_deactivate,
382 .data_create = i9300_data_create,
383 .data_destroy = i9300_data_destroy,
386 struct ipc_client_gprs_specs i9300_gprs_specs = {
387 .gprs_get_iface = xmm626_sec_modem_gprs_get_iface,
388 .gprs_get_capabilities = xmm626_sec_modem_gprs_get_capabilities,
391 struct ipc_client_nv_data_specs i9300_nv_data_specs = {
392 .nv_data_path = XMM626_NV_DATA_PATH,
393 .nv_data_md5_path = XMM626_NV_DATA_MD5_PATH,
394 .nv_data_backup_path = XMM626_NV_DATA_BACKUP_PATH,
395 .nv_data_backup_md5_path = XMM626_NV_DATA_BACKUP_MD5_PATH,
396 .nv_data_secret = XMM626_NV_DATA_SECRET,
397 .nv_data_size = XMM626_NV_DATA_SIZE,
398 .nv_data_chunk_size = XMM626_NV_DATA_CHUNK_SIZE,
401 // vim:ts=4:sw=4:expandtab