1 // 2 // Copyright (c) 2010-2024 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using Antmicro.Renode.Core; 8 using Antmicro.Renode.Logging; 9 using Antmicro.Renode.Utilities; 10 11 namespace Antmicro.Renode.Peripherals.Network 12 { 13 public class Quectel_BG96 : QuectelModem 14 { Quectel_BG96(IMachine machine, string imeiNumber = DefaultImeiNumber, string softwareVersionNumber = DefaultSoftwareVersionNumber, string serialNumber = DefaultSerialNumber)15 public Quectel_BG96(IMachine machine, string imeiNumber = DefaultImeiNumber, 16 string softwareVersionNumber = DefaultSoftwareVersionNumber, 17 string serialNumber = DefaultSerialNumber) : base(machine, imeiNumber, softwareVersionNumber, serialNumber) 18 { 19 } 20 21 // CEREG - EPS Network Registration Status 22 [AtCommand("AT+CEREG", CommandType.Write)] CeregWrite(NetworkRegistrationUrcType type)23 protected override Response CeregWrite(NetworkRegistrationUrcType type) 24 { 25 // EMM cause information is not supported on this modem 26 if(type == NetworkRegistrationUrcType.StatLocationEmmCause || 27 type == NetworkRegistrationUrcType.StatLocationEmmCausePsm) 28 { 29 return Error; 30 } 31 return base.CeregWrite(type); 32 } 33 34 // CREG - Network Registration 35 [AtCommand("AT+CREG", CommandType.Write)] CregWrite(NetworkRegistrationUrcType type)36 protected override Response CregWrite(NetworkRegistrationUrcType type) 37 { 38 if(type > NetworkRegistrationUrcType.StatLocation) 39 { 40 this.Log(LogLevel.Warning, "AT+CREG: Argument <n> set to {0}, not supported by this modem", (int)type); 41 return Error; 42 } 43 return base.CregWrite(type); 44 } 45 46 // CESQ - Extended Signal Quality 47 // CESQ is not supported by this modem. We override Cesq without marking it with [AtCommand] 48 // in order to remove it from the command set (including the test command, AT+CESQ=?). Cesq()49 protected override Response Cesq() => Error; 50 51 // CGDCONT - Define PDP Context 52 [AtCommand("AT+CGDCONT", CommandType.Read)] Cgdcont()53 protected override Response Cgdcont() => Ok.WithParameters($"+CGDCONT: 1,\"IP\",\"{pdpContextApn}\",\"{NetworkIp}\",0,0"); // stub 54 55 // CGMI - Request Manufacturer Identification 56 [AtCommand("AT+CGMI")] Cgmi()57 protected override Response Cgmi() => Ok.WithParameters(Vendor); 58 59 // CGSN - Request Product Serial Number 60 // CGSN only supports reading the IMEI on this modem and is available only as an execution command 61 // Also, it returns only the IMEI itself instead of "+CGSN: <imei>" 62 [AtCommand("AT+CGSN")] Cgsn()63 protected override Response Cgsn() => Ok.WithParameters(imeiNumber); 64 65 [AtCommand("AT+CGSN", CommandType.Write)] CgsnWrite(SerialNumberType serialNumberType = SerialNumberType.Device)66 protected override Response CgsnWrite(SerialNumberType serialNumberType = SerialNumberType.Device) => Error; 67 68 // CMEE - Report Mobile Termination Error 69 [AtCommand("AT+CMEE", CommandType.Write)] Cmee(MobileTerminationResultCodeMode mode = MobileTerminationResultCodeMode.Numeric)70 protected override Response Cmee(MobileTerminationResultCodeMode mode = MobileTerminationResultCodeMode.Numeric) 71 { 72 return base.Cmee(mode); 73 } 74 75 // CSCON - Signaling Connection Status 76 // Not supported Cscon(int enable = 0)77 protected override Response Cscon(int enable = 0) => Error; 78 79 // QBAND - Get and Set Mobile Operation Band 80 // Not supported Qband(int numberOfBands, params int[] bands)81 protected override Response Qband(int numberOfBands, params int[] bands) => Error; 82 83 // QCCID - USIM Card Identification 84 // Not supported Qccid()85 protected override Response Qccid() => Error; 86 87 // CCLK - Set and Get Current Date and Time 88 [AtCommand("AT+CCLK", CommandType.Read)] CclkRead()89 protected virtual Response CclkRead() 90 { 91 return Ok.WithParameters("+CCLK: " + machine.RealTimeClockDateTime.ToString("yy/MM/dd,HH:mm:sszz").SurroundWith("\"")); 92 } 93 94 // QCFG - System Configuration 95 [AtCommand("AT+QCFG", CommandType.Write)] Qcfg(string function, params int[] args)96 protected override Response Qcfg(string function, params int[] args) 97 { 98 switch(function) 99 { 100 case "ledmode": // NETLIGHT output Mode 101 { 102 if(args.Length == 1) 103 { 104 return SetNetLightMode(args[0]); 105 } 106 return base.Qcfg(function, args); 107 } 108 case "apready": // AP_READY Pin 109 case "band": // band configuration 110 case "celevel": // get LTE Cat NB1 coverage enhancement level 111 case "cmux/urcport": // URC output port for CMUX 112 case "ims": // IMS function control 113 case "iotopmode": // network category to be searched under LTE RAT 114 case "msc": // MSC release version configuration 115 case "nb1/bandprior": // band scan priority under LTE Cat NB1 116 case "nwscanmode": // RAT(s) to be searched 117 case "nwscanseq": // RAT searching sequence 118 case "pdp/duplicatechk": // establish multi PDNs with the same APN 119 case "psm/enter": // trigger PSM immediately 120 case "psm/urc": // enable/disable PSM entry indication 121 case "risignaltype": // RI signal output carrier 122 case "roamservice": // roam service configuration 123 case "servicedomain": // service domain configuration 124 case "sgsn": // SGSN release version configuration 125 case "urc/delay": // delay URC indication 126 case "urc/ri/other": // RI behavior when other URCs are presented 127 case "urc/ri/ring": // RI behavior when RING URC is presented 128 case "urc/ri/smsincoming": // RI behavior when incoming SMS URCs are presented 129 this.Log(LogLevel.Warning, "Config value '{0}' set to {1}, not implemented", function, string.Join(", ", args)); 130 break; 131 default: 132 return base.Qcfg(function, args); 133 } 134 return Ok; 135 } 136 137 // QENG - Engineering Mode 138 // Not supported Qeng(int mode)139 protected override Response Qeng(int mode) => Error; 140 141 // QIACT - Activate a PDP Context 142 [AtCommand("AT+QIACT", CommandType.Write)] Qiact(int contextId)143 protected Response Qiact(int contextId) 144 { 145 if(!IsValidContextId(contextId)) 146 { 147 return Error; 148 } 149 return Ok; // stub 150 } 151 152 // QICFG - Configure Optional TCP/IP Parameters 153 [AtCommand("AT+QICFG", CommandType.Write)] Qicfg(string parameter, params int[] args)154 protected override Response Qicfg(string parameter, params int[] args) 155 { 156 if(args.Length < 1) 157 { 158 return Error; 159 } 160 161 switch(parameter) 162 { 163 case "dataformat": 164 if(args.Length < 2) 165 { 166 return Error; 167 } 168 sendDataFormat = args[0] != 0 ? DataFormat.Hex : DataFormat.Text; 169 receiveDataFormat = args[1] != 0 ? DataFormat.Hex : DataFormat.Text; 170 break; 171 case "viewmode": 172 dataOutputSeparator = args[0] != 0 ? "," : CrLf; 173 break; 174 case "transpktsize": // packet size for transparent mode 175 case "transwaittm": // wait time for transparent mode 176 case "tcp/retranscfg": // maximum interval time and number for TCP retransmissions 177 case "dns/cache": // enable the DNS cache 178 case "qisend/timeout": // input data timeout 179 case "passiveclosed": // passive close of TCP connection when the server is closed 180 this.Log(LogLevel.Warning, "TCP/IP config value '{0}' set to {1}, not implemented", parameter, args.Stringify()); 181 break; 182 default: 183 return base.Qicfg(parameter, args); 184 } 185 return Ok; 186 } 187 188 // QICLOSE - Close a Socket Service 189 [AtCommand("AT+QICLOSE", CommandType.Write)] Qiclose(int connectionId, int timeout = 10)190 protected /* override */ Response Qiclose(int connectionId, int timeout = 10) 191 { 192 return base.Qiclose(connectionId); 193 } 194 195 // QICSGP - Configure Parameters of a TCP/IP Context 196 [AtCommand("AT+QICSGP", CommandType.Write)] Qicsgp(int contextId, ProtocolType contextType = ProtocolType.IpV4, string apn = R, string username = R, string password = R, AuthenticationMethod authenticationType = AuthenticationMethod.None)197 protected virtual Response Qicsgp(int contextId, ProtocolType contextType = ProtocolType.IpV4, 198 string apn = "", string username = "", string password = "", 199 AuthenticationMethod authenticationType = AuthenticationMethod.None) 200 { 201 if(!IsValidContextId(contextId)) 202 { 203 return Error; 204 } 205 return Ok; // stub 206 } 207 208 // QIDEACT - Deactivate a PDP Context 209 [AtCommand("AT+QIDEACT", CommandType.Write)] Qideact(int contextId)210 protected virtual Response Qideact(int contextId) 211 { 212 if(!IsValidContextId(contextId)) 213 { 214 return Error; 215 } 216 return Ok; // stub 217 } 218 219 // QISEND - Send Hex/Text String Data 220 [AtCommand("AT+QISEND", CommandType.Write)] Qisend(int connectionId, int? sendLength = null, string data = null, int? raiMode = null)221 protected override Response Qisend(int connectionId, int? sendLength = null, string data = null, int? raiMode = null) 222 { 223 // The BG96 doesn't support non-data mode in AT+QISEND 224 if(data != null) 225 { 226 return Error; 227 } 228 229 return base.Qisend(connectionId, sendLength, data); 230 } 231 232 // QNBIOTEVENT - Enable/Disable NB-IoT Related Event Report 233 // Not supported Qnbiotevent(int enable = 0, int eventType = 1)234 protected override Response Qnbiotevent(int enable = 0, int eventType = 1) => Error; 235 236 // QNBIOTRAI - NB-IoT Release Assistance Indication 237 // Not supported Qnbiotrai(int raiMode = 0)238 protected override Response Qnbiotrai(int raiMode = 0) => Error; 239 240 // QRST - Module Reset 241 // Not supported QrstWrite(int mode = 1)242 protected override Response QrstWrite(int mode = 1) => Error; 243 244 protected override string Vendor => "Quectel"; 245 protected override string ModelName => "BG96"; 246 protected override string Revision => "Revision: BG96MAR01A01M1G"; 247 protected override string ManufacturerRevision => "BG96MAR01A01M1G"; 248 protected override string SoftwareRevision => "01.008.01.008"; 249 250 private const string DefaultImeiNumber = "866818039921444"; 251 private const string DefaultSoftwareVersionNumber = "31"; 252 private const string DefaultSerialNumber = "<serial number>"; 253 254 protected enum ProtocolType 255 { 256 IpV4 = 1, 257 IpV4V6, 258 } 259 260 protected enum AuthenticationMethod 261 { 262 None, 263 Pap, 264 Chap, 265 PapOrChap, 266 } 267 } 268 } 269