sem_t sem_tx; // 管道数据发送等待信号量.
uint8_t pipe_buf[TRANSMIT_DATA_BUFFER_SIZE] = {0};// 全局管道数据缓冲区, 与读管道的的线程使用.
void init_sem_tx_can( void ) // 初始化管道传输信号量->控制pipe_buf
{
sem_init( &sem_tx, 0, 0 );
}
int system_raw_queue_tx( void *frame, uint16_t frame_len, uint8_t data_type, const uint8_t dest_mac[6], bool isresp )
{
assert( frame);
int ret = -1;
if( (data_type == TRANSMIT_TYPE_ADP) || (data_type == TRANSMIT_TYPE_ACMP) || (data_type == TRANSMIT_TYPE_AECP) )
{
tx_data tx;
uint8_t *tran_buf = pipe_buf;
if( frame_len > TRANSMIT_DATA_BUFFER_SIZE )
{
DEBUG_INFO( "frame_len bigger than pipe transmit buffer!" );
return -1;
}
memset( &tx.udp_sin, 0, sizeof(struct sockaddr_in) );
memset( tran_buf, 0, sizeof(pipe_buf) );
memcpy( tx.raw_dest.value, dest_mac, sizeof(struct jdksavdecc_eui48) );
memcpy( tran_buf, (uint8_t*)frame, frame_len );
tx.frame = tran_buf;
tx.data_type = data_type;
tx.frame_len = frame_len;
tx.notification_flag = RUNINFLIGHT;
tx.resp = isresp;
if( (ret = write_pipe_tx(&tx, sizeof(tx_data))) == -1 )
{
DEBUG_INFO( "ERR transmit data to PIPE" );
assert(-1 != ret);
}
sem_wait( &sem_tx );
}
else
{
DEBUG_INFO( "ERR transmit data type" );
}
return ret;
}
int thread_pipe_fn( void *pgm )
{
struct fds *kfds = ( struct fds* )pgm;
struct fds thr_fds;
sdpwqueue* send_wq = &net_send_queue;
assert( send_wq );
memcpy( &thr_fds, kfds, sizeof(struct fds));
while(1)
{
if( check_pipe_read_ready( thr_fds.tx_pipe[PIPE_RD]) )
{
tx_data tnt;
int result = read_pipe_tx( &tnt, sizeof(tx_data) );
//DEBUG_INFO( "frame len = %d ", tnt.frame_len );
if( result > 0 )
{
// 加入网络数据发送队列
uint8_t* frame_buf = NULL;
uint16_t frame_len = tnt.frame_len;
pthread_mutex_lock( &send_wq->control.mutex );
// heap using later free by sending thread.frame_buf space must to be free!
frame_buf = allot_heap_space( TRANSMIT_DATA_BUFFER_SIZE, &frame_buf );
if( NULL == frame_buf )
{
DEBUG_INFO( "system_raw_queue_tx Err: allot space for frame failed!" );
pthread_mutex_unlock( &send_wq->control.mutex ); // unlock mutex
pthread_cond_signal( &send_wq->control.cond );
sem_post( &sem_tx ); // 用于tnt.frame 指针的同步操作
continue;
}
if( frame_len > TRANSMIT_DATA_BUFFER_SIZE )
{
pthread_mutex_unlock( &send_wq->control.mutex ); // unlock mutex
pthread_cond_signal( &send_wq->control.cond );
sem_post( &sem_tx ); // 用于tnt.frame 指针的同步操作
continue;
}
memset( frame_buf, 0, TRANSMIT_DATA_BUFFER_SIZE );
memcpy( frame_buf, tnt.frame, tnt.frame_len );
tnt.frame = frame_buf; // change the tnt frame buf to heap space
send_work_queue_message_save( &tnt, send_wq );
int queue_len = get_queue_length( &send_wq->work );
DEBUG_INFO( "save queue len = %d ", queue_len );
pthread_mutex_unlock( &send_wq->control.mutex ); // unlock mutex
pthread_cond_signal( &send_wq->control.cond );
sem_post( &sem_tx );
}
else
{
assert( tnt.frame && (result >= 0) );
}
}
else
{
DEBUG_INFO( "read pipe is not ready!" );
continue;
}
}
return 0;
}
int thread_send_func( void *pgm )
{
sdpwqueue* p_send_wq = &net_send_queue;
assert( p_send_wq );
while( 1 )
{
pthread_mutex_lock( &p_send_wq->control.mutex ); // lock mutex
while( p_send_wq->work.front == NULL && p_send_wq->control.active )
{
DEBUG_INFO( "active = %d", p_send_wq->control.active );
pthread_cond_wait( &p_send_wq->control.cond, &p_send_wq->control.mutex );
}
// 获取队列数据
p_sdpqueue_wnode p_send_wnode = NULL;
bool is_resp_data = false;
p_send_wnode = send_queue_message_get( p_send_wq );
if( NULL == p_send_wnode )
{
DEBUG_INFO( "No send queue message: ERROR!" );
pthread_mutex_unlock( &p_send_wq->control.mutex );
continue;
}
int queue_len = get_queue_length( &p_send_wq->work );
DEBUG_INFO( "after get queue len = %d ", queue_len );
pthread_mutex_unlock( &p_send_wq->control.mutex ); // unlock mutex
// ready to sending data
is_resp_data = p_send_wnode->job_data.resp;
tx_packet_event( p_send_wnode->job_data.data_type,
p_send_wnode->job_data.notification_flag,
p_send_wnode->job_data.frame,
p_send_wnode->job_data.frame_len,
&net_fd,// network fds
command_send_guard,
p_send_wnode->job_data.raw_dest.value,
&p_send_wnode->job_data.udp_sin,
is_resp_data ); // 数据向外发送函数
release_heap_space( &p_send_wnode->job_data.frame ); // free heap space mallo by write pipe thread
assert( p_send_wnode->job_data.frame == NULL ); // free successfully and result is NULL?
if( NULL != p_send_wnode )
{
free( p_send_wnode );
p_send_wnode = NULL;
}
/*发送下一条数据的条件-数据获得响应或数据超时或时间间隔到了(注:时间间隔只适用于系统响应数据或摄像头控制数据的发送)*/
if( is_wait_messsage_primed_state() )
{
int status = -1;
struct timespec timeout;
int ret = 0;
if ( clock_gettime( CLOCK_REALTIME, &timeout ) == -1)
{
perror("clock_gettime:");
return -1;
}
timeout.tv_sec += 4; // timeouts is 4 seconds
if( !is_resp_data )
{
status = set_wait_message_active_state();
assert( status == 0 );
//sem_wait( &sem_waiting );
ret = sem_timedwait( &sem_waiting, &timeout );
if( ret == -1 )
{
if( errno == ETIMEDOUT )
{
DEBUG_INFO( "sem_timedwait(): time out!send pthread proccess continue" );
sem_post( &sem_waiting );
}
else
{
perror( "sem_timedwait():" );
}
}
status = set_wait_message_idle_state();
assert( status == 0 );
}
else
{
status = set_wait_message_active_state();
assert( status == 0 );
uart_resp_send_interval_timer_start(); // start timer
//sem_wait( &sem_waiting );
ret = sem_timedwait( &sem_waiting, &timeout );
if( ret == -1 )
{
if( errno == ETIMEDOUT )
{
DEBUG_INFO( "sem_timedwait(): time out! send pthread proccess continue" );
sem_post( &sem_waiting );
}
else
{
perror( "sem_timedwait():" );
}
}
resp_send_interval_timer_stop();
status = set_wait_message_idle_state();
assert( status == 0 );
}
}
else
{
DEBUG_INFO(" not message primed success!" );
}
}
return 0;