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_hsic.h"
36 int xmm6260_hsic_ack_read(int device_fd, unsigned short ack)
38 struct timeval timeout;
49 FD_SET(device_fd, &fds);
51 for (i = 0; i < 50; i++) {
52 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
57 rc = read(device_fd, &value, sizeof(value));
58 if (rc < (int) sizeof(value))
68 int xmm6260_hsic_psi_send(struct ipc_client *client, int device_fd,
69 void *psi_data, unsigned short psi_size)
71 struct xmm6260_hsic_psi_header psi_header;
72 char at[] = XMM6260_AT;
73 unsigned char psi_ack;
74 unsigned char chip_id;
75 unsigned char psi_crc;
77 struct timeval timeout;
86 if (client == NULL || device_fd < 0 || psi_data == NULL || psi_size == 0)
95 FD_SET(device_fd, &fds);
98 timeout.tv_usec = 100000;
100 rc = write(device_fd, at, length);
102 ipc_client_log(client, "Writing ATAT in ASCII failed");
105 ipc_client_log(client, "Wrote ATAT in ASCII");
107 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
109 ipc_client_log(client, "Waiting for bootup failed");
114 ipc_client_log(client, "Waiting for bootup failed");
119 FD_SET(device_fd, &fds);
122 timeout.tv_usec = 100000;
124 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
126 ipc_client_log(client, "Reading chip id failed");
131 rc = read(device_fd, &psi_ack, sizeof(psi_ack));
132 if (rc < 0 || psi_ack != XMM6260_HSIC_BOOT0_ACK) {
133 ipc_client_log(client, "Reading boot ACK failed");
137 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
139 ipc_client_log(client, "Reading chip id failed");
144 rc = read(device_fd, &chip_id, sizeof(chip_id));
146 ipc_client_log(client, "Reading chip id failed");
149 ipc_client_log(client, "Read chip id (0x%x)", chip_id);
151 psi_header.magic = XMM6260_PSI_MAGIC;
152 psi_header.length = psi_size;
153 psi_header.padding = XMM6260_PSI_PADDING;
155 rc = write(device_fd, &psi_header, sizeof(psi_header));
156 if (rc < (int) sizeof(psi_header)) {
157 ipc_client_log(client, "Writing PSI header failed");
160 ipc_client_log(client, "Wrote PSI header");
162 p = (unsigned char *) psi_data;
165 while (wc < psi_size) {
166 rc = write(device_fd, (void *) p, psi_size - wc);
168 ipc_client_log(client, "Writing PSI failed");
176 psi_crc = xmm6260_crc_calculate(psi_data, psi_size);
178 ipc_client_log(client, "Wrote PSI, CRC is 0x%x", psi_crc);
180 rc = write(device_fd, &psi_crc, sizeof(psi_crc));
181 if (rc < (int) sizeof(psi_crc)) {
182 ipc_client_log(client, "Writing PSI CRC failed");
185 ipc_client_log(client, "Wrote PSI CRC (0x%x)", psi_crc);
188 timeout.tv_usec = 100000;
190 for (i = 0; i < XMM6260_HSIC_PSI_UNKNOWN_COUNT; i++) {
191 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
193 ipc_client_log(client, "Reading PSI unknown failed");
197 rc = read(device_fd, &psi_ack, sizeof(psi_ack));
198 if (rc < (int) sizeof(psi_ack)) {
199 ipc_client_log(client, "Reading PSI unknown failed");
204 for (i = 0; i < XMM6260_HSIC_PSI_CRC_ACK_COUNT ; i++) {
205 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
207 ipc_client_log(client, "Reading PSI CRC ACK failed");
211 rc = read(device_fd, &psi_ack, sizeof(psi_ack));
212 if (rc < (int) sizeof(psi_ack) || psi_ack != XMM6260_HSIC_PSI_CRC_ACK) {
213 ipc_client_log(client, "Reading PSI CRC ACK failed");
217 ipc_client_log(client, "Read PSI CRC ACK");
219 rc = xmm6260_hsic_ack_read(device_fd, XMM6260_HSIC_PSI_ACK);
221 ipc_client_log(client, "Reading PSI ACK failed");
224 ipc_client_log(client, "Read PSI ACK");
236 int xmm6260_hsic_ebl_send(struct ipc_client *client, int device_fd,
237 void *ebl_data, int ebl_size)
239 unsigned char ebl_crc;
249 if (client == NULL || device_fd < 0 || ebl_data == NULL || ebl_size <= 0)
252 length = sizeof(ebl_size);
254 rc = write(device_fd, &ebl_size, length);
256 ipc_client_log(client, "Writing EBL size failed");
259 ipc_client_log(client, "Wrote EBL size");
261 rc = xmm6260_hsic_ack_read(device_fd, XMM6260_HSIC_EBL_SIZE_ACK);
263 ipc_client_log(client, "Reading EBL size ACK failed");
267 p = (unsigned char *) ebl_data;
269 chunk = XMM6260_HSIC_EBL_CHUNK;
271 while (wc < ebl_size) {
272 count = chunk < ebl_size - wc ? chunk : ebl_size - wc;
274 rc = write(device_fd, (void *) p, count);
276 ipc_client_log(client, "Writing EBL failed");
284 ebl_crc = xmm6260_crc_calculate(ebl_data, ebl_size);
286 ipc_client_log(client, "Wrote EBL, CRC is 0x%x", ebl_crc);
288 rc = write(device_fd, &ebl_crc, sizeof(ebl_crc));
289 if (rc < (int) sizeof(ebl_crc)) {
290 ipc_client_log(client, "Writing EBL CRC failed");
293 ipc_client_log(client, "Wrote EBL CRC (0x%x)", ebl_crc);
295 rc = xmm6260_hsic_ack_read(device_fd, XMM6260_HSIC_EBL_ACK);
297 ipc_client_log(client, "Reading EBL ACK failed");
311 int xmm6260_hsic_command_send(int device_fd, unsigned short code,
312 void *data, int size, int command_data_size, int ack)
314 struct xmm6260_hsic_command_header header;
318 struct timeval timeout;
325 if (device_fd < 0 || data == NULL || size <= 0 || command_data_size < size)
328 header.checksum = (size & 0xffff) + code;
330 header.data_size = size;
332 p = (unsigned char *) data;
334 for (i = 0; i < size; i++)
335 header.checksum += *p++;
337 length = command_data_size + sizeof(header);
338 buffer = malloc(length);
340 memset(buffer, 0, length);
341 p = (unsigned char *) buffer;
342 memcpy(p, &header, sizeof(header));
344 memcpy(p, data, size);
346 rc = write(device_fd, buffer, length);
355 memset(buffer, 0, length);
358 FD_SET(device_fd, &fds);
363 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
367 rc = read(device_fd, &header, sizeof(header));
368 if (rc < (int) sizeof(header))
371 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
375 rc = read(device_fd, buffer, command_data_size);
376 if (rc < command_data_size)
379 if (header.code != code)
395 int xmm6260_hsic_modem_data_send(int device_fd, void *data, int size, int address)
404 if (device_fd < 0 || data == NULL || size <= 0)
407 rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_FLASH_SET_ADDRESS, &address, sizeof(address), XMM6260_HSIC_FLASH_SET_ADDRESS_SIZE, 1);
411 p = (unsigned char *) data;
413 chunk = XMM6260_HSIC_MODEM_DATA_CHUNK;
416 count = chunk < size - c ? chunk : size - c;
418 rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_FLASH_WRITE_BLOCK, p, count, XMM6260_HSIC_FLASH_WRITE_BLOCK_SIZE, 0);
436 int xmm6260_hsic_port_config_send(struct ipc_client *client, int device_fd)
441 struct timeval timeout;
446 if (client == NULL || device_fd < 0)
450 FD_SET(device_fd, &fds);
455 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
459 length = XMM6260_HSIC_PORT_CONFIG_SIZE;
460 buffer = malloc(length);
462 rc = select(device_fd + 1, &fds, NULL, NULL, &timeout);
466 rc = read(device_fd, buffer, length);
468 ipc_client_log(client, "Reading port config failed");
471 ipc_client_log(client, "Read port config");
473 rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_SET_PORT_CONFIG, buffer, length, XMM6260_HSIC_SET_PORT_CONFIG_SIZE, 1);
475 ipc_client_log(client, "Sending port config command failed");
492 int xmm6260_hsic_sec_start_send(struct ipc_client *client, int device_fd,
493 void *sec_data, int sec_size)
497 if (client == NULL || device_fd < 0 || sec_data == NULL || sec_size <= 0)
500 rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_SEC_START, sec_data, sec_size, XMM6260_HSIC_SEC_START_SIZE, 1);
507 int xmm6260_hsic_sec_end_send(struct ipc_client *client, int device_fd)
509 unsigned short sec_data;
513 if (client == NULL || device_fd < 0)
516 sec_data = XMM6260_SEC_END_MAGIC;
517 sec_size = sizeof(sec_data);
519 rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_SEC_END, &sec_data, sec_size, XMM6260_HSIC_SEC_END_SIZE, 1);
526 int xmm6260_hsic_firmware_send(struct ipc_client *client, int device_fd,
527 void *firmware_data, int firmware_size)
531 if (client == NULL || device_fd < 0 || firmware_data == NULL || firmware_size <= 0)
534 rc = xmm6260_hsic_modem_data_send(device_fd, firmware_data, firmware_size, XMM6260_FIRMWARE_ADDRESS);
541 int xmm6260_hsic_nv_data_send(struct ipc_client *client, int device_fd)
543 void *nv_data = NULL;
547 if (client == NULL || device_fd < 0)
550 rc = nv_data_check(client);
552 ipc_client_log(client, "Checking nv_data failed");
555 ipc_client_log(client, "Checked nv_data");
557 rc = nv_data_md5_check(client);
559 ipc_client_log(client, "Checking nv_data md5 failed");
562 ipc_client_log(client, "Checked nv_data md5");
564 nv_data = file_data_read(ipc_client_nv_data_path(client), ipc_client_nv_data_size(client), ipc_client_nv_data_chunk_size(client), 0);
565 if (nv_data == NULL) {
566 ipc_client_log(client, "Reading nv_data failed");
569 ipc_client_log(client, "Read nv_data");
571 nv_size = ipc_client_nv_data_size(client);
573 rc = xmm6260_hsic_modem_data_send(device_fd, nv_data, nv_size, XMM6260_NV_DATA_ADDRESS);
590 int xmm6260_hsic_hw_reset_send(struct ipc_client *client, int device_fd)
592 unsigned int hw_reset_data;
596 if (client == NULL || device_fd < 0)
599 hw_reset_data = XMM6260_HW_RESET_MAGIC;
600 hw_reset_size = sizeof(hw_reset_data);
602 rc = xmm6260_hsic_command_send(device_fd, XMM6260_COMMAND_HW_RESET, &hw_reset_data, hw_reset_size, XMM6260_HSIC_HW_RESET_SIZE, 0);
609 // vim:ts=4:sw=4:expandtab