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 galaxys2_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 galaxys2 modem boot");
48 modem_image_fd = open(GALAXYS2_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, GALAXYS2_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_power(modem_boot_fd, 0);
77 rc |= xmm626_sec_modem_link_control_enable(modem_link_fd, 0);
78 rc |= xmm626_sec_modem_hci_power(0);
79 rc |= xmm626_sec_modem_link_control_active(modem_link_fd, 0);
82 ipc_client_log(client, "Turning the modem off failed");
85 ipc_client_log(client, "Turned the modem off");
87 rc = xmm626_sec_modem_power(modem_boot_fd, 1);
88 rc |= xmm626_sec_modem_link_control_enable(modem_link_fd, 1);
89 rc |= xmm626_sec_modem_hci_power(1);
90 rc |= xmm626_sec_modem_link_control_active(modem_link_fd, 1);
93 ipc_client_log(client, "Turning the modem on failed");
96 ipc_client_log(client, "Turned the modem on");
98 rc = xmm626_sec_modem_link_connected_wait(modem_link_fd);
100 ipc_client_log(client, "Waiting for link connected failed");
103 ipc_client_log(client, "Waited for link connected");
105 p = (unsigned char *) modem_image_data + GALAXYS2_PSI_OFFSET;
107 rc = xmm626_hsic_psi_send(client, modem_boot_fd, (void *) p, GALAXYS2_PSI_SIZE);
109 ipc_client_log(client, "Sending XMM626 HSIC PSI failed");
112 ipc_client_log(client, "Sent XMM626 HSIC PSI");
114 p = (unsigned char *) modem_image_data + GALAXYS2_EBL_OFFSET;
116 rc = xmm626_hsic_ebl_send(client, modem_boot_fd, (void *) p, GALAXYS2_EBL_SIZE);
118 ipc_client_log(client, "Sending XMM626 HSIC EBL failed");
121 ipc_client_log(client, "Sent XMM626 HSIC EBL");
123 rc = xmm626_hsic_port_config_send(client, modem_boot_fd);
125 ipc_client_log(client, "Sending XMM626 HSIC port config failed");
128 ipc_client_log(client, "Sent XMM626 HSIC port config");
130 p = (unsigned char *) modem_image_data + GALAXYS2_SEC_START_OFFSET;
132 rc = xmm626_hsic_sec_start_send(client, modem_boot_fd, (void *) p, GALAXYS2_SEC_START_SIZE);
134 ipc_client_log(client, "Sending XMM626 HSIC SEC start failed");
137 ipc_client_log(client, "Sent XMM626 HSIC SEC start");
139 p = (unsigned char *) modem_image_data + GALAXYS2_FIRMWARE_OFFSET;
141 rc = xmm626_hsic_firmware_send(client, modem_boot_fd, (void *) p, GALAXYS2_FIRMWARE_SIZE);
143 ipc_client_log(client, "Sending XMM626 HSIC firmware failed");
146 ipc_client_log(client, "Sent XMM626 HSIC firmware");
148 rc = xmm626_hsic_nv_data_send(client, modem_boot_fd);
150 ipc_client_log(client, "Sending XMM626 HSIC nv_data failed");
153 ipc_client_log(client, "Sent XMM626 HSIC nv_data");
155 rc = xmm626_hsic_sec_end_send(client, modem_boot_fd);
157 ipc_client_log(client, "Sending XMM626 HSIC SEC end failed");
160 ipc_client_log(client, "Sent XMM626 HSIC SEC end");
162 rc = xmm626_hsic_hw_reset_send(client, modem_boot_fd);
164 ipc_client_log(client, "Sending XMM626 HSIC HW reset failed");
167 ipc_client_log(client, "Sent XMM626 HSIC HW reset");
171 rc = xmm626_sec_modem_link_get_hostwake_wait(modem_link_fd);
173 ipc_client_log(client, "Waiting for host wake failed");
176 rc = xmm626_sec_modem_link_control_enable(modem_link_fd, 0);
177 rc |= xmm626_sec_modem_hci_power(0);
178 rc |= xmm626_sec_modem_link_control_active(modem_link_fd, 0);
181 ipc_client_log(client, "Turning the modem off failed");
185 rc = xmm626_sec_modem_link_get_hostwake_wait(modem_link_fd);
187 ipc_client_log(client, "Waiting for host wake failed");
190 ipc_client_log(client, "Waited for host wake");
192 rc = xmm626_sec_modem_link_control_enable(modem_link_fd, 1);
193 rc |= xmm626_sec_modem_hci_power(1);
194 rc |= xmm626_sec_modem_link_control_active(modem_link_fd, 1);
197 ipc_client_log(client, "Turning the modem on failed");
201 rc = xmm626_sec_modem_link_connected_wait(modem_link_fd);
203 ipc_client_log(client, "Waiting for link connected failed");
206 ipc_client_log(client, "Waited for link connected");
217 if (modem_image_data != NULL)
218 munmap(modem_image_data, GALAXYS2_MODEM_IMAGE_SIZE);
220 if (modem_image_fd >= 0)
221 close(modem_image_fd);
223 if (modem_boot_fd >= 0)
224 close(modem_boot_fd);
226 if (modem_link_fd >= 0)
227 close(modem_link_fd);
232 int galaxys2_open(void *data, int type)
234 struct galaxys2_transport_data *transport_data;
239 transport_data = (struct galaxys2_transport_data *) data;
241 transport_data->fd = xmm626_sec_modem_open(type);
242 if (transport_data->fd < 0)
248 int galaxys2_close(void *data)
250 struct galaxys2_transport_data *transport_data;
255 transport_data = (struct galaxys2_transport_data *) data;
257 xmm626_sec_modem_close(transport_data->fd);
258 transport_data->fd = -1;
263 int galaxys2_read(void *data, void *buffer, size_t length)
265 struct galaxys2_transport_data *transport_data;
271 transport_data = (struct galaxys2_transport_data *) data;
273 rc = xmm626_sec_modem_read(transport_data->fd, buffer, length);
278 int galaxys2_write(void *data, const void *buffer, size_t length)
280 struct galaxys2_transport_data *transport_data;
286 transport_data = (struct galaxys2_transport_data *) data;
288 rc = xmm626_sec_modem_write(transport_data->fd, buffer, length);
293 int galaxys2_poll(void *data, struct timeval *timeout)
295 struct galaxys2_transport_data *transport_data;
301 transport_data = (struct galaxys2_transport_data *) data;
303 rc = xmm626_sec_modem_poll(transport_data->fd, timeout);
308 int galaxys2_power_on(void *data)
313 int galaxys2_power_off(void *data)
318 fd = open(XMM626_SEC_MODEM_BOOT0_DEVICE, O_RDWR | O_NOCTTY | O_NONBLOCK);
322 rc = xmm626_sec_modem_power(fd, 0);
332 int galaxys2_gprs_activate(void *data, unsigned int cid)
337 int galaxys2_gprs_deactivate(void *data, unsigned int cid)
342 int galaxys2_data_create(void **transport_data, void **power_data,
345 if (transport_data == NULL)
348 *transport_data = calloc(1, sizeof(struct galaxys2_transport_data));
353 int galaxys2_data_destroy(void *transport_data, void *power_data,
356 if (transport_data == NULL)
359 free(transport_data);
364 struct ipc_client_ops galaxys2_fmt_ops = {
365 .boot = galaxys2_boot,
366 .send = xmm626_sec_modem_fmt_send,
367 .recv = xmm626_sec_modem_fmt_recv,
370 struct ipc_client_ops galaxys2_rfs_ops = {
372 .send = xmm626_sec_modem_rfs_send,
373 .recv = xmm626_sec_modem_rfs_recv,
376 struct ipc_client_handlers galaxys2_handlers = {
377 .read = galaxys2_read,
378 .write = galaxys2_write,
379 .open = galaxys2_open,
380 .close = galaxys2_close,
381 .poll = galaxys2_poll,
382 .transport_data = NULL,
383 .power_on = galaxys2_power_on,
384 .power_off = galaxys2_power_off,
386 .gprs_activate = galaxys2_gprs_activate,
387 .gprs_deactivate = galaxys2_gprs_deactivate,
389 .data_create = galaxys2_data_create,
390 .data_destroy = galaxys2_data_destroy,
393 struct ipc_client_gprs_specs galaxys2_gprs_specs = {
394 .gprs_get_iface = xmm626_sec_modem_gprs_get_iface,
395 .gprs_get_capabilities = xmm626_sec_modem_gprs_get_capabilities,
398 struct ipc_client_nv_data_specs galaxys2_nv_data_specs = {
399 .nv_data_path = XMM626_NV_DATA_PATH,
400 .nv_data_md5_path = XMM626_NV_DATA_MD5_PATH,
401 .nv_data_backup_path = XMM626_NV_DATA_BACKUP_PATH,
402 .nv_data_backup_md5_path = XMM626_NV_DATA_BACKUP_MD5_PATH,
403 .nv_data_secret = XMM626_NV_DATA_SECRET,
404 .nv_data_size = XMM626_NV_DATA_SIZE,
405 .nv_data_chunk_size = XMM626_NV_DATA_CHUNK_SIZE,
408 // vim:ts=4:sw=4:expandtab