2 * This file is part of libsamsung-ipc.
4 * Copyright (C) 2012 Alexander Tarasikov <alexander.tarasikov@gmail.com>
5 * Copyright (C) 2013 Paul Kocialkowski <contact@paulk.fr>
7 * Based on the incomplete C++ implementation which is:
8 * Copyright (C) 2012 Sergey Gridasov <grindars@gmail.com>
10 * libsamsung-ipc is free software: you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation, either version 2 of the License, or
13 * (at your option) any later version.
15 * libsamsung-ipc is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>.
28 #include <sys/select.h>
30 #include <samsung-ipc.h>
34 #include "xmm6260_mipi.h"
36 int xmm6260_mipi_crc_calculate(void *buffer, int length)
41 crc = xmm6260_crc_calculate(buffer, length);
42 mipi_crc = (crc << 24) | 0xffffff;
47 int xmm6260_mipi_ack_read(int device_fd, unsigned short ack)
49 struct timeval timeout;
60 FD_SET(device_fd, &fds);
62 for (i = 0; i < 50; i++) {
63 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
68 rc = read(device_fd, &value, sizeof(value));
69 if (rc < (int) sizeof(value))
72 if ((value & 0xffff) == ack)
79 int xmm6260_mipi_psi_send(struct ipc_client *client, int device_fd,
80 void *psi_data, unsigned short psi_size)
82 struct xmm6260_mipi_psi_header psi_header;
83 char at[] = XMM6260_AT;
86 struct timeval timeout;
95 if (client == NULL || device_fd < 0 || psi_data == NULL || psi_size == 0)
104 FD_SET(device_fd, &fds);
107 timeout.tv_usec = 100000;
109 rc = write(device_fd, at, length);
111 ipc_client_log(client, "Writing ATAT in ASCII failed");
114 ipc_client_log(client, "Wrote ATAT in ASCII");
116 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
118 ipc_client_log(client, "Waiting for bootup failed");
123 ipc_client_log(client, "Waiting for bootup failed");
128 rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_BOOT0_ACK);
130 ipc_client_log(client, "Reading boot ACK failed");
134 psi_header.padding = XMM6260_PSI_PADDING;
135 psi_header.length = ((psi_size >> 8) & 0xff) | ((psi_size & 0xff) << 8);
136 psi_header.magic = XMM6260_PSI_MAGIC;
138 rc = write(device_fd, &psi_header, sizeof(psi_header));
139 if (rc < (int) sizeof(psi_header)) {
140 ipc_client_log(client, "Writing PSI header failed");
143 ipc_client_log(client, "Wrote PSI header");
145 p = (unsigned char *) psi_data;
148 while (wc < psi_size) {
149 rc = write(device_fd, (void *) p, psi_size - wc);
151 ipc_client_log(client, "Writing PSI failed");
159 psi_crc = xmm6260_mipi_crc_calculate(psi_data, psi_size);
161 ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc);
163 rc = write(device_fd, &psi_crc, sizeof(psi_crc));
164 if (rc < (int) sizeof(psi_crc)) {
165 ipc_client_log(client, "Writing PSI CRC failed");
168 ipc_client_log(client, "Wrote PSI CRC (0x%x)", psi_crc);
170 rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_PSI_ACK);
172 ipc_client_log(client, "Reading PSI ACK failed");
186 int xmm6260_mipi_ebl_send(struct ipc_client *client, int device_fd,
187 void *ebl_data, int ebl_size)
189 unsigned short boot_magic[4];
190 unsigned char ebl_crc;
200 if (client == NULL || device_fd < 0 || ebl_data == NULL || ebl_size <= 0)
205 boot_magic[2] = XMM6260_MIPI_BOOT1_MAGIC;
206 boot_magic[3] = XMM6260_MIPI_BOOT1_MAGIC;
208 length = sizeof(boot_magic);
210 rc = write(device_fd, &length, sizeof(length));
211 if (rc < (int) sizeof(length)) {
212 ipc_client_log(client, "Writing boot magic length failed");
216 rc = write(device_fd, &boot_magic, length);
218 ipc_client_log(client, "Writing boot magic failed");
221 ipc_client_log(client, "Wrote boot magic");
223 rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_BOOT1_ACK);
225 ipc_client_log(client, "Reading boot magic ACK failed");
229 length = sizeof(ebl_size);
231 rc = write(device_fd, &length, sizeof(length));
232 if (rc < (int) sizeof(length)) {
233 ipc_client_log(client, "Writing EBL size length failed");
237 rc = write(device_fd, &ebl_size, length);
239 ipc_client_log(client, "Writing EBL size failed");
242 ipc_client_log(client, "Wrote EBL size");
244 rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_EBL_SIZE_ACK);
246 ipc_client_log(client, "Reading EBL size ACK failed");
252 rc = write(device_fd, &ebl_size, length);
254 ipc_client_log(client, "Writing EBL size failed");
260 p = (unsigned char *) ebl_data;
262 chunk = XMM6260_MIPI_EBL_CHUNK;
264 while (wc < ebl_size) {
265 count = chunk < ebl_size - wc ? chunk : ebl_size - wc;
267 rc = write(device_fd, (void *) p, count);
269 ipc_client_log(client, "Writing EBL failed");
277 ebl_crc = xmm6260_crc_calculate(ebl_data, ebl_size);
279 ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc);
281 rc = write(device_fd, &ebl_crc, sizeof(ebl_crc));
282 if (rc < (int) sizeof(ebl_crc)) {
283 ipc_client_log(client, "Writing EBL CRC failed");
286 ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc);
288 rc = xmm6260_mipi_ack_read(device_fd, XMM6260_MIPI_EBL_ACK);
290 ipc_client_log(client, "Reading EBL ACK failed");
304 int xmm6260_mipi_command_send(int device_fd, unsigned short code,
305 void *data, int size, int ack, int short_footer)
307 struct xmm6260_mipi_command_header header;
308 struct xmm6260_mipi_command_footer footer;
313 struct timeval timeout;
322 if (device_fd < 0 || data == NULL || size <= 0)
325 header.size = size + sizeof(header);
326 header.magic = XMM6260_MIPI_COMMAND_HEADER_MAGIC;
328 header.data_size = size;
330 footer.checksum = (size & 0xffff) + code;
331 footer.magic = XMM6260_MIPI_COMMAND_FOOTER_MAGIC;
332 footer.unknown = XMM6260_MIPI_COMMAND_FOOTER_UNKNOWN;
334 p = (unsigned char *) data;
336 for (i = 0; i < size; i++)
337 footer.checksum += *p++;
339 footer_size = sizeof(footer);
341 footer_size -= sizeof(short);
343 length = sizeof(header) + size + footer_size;
344 buffer = malloc(length);
346 p = (unsigned char *) buffer;
347 memcpy(p, &header, sizeof(header));
349 memcpy(p, data, size);
351 memcpy(p, &footer, footer_size);
353 rc = write(device_fd, buffer, length);
366 FD_SET(device_fd, &fds);
371 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
375 rc = read(device_fd, &length, sizeof(length));
376 if (rc < (int) sizeof(length) || length <= 0)
379 length += sizeof(unsigned int);
381 length += length % 4;
383 if (length < (int) sizeof(buffer))
386 buffer = malloc(length);
388 p = (unsigned char *) buffer;
389 memcpy(p, &length, sizeof(length));
395 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
399 rc = read(device_fd, (void *) p, chunk);
407 memcpy(&header, buffer, sizeof(header));
408 if (header.code != code)
424 int xmm6260_mipi_modem_data_send(int device_fd, void *data, int size, int address)
433 if (device_fd < 0 || data == NULL || size <= 0)
436 rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_FLASH_SET_ADDRESS, &address, sizeof(address), 1, 0);
440 p = (unsigned char *) data;
442 chunk = XMM6260_MIPI_MODEM_DATA_CHUNK;
445 count = chunk < size - c ? chunk : size - c;
447 rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_FLASH_WRITE_BLOCK, p, count, 1, 1);
465 int xmm6260_mipi_port_config_send(struct ipc_client *client, int device_fd)
470 struct timeval timeout;
479 if (client == NULL || device_fd < 0)
483 FD_SET(device_fd, &fds);
488 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
492 rc = read(device_fd, &length, sizeof(length));
493 if (rc < (int) sizeof(length) || length <= 0) {
494 ipc_client_log(client, "Reading port config length failed");
497 ipc_client_log(client, "Read port config length (0x%x)", length);
499 buffer = malloc(length);
501 p = (unsigned char *) buffer;
506 count = chunk < length - c ? chunk : length - c;
508 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
512 rc = read(device_fd, p, count);
514 ipc_client_log(client, "Reading port config failed");
521 ipc_client_log(client, "Read port config");
523 rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_SET_PORT_CONFIG, buffer, length, 1, 0);
525 ipc_client_log(client, "Sending port config command failed");
542 int xmm6260_mipi_sec_start_send(struct ipc_client *client, int device_fd,
543 void *sec_data, int sec_size)
547 if (client == NULL || device_fd < 0 || sec_data == NULL || sec_size <= 0)
550 rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_SEC_START, sec_data, sec_size, 1, 0);
557 int xmm6260_mipi_sec_end_send(struct ipc_client *client, int device_fd)
559 unsigned short sec_data;
563 if (client == NULL || device_fd < 0)
566 sec_data = XMM6260_SEC_END_MAGIC;
567 sec_size = sizeof(sec_data);
569 rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_SEC_END, &sec_data, sec_size, 1, 1);
576 int xmm6260_mipi_firmware_send(struct ipc_client *client, int device_fd,
577 void *firmware_data, int firmware_size)
581 if (client == NULL || device_fd < 0 || firmware_data == NULL || firmware_size <= 0)
584 rc = xmm6260_mipi_modem_data_send(device_fd, firmware_data, firmware_size, XMM6260_FIRMWARE_ADDRESS);
591 int xmm6260_mipi_nv_data_send(struct ipc_client *client, int device_fd)
593 void *nv_data = NULL;
597 if (client == NULL || device_fd < 0)
600 nv_size = ipc_client_nv_data_size(client);
602 nv_data = ipc_nv_data_load(client);
603 if (nv_data == NULL) {
604 ipc_client_log(client, "Loading nv_data failed");
607 ipc_client_log(client, "Loaded nv_data");
609 rc = xmm6260_mipi_modem_data_send(device_fd, nv_data, nv_size, XMM6260_NV_DATA_ADDRESS);
626 int xmm6260_mipi_mps_data_send(struct ipc_client *client, int device_fd,
627 void *mps_data, int mps_size)
631 if (client == NULL || device_fd < 0 || mps_data == NULL || mps_size <= 0)
634 rc = xmm6260_mipi_modem_data_send(device_fd, mps_data, mps_size, XMM6260_MPS_DATA_ADDRESS);
641 int xmm6260_mipi_hw_reset_send(struct ipc_client *client, int device_fd)
643 unsigned int hw_reset_data;
647 if (client == NULL || device_fd < 0)
650 hw_reset_data = XMM6260_HW_RESET_MAGIC;
651 hw_reset_size = sizeof(hw_reset_data);
653 rc = xmm6260_mipi_command_send(device_fd, XMM6260_COMMAND_HW_RESET, &hw_reset_data, hw_reset_size, 0, 1);
660 // vim:ts=4:sw=4:expandtab