/** * Samsung RIL Client (Samsung RIL Socket Client-side implementation) * * Copyright (C) 2011 Paul Kocialkowski * * samsung-ril-client 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 3 of the License, or * (at your option) any later version. * * samsung-ril-client 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 samsung-ril-client. If not, see . * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define LOG_TAG "SRS-Client" #include #include #include /* * Structures */ struct srs_client { int fd; }; /* * SRS transport */ int srs_send_message(struct srs_client *client, struct srs_message *message) { struct srs_header header; void *data; int client_fd = client->fd; fd_set fds; int rc; if(client_fd < 0) return -1; header.length = message->data_len + sizeof(header); header.group = SRS_GROUP(message->command); header.index = SRS_INDEX(message->command); data = malloc(header.length); memset(data, 0, header.length); memcpy(data, &header, sizeof(header)); memcpy((void *) (data + sizeof(header)), message->data, message->data_len); FD_ZERO(&fds); FD_SET(client_fd, &fds); // We can't rely on select RC select(client_fd + 1, NULL, &fds, NULL, NULL); rc = write(client_fd, data, header.length); free(data); return rc; } int srs_send(struct srs_client *client, unsigned short command, void *data, int data_len) { struct srs_message message; int rc; LOGE("%s", __func__); message.command = command; message.data = data; message.data_len = data_len; rc = srs_send_message(client, &message); return rc; } int srs_recv_timed(struct srs_client *client, struct srs_message *message, long sec, long usec) { void *raw_data = malloc(SRS_DATA_MAX_SIZE); struct srs_header *header; int rc; int client_fd = client->fd; if(client_fd < 0) return -1; struct timeval timeout; fd_set fds; FD_ZERO(&fds); FD_SET(client_fd, &fds); timeout.tv_sec = sec; timeout.tv_usec = usec; select(client_fd + 1, &fds, NULL, NULL, &timeout); rc = read(client_fd, raw_data, SRS_DATA_MAX_SIZE); if(rc < sizeof(struct srs_header)) { return -1; } header = raw_data; message->command = SRS_COMMAND(header); message->data_len = header->length - sizeof(struct srs_header); message->data = malloc(message->data_len); memcpy(message->data, raw_data + sizeof(struct srs_header), message->data_len); free(raw_data); return 0; } int srs_recv(struct srs_client *client, struct srs_message *message) { return srs_recv_timed(client, message, 0, 0); } int srs_ping(struct srs_client *client) { int caffe_w = SRS_CONTROL_CAFFE; int caffe_r = 0; int rc = 0; struct srs_message message; rc = srs_send(client, SRS_CONTROL_PING, &caffe_w, sizeof(caffe_w)); if(rc < 0) { return -1; } rc = srs_recv_timed(client, &message, 0, 300); if(rc < 0) { return -1; } if(message.data == NULL) return -1; caffe_r = *((int *) message.data); if(caffe_r == SRS_CONTROL_CAFFE) { LOGD("Caffe is ready!"); rc = 0; } else { LOGE("Caffe went wrong!"); rc = -1; } free(message.data); return rc; } /* * Interface */ void *OpenClient_RILD(void) { struct srs_client *client = NULL; LOGE("%s", __func__); signal(SIGPIPE, SIG_IGN); client = calloc(1, sizeof(struct srs_client)); client->fd = -1; return (void *) client; } int Connect_RILD(void *data) { struct srs_client *client = (struct srs_client *) data; int t = 0; int fd = -1; int rc; LOGE("%s", __func__); if(client == NULL) return RIL_CLIENT_ERR_INVAL; socket_connect: while(t < 5) { fd = socket_local_client(SRS_SOCKET_NAME, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM); if(fd > 0) break; LOGE("Socket creation to RIL failed: trying another time"); t++; usleep(300); } if(fd < 0) { LOGE("Socket creation to RIL failed too many times"); return RIL_CLIENT_ERR_CONNECT; } client->fd = fd; LOGE("Socket creation done, sending ping"); rc = srs_ping(client); if(rc < 0) { LOGE("Ping failed!"); goto socket_connect; } else { LOGD("Ping went alright"); } return RIL_CLIENT_ERR_SUCCESS; } int Disconnect_RILD(void *data) { struct srs_client *client = (struct srs_client *) data; LOGE("%s", __func__); if(client == NULL) return RIL_CLIENT_ERR_INVAL; if(client->fd > 0) close(client->fd); return RIL_CLIENT_ERR_SUCCESS; } int CloseClient_RILD(void *data) { struct srs_client *client = (struct srs_client *) data; LOGE("%s", __func__); if(client == NULL) return RIL_CLIENT_ERR_INVAL; free(client); return RIL_CLIENT_ERR_SUCCESS; } int isConnected_RILD(void *data) { struct srs_client *client = (struct srs_client *) data; int rc; LOGE("%s", __func__); if(client == NULL) return RIL_CLIENT_ERR_INVAL; if(client->fd < 0) return 0; rc = srs_ping(client); if(rc < 0) { LOGE("Ping failed!"); close(client->fd); return 0; } else { LOGD("Ping went alright"); } return 1; } int SetCallVolume(void *data, enum ril_sound_type type, int vol_level) { struct srs_client *client = (struct srs_client *) data; struct srs_snd_call_volume call_volume; LOGD("Asking call volume"); if(client == NULL) return RIL_CLIENT_ERR_INVAL; call_volume.type = (enum srs_snd_type) type; call_volume.volume = vol_level; srs_send(client, SRS_SND_SET_CALL_VOLUME, (void *) &call_volume, sizeof(call_volume)); return RIL_CLIENT_ERR_SUCCESS; } int SetCallAudioPath(void *data, enum ril_audio_path path) { struct srs_client *client = (struct srs_client *) data; LOGD("Asking audio path"); if(client == NULL) return RIL_CLIENT_ERR_INVAL; srs_send(client, SRS_SND_SET_CALL_AUDIO_PATH, (void *) &path, sizeof(enum srs_snd_path)); return RIL_CLIENT_ERR_SUCCESS; } int SetCallClockSync(void *data, enum ril_clock_state condition) { struct srs_client *client = (struct srs_client *) data; unsigned char clock_data = condition; LOGD("Asking clock sync"); if(client == NULL) return RIL_CLIENT_ERR_INVAL; srs_send(client, SRS_SND_SET_CALL_CLOCK_SYNC, &clock_data, sizeof(data)); return RIL_CLIENT_ERR_SUCCESS; } int RegisterUnsolicitedHandler(void *data, int command, void *callback) { LOGD("Unsolicited handler isn't implemented yet!"); return RIL_CLIENT_ERR_SUCCESS; }