blob: 192a06e12f6c1d5387f1087c1fa61d91b4966811 [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.
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#define THREAD_NUM 300
#define DEV "/dev/usf1"
/* min, max array dimension */
#define MIN_MAX_DIM 2
#define USF_MAX_PORT_NUM 8
static const unsigned short PortSamplesDataSize = 768;
/* Encoder (TX), decoder (RX) supported US data formats */
#define USF_POINT_EPOS_FORMAT 0
#define USF_RAW_FORMAT 1
/* Indexes of event types, produced by the calculators */
#define USF_TSC_EVENT_IND 0
#define USF_TSC_PTR_EVENT_IND 1
#define USF_MOUSE_EVENT_IND 2
#define USF_KEYBOARD_EVENT_IND 3
#define USF_TSC_EXT_EVENT_IND 4
#define USF_MAX_EVENT_IND 5
/* Types of events, produced by the calculators */
#define USF_NO_EVENT 0
#define USF_TSC_EVENT (1 << USF_TSC_EVENT_IND)
#define USF_TSC_PTR_EVENT (1 << USF_TSC_PTR_EVENT_IND)
#define USF_MOUSE_EVENT (1 << USF_MOUSE_EVENT_IND)
#define USF_KEYBOARD_EVENT (1 << USF_KEYBOARD_EVENT_IND)
#define USF_TSC_EXT_EVENT (1 << USF_TSC_EXT_EVENT_IND)
#define USF_ALL_EVENTS \
(USF_TSC_EVENT | USF_TSC_PTR_EVENT | USF_MOUSE_EVENT | USF_KEYBOARD_EVENT | \
USF_TSC_EXT_EVENT)
void *child_ioctl_0(void *no_use);
void *child_ioctl_1(void *no_use);
/* Info structure common for TX and RX */
struct us_xx_info_type {
/* Input: general info */
/* Name of the client - event calculator */
const char __user *client_name;
/* Selected device identification, accepted in the kernel's CAD */
uint32_t dev_id;
/* 0 - point_epos type; (e.g. 1 - gr_mmrd) */
uint32_t stream_format;
/* Required sample rate in Hz */
uint32_t sample_rate;
/* Size of a buffer (bytes) for US data transfer between the module and USF */
uint32_t buf_size;
/* Number of the buffers for the US data transfer */
uint16_t buf_num;
/* Number of the microphones (TX) or speakers(RX) */
uint16_t port_cnt;
/* Microphones(TX) or speakers(RX) indexes in their enumeration */
uint8_t port_id[USF_MAX_PORT_NUM];
/* Bits per sample 16 or 32 */
uint16_t bits_per_sample;
/* Input: Transparent info for encoder in the LPASS */
/* Parameters data size in bytes */
uint16_t params_data_size;
/* Pointer to the parameters */
uint8_t __user *params_data;
/* Max size of buffer for get and set parameter */
uint32_t max_get_set_param_buf_size;
};
struct us_input_info_type {
/* Touch screen dimensions: min & max;for input module */
int tsc_x_dim[MIN_MAX_DIM];
int tsc_y_dim[MIN_MAX_DIM];
int tsc_z_dim[MIN_MAX_DIM];
/* Touch screen tilt dimensions: min & max;for input module */
int tsc_x_tilt[MIN_MAX_DIM];
int tsc_y_tilt[MIN_MAX_DIM];
/* Touch screen pressure limits: min & max; for input module */
int tsc_pressure[MIN_MAX_DIM];
/* The requested buttons bitmap */
uint16_t req_buttons_bitmap;
/* Bitmap of types of events (USF_X_EVENT), produced by calculator */
uint16_t event_types;
/* Bitmap of types of events from devs, conflicting with USF */
uint16_t conflicting_event_types;
};
struct us_tx_info_type {
/* Common info */
struct us_xx_info_type us_xx_info;
/* Info specific for TX*/
struct us_input_info_type input_info;
};
struct us_rx_info_type {
/* Common info */
struct us_xx_info_type us_xx_info;
/* Info specific for RX*/
};
struct us_stream_param_type {
/* Id of module */
uint32_t module_id;
/* Id of parameter */
uint32_t param_id;
/* Size of memory of the parameter buffer */
uint32_t buf_size;
/* Pointer to the memory of the parameter buffer */
uint8_t __user *pbuf;
};
#define USF_IOCTL_MAGIC 'U'
#define US_SET_TX_INFO _IOW(USF_IOCTL_MAGIC, 0, struct us_tx_info_type)
#define US_START_TX _IO(USF_IOCTL_MAGIC, 1)
#define US_GET_TX_UPDATE \
_IOWR(USF_IOCTL_MAGIC, 2, struct us_tx_update_info_type)
#define US_SET_RX_INFO _IOW(USF_IOCTL_MAGIC, 3, struct us_rx_info_type)
#define US_SET_RX_UPDATE \
_IOWR(USF_IOCTL_MAGIC, 4, struct us_rx_update_info_type)
#define US_START_RX _IO(USF_IOCTL_MAGIC, 5)
#define US_STOP_TX _IO(USF_IOCTL_MAGIC, 6)
#define US_STOP_RX _IO(USF_IOCTL_MAGIC, 7)
#define US_SET_TX_STREAM_PARAM \
_IOW(USF_IOCTL_MAGIC, 10, struct us_stream_param_type)
#define US_GET_TX_STREAM_PARAM \
_IOWR(USF_IOCTL_MAGIC, 11, struct us_stream_param_type)
#define US_SET_RX_STREAM_PARAM \
_IOW(USF_IOCTL_MAGIC, 12, struct us_stream_param_type)
#define US_GET_RX_STREAM_PARAM \
_IOWR(USF_IOCTL_MAGIC, 13, struct us_stream_param_type)
int fd;
pthread_t thread_id[THREAD_NUM + 1] = {0};
int thread_ret[THREAD_NUM] = {0};
// RX configuration
static struct us_rx_info_type s_rx_info;
static struct us_rx_info_type s_rx_info1;
static void set_valid_rx_configuration(void);
static void set_valid_rx_configuration_for_fail(void);
static void set_valid_rx_configuration() {
typedef struct {
unsigned short frameSize;
unsigned short groupFactor;
} TransparentDataRxType;
static TransparentDataRxType transparentRxData;
unsigned short frame_size = 0;
transparentRxData.frameSize = PortSamplesDataSize;
transparentRxData.groupFactor = 1;
s_rx_info.us_xx_info.client_name = "tester";
s_rx_info.us_xx_info.dev_id = 0;
s_rx_info.us_xx_info.stream_format = USF_RAW_FORMAT;
s_rx_info.us_xx_info.sample_rate = 96000;
s_rx_info.us_xx_info.buf_num = 3;
s_rx_info.us_xx_info.port_cnt = 1;
s_rx_info.us_xx_info.port_id[0] = 1;
s_rx_info.us_xx_info.bits_per_sample = 16;
s_rx_info.us_xx_info.params_data_size = sizeof(TransparentDataRxType);
s_rx_info.us_xx_info.params_data = (unsigned char*)&transparentRxData;
frame_size = PortSamplesDataSize *
(s_rx_info.us_xx_info.bits_per_sample / 8) *
s_rx_info.us_xx_info.port_cnt;
// group size
s_rx_info.us_xx_info.buf_size = frame_size * transparentRxData.groupFactor;
} // set_valid_rx_configuration
static void set_valid_rx_configuration_for_fail() {
typedef struct {
unsigned short frameSize;
unsigned short groupFactor;
} TransparentDataRxType;
static TransparentDataRxType transparentRxData;
unsigned short frame_size = 0;
transparentRxData.frameSize = PortSamplesDataSize;
transparentRxData.groupFactor = 1;
s_rx_info1.us_xx_info.client_name = "tester";
s_rx_info1.us_xx_info.dev_id = 0;
s_rx_info1.us_xx_info.stream_format = USF_RAW_FORMAT;
s_rx_info1.us_xx_info.sample_rate = 96000;
s_rx_info1.us_xx_info.buf_num = 3;
s_rx_info1.us_xx_info.port_cnt = 1;
s_rx_info1.us_xx_info.port_id[0] = 1;
s_rx_info1.us_xx_info.bits_per_sample = 16;
s_rx_info1.us_xx_info.params_data_size = sizeof(TransparentDataRxType);
frame_size = PortSamplesDataSize *
(s_rx_info1.us_xx_info.bits_per_sample / 8) *
s_rx_info1.us_xx_info.port_cnt;
// group size
s_rx_info1.us_xx_info.buf_size = frame_size * transparentRxData.groupFactor;
// for fail
s_rx_info1.us_xx_info.max_get_set_param_buf_size = (uint32_t) 100000000000000;
} // set_valid_rx_configuration
static int set_affinity(int num) {
int ret = 0;
cpu_set_t mask;
CPU_ZERO(&mask);
CPU_SET(num, &mask);
ret = sched_setaffinity(0, sizeof(cpu_set_t), &mask);
if (ret == -1) {
printf("[-] set affinity failed: [%d]-%s\n", errno, strerror(errno));
}
return ret;
}
void *child_ioctl_0(void *no_use) {
int ret = 1;
set_affinity(1);
while (1) {
ret = ioctl(fd, US_SET_RX_INFO, &s_rx_info1);
}
}
void* child_ioctl_1(void* no_use) {
int ret = 1;
set_affinity(2);
while (1) {
ret = ioctl(fd, US_SET_RX_INFO, &s_rx_info1);
}
}
int main() {
int i, ret;
/* bind_cpu */
set_affinity(0);
set_valid_rx_configuration();
set_valid_rx_configuration_for_fail();
/* open dev */
fd = open(DEV, O_RDONLY);
if (fd == -1) {
return 0;
}
/* create thread */
for (i = 0; i < THREAD_NUM; i = i + 2) {
thread_ret[i] = pthread_create(thread_id + i, NULL, child_ioctl_0, NULL);
thread_ret[i + 1] =
pthread_create(thread_id + i + 1, NULL, child_ioctl_1, NULL);
}
}