Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1 | """Code related to the Card Application Toolkit (CAT) as described in |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 2 | mainly) ETSI TS 102 223, ETSI TS 101 220 and USIM Application Toolkit (SAT) |
| 3 | as described in 3GPP TS 31.111.""" |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 4 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 5 | # (C) 2021-2022 by Harald Welte <laforge@osmocom.org> |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 6 | # |
| 7 | # This program is free software: you can redistribute it and/or modify |
| 8 | # it under the terms of the GNU General Public License as published by |
| 9 | # the Free Software Foundation, either version 2 of the License, or |
| 10 | # (at your option) any later version. |
| 11 | # |
| 12 | # This program is distributed in the hope that it will be useful, |
| 13 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 14 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 15 | # GNU General Public License for more details. |
| 16 | # |
| 17 | # You should have received a copy of the GNU General Public License |
| 18 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
| 19 | |
| 20 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 21 | from bidict import bidict |
| 22 | from typing import List |
| 23 | from pySim.utils import b2h, h2b, dec_xplmn_w_act |
| 24 | from pySim.tlv import TLV_IE, COMPR_TLV_IE, BER_TLV_IE, TLV_IE_Collection |
| 25 | from pySim.construct import BcdAdapter, HexAdapter, GsmStringAdapter, TonNpi |
| 26 | from construct import Int8ub, Int16ub, Byte, Bytes, Bit, Flag, BitsInteger |
| 27 | from construct import Struct, Enum, Tell, BitStruct, this, Padding, RepeatUntil |
| 28 | from construct import GreedyBytes, Switch, GreedyRange, FlagsEnum |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 29 | |
| 30 | # Tag values as per TS 101 220 Table 7.23 |
| 31 | |
| 32 | # TS 102 223 Section 8.1 |
| 33 | class Address(COMPR_TLV_IE, tag=0x06): |
| 34 | _construct = Struct('ton_npi'/Int8ub, |
| 35 | 'call_number'/BcdAdapter(Bytes(this._.total_len-1))) |
| 36 | |
| 37 | # TS 102 223 Section 8.2 |
| 38 | class AlphaIdentifier(COMPR_TLV_IE, tag=0x05): |
| 39 | # FIXME: like EF.ADN |
| 40 | pass |
| 41 | |
| 42 | # TS 102 223 Section 8.3 |
| 43 | class Subaddress(COMPR_TLV_IE, tag=0x08): |
| 44 | pass |
| 45 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 46 | # TS 102 223 Section 8.4 + TS 31.111 Section 8.4 |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 47 | class CapabilityConfigParams(COMPR_TLV_IE, tag=0x07): |
| 48 | pass |
| 49 | |
| 50 | # TS 31.111 Section 8.5 |
| 51 | class CBSPage(COMPR_TLV_IE, tag=0x0C): |
| 52 | pass |
| 53 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 54 | # TS 102 223 Section 8.6 + TS 31.111 Section 8.6 |
| 55 | class CommandDetails(COMPR_TLV_IE, tag=0x81): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 56 | _construct = Struct('command_number'/Int8ub, |
| 57 | 'type_of_command'/Int8ub, |
| 58 | 'command_qualifier'/Int8ub) |
| 59 | |
| 60 | # TS 102 223 Section 8.7 |
Harald Welte | 9edbdb9 | 2021-10-08 15:46:42 +0200 | [diff] [blame] | 61 | class DeviceIdentities(COMPR_TLV_IE, tag=0x82): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 62 | DEV_IDS = bidict({ |
| 63 | 0x01: 'keypad', |
| 64 | 0x02: 'display', |
| 65 | 0x03: 'earpiece', |
| 66 | 0x10: 'addl_card_reader_0', |
| 67 | 0x11: 'addl_card_reader_1', |
| 68 | 0x12: 'addl_card_reader_2', |
| 69 | 0x13: 'addl_card_reader_3', |
| 70 | 0x14: 'addl_card_reader_4', |
| 71 | 0x15: 'addl_card_reader_5', |
| 72 | 0x16: 'addl_card_reader_6', |
| 73 | 0x17: 'addl_card_reader_7', |
| 74 | 0x21: 'channel_1', |
| 75 | 0x22: 'channel_2', |
| 76 | 0x23: 'channel_3', |
| 77 | 0x24: 'channel_4', |
| 78 | 0x25: 'channel_5', |
| 79 | 0x26: 'channel_6', |
| 80 | 0x27: 'channel_7', |
| 81 | 0x31: 'ecat_client_1', |
| 82 | 0x32: 'ecat_client_2', |
| 83 | 0x33: 'ecat_client_3', |
| 84 | 0x34: 'ecat_client_4', |
| 85 | 0x35: 'ecat_client_5', |
| 86 | 0x36: 'ecat_client_6', |
| 87 | 0x37: 'ecat_client_7', |
| 88 | 0x38: 'ecat_client_8', |
| 89 | 0x39: 'ecat_client_9', |
| 90 | 0x3a: 'ecat_client_a', |
| 91 | 0x3b: 'ecat_client_b', |
| 92 | 0x3c: 'ecat_client_c', |
| 93 | 0x3d: 'ecat_client_d', |
| 94 | 0x3e: 'ecat_client_e', |
| 95 | 0x3f: 'ecat_client_f', |
| 96 | 0x81: 'uicc', |
| 97 | 0x82: 'terminal', |
| 98 | 0x83: 'network', |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 99 | }) |
| 100 | |
| 101 | def _from_bytes(self, do: bytes): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 102 | return {'source_dev_id': self.DEV_IDS[do[0]], 'dest_dev_id': self.DEV_IDS[do[1]]} |
| 103 | |
| 104 | def _to_bytes(self): |
| 105 | src = self.DEV_IDS.inverse[self.decoded['source_dev_id']] |
| 106 | dst = self.DEV_IDS.inverse[self.decoded['dest_dev_id']] |
| 107 | return bytes([src, dst]) |
| 108 | |
| 109 | # TS 102 223 Section 8.8 |
| 110 | class Duration(COMPR_TLV_IE, tag=0x04): |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 111 | _construct = Struct('time_unit'/Enum(Int8ub, minutes=0, seconds=1, tenths_of_seconds=2), |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 112 | 'time_interval'/Int8ub) |
| 113 | |
| 114 | # TS 102 223 Section 8.9 |
| 115 | class Item(COMPR_TLV_IE, tag=0x0f): |
| 116 | _construct = Struct('identifier'/Int8ub, |
| 117 | 'text_string'/GsmStringAdapter(GreedyBytes)) |
| 118 | |
| 119 | # TS 102 223 Section 8.10 |
| 120 | class ItemIdentifier(COMPR_TLV_IE, tag=0x10): |
| 121 | _construct = Struct('identifier'/Int8ub) |
| 122 | |
| 123 | # TS 102 223 Section 8.11 |
| 124 | class ResponseLength(COMPR_TLV_IE, tag=0x11): |
| 125 | _construct = Struct('minimum_length'/Int8ub, |
| 126 | 'maximum_length'/Int8ub) |
| 127 | |
| 128 | # TS 102 223 Section 8.12 |
| 129 | class Result(COMPR_TLV_IE, tag=0x03): |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 130 | GeneralResult = Enum(Int8ub, |
| 131 | # '0X' and '1X' indicate that the command has been performed |
| 132 | performed_successfully=0, |
| 133 | performed_with_partial_comprehension=1, |
| 134 | performed_with_missing_information=2, |
| 135 | refresh_performed_with_addl_efs_read=3, |
| 136 | porformed_successfully_but_reqd_item_not_displayed=4, |
| 137 | performed_but_modified_by_call_control_by_naa=5, |
| 138 | performed_successfully_limited_service=6, |
| 139 | performed_with_modification=7, |
| 140 | refresh_performed_but_indicated_naa_was_not_active=8, |
| 141 | performed_successfully_tone_not_played=9, |
| 142 | proactive_uicc_session_terminated_by_user=0x10, |
| 143 | backward_move_in_proactive_uicc_session_requested_by_user=0x11, |
| 144 | no_response_from_user=0x12, |
| 145 | help_information_required_by_user=0x13, |
| 146 | # '2X' indicate to the UICC that it may be worth re-trying later |
| 147 | terminal_currently_unable_to_process=0x20, |
| 148 | network_currently_unable_to_process=0x21, |
| 149 | user_did_not_accept_proactive_cmd=0x22, |
| 150 | user_cleared_down_call_before_release=0x23, |
| 151 | action_in_contradiction_with_current_timer_state=0x24, |
| 152 | interaction_with_call_control_by_naa_temporary=0x25, |
| 153 | launch_browser_generic_error=0x26, |
| 154 | mms_temporary_problem=0x27, |
| 155 | # '3X' indicate that it is not worth the UICC re-trying with an identical command |
| 156 | command_beyond_terminal_capability=0x30, |
| 157 | command_type_not_understood_by_terminal=0x31, |
| 158 | command_data_not_understood_by_terminal=0x32, |
| 159 | command_number_not_known_by_terminal=0x33, |
| 160 | error_required_values_missing=0x36, |
| 161 | multiple_card_commands_error=0x38, |
| 162 | #interaction_with_call_control_by_naa_permanent=0x39, # see below 3GPP |
| 163 | bearer_independent_protocol_error=0x3a, |
| 164 | access_technology_unable_to_process_command=0x3b, |
| 165 | frames_error=0x3c, |
| 166 | mms_error=0x3d, |
| 167 | # 3GPP TS 31.111 Section 8.12 |
| 168 | ussd_or_ss_transaction_terminated_by_user=0x14, |
| 169 | ss_return_error=0x34, |
| 170 | sms_rp_error=0x35, |
| 171 | ussd_return_error=0x37, |
| 172 | interaction_with_cc_by_usim_or_mo_sm_by_usim_permanent=0x39) |
| 173 | # TS 102 223 Section 8.12.2 |
| 174 | AddlInfoTermProblem = Enum(Int8ub, |
| 175 | no_specific_cause=0x00, |
| 176 | screen_is_busy=0x01, |
| 177 | terminal_currently_busy_on_call=0x02, |
| 178 | no_service=0x04, |
| 179 | access_control_class_bar=0x05, |
| 180 | radio_resource_not_granted=0x06, |
| 181 | not_in_speech_call=0x07, |
| 182 | terminal_currently_busy_on_send_dtmf=0x09, |
| 183 | no_naa_active=0x10, |
| 184 | # TS 31.111 section 8.12 |
| 185 | me_currently_busy_on_ss_transaction=0x03, |
| 186 | me_currently_busy_on_ussd_transaction=0x08) |
| 187 | # TS 102 223 Section 8.12.8 / TS 31.111 Section 8.12.8 |
| 188 | AddlInfoCallControl= Enum(Int8ub, |
| 189 | no_specific_cause=0x00, |
| 190 | action_not_allowed=0x01, |
| 191 | the_type_of_request_has_changed=0x02) |
| 192 | # TS 102 223 Section 8.12.9 |
| 193 | AddlInfoMultipleCard = Enum(Int8ub, |
| 194 | no_specific_cause=0x00, |
| 195 | card_reader_removed_or_not_present=0x01, |
| 196 | card_removed_or_not_present=0x02, |
| 197 | card_reader_busy=0x03, |
| 198 | card_powered_off=0x04, |
| 199 | capdu_format_error=0x05, |
| 200 | mute_card=0x06, |
| 201 | transmission_error=0x07, |
| 202 | protocol_not_supported=0x08, |
| 203 | specified_reader_not_valid=0x09) |
| 204 | # TS 102 223 Section 8.12.10 |
| 205 | AddlInfoLaunchBrowser = Enum(Int8ub, |
| 206 | no_specific_cause=0x00, |
| 207 | bearer_unavailable=0x01, |
| 208 | browser_unavailable=0x02, |
| 209 | terminal_unable_to_read_provisioning_data=0x03, |
| 210 | default_url_unavailable=0x04) |
| 211 | # TS 102 223 Section 8.12.11 |
| 212 | AddlInfoBip = Enum(Int8ub, no_specific_cause=0x00, |
| 213 | no_channel_availabile=0x01, |
| 214 | channel_closed=0x02, |
| 215 | channel_id_not_valid=0x03, |
| 216 | requested_buffer_size_not_available=0x04, |
| 217 | security_error=0x05, |
| 218 | requested_uicc_if_transp_level_not_available=0x06, |
| 219 | remote_device_not_reachable=0x07, |
| 220 | service_error=0x08, |
| 221 | service_identifer_unknown=0x09, |
| 222 | port_not_available=0x10, |
| 223 | launch_parameters_missing_or_incorrect=0x11, |
| 224 | application_launch_failed=0x12) |
| 225 | # TS 102 223 Section 8.12.11 |
| 226 | AddlInfoFrames = Enum(Int8ub, |
| 227 | no_specific_cause=0x00, |
| 228 | frame_identifier_not_valid=0x01, |
| 229 | num_of_frames_beyond_terminal_capabilities=0x02, |
| 230 | no_frame_defined=0x03, |
| 231 | requested_size_not_supported=0x04, |
| 232 | default_active_frame_not_valid=0x05) |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 233 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 234 | _construct = Struct('general_result'/GeneralResult, |
| 235 | 'additional_information'/Switch(this.general_result, |
| 236 | { |
| 237 | 'terminal_currently_unable_to_process': AddlInfoTermProblem, |
| 238 | 'interaction_with_cc_by_usim_or_mo_sm_by_usim_permanent': AddlInfoCallControl, |
| 239 | 'multiple_card_commands_error': AddlInfoMultipleCard, |
| 240 | 'launch_browser_generic_error': AddlInfoLaunchBrowser, |
| 241 | 'bearer_independent_protocol_error': AddlInfoBip, |
| 242 | 'frames_error': AddlInfoFrames |
| 243 | }, default=HexAdapter(GreedyBytes))) |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 244 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 245 | # TS 102 223 Section 8.13 + TS 31.111 Section 8.13 |
Harald Welte | 9edbdb9 | 2021-10-08 15:46:42 +0200 | [diff] [blame] | 246 | class SMS_TPDU(COMPR_TLV_IE, tag=0x8B): |
| 247 | _construct = Struct('tpdu'/HexAdapter(GreedyBytes)) |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 248 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 249 | # TS 31.111 Section 8.14 |
| 250 | class SsString(COMPR_TLV_IE, tag=0x89): |
| 251 | _construct = Struct('ton_npi'/TonNpi, 'ss_string'/HexAdapter(GreedyBytes)) |
| 252 | |
| 253 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 254 | # TS 102 223 Section 8.15 |
| 255 | class TextString(COMPR_TLV_IE, tag=0x0d): |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 256 | _construct = Struct('dcs'/Int8ub, # TS 03.38 |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 257 | 'text_string'/HexAdapter(GreedyBytes)) |
| 258 | |
| 259 | # TS 102 223 Section 8.16 |
| 260 | class Tone(COMPR_TLV_IE, tag=0x0e): |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 261 | _construct = Struct('tone'/Enum(Int8ub, dial_tone=0x01, |
| 262 | called_subscriber_busy=0x02, |
| 263 | congestion=0x03, |
| 264 | radio_path_acknowledge=0x04, |
| 265 | radio_path_not_available=0x05, |
| 266 | error_special_info=0x06, |
| 267 | call_waiting_tone=0x07, |
| 268 | ringing_tone=0x08, |
| 269 | general_beep=0x10, |
| 270 | positive_ack_tone=0x11, |
| 271 | negative_ack_or_error_tone=0x12, |
| 272 | ringing_tone_speech=0x13, |
| 273 | alert_tone_sms=0x14, |
| 274 | critical_alert=0x15, |
| 275 | vibrate_only=0x20, |
| 276 | happy_tone=0x30, |
| 277 | sad_tone=0x31, |
| 278 | urgent_action_tone=0x32, |
| 279 | question_tone=0x33, |
| 280 | message_received_tone=0x34, |
| 281 | melody_1=0x40, |
| 282 | melody_2=0x41, |
| 283 | melody_3=0x42, |
| 284 | melody_4=0x43, |
| 285 | melody_5=0x44, |
| 286 | melody_6=0x45, |
| 287 | melody_7=0x46, |
| 288 | melody_8=0x47)) |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 289 | |
| 290 | # TS 31 111 Section 8.17 |
| 291 | class USSDString(COMPR_TLV_IE, tag=0x0a): |
| 292 | _construct = Struct('dcs'/Int8ub, |
| 293 | 'ussd_string'/HexAdapter(GreedyBytes)) |
| 294 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 295 | # TS 102 223 Section 8.18 |
| 296 | class FileList(COMPR_TLV_IE, tag=0x12): |
| 297 | FileId=HexAdapter(Bytes(2)) |
| 298 | _construct = Struct('number_of_files'/Int8ub, |
| 299 | 'files'/GreedyRange(FileId)) |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 300 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 301 | # TS 102 223 Secton 8.19 |
| 302 | class LocationInformation(COMPR_TLV_IE, tag=0x93): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 303 | pass |
| 304 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 305 | # TS 102 223 Secton 8.20 |
| 306 | class IMEI(COMPR_TLV_IE, tag=0x94): |
| 307 | _construct = BcdAdapter(GreedyBytes) |
| 308 | |
| 309 | # TS 102 223 Secton 8.21 |
| 310 | class HelpRequest(COMPR_TLV_IE, tag=0x95): |
| 311 | pass |
| 312 | |
| 313 | # TS 102 223 Secton 8.22 |
| 314 | class NetworkMeasurementResults(COMPR_TLV_IE, tag=0x96): |
| 315 | _construct = BcdAdapter(GreedyBytes) |
| 316 | |
| 317 | # TS 102 223 Section 8.23 |
| 318 | class DefaultText(COMPR_TLV_IE, tag=0x97): |
| 319 | _construct = Struct('dcs'/Int8ub, |
| 320 | 'text_string'/HexAdapter(GreedyBytes)) |
| 321 | |
| 322 | # TS 102 223 Section 8.24 |
| 323 | class ItemsNextActionIndicator(COMPR_TLV_IE, tag=0x18): |
| 324 | _construct = GreedyRange(Int8ub) |
| 325 | |
| 326 | class EventList(COMPR_TLV_IE, tag=0x99): |
| 327 | Event = Enum(Int8ub, mt_call=0x00, |
| 328 | call_connected=0x01, |
| 329 | call_disconnected=0x02, |
| 330 | location_status=0x03, |
| 331 | user_activity=0x04, |
| 332 | idle_screen_available=0x05, |
| 333 | card_reader_status=0x06, |
| 334 | language_selection=0x07, |
| 335 | browser_termination=0x08, |
| 336 | data_available=0x09, |
| 337 | channel_status=0x0a, |
| 338 | access_technology_change=0x0b, |
| 339 | display_parameters_changed=0x0c, |
| 340 | local_connection=0x0d, |
| 341 | network_search_mode_change=0x0e, |
| 342 | browsing_status=0x0f, |
| 343 | frames_informtion_change=0x10, |
| 344 | hci_connectivity_event=0x13, |
| 345 | access_technology_change_multiple=0x14, |
| 346 | contactless_state_request=0x16, |
| 347 | profile_container=0x19, |
| 348 | secured_profile_container=0x1b, |
| 349 | poll_interval_negotation=0x1c, |
| 350 | # TS 31.111 Section 8.25 |
| 351 | wlan_access_status=0x11, |
| 352 | network_rejection=0x12, |
| 353 | csg_cell_selection=0x15, |
| 354 | ims_registration=0x17, |
| 355 | incoming_ims_data=0x18, |
| 356 | data_connection_status_change=0x1d) |
| 357 | _construct = GreedyRange(Event) |
| 358 | |
| 359 | # TS 102 223 Section 8.26 |
| 360 | class Cause(COMPR_TLV_IE, tag=0x9a): |
| 361 | pass |
| 362 | |
| 363 | # TS 102 223 Section 8.27 |
| 364 | class LocationStatus(COMPR_TLV_IE, tag=0x9b): |
| 365 | _construct = Enum(Int8ub, normal_service=0, limited_service=1, no_service=2) |
| 366 | |
| 367 | # TS 102 223 Section 8.31 |
| 368 | class IconIdentifier(COMPR_TLV_IE, tag=0x1e): |
| 369 | _construct = Struct('icon_qualifier'/FlagsEnum(Int8ub, not_self_explanatory=1), |
| 370 | 'icon_identifier'/Int8ub) |
| 371 | |
| 372 | # TS 102 223 Section 8.32 |
| 373 | class ItemIconIdentifierList(COMPR_TLV_IE, tag=0x9f): |
| 374 | _construct = Struct('icon_list_qualifier'/FlagsEnum(Int8ub, not_self_explanatory=1), |
| 375 | 'icon_identifiers'/GreedyRange(Int8ub)) |
| 376 | |
| 377 | # TS 102 223 Section 8.35 |
| 378 | class CApdu(COMPR_TLV_IE, tag=0xA2): |
| 379 | _construct = HexAdapter(GreedyBytes) |
| 380 | |
| 381 | # TS 102 223 Section 8.37 |
| 382 | class TimerIdentifier(COMPR_TLV_IE, tag=0xA4): |
| 383 | _construct = Int8ub |
| 384 | |
| 385 | # TS 102 223 Section 8.38 |
| 386 | class TimerValue(COMPR_TLV_IE, tag=0xA5): |
| 387 | _construct = Struct('hour'/Int8ub, 'minute'/Int8ub, 'second'/Int8ub) |
| 388 | |
| 389 | # TS 102 223 Section 8.40 |
| 390 | class AtCommand(COMPR_TLV_IE, tag=0xA8): |
| 391 | _construct = HexAdapter(GreedyBytes) |
| 392 | |
| 393 | # TS 102 223 Section 8.43 |
| 394 | class ImmediateResponse(COMPR_TLV_IE, tag=0x2b): |
| 395 | pass |
| 396 | |
| 397 | # TS 102 223 Section 8.45 |
| 398 | class Language(COMPR_TLV_IE, tag=0xAD): |
| 399 | _construct = HexAdapter(GreedyBytes) |
| 400 | |
| 401 | # TS 31.111 Section 8.46 |
| 402 | class TimingAdvance(COMPR_TLV_IE, tag=0x46): |
| 403 | _construct = Struct('me_status'/Enum(Int8ub, in_idle_state=0, not_in_idle_state=1), |
| 404 | 'timing_advance'/Int8ub) |
| 405 | |
| 406 | # TS 31.111 Section 8.49 |
| 407 | class Bearer(COMPR_TLV_IE, tag=0xB2): |
| 408 | SingleBearer = Enum(Int8ub, sms=0, csd=1, ussd=2, packet_Service=3) |
| 409 | _construct = GreedyRange(SingleBearer) |
| 410 | |
| 411 | # TS 102 223 Section 8.52 |
| 412 | class BearerDescription(COMPR_TLV_IE, tag=0xB5): |
| 413 | # TS 31.111 Section 8.52.1 |
| 414 | BearerParsCs = Struct('data_rate'/Int8ub, |
| 415 | 'bearer_service'/Int8ub, |
| 416 | 'connection_element'/Int8ub) |
| 417 | # TS 31.111 Section 8.52.2 |
| 418 | BearerParsPacket = Struct('precendence_class'/Int8ub, |
| 419 | 'delay'/Int8ub, |
| 420 | 'reliability'/Int8ub, |
| 421 | 'peak_throughput'/Int8ub, |
| 422 | 'mean_throughput'/Int8ub, |
| 423 | 'pdp_type'/Enum(Int8ub, ip=0x02, non_ip=0x07)) |
| 424 | # TS 31.111 Section 8.52.3 |
| 425 | BearerParsPacketExt = Struct('traffic_class'/Int8ub, |
| 426 | 'max_bitrate_ul'/Int16ub, |
| 427 | 'max_bitrate_dl'/Int16ub, |
| 428 | 'guaranteed_bitrate_ul'/Int16ub, |
| 429 | 'guaranteed_bitrate_dl'/Int16ub, |
| 430 | 'delivery_order'/Int8ub, |
| 431 | 'max_sdu_size'/Int8ub, |
| 432 | 'sdu_err_ratio'/Int8ub, |
| 433 | 'residual_ber'/Int8ub, |
| 434 | 'delivery_of_erroneous_sdu'/Int8ub, |
| 435 | 'transfer_delay'/Int8ub, |
| 436 | 'traffic_handling_priority'/Int8ub, |
| 437 | 'pdp_type'/Enum(Int8ub, ip=0x02, non_ip=0x07)) # 24.008 |
| 438 | # TODO: TS 31.111 Section 8.52.4 I-WLAN |
| 439 | # TODO: TS 31.111 Section 8.52.5 E-UTRAN / mapped UTRAN packet service |
| 440 | # TS 31.111 Section 8.52.6 |
| 441 | BearerParsNgRan = Struct('pdu_session_type'/Int8ub) |
| 442 | _construct = Struct('bearer_type'/Enum(Int8ub, |
| 443 | # TS 31.111 section 8.52 |
| 444 | csd=1, packet_grps_utran_eutran=2, packet_with_extd_params=9, wlan=0x0a, |
| 445 | packet_eutran_mapped_utran=0x0b, ng_ran=0x0c, |
| 446 | # TS 102 223 Section 8.52 |
| 447 | default=3, local_link=4, bluetooth=5, irda=6, rs232=7, cdma2000=8, |
| 448 | usb=10), |
| 449 | 'bearer_parameters'/Switch(this.bearer_type,{ |
| 450 | 'csd': BearerParsCs, |
| 451 | 'packet_grps_utran_eutran': BearerParsPacket, |
| 452 | 'packet_with_extd_params': BearerParsPacketExt, |
| 453 | 'ng_ran': BearerParsNgRan, |
| 454 | }, default=HexAdapter(GreedyBytes))) |
| 455 | |
| 456 | # TS 102 223 Section 8.53 |
| 457 | class ChannelData(COMPR_TLV_IE, tag = 0xB6): |
| 458 | _construct = HexAdapter(GreedyBytes) |
| 459 | |
| 460 | # TS 102 223 Section 8.54 |
| 461 | class ChannelDataLength(COMPR_TLV_IE, tag = 0xB7): |
| 462 | _construct = Int8ub |
| 463 | |
| 464 | # TS 102 223 Section 8.55 |
| 465 | class BufferSize(COMPR_TLV_IE, tag = 0xB9): |
| 466 | _construct = Int16ub |
| 467 | |
| 468 | # TS 31.111 Section 8.56 |
| 469 | class ChannelStatus(COMPR_TLV_IE, tag = 0xB8): |
| 470 | # complex decoding, depends on out-of-band context/knowledge :( |
| 471 | pass |
| 472 | |
| 473 | # TS 102 223 Section 8.58 |
| 474 | class OtherAddress(COMPR_TLV_IE, tag = 0xBE): |
| 475 | _construct = Struct('type_of_address'/Enum(Int8ub, ipv4=0x21, ipv6=0x57), |
| 476 | 'address'/HexAdapter(GreedyBytes)) |
| 477 | |
| 478 | # TS 102 223 Section 8.59 |
| 479 | class UiccTransportLevel(COMPR_TLV_IE, tag = 0xBC): |
| 480 | _construct = Struct('protocol_type'/Enum(Int8ub, udp_uicc_client_remote=1, tcp_uicc_client_remote=2, |
| 481 | tcp_uicc_server=3, udp_uicc_client_local=4, |
| 482 | tcp_uicc_client_local=5, direct_channel=6), |
| 483 | 'port_number'/Int16ub) |
| 484 | |
| 485 | # TS 102 223 Section 8.60 |
| 486 | class Aid(COMPR_TLV_IE, tag=0x2f): |
| 487 | _construct = Struct('aid'/HexAdapter(GreedyBytes)) |
| 488 | |
| 489 | # TS 102 223 Section 8.61 |
| 490 | class AccessTechnology(COMPR_TLV_IE, tag=0xBF): |
| 491 | SingleAccessTech = Enum(Int8ub, gsm=0, tia_eia_533=1, tia_eia_136_270=2, utran=3, tetra=4, |
| 492 | tia_eia_95_b=5, cdma1000_1x=6, cdma2000_hrpd=7, eutran=8, |
| 493 | ehrpd=9, nr=0x0a) |
| 494 | _construct = GreedyRange(SingleAccessTech) |
| 495 | |
| 496 | # TS 102 223 Section 8.63 |
| 497 | class ServiceRecord(COMPR_TLV_IE, tag=0xC1): |
| 498 | BearerTechId = Enum(Int8ub, technology_independent=0, bluetooth=1, irda=2, rs232=3, usb=4) |
| 499 | _construct = Struct('local_bearer_technology'/BearerTechId, |
| 500 | 'service_identifier'/Int8ub, |
| 501 | 'service_record'/HexAdapter(GreedyBytes)) |
| 502 | |
| 503 | # TS 102 223 Section 8.64 |
| 504 | class DeviceFilter(COMPR_TLV_IE, tag=0xC2): |
| 505 | _construct = Struct('local_bearer_technology'/ServiceRecord.BearerTechId, |
| 506 | 'device_filter'/HexAdapter(GreedyBytes)) |
| 507 | |
| 508 | # TS 102 223 Section 8.65 |
| 509 | class ServiceSearchIE(COMPR_TLV_IE, tag=0xC3): |
| 510 | _construct = Struct('local_bearer_technology'/ServiceRecord.BearerTechId, |
| 511 | 'service_search'/HexAdapter(GreedyBytes)) |
| 512 | |
| 513 | # TS 102 223 Section 8.66 |
| 514 | class AttributeInformation(COMPR_TLV_IE, tag=0xC4): |
| 515 | _construct = Struct('local_bearer_technology'/ServiceRecord.BearerTechId, |
| 516 | 'attribute_information'/HexAdapter(GreedyBytes)) |
| 517 | |
| 518 | |
| 519 | # TS 102 223 Section 8.68 |
| 520 | class RemoteEntityAddress(COMPR_TLV_IE, tag=0xC9): |
| 521 | _construct = Struct('coding_type'/Enum(Int8ub, ieee802_16=0, irda=1), |
| 522 | 'address'/HexAdapter(GreedyBytes)) |
| 523 | |
| 524 | # TS 102 223 Section 8.70 |
| 525 | class NetworkAccessName(COMPR_TLV_IE, tag=0xC7): |
| 526 | _construct = HexAdapter(GreedyBytes) |
| 527 | |
| 528 | # TS 102 223 Section 8.72 |
| 529 | class TextAttribute(COMPR_TLV_IE, tag=0x50): |
| 530 | pass |
| 531 | |
| 532 | # TS 31.111 Section 8.72 |
| 533 | class PdpContextActivationParams(COMPR_TLV_IE, tag=0xD2): |
| 534 | pass |
| 535 | |
| 536 | # TS 31.111 Section 8.73 |
| 537 | class UtranEutranMeasurementQualifier(COMPR_TLV_IE, tag=0xE9): |
| 538 | _construct = Enum(Int8ub, utran_intra_freq=0x01, |
| 539 | utran_inter_freq=0x02, |
| 540 | utran_inter_rat_geran=0x03, |
| 541 | utran_inter_rat_eutran=0x04, |
| 542 | eutran_intra_freq=0x05, |
| 543 | eutran_inter_freq=0x06, |
| 544 | eutran_inter_rat_geran=0x07, |
| 545 | eutran_inter_rat_utran=0x08, |
| 546 | eutran_inter_rat_nr=0x09) |
| 547 | |
| 548 | # TS 102 223 Section 8.75 |
| 549 | class NetworkSearchMode(COMPR_TLV_IE, tag=0xE5): |
| 550 | _construct = Enum(Int8ub, manual=0, automatic=1) |
| 551 | |
| 552 | # TS 102 223 Section 8.76 |
| 553 | class BatteryState(COMPR_TLV_IE, tag=0xE3): |
| 554 | _construct = Enum(Int8ub, very_low=0, low=1, average=2, good=3, full=5) |
| 555 | |
| 556 | # TS 102 223 Section 8.78 |
| 557 | class FrameLayout(COMPR_TLV_IE, tag=0xE6): |
| 558 | _construct = Struct('layout'/Enum(Int8ub, horizontal=1, vertical=2), |
| 559 | 'relative_sized_frame'/GreedyRange(Int8ub)) |
| 560 | |
| 561 | class ItemTextAttributeList(COMPR_TLV_IE, tag=0xD1): |
| 562 | _construct = GreedyRange(Int8ub) |
| 563 | |
| 564 | # TS 102 223 Section 8.80 |
| 565 | class FrameIdentifier(COMPR_TLV_IE, tag=0x68): |
| 566 | _construct = Struct('identifier'/Int8ub) |
| 567 | |
| 568 | # TS 102 223 Section 8.82 |
| 569 | class MultimediaMessageReference(COMPR_TLV_IE, tag=0xEA): |
| 570 | _construct = HexAdapter(GreedyBytes) |
| 571 | |
| 572 | # TS 102 223 Section 8.83 |
| 573 | class MultimediaMessageIdentifier(COMPR_TLV_IE, tag=0xEB): |
| 574 | _construct = HexAdapter(GreedyBytes) |
| 575 | |
| 576 | # TS 102 223 Section 8.85 |
| 577 | class MmContentIdentifier(COMPR_TLV_IE, tag=0xEE): |
| 578 | _construct = HexAdapter(GreedyBytes) |
| 579 | |
| 580 | # TS 102 223 Section 8.89 |
| 581 | class ActivateDescriptor(COMPR_TLV_IE, tag=0xFB): |
| 582 | _construct = Struct('target'/Int8ub) |
| 583 | |
| 584 | # TS 31.111 Section 8.90 |
| 585 | class PlmnWactList(COMPR_TLV_IE, tag=0xF2): |
| 586 | def _from_bytes(self, x): |
| 587 | r = [] |
| 588 | i = 0 |
| 589 | while i < len(x): |
| 590 | r.append(dec_xplmn_w_act(b2h(x[i:i+5]))) |
| 591 | i += 5 |
| 592 | return r |
| 593 | |
| 594 | # TS 102 223 Section 8.92 |
| 595 | class ContactlessFunctionalityState(COMPR_TLV_IE, tag=0xD4): |
| 596 | _construct = Enum(Int8ub, enabled=0, disabled=1) |
| 597 | |
| 598 | # TS 31.111 Section 8.91 |
| 599 | class RoutingAreaIdentification(COMPR_TLV_IE, tag=0xF3): |
| 600 | _construct = Struct('mcc_mnc'/BcdAdapter(Bytes(3)), |
| 601 | 'lac'/HexAdapter(Bytes(2)), |
| 602 | 'rac'/Int8ub) |
| 603 | |
| 604 | # TS 31.111 Section 8.92 |
| 605 | class UpdateAttachRegistrationType(COMPR_TLV_IE, tag=0xF4): |
| 606 | _construct = Enum(Int8ub, normal_location_updating_lu=0x00, |
| 607 | periodic_updating_lu=0x01, |
| 608 | imsi_attach_lu=0x02, |
| 609 | gprs_attach=0x03, |
| 610 | combined_gprs_imsi_attach=0x04, |
| 611 | ra_updating_rau=0x05, |
| 612 | combined_ra_la_updting_rau=0x06, |
| 613 | combined_ra_la_updting_with_imsi_attach_rau=0x07, |
| 614 | periodic_updating_rau=0x08, |
| 615 | eps_attach_emm=0x09, |
| 616 | combined_eps_imsi_attach_emm=0x0a, |
| 617 | ta_updating_tau=0x0b, |
| 618 | combined_ta_la_updating_tau=0x0c, |
| 619 | combined_ta_la_updating_with_imsi_attach_tau=0x0d, |
| 620 | periodic_updating_tau=0x0e, |
| 621 | initial_registration_5grr=0x0f, |
| 622 | mobility_registration_updating_5grr=0x10, |
| 623 | periodic_registration_updating_5grr=0x11) |
| 624 | |
| 625 | # TS 31.111 Section 8.93 |
| 626 | class RejectionCauseCode(COMPR_TLV_IE, tag=0xF5): |
| 627 | _construct = Int8ub |
| 628 | |
| 629 | # TS 31.111 Section 8.94 |
| 630 | class GeographicalLocationParameters(COMPR_TLV_IE, tag=0xF6): |
| 631 | _construct = Struct('horizontal_accuracy'/Int8ub, |
| 632 | 'vertical_coordinate'/Int8ub, |
| 633 | 'velocity'/FlagsEnum(Int8ub, horizontal_requested=0, vertical_requested=1, |
| 634 | horizontal_uncertainty_requested=2, |
| 635 | vertical_uncertainty_requested=4), |
| 636 | 'preferred_gad_shapes'/FlagsEnum(Int8ub, ellipsoid_point=0, |
| 637 | ellipsoid_point_with_uncertainty_circle=1, |
| 638 | ellipsoid_point_with_uncertainty_ellipse=2, |
| 639 | ellipsoid_point_with_altitude=3, |
| 640 | polygon=4, |
| 641 | ellipsoid_point_with_altitude_and_uncertainty_ellipsoid=5, |
| 642 | ellipsoid_arc=6), |
| 643 | 'preferred_nmea_sentences'/FlagsEnum(Int8ub, rmc=0, gga=1, gll=2, gns=3), |
| 644 | 'preferred_maximum_response_time'/Int8ub) |
| 645 | |
| 646 | # TS 31.111 Section 8.97 |
| 647 | class PlmnList(COMPR_TLV_IE, tag=0xF9): |
| 648 | _construct = GreedyRange('mcc_mnc'/HexAdapter(Bytes(3))) |
| 649 | |
| 650 | # TS 102 223 Section 8.98 |
| 651 | class EcatSequenceNumber(COMPR_TLV_IE, tag=0xA1): |
| 652 | CmdTypeIndicator = Enum(BitsInteger(2), command_container=0, |
| 653 | terminal_response=1, |
| 654 | envelope_profile_container_event=2, |
| 655 | envelope_profile_container_response=3) |
| 656 | _construct = BitStruct('command_type_indicator'/CmdTypeIndicator, |
| 657 | 'counter'/BitsInteger(22)) |
| 658 | |
| 659 | # TS 102 223 Section 8.99 |
| 660 | class EncryptedTlvList(COMPR_TLV_IE, tag=0xA2): |
| 661 | _construct = HexAdapter(GreedyBytes) |
| 662 | |
| 663 | # TS 102 223 Section 8.100 |
| 664 | class Mac(COMPR_TLV_IE, tag=0xE0): |
| 665 | _construct = HexAdapter(GreedyBytes) |
| 666 | |
| 667 | # TS 102 223 Section 8.101 |
| 668 | class SaTemplate(COMPR_TLV_IE, tag=0xA3): |
| 669 | _construct = HexAdapter(GreedyBytes) |
| 670 | |
| 671 | # TS 102 223 Section 8.103 |
| 672 | class RefreshEnforcementPolicy(COMPR_TLV_IE, tag=0x3A): |
| 673 | _construct = FlagsEnum(Byte, even_if_navigating_menus=0, even_if_data_call=1, even_if_voice_call=2) |
| 674 | |
| 675 | # TS 102 223 Section 8.104 |
| 676 | class DnsServerAddress(COMPR_TLV_IE, tag=0xC0): |
| 677 | _construct = HexAdapter(GreedyBytes) |
| 678 | |
| 679 | # TS 102 223 Section 8.105 |
| 680 | class SupportedRadioAccessTechnologies(COMPR_TLV_IE, tag=0xB4): |
| 681 | AccessTechTuple = Struct('technology'/AccessTechnology.SingleAccessTech, |
| 682 | 'state'/FlagsEnum(Int8ub, enabled=0)) |
| 683 | _construct = GreedyRange(AccessTechTuple) |
| 684 | |
| 685 | # TS 102 223 Section 8.107 |
| 686 | class ApplicationSpecificRefreshData(COMPR_TLV_IE, tag=0x3B): |
| 687 | pass |
| 688 | |
| 689 | # TS 31.111 Section 8.108 |
| 690 | class ImsUri(COMPR_TLV_IE, tag=0xB1): |
| 691 | pass |
| 692 | |
| 693 | # TS 31.111 Section 8.132 |
| 694 | class MediaType(COMPR_TLV_IE, tag=0xFE): |
| 695 | _construct = FlagsEnum(Int8ub, voice=0, video=1) |
| 696 | |
| 697 | # TS 31.111 Section 8.137 |
| 698 | class DataConnectionStatus(COMPR_TLV_IE, tag=0x9D): |
| 699 | _construct = Enum(Int8ub, successful=0, rejected=1, dropped_or_deactivated=2) |
| 700 | |
| 701 | # TS 31.111 Section 8.138 |
| 702 | class DataConnectionType(COMPR_TLV_IE, tag=0xAA): |
| 703 | _construct = Enum(Int8ub, pdp=0, pdn=1, pdu=2) |
| 704 | |
| 705 | # TS 31.111 Section 8.139 |
| 706 | class SmCause(COMPR_TLV_IE, tag=0xAE): |
| 707 | _construct = Int8ub |
| 708 | |
| 709 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 710 | # TS 101 220 Table 7.17 + 31.111 7.1.1.2 |
| 711 | class SMSPPDownload(BER_TLV_IE, tag=0xD1, |
| 712 | nested=[DeviceIdentities, Address, SMS_TPDU]): |
| 713 | pass |
| 714 | |
| 715 | # TS 101 220 Table 7.17 + 31.111 7.1.1.3 |
| 716 | class SMSCBDownload(BER_TLV_IE, tag=0xD2, |
| 717 | nested=[DeviceIdentities, CBSPage]): |
| 718 | pass |
| 719 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 720 | |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 721 | class USSDDownload(BER_TLV_IE, tag=0xD9, |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 722 | nested=[DeviceIdentities, USSDString]): |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 723 | pass |
| 724 | |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 725 | |
Harald Welte | 5a4891a | 2022-08-06 16:15:54 +0200 | [diff] [blame] | 726 | |
| 727 | |
| 728 | class ProactiveCmd(BER_TLV_IE): |
| 729 | def _compute_tag(self) -> int: |
| 730 | return 0xD0 |
| 731 | |
| 732 | |
| 733 | # TS 101 220 Table 7.17 + 102 223 6.6.13/9.4 + TS 31.111 6.6.13 |
| 734 | class Refresh(ProactiveCmd, tag=0x01, |
| 735 | nested=[CommandDetails, DeviceIdentities, FileList, Aid, AlphaIdentifier, |
| 736 | IconIdentifier, TextAttribute, FrameIdentifier, RefreshEnforcementPolicy, |
| 737 | ApplicationSpecificRefreshData, PlmnWactList, PlmnList]): |
| 738 | pass |
| 739 | |
| 740 | class MoreTime(ProactiveCmd, tag=0x02, |
| 741 | nested=[CommandDetails]): |
| 742 | pass |
| 743 | |
| 744 | class PollInterval(ProactiveCmd, tag=0x03, |
| 745 | nested=[CommandDetails]): |
| 746 | pass |
| 747 | |
| 748 | class PollingOff(ProactiveCmd, tag=0x04, |
| 749 | nested=[CommandDetails]): |
| 750 | pass |
| 751 | |
| 752 | class SetUpEventList(ProactiveCmd, tag=0x05, |
| 753 | nested=[CommandDetails]): |
| 754 | pass |
| 755 | |
| 756 | # TS 31.111 Section 6.6.12 |
| 757 | class SetUpCall(ProactiveCmd, tag=0x10, |
| 758 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, Address, ImsUri, |
| 759 | CapabilityConfigParams, Subaddress, Duration, IconIdentifier, AlphaIdentifier, |
| 760 | TextAttribute, FrameIdentifier, MediaType]): |
| 761 | pass |
| 762 | |
| 763 | # TS 31.111 Section 6.6.10 |
| 764 | class SendSS(ProactiveCmd, tag=0x11, |
| 765 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, SsString, IconIdentifier, |
| 766 | TextAttribute, FrameIdentifier]): |
| 767 | pass |
| 768 | |
| 769 | # TS 31.111 Section 6.6.11 |
| 770 | class SendUSSD(ProactiveCmd, tag=0x12, |
| 771 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, USSDString, IconIdentifier, |
| 772 | TextAttribute, FrameIdentifier]): |
| 773 | pass |
| 774 | |
| 775 | # TS 101 220 Table 7.17 + 102 223 6.6.9/9.4 + TS 31.111 Section 6.6.9 |
| 776 | class SendShortMessage(ProactiveCmd, tag=0x13, |
| 777 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, Address, |
| 778 | SMS_TPDU, IconIdentifier, TextAttribute, FrameIdentifier]): |
| 779 | pass |
| 780 | |
| 781 | class SendDTMF(ProactiveCmd, tag=0x14, |
| 782 | nested=[CommandDetails]): |
| 783 | pass |
| 784 | |
| 785 | class LaunchBrowser(ProactiveCmd, tag=0x15, |
| 786 | nested=[CommandDetails]): |
| 787 | pass |
| 788 | |
| 789 | class GeographicalLocationRequest(ProactiveCmd, tag=0x16, |
| 790 | nested=[CommandDetails]): |
| 791 | pass |
| 792 | |
| 793 | class PlayTone(ProactiveCmd, tag=0x20, |
| 794 | nested=[CommandDetails]): |
| 795 | pass |
| 796 | |
| 797 | # TS 101 220 Table 7.17 + 102 223 6.6.1/9.4 CMD=0x21 |
| 798 | class DisplayText(ProactiveCmd, tag=0x21, |
| 799 | nested=[CommandDetails, DeviceIdentities, TextString, IconIdentifier, |
| 800 | ImmediateResponse, Duration, TextAttribute, FrameIdentifier]): |
| 801 | pass |
| 802 | |
| 803 | # TS 102 223 6.6.2 |
| 804 | class GetInkey(ProactiveCmd, tag=0x22, |
| 805 | nested=[CommandDetails, DeviceIdentities, TextString, IconIdentifier, Duration, |
| 806 | TextAttribute, FrameIdentifier]): |
| 807 | pass |
| 808 | |
| 809 | # TS 102 223 6.6.3 |
| 810 | class GetInput(ProactiveCmd, tag=0x23, |
| 811 | nested=[CommandDetails, DeviceIdentities, TextString, ResponseLength, DefaultText, |
| 812 | IconIdentifier, TextAttribute, FrameIdentifier, Duration]): |
| 813 | pass |
| 814 | |
| 815 | # TS 102 223 6.6.8 |
| 816 | class SelectItem(ProactiveCmd, tag=0x24, |
| 817 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, # |
| 818 | ItemsNextActionIndicator, ItemIdentifier, IconIdentifier, ItemIconIdentifierList, |
| 819 | TextAttribute, ItemTextAttributeList, FrameIdentifier]): |
| 820 | pass |
| 821 | |
| 822 | # TS 102 223 6.6.7 |
| 823 | class SetUpMenu(ProactiveCmd, tag=0x25, |
| 824 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, # |
| 825 | ItemsNextActionIndicator, IconIdentifier, ItemIconIdentifierList, |
| 826 | TextAttribute, ItemTextAttributeList]): |
| 827 | pass |
| 828 | |
| 829 | # TS 102 223 6.6.15 |
| 830 | class ProvideLocalInformation(ProactiveCmd, tag=0x26, |
| 831 | nested=[CommandDetails, DeviceIdentities]): |
| 832 | pass |
| 833 | |
| 834 | # TS 102 223 6.6.21 |
| 835 | class TimerManagement(ProactiveCmd, tag=0x27, |
| 836 | nested=[CommandDetails, DeviceIdentities, TimerIdentifier, TimerValue]): |
| 837 | pass |
| 838 | |
| 839 | # TS 102 223 6.6.22 |
| 840 | class SetUpIdleModeText(ProactiveCmd, tag=0x28, |
| 841 | nested=[CommandDetails, DeviceIdentities, TextString, IconIdentifier, TextAttribute, |
| 842 | FrameIdentifier]): |
| 843 | pass |
| 844 | |
| 845 | # TS 102 223 6.6.17 |
| 846 | class PerformCardApdu(ProactiveCmd, tag=0x30, |
| 847 | nested=[CommandDetails, DeviceIdentities, CApdu]): |
| 848 | pass |
| 849 | |
| 850 | # TS 102 223 6.6.19 |
| 851 | class PowerOnCard(ProactiveCmd, tag=0x31, |
| 852 | nested=[CommandDetails, DeviceIdentities]): |
| 853 | pass |
| 854 | |
| 855 | # TS 102 223 6.6.18 |
| 856 | class PowerOffCard(ProactiveCmd, tag=0x32, |
| 857 | nested=[CommandDetails, DeviceIdentities]): |
| 858 | pass |
| 859 | |
| 860 | # TS 102 223 6.6.20 |
| 861 | class GetReaderStatus(ProactiveCmd, tag=0x33, |
| 862 | nested=[CommandDetails, DeviceIdentities]): |
| 863 | pass |
| 864 | |
| 865 | # TS 102 223 6.6.23 |
| 866 | class RunAtCommand(ProactiveCmd, tag=0x34, |
| 867 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, AtCommand, IconIdentifier, |
| 868 | TextAttribute, FrameIdentifier]): |
| 869 | pass |
| 870 | |
| 871 | # TS 102 223 6.6.25 |
| 872 | class LanguageNotification(ProactiveCmd, tag=0x35, |
| 873 | nested=[CommandDetails, DeviceIdentities, Language]): |
| 874 | pass |
| 875 | |
| 876 | # TS 102 223 6.6.27 |
| 877 | class OpenChannel(ProactiveCmd, tag=0x40, |
| 878 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, IconIdentifier, Address, Subaddress, |
| 879 | Duration, BearerDescription, BufferSize, NetworkAccessName, OtherAddress, |
| 880 | TextString, UiccTransportLevel, RemoteEntityAddress, TextAttribute, |
| 881 | FrameIdentifier]): |
| 882 | pass |
| 883 | |
| 884 | # TS 102 223 6.6.28 |
| 885 | class CloseChannel(ProactiveCmd, tag=0x41, |
| 886 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, IconIdentifier, TextAttribute, |
| 887 | FrameIdentifier]): |
| 888 | pass |
| 889 | |
| 890 | # TS 102 223 6.6.29 |
| 891 | class ReceiveData(ProactiveCmd, tag=0x42, |
| 892 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, IconIdentifier, ChannelDataLength, |
| 893 | TextAttribute, FrameIdentifier]): |
| 894 | pass |
| 895 | |
| 896 | # TS 102 223 6.6.30 |
| 897 | class SendData(ProactiveCmd, tag=0x43, |
| 898 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, IconIdentifier, ChannelData, |
| 899 | TextAttribute, FrameIdentifier]): |
| 900 | pass |
| 901 | |
| 902 | # TS 102 223 6.6.31 |
| 903 | class GetChannelStatus(ProactiveCmd, tag=0x44, |
| 904 | nested=[CommandDetails, DeviceIdentities]): |
| 905 | pass |
| 906 | |
| 907 | # TS 102 223 6.6.32 |
| 908 | class ServiceSearch(ProactiveCmd, tag=0x45, |
| 909 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, IconIdentifier, ServiceSearchIE, |
| 910 | DeviceFilter, TextAttribute, FrameIdentifier]): |
| 911 | pass |
| 912 | |
| 913 | # TS 102 223 6.6.33 |
| 914 | class GetServiceInformation(ProactiveCmd, tag=0x46, |
| 915 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, IconIdentifier, AttributeInformation, |
| 916 | TextAttribute, FrameIdentifier]): |
| 917 | pass |
| 918 | |
| 919 | # TS 102 223 6.6.34 |
| 920 | class DeclareService(ProactiveCmd, tag=0x47, |
| 921 | nested=[CommandDetails, DeviceIdentities, ServiceRecord, UiccTransportLevel]): |
| 922 | pass |
| 923 | |
| 924 | # TS 102 223 6.6.35 |
| 925 | class SetFrames(ProactiveCmd, tag=0x50, |
| 926 | nested=[CommandDetails, DeviceIdentities, FrameIdentifier, FrameLayout]): |
| 927 | pass |
| 928 | |
| 929 | # TS 102 223 6.6.36 |
| 930 | class GetFramesStatus(ProactiveCmd, tag=0x51, |
| 931 | nested=[CommandDetails, DeviceIdentities]): |
| 932 | pass |
| 933 | |
| 934 | # TS 102 223 6.6.37 |
| 935 | class RetrieveMultimediaMessage(ProactiveCmd, tag=0x60, |
| 936 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, MultimediaMessageReference, |
| 937 | FileList, MmContentIdentifier, MultimediaMessageIdentifier, TextAttribute, |
| 938 | FrameIdentifier]): |
| 939 | pass |
| 940 | |
| 941 | # TS 102 223 6.6.38 |
| 942 | class SubmitMultimediaMessage(ProactiveCmd, tag=0x61, |
| 943 | nested=[CommandDetails, DeviceIdentities, AlphaIdentifier, IconIdentifier, FileList, |
| 944 | MultimediaMessageIdentifier, TextAttribute, FrameIdentifier]): |
| 945 | pass |
| 946 | |
| 947 | # TS 102 223 6.6.39 |
| 948 | class DisplayMultimediaMessage(ProactiveCmd, tag=0x62, |
| 949 | nested=[CommandDetails, DeviceIdentities, FileList, MultimediaMessageIdentifier, |
| 950 | ImmediateResponse, FrameIdentifier]): |
| 951 | pass |
| 952 | |
| 953 | # TS 102 223 6.6.40 |
| 954 | class Activate(ProactiveCmd, tag=0x70, |
| 955 | nested=[CommandDetails, DeviceIdentities, ActivateDescriptor]): |
| 956 | pass |
| 957 | |
| 958 | # TS 102 223 6.6.41 |
| 959 | class ContactlessStateChanged(ProactiveCmd, tag=0x71, |
| 960 | nested=[CommandDetails, DeviceIdentities, ContactlessFunctionalityState]): |
| 961 | pass |
| 962 | |
| 963 | # TS 102 223 6.6.42 |
| 964 | class CommandContainer(ProactiveCmd, tag=0x72, |
| 965 | nested=[CommandDetails, DeviceIdentities, EcatSequenceNumber, Mac, EncryptedTlvList]): |
| 966 | pass |
| 967 | |
| 968 | # TS 102 223 6.6.43 |
| 969 | class EncapsulatedSessionControl(ProactiveCmd, tag=0x73, |
| 970 | nested=[CommandDetails, DeviceIdentities, SaTemplate]): |
| 971 | pass |
| 972 | |
| 973 | |
| 974 | |
| 975 | # TS 101 220 Table 7.17: FIXME: Merge all nested? |
| 976 | class ProactiveCommandBase(BER_TLV_IE, tag=0xD0, nested=[CommandDetails]): |
| 977 | def find_cmd_details(self): |
| 978 | for c in self.children: |
| 979 | if type(c).__name__ == 'CommandDetails': |
| 980 | return c |
| 981 | else: |
| 982 | return None |
| 983 | |
| 984 | class ProactiveCommand(TLV_IE_Collection, |
| 985 | nested=[Refresh, MoreTime, PollInterval, PollingOff, SetUpEventList, SetUpCall, |
| 986 | SendSS, SendUSSD, SendShortMessage, SendDTMF, LaunchBrowser, |
| 987 | GeographicalLocationRequest, PlayTone, DisplayText, GetInkey, GetInput, |
| 988 | SelectItem, SetUpMenu, ProvideLocalInformation, TimerManagement, |
| 989 | SetUpIdleModeText, PerformCardApdu, PowerOnCard, PowerOffCard, |
| 990 | GetReaderStatus, RunAtCommand, LanguageNotification, OpenChannel, |
| 991 | CloseChannel, ReceiveData, SendData, GetChannelStatus, ServiceSearch, |
| 992 | GetServiceInformation, DeclareService, SetFrames, GetFramesStatus, |
| 993 | RetrieveMultimediaMessage, SubmitMultimediaMessage, DisplayMultimediaMessage, |
| 994 | Activate, ContactlessStateChanged, CommandContainer, |
| 995 | EncapsulatedSessionControl]): |
| 996 | """Class representing a CAT proactive command, as (for example) sent via a FETCH response. Parsing this is |
| 997 | more difficult than any normal TLV IE Collection, because the content of one of the IEs defines the |
| 998 | definitions of all the other IEs. So we first need to find the CommandDetails, and then parse according |
| 999 | to the command type indicated in that IE data.""" |
| 1000 | def from_bytes(self, binary: bytes) -> List[TLV_IE]: |
| 1001 | # do a first parse step to get the CommandDetails |
| 1002 | pcmd = ProactiveCommandBase() |
| 1003 | pcmd.from_tlv(binary) |
| 1004 | cmd_details = pcmd.find_cmd_details() |
| 1005 | # then do a second decode stage for the specific |
| 1006 | cmd_type = cmd_details.decoded['type_of_command'] |
| 1007 | if cmd_type in self.members_by_tag: |
| 1008 | cls = self.members_by_tag[cmd_type] |
| 1009 | inst = cls() |
| 1010 | dec, remainder = inst.from_tlv(binary) |
| 1011 | self.decoded = inst |
| 1012 | else: |
| 1013 | self.decoded = pcmd |
| 1014 | return self.decoded |
| 1015 | |
| 1016 | #def from_dict(self, decoded): |
| 1017 | # pass |
| 1018 | |
| 1019 | def to_dict(self): |
| 1020 | return self.decoded.to_dict() |
| 1021 | |
| 1022 | def to_bytes(self): |
| 1023 | return self.decoded.to_tlv() |
| 1024 | |
| 1025 | |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1026 | # reasonable default for playing with OTA |
| 1027 | # 010203040506070809101112131415161718192021222324252627282930313233 |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1028 | # '7fe1e10e000000000000001f43000000ff00000000000000000000000000000000' |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1029 | |
| 1030 | # TS 102 223 Section 5.2 |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1031 | term_prof_bits = { |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1032 | # first byte |
| 1033 | 1: 'Profile download', |
| 1034 | 2: 'SMS-PP data download', |
| 1035 | 3: 'Cell Broadcast data download', |
| 1036 | 4: 'Menu selection', |
| 1037 | 5: 'SMS-PP data download', |
| 1038 | 6: 'Timer expiration', |
| 1039 | 7: 'USSD string DO support in CC by USIM', |
| 1040 | 8: 'Call Control by NAA', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1041 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1042 | # first byte |
| 1043 | 9: 'Command result', |
| 1044 | 10: 'Call Control by NAA', |
| 1045 | 11: 'Call Control by NAA', |
| 1046 | 12: 'MO short message control support', |
| 1047 | 13: 'Call Control by NAA', |
| 1048 | 14: 'UCS2 Entry supported', |
| 1049 | 15: 'UCS2 Display supported', |
| 1050 | 16: 'Display Text', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1051 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1052 | # third byte |
| 1053 | 17: 'Proactive UICC: DISPLAY TEXT', |
| 1054 | 18: 'Proactive UICC: GET INKEY', |
| 1055 | 19: 'Proactive UICC: GET INPUT', |
| 1056 | 20: 'Proactive UICC: MORE TIME', |
| 1057 | 21: 'Proactive UICC: PLAY TONE', |
| 1058 | 22: 'Proactive UICC: POLL INTERVAL', |
| 1059 | 23: 'Proactive UICC: POLLING OFF', |
| 1060 | 24: 'Proactive UICC: REFRESH', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1061 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1062 | # fourth byte |
| 1063 | 25: 'Proactive UICC: SELECT ITEM', |
| 1064 | 26: 'Proactive UICC: SEND SHORT MESSAGE with 3GPP-SMS-TPDU', |
| 1065 | 27: 'Proactive UICC: SEND SS', |
| 1066 | 28: 'Proactive UICC: SEND USSD', |
| 1067 | 29: 'Proactive UICC: SET UP CALL', |
| 1068 | 30: 'Proactive UICC: SET UP MENU', |
| 1069 | 31: 'Proactive UICC: PROVIDE LOCAL INFORMATION (MCC, MNC, LAC, Cell ID & IMEI)', |
| 1070 | 32: 'Proactive UICC: PROVIDE LOCAL INFORMATION (NMR)', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1071 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1072 | # fifth byte |
| 1073 | 33: 'Proactive UICC: SET UP EVENT LIST', |
| 1074 | 34: 'Event: MT call', |
| 1075 | 35: 'Event: Call connected', |
| 1076 | 36: 'Event: Call disconnected', |
| 1077 | 37: 'Event: Location status', |
| 1078 | 38: 'Event: User activity', |
| 1079 | 39: 'Event: Idle screen available', |
| 1080 | 40: 'Event: Card reader status', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1081 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1082 | # sixth byte |
| 1083 | 41: 'Event: Language selection', |
| 1084 | 42: 'Event: Browser Termination', |
| 1085 | 43: 'Event: Data aailable', |
| 1086 | 44: 'Event: Channel status', |
| 1087 | 45: 'Event: Access Technology Change', |
| 1088 | 46: 'Event: Display parameters changed', |
| 1089 | 47: 'Event: Local Connection', |
| 1090 | 48: 'Event: Network Search Mode Change', |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1091 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1092 | # seventh byte |
| 1093 | 49: 'Proactive UICC: POWER ON CARD', |
| 1094 | 50: 'Proactive UICC: POWER OFF CARD', |
| 1095 | 51: 'Proactive UICC: PERFORM CARD RESET', |
| 1096 | 52: 'Proactive UICC: GET READER STATUS (Card reader status)', |
| 1097 | 53: 'Proactive UICC: GET READER STATUS (Card reader identifier)', |
| 1098 | # RFU: 3 bit (54,55,56) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1099 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1100 | # eighth byte |
| 1101 | 57: 'Proactive UICC: TIMER MANAGEMENT (start, stop)', |
| 1102 | 58: 'Proactive UICC: TIMER MANAGEMENT (get current value)', |
| 1103 | 59: 'Proactive UICC: PROVIDE LOCAL INFORMATION (date, time and time zone)', |
| 1104 | 60: 'GET INKEY', |
| 1105 | 61: 'SET UP IDLE MODE TEXT', |
| 1106 | 62: 'RUN AT COMMAND', |
| 1107 | 63: 'SETUP CALL', |
| 1108 | 64: 'Call Control by NAA', |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1109 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1110 | # ninth byte |
| 1111 | 65: 'DISPLAY TEXT', |
| 1112 | 66: 'SEND DTMF command', |
| 1113 | 67: 'Proactive UICC: PROVIDE LOCAL INFORMATION (NMR)', |
| 1114 | 68: 'Proactive UICC: PROVIDE LOCAL INFORMATION (language)', |
| 1115 | 69: 'Proactive UICC: PROVIDE LOCAL INFORMATION (Timing Advance)', |
| 1116 | 70: 'Proactive UICC: LANGUAGE NOTIFICATION', |
| 1117 | 71: 'Proactive UICC: LAUNCH BROWSER', |
| 1118 | 72: 'Proactive UICC: PROVIDE LOCAL INFORMATION (Access Technology)', |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1119 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1120 | # tenth byte |
| 1121 | 73: 'Soft keys support for SELECT ITEM', |
| 1122 | 74: 'Soft keys support for SET UP MENU ITEM', |
| 1123 | # RFU: 6 bit (75-80) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1124 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1125 | # eleventh byte: max number of soft keys as 8bit value (81..88) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1126 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1127 | # twelfth byte |
| 1128 | 89: 'Proactive UICC: OPEN CHANNEL', |
| 1129 | 90: 'Proactive UICC: CLOSE CHANNEL', |
| 1130 | 91: 'Proactive UICC: RECEIVE DATA', |
| 1131 | 92: 'Proactive UICC: SEND DATA', |
| 1132 | 93: 'Proactive UICC: GET CHANNEL STATUS', |
| 1133 | 94: 'Proactive UICC: SERVICE SEARCH', |
| 1134 | 95: 'Proactive UICC: GET SERVICE INFORMATION', |
| 1135 | 96: 'Proactive UICC: DECLARE SERVICE', |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1136 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1137 | # thirteenth byte |
| 1138 | 97: 'BIP supported Bearer: CSD', |
| 1139 | 98: 'BIP supported Bearer: GPRS', |
| 1140 | 99: 'BIP supported Bearer: Bluetooth', |
| 1141 | 100: 'BIP supported Bearer: IrDA', |
| 1142 | 101: 'BIP supported Bearer: RS232', |
| 1143 | # 3 bits: number of channels supported (102..104) |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1144 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1145 | # fourtheenth byte (screen height) |
| 1146 | # fifteenth byte (screen width) |
| 1147 | # sixeenth byte (screen effects) |
| 1148 | # seventeenth byte (BIP supported bearers) |
| 1149 | 129: 'BIP: TCP, UICC in client mode, remote connection', |
| 1150 | 130: 'BIP: UDP, UICC in client mode, remote connection', |
| 1151 | 131: 'BIP: TCP, UICC in server mode', |
| 1152 | 132: 'BIP: TCP, UICC in client mode, local connection', |
| 1153 | 133: 'BIP: UDP, UICC in client mode, local connection', |
| 1154 | 134: 'BIP: direct communication channel', |
| 1155 | # 2 bits reserved: 135, 136 |
Harald Welte | f235954 | 2021-10-08 15:46:25 +0200 | [diff] [blame] | 1156 | |
Harald Welte | c91085e | 2022-02-10 18:05:45 +0100 | [diff] [blame] | 1157 | # FIXME: remainder |
Harald Welte | bb3b5df | 2021-05-24 23:15:54 +0200 | [diff] [blame] | 1158 | } |