FreeCalypso > hg > fc-tourmaline
view src/g23m-fad/tcpip/rnet/rnet_api.c @ 303:f76436d19a7a default tip
!GPRS config: fix long-standing AT+COPS chance hanging bug
There has been a long-standing bug in FreeCalypso going back years:
sometimes in the AT command bring-up sequence of an ACI-only MS,
the AT+COPS command would produce only a power scan followed by
cessation of protocol stack activity (only L1 ADC traces), instead
of the expected network search sequence. This behaviour was seen
in different FC firmware versions going back to Citrine, and seemed
to follow some law of chance, not reliably repeatable.
This bug has been tracked down and found to be specific to !GPRS
configuration, stemming from our TCS2/TCS3 hybrid and reconstruction
of !GPRS support that was bitrotten in TCS3.2/LoCosto version.
ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3
version and had to be pulled from TCS2 - but as it turns out,
there is a new field in the MMR_REG_REQ primitive that needs to be
set correctly, and that psa_mms.c module is the place where this
initialization needed to be added.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 08 Jun 2023 08:23:37 +0000 |
parents | fa8dc04885d8 |
children |
line wrap: on
line source
/** * @file rnet_api.c * * Riviera NET. * * Code of the Riviera TCP/IP stack (non-blocking) API. * Platform independent code. * * @author Vincent Oberle (v-oberle@ti.com) * @version 0.1 */ /* * History: * * Date Author Modification * -------------------------------------------------- * 01/25/2002 Vincent Oberle Create * 03/14/2002 Vincent Oberle Support of multiple implementations * 03/27/2002 Jose Yp-Tcha Adding Real Transport configuration * 06/24/2002 Regis Feneon Adding RNET_RT+WINDOWS configuration * (C) Copyright 2002 by Texas Instruments Incorporated, All Rights Reserved */ /* See this file for comments */ #include "rnet_api.h" #include "rnet_trace_i.h" #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK #include "rnet_ws/rnet_ws_api.h" #elif defined RNET_CFG_REAL_TRANSPORT #include "rnet_rt/rnet_rt_api.h" #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #include "rnet_rt/rnet_rt_api.h" #elif defined RNET_CFG_BRIDGE #include "rnet_br/rnet_br_api.h" #endif #endif //#define RNET_BENCHMARKING #ifdef RNET_BENCHMARKING #include "timer.h" #define MAX_FUNCTION 20 typedef enum { new = 0, set_traffic_class, bind, listen, connect, send, recv, recv_from, shutdown, close, get_local_adr, get_buff_size, get_max_packet_size, get_host_info, get_proto, set_user_data, get_user_data } RNET_BENCHMARK_FUNC; struct { UINT16 nbtick_avg; UINT16 nbtick_max; UINT16 nbtick_min; UINT32 nb_calls; UINT8 overload; } rnet_benchmarking[MAX_FUNCTION]; T_RNET_RET ret; void rnet_benchmarking_start_timer(void) { TM_EnableTimer( 1 ); TM_ResetTimer( 1, 0xFFFF, 0, 0 ); // un tick = 2.4 microsecondes TM_StartTimer( 1 ); } void rnet_benchmarking_stop_timer(void) { TM_StopTimer( 1 ); } UINT16 rnet_benchmarking_read_timer(void) { return((0xFFFF - TM_ReadTimer(1))); } void rnet_benchmarking_todo(RNET_BENCHMARK_FUNC val, char *lib) { UINT16 cur_timer; char loclib[80]; rnet_benchmarking[val].nb_calls++; cur_timer = rnet_benchmarking_read_timer(); if (cur_timer == 0) rnet_benchmarking[val].overload++; else { rnet_benchmarking[val].nbtick_avg = ((rnet_benchmarking[val].nbtick_avg * (rnet_benchmarking[val].nb_calls-1)) + cur_timer ) / rnet_benchmarking[val].nb_calls; if (rnet_benchmarking[val].nbtick_max < cur_timer) rnet_benchmarking[val].nbtick_max = cur_timer; if ((rnet_benchmarking[val].nbtick_min > cur_timer) || (rnet_benchmarking[val].nbtick_min == 0)) rnet_benchmarking[val].nbtick_min = cur_timer; } sprintf(loclib, "RNET_RT benchmarking %s nbtick_avg: %d\n", lib, rnet_benchmarking[val].nbtick_avg); RNET_TRACE_LOW(loclib); sprintf(loclib, "RNET_RT benchmarking %s nbtick_max: %d\n", lib, rnet_benchmarking[val].nbtick_max); RNET_TRACE_LOW(loclib); sprintf(loclib, "RNET_RT benchmarking %s nbtick_min: %d\n", lib, rnet_benchmarking[val].nbtick_min); RNET_TRACE_LOW(loclib); sprintf(loclib, "RNET_RT benchmarking %s nb_calls: %d\n", lib, rnet_benchmarking[val].nb_calls); RNET_TRACE_LOW(loclib); sprintf(loclib, "RNET_RT benchmarking %s overload: %d\n", lib, rnet_benchmarking[val].overload); RNET_TRACE_LOW(loclib); } #endif /** * Creates a new connection identifier (T_RNET_DESC). */ T_RNET_RET rnet_new (T_RNET_IPPROTO proto, T_RNET_DESC ** desc, T_RV_RETURN_PATH return_path) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_new(proto, desc, return_path); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_new(proto, desc, return_path); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_new(proto, desc, return_path); rnet_benchmarking_todo(new, "new"); return(ret); #else return rnet_rt_new(proto, desc, return_path); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_new(proto, desc, return_path); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Sets the traffic class of a connection ID. * * Note that this function is NOT implemented under Windows. */ T_RNET_RET rnet_set_traffic_class (T_RNET_DESC * desc, T_RNET_TRAFFIC_CLASS traffic_class) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK RNET_TRACE_ERROR("RNET: rnet_set_traffic_class not supported under Windows"); return RNET_NOT_SUPPORTED; #elif defined RNET_CFG_REAL_TRANSPORT RNET_TRACE_ERROR("RNET: rnet_set_traffic_class not supported for step one"); return RNET_NOT_SUPPORTED; #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT RNET_TRACE_ERROR("RNET: rnet_set_traffic_class not supported for step one"); return RNET_NOT_SUPPORTED; #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Binds the connection to a local IP address and port number. */ T_RNET_RET rnet_bind (T_RNET_DESC * desc, T_RNET_IP_ADDR local_addr, T_RNET_PORT local_port) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_bind(desc, local_addr, local_port); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_bind(desc, local_addr, local_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_bind(desc, local_addr, local_port); rnet_benchmarking_todo(bind, "bind"); return(ret); #else return rnet_rt_bind(desc, local_addr, local_port); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_bind(desc, local_addr, local_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Commands a connection to start listening for incoming connections. */ T_RNET_RET rnet_listen (T_RNET_DESC *desc) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_listen(desc); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_listen(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_listen(desc); rnet_benchmarking_todo(listen, "listen"); return(ret); #else return rnet_rt_listen(desc); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_listen(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Sets up the connection ID to connect to the remote host. */ T_RNET_RET rnet_connect (T_RNET_DESC * desc, T_RNET_IP_ADDR peer_addr, T_RNET_PORT peer_port) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_connect(desc, peer_addr, peer_port); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_connect(desc, peer_addr, peer_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_connect(desc, peer_addr, peer_port); rnet_benchmarking_todo(connect, "connect"); return(ret); #else return rnet_rt_connect(desc, peer_addr, peer_port); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_connect(desc, peer_addr, peer_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Enqueues the data for sending. */ T_RNET_RET rnet_send (T_RNET_DESC * desc, T_RVF_BUFFER *buff, UINT16 * len_p) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_send(desc, buff, len_p); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_send(desc, buff, len_p); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_send(desc, buff, len_p); rnet_benchmarking_todo(send, "send"); return(ret); #else return rnet_rt_send(desc, buff, len_p); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_send(desc, buff, len_p); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Read the waiting data. */ T_RNET_RET rnet_recv (T_RNET_DESC * desc, T_RVF_BUFFER *buff, UINT16 * len_p) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_recv(desc, buff, len_p); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_recv(desc, buff, len_p); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_recv(desc, buff, len_p); rnet_benchmarking_todo(recv, "recv"); return(ret); #else return rnet_rt_recv(desc, buff, len_p); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_recv(desc, buff, len_p); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Read the waiting data. */ T_RNET_RET rnet_recv_from (T_RNET_DESC * desc, T_RVF_BUFFER * buff, UINT16 * len_p, T_RNET_IP_ADDR * from_addr, T_RNET_PORT * from_port) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_recv_from(desc, buff, len_p, from_addr, from_port); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_recv_from(desc, buff, len_p, from_addr, from_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_recv_from(desc, buff, len_p, from_addr, from_port); rnet_benchmarking_todo(recv_from, "recv_from"); return(ret); #else return rnet_rt_recv_from(desc, buff, len_p, from_addr, from_port); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_recv_from(desc, buff, len_p, from_addr, from_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Disables the sending on a socket and informs the peer * about it. */ T_RNET_RET rnet_shutdown (T_RNET_DESC * desc) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_shutdown(desc); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_shutdown(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_shutdown(desc); rnet_benchmarking_todo(shutdown, "shutdown"); return(ret); #else return rnet_rt_shutdown(desc); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_shutdown(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Closes the connection. */ T_RNET_RET rnet_close (T_RNET_DESC * desc) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_close(desc); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_close(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_close(desc); rnet_benchmarking_todo(close, "close"); return(ret); #else return rnet_rt_close(desc); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_close(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Gets the local address and port of a connection ID. */ T_RNET_RET rnet_get_local_addr_port (T_RNET_DESC * desc, T_RNET_IP_ADDR * local_addr, T_RNET_PORT * local_port) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_get_local_addr_port(desc, local_addr, local_port); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_get_local_addr_port(desc, local_addr, local_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_get_local_addr_port(desc, local_addr, local_port); rnet_benchmarking_todo(get_local_adr, "get_local_adr"); return(ret); #else return rnet_rt_get_local_addr_port(desc, local_addr, local_port); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_get_local_addr_port(desc, local_addr, local_port); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Use to determine the amount of data pending in the network's input buffer * that can be read from the connection ID. */ T_RNET_RET rnet_get_buff_size (T_RNET_DESC * desc, UINT32 * size) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_get_buff_size(desc, size); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_get_buff_size(desc, size); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_get_buff_size(desc, size); rnet_benchmarking_todo(get_buff_size, "get_buff_size"); return(ret); #else return rnet_rt_get_buff_size(desc, size); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_get_buff_size(desc, size); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Indicates the maximum send size of a message for message-oriented * descriptor (UDP) as implemented by a particular service provider. */ T_RNET_RET rnet_get_max_packet_size (T_RNET_DESC * desc, UINT32 * size) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_get_max_packet_size(desc, size); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_get_max_packet_size(desc, size); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_get_max_packet_size(desc, size); rnet_benchmarking_todo(get_max_packet_size, "get_max_packet_size"); return(ret); #else return rnet_rt_get_max_packet_size(desc, size); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_get_max_packet_size(desc, size); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Requests host information corresponding to a host name or to a * network address. */ T_RNET_RET rnet_get_host_info (char *name, T_RNET_IP_ADDR addr, T_RV_RETURN_PATH return_path, void * user_data) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_get_host_info(name, addr, return_path,user_data); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_get_host_info(name, addr, return_path,user_data); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_get_host_info(name, addr, return_path,user_data); rnet_benchmarking_todo(get_host_info, "get_host_info"); return(ret); #else return rnet_rt_get_host_info(name, addr, return_path,user_data); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_get_host_info(name, addr, return_path,user_data); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #endif } /** * Retrieves the protocol associated to a connection descriptor. */ T_RNET_IPPROTO rnet_get_proto (T_RNET_DESC *desc) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_get_proto(desc); #elif defined RNET_CFG_REAL_TRANSPORT return rnet_rt_get_proto(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); ret = rnet_rt_get_proto(desc); rnet_benchmarking_todo(get_proto, "get_proto"); return(ret); #else return rnet_rt_get_proto(desc); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_get_proto(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_IPPROTO_UDP; #endif #endif } /** * Associates an application specific pointer to a connection ID. */ void rnet_set_user_data (T_RNET_DESC *desc, void *user_data) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK rnet_ws_set_user_data(desc, user_data); #elif defined RNET_CFG_REAL_TRANSPORT rnet_rt_set_user_data(desc, user_data); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING rnet_benchmarking_start_timer(); rnet_rt_set_user_data(desc, user_data); rnet_benchmarking_todo(set_user_data, "set_user_data"); #else rnet_rt_set_user_data(desc, user_data); #endif #elif defined RNET_CFG_BRIDGE rnet_br_set_user_data(desc, user_data); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); #endif #endif } /** * Returns the application specific pointer associated to the connection ID. */ void * rnet_get_user_data (T_RNET_DESC *desc) { #ifdef _WINDOWS #if defined RNET_CFG_WINSOCK return rnet_ws_get_user_data(desc); #elif defined RNET_CFG_REAL_TRANSPORT return (void *)rnet_rt_get_user_data(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return RNET_NOT_SUPPORTED; #endif #else #if defined RNET_CFG_REAL_TRANSPORT #ifdef RNET_BENCHMARKING void *retv; rnet_benchmarking_start_timer(); retv = (void *)rnet_rt_get_user_data(desc); rnet_benchmarking_todo(get_user_data, "get_user_data"); return(retv); #else return (void *)rnet_rt_get_user_data(desc); #endif #elif defined RNET_CFG_BRIDGE return rnet_br_get_user_data(desc); #else RNET_TRACE_ERROR("RNET: No implementation chosen"); return NULL; #endif #endif }