static err_t low_level_output(struct netif *netif, struct pbuf *p) { //struct ethernetif *ethernetif = netif->state; /* Interrupts are disabled through this whole thing to support multi-threading transmit calls. Also this function might be called from an ISR. */ return PacketSend(p); // 调用网卡发送函数发送一帧数据 }
void I_NetCmd (void) { if (doomcom.command == CMD_SEND) { PacketSend (); } else if (doomcom.command == CMD_GET) { PacketGet (); } else I_Error ("Bad net cmd: %i\n",doomcom.command); }
/**************************************************************************//** * @brief Request AEM (Advanced Energy Monitoring) voltage from board controller. * * @note Assumes that BSP_Init() has been called with @ref BSP_INIT_STK_BCUART * bitmask. * * @return * The voltage. Returns 0.0 on board controller communication * error. *****************************************************************************/ float BSP_VoltageGet(void) { STK_Packet pkt; float voltage; pkt.type = STK_PACKETTYPE_VOLTAGE_REQ; pkt.payloadLength = 0; /* Send Request/Get reply */ PacketSend(&pkt); PacketReceive(&pkt); /* Process reply */ if (pkt.type == STK_PACKETTYPE_VOLTAGE_REPLY) { memcpy(&voltage, pkt.data, sizeof(float)); return voltage; } else { return (float) 0.0; } }
/**************************************************************************//** * @brief Request AEM (Advanced Energy Monitoring) current from board controller. * * @note Assumes that BSP_Init() has been called with @ref BSP_INIT_STK_BCUART * bitmask. * * @return * The current expressed in milliamperes. Returns 0.0 on board controller * communication error. *****************************************************************************/ float BSP_CurrentGet(void) { STK_Packet pkt; float current; pkt.type = STK_PACKETTYPE_CURRENT_REQ; pkt.payloadLength = 0; /* Send Request/Get reply */ PacketSend(&pkt); PacketReceive(&pkt); /* Process reply */ if (pkt.type == STK_PACKETTYPE_CURRENT_REPLY) { memcpy(¤t, pkt.data, sizeof(float)); return current; } else { return (float) 0.0; } }
/** * CmdQUpdateAllSends updates the sending of all packets. * Packets that need to be transferred are sent. Those that don't, don't. * The amount of packets sent depends on the baud rate and the last time * this routine was called. * *<!-----------------------------------------------------------------------*/ T_void CmdQUpdateAllSends(T_void) { T_byte8 currentCmd; T_cmdQPacketStruct *p_packet = NULL; T_cmdQPacketStruct *p_next = NULL; T_byte8 packetLength; T_word32 time; T_sword16 status; T_word16 bytesused; T_word32 maxOutput; E_Boolean onceFlag = FALSE; E_Boolean sentAny; DebugRoutine("CmdQUpdateAllSends") ; /* Get the current time. */ time = TickerGet(); bytesused = 0; maxOutput = 100; currentCmd = 0; if (bytesused < maxOutput) { do { sentAny = FALSE; p_next = 0; p_packet = G_activeCmdQList[currentCmd].first; do { /* Try sending the command at currentCmd. */ /* See if there is anything that needs to be sent. */ if ((p_packet != NULL) && (bytesused < maxOutput)) { DebugCheck(currentCmd < PACKET_COMMAND_UNKNOWN); p_next = p_packet->next; #ifndef NDEBUG if (strcmp(p_packet->tag, "CmQ") != 0) { printf("Bad packet %p\n", p_packet); DebugCheck(FALSE); } #endif /* See if it is time to send it. */ /** (It's always time to send an ACK.) **/ if ((currentCmd == PACKET_COMMAND_ACK) || (p_packet->timeToRetry < time)) { /* Yes, it is time to send it. */ packetLength = p_packet->packet.header.packetLength; /* Add the count to the output. */ bytesused += packetLength + sizeof(T_packetHeader); /* Make sure this didn't go over the threshold. */ if (bytesused >= maxOutput) break; /* Let's send that packet to the given destination. */ DirectTalkSetDestination(&p_packet->destination); status = PacketSend( (T_packetEitherShortOrLong *)(&p_packet->packet)); sentAny = TRUE; #ifdef COMPILE_OPTION_CREATE_PACKET_DATA_FILE fprintf(G_packetFile, "S(%d) cmd=%2d, id=%ld, time=%ld\n", CmdQGetActivePortNum (), p_packet->packet.data[0], p_packet->packet.header.id, SyncTimeGet()); fflush(G_packetFile); #endif /* Was the packet actually sent? */ if (status == 0) { /* Packet was sent correctly (as far as we know). */ /* Is this a lossy or lossless command queue? */ if ((G_CmdQTypeCommand[currentCmd] == PACKET_COMMAND_TYPE_LOSSY) || (DirectTalkIsBroadcastAddress( &p_packet->destination))) { /* Lossy. Means we can go ahead and */ /* discard this packet. */ ICmdQDiscardPacket(currentCmd, p_packet); } else { /* Lossless. Means we must wait for an ACK */ /* packet to confirm that we were sent. */ /* Until then, we can't discard the packet. */ /* But we might have to resend latter. */ /* Set up the retry time. */ p_packet->timeToRetry = time + p_packet->retryTime; } } else { /* Packet was NOT sent correctly. */ /** -- IFF the packet is lossless... **/ /* We'll have to retry later. Change the time, */ /* but don't remove it from the linked list. */ if (G_CmdQTypeCommand[currentCmd] == PACKET_COMMAND_TYPE_LOSSLESS) { p_packet->timeToRetry = time + p_packet->retryTime; } else { /* Waste it! We can't wait around */ ICmdQDiscardPacket(currentCmd, p_packet); } } } else { /* Don't loop if it is not time to send. */ break; } /** Now, if we aren't checking the ACK queue, we need **/ /** to break after the first send. If we are, we **/ /** want to dump everything in the queue. **/ if (currentCmd != PACKET_COMMAND_ACK) break; } // Move to the next packet (if any) p_packet = p_next; while (!p_packet) { /* Update to the next command. */ currentCmd++; if (currentCmd < PACKET_COMMAND_MAX) { // Get the beginning of the list p_packet = G_activeCmdQList[currentCmd].first; if (p_packet) p_next = p_packet->next; else p_next = 0; } else { break; } } } while (currentCmd < PACKET_COMMAND_MAX); // Loop back to the start looking for more to send currentCmd = 0; } while ((bytesused < maxOutput) && (sentAny == TRUE)); } DebugEnd() ; }
/***************************************************************************** * Entry point *****************************************************************************/ int main( int i_argc, char **pp_argv ) { int i, c; int i_priority = -1; int i_ttl = 0; struct pollfd *pfd = NULL; int i_fd; bool b_tcp; #define ADD_INPUT \ p_inputs = realloc( p_inputs, ++i_nb_inputs * sizeof(input_t) ); \ p_inputs[i_nb_inputs - 1].i_fd = i_fd; \ p_inputs[i_nb_inputs - 1].b_tcp = b_tcp; \ p_inputs[i_nb_inputs - 1].p_block = NULL; \ pfd = realloc( pfd, i_nb_inputs * sizeof(struct pollfd) ); \ pfd[i_nb_inputs - 1].fd = i_fd; \ pfd[i_nb_inputs - 1].events = POLLIN | POLLERR | POLLRDHUP | POLLHUP; while ( (c = getopt( i_argc, pp_argv, "i:t:b:g:j:r:n:x:X:Um:R:h" )) != -1 ) { switch ( c ) { case 'i': i_priority = strtol( optarg, NULL, 0 ); break; case 't': i_ttl = strtol( optarg, NULL, 0 ); break; case 'b': i_buffer_length = strtoll( optarg, NULL, 0 ) * 27000; break; case 'g': i_cr_max_gap = strtoll( optarg, NULL, 0 ) * 27000; break; case 'j': i_cr_max_jitter = strtoll( optarg, NULL, 0 ) * 27000; break; case 'r': i_cr_average = strtol( optarg, NULL, 0 ); break; case 'n': i_max_retx_burst = strtoul( optarg, NULL, 0 ); break; case 'x': i_retx_delay = strtoll( optarg, NULL, 0 ) * 27000; break; case 'X': i_retx_fd = i_fd = OpenSocket( optarg, 0, 0, 0, NULL, &b_tcp, NULL ); if ( i_fd == -1 ) { msg_Err( NULL, "unable to set up retx with %s\n", optarg ); exit(EXIT_FAILURE); } ADD_INPUT break; case 'U': b_udp = 1; break; case 'm': i_asked_payload_size = strtol( optarg, NULL, 0 ); break; case 'R': i_rtp_header_size = strtol( optarg, NULL, 0 ); break; case 'h': default: usage(); break; } } if ( optind >= i_argc - 1 ) usage(); while ( optind < i_argc - 1 ) { i_fd = OpenSocket( pp_argv[optind], 0, DEFAULT_PORT, 0, NULL, &b_tcp, NULL ); if ( i_fd == -1 ) { msg_Err( NULL, "unable to open input %s\n", pp_argv[optind] ); exit(EXIT_FAILURE); } optind++; ADD_INPUT } msg_Dbg( NULL, "%d inputs", i_nb_inputs ); i_nb_retx = (i_buffer_length - MIN_RETX_DELAY) / i_retx_delay; pp_retx = malloc( i_nb_retx * sizeof(block_t *) ); for ( i = 0; i < i_nb_retx; i++ ) pp_retx[i] = NULL; if ( i_retx_fd && i_nb_retx ) msg_Dbg( NULL, "%d retx passes", i_nb_retx ); i_output_fd = OpenSocket( pp_argv[optind], i_ttl, 0, DEFAULT_PORT, NULL, NULL, NULL ); if ( i_output_fd == -1 ) { msg_Err( NULL, "unable to open output %s\n", pp_argv[optind] ); exit(EXIT_FAILURE); } clock_Init(); if ( i_priority > 0 ) { struct sched_param param; int i_error; memset( ¶m, 0, sizeof(struct sched_param) ); param.sched_priority = i_priority; if ( (i_error = pthread_setschedparam( pthread_self(), SCHED_RR, ¶m )) ) { msg_Warn( NULL, "couldn't set thread priority: %s", strerror(i_error) ); } } for ( ; ; ) { int i_timeout = -1; uint64_t i_current_date; while ( p_first != NULL && p_first->i_date <= (i_current_date = wall_Date()) + 26999 ) PacketSend(); i_current_date = wall_Date(); RetxCheck( i_current_date ); i_current_date = wall_Date(); if ( p_first != NULL ) i_timeout = (p_first->i_date - i_current_date) / 27000; if ( poll( pfd, i_nb_inputs, i_timeout ) < 0 ) { int saved_errno = errno; msg_Warn( NULL, "couldn't poll(): %s", strerror(errno) ); if ( saved_errno == EINTR ) continue; exit(EXIT_FAILURE); } i_current_date = wall_Date(); for ( i = 0; i < i_nb_inputs; i++ ) { input_t *p_input = &p_inputs[i]; if ( pfd[i].revents & POLLIN ) { ssize_t i_size = i_asked_payload_size + i_rtp_header_size; uint8_t *p_buffer; if ( p_input->p_block == NULL ) { p_input->p_block = malloc( sizeof(block_t) + i_size ); p_buffer = p_input->p_block->p_data = (uint8_t *)p_input->p_block + sizeof(block_t); p_input->p_block->i_size = 0; } else { p_buffer = p_input->p_block->p_data + p_input->p_block->i_size; i_size -= p_input->p_block->i_size; } i_size = read( p_input->i_fd, p_buffer, i_size ); if ( i_size < 0 && errno != EAGAIN && errno != EINTR && errno != ECONNREFUSED ) { msg_Err( NULL, "unrecoverable read error, dying (%s)", strerror(errno) ); exit(EXIT_FAILURE); } if ( i_size <= 0 ) continue; p_input->p_block->i_size += i_size; if ( p_input->b_tcp && p_input->p_block->i_size != i_asked_payload_size + i_rtp_header_size ) continue; if ( i_retx_fd == -1 || i ) PacketRecv( p_input->p_block, i_current_date ); else PacketRecv( p_input->p_block, 0 ); p_input->p_block = NULL; } else if ( pfd[i].revents & (POLLERR | POLLRDHUP | POLLHUP) ) { msg_Err( NULL, "poll error on input %d" ); exit(EXIT_FAILURE); } } } return EXIT_SUCCESS; }