1 # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import logging 6 import traceback 7 8 import common 9 from autotest_lib.client.common_lib import error 10 11 12 class MBIMComplianceError(error.TestFail): 13 """ Base class for all errors overtly raised in the suite. """ 14 pass 15 16 17 class MBIMComplianceFrameworkError(MBIMComplianceError): 18 """ 19 Errors raised by any of the framework code. 20 21 These errors are raised by code that is not part of a test / sequence / 22 assertion. 23 24 """ 25 pass 26 27 28 class MBIMComplianceChannelError(MBIMComplianceError): 29 """ Errors raised in the MBIM communication channel. """ 30 pass 31 32 33 class MBIMComplianceControlMessageError(MBIMComplianceError): 34 """ Errors raised in the MBIM control module. """ 35 pass 36 37 38 class MBIMComplianceDataTransferError(MBIMComplianceError): 39 """ Errors raised in the MBIM data transfer module. """ 40 pass 41 42 43 class MBIMComplianceNtbError(MBIMComplianceError): 44 """ Errors raised in the MBIM NTB module. """ 45 pass 46 47 48 class MBIMComplianceTestError(MBIMComplianceError): 49 """ Errors raised by compliance suite tests. """ 50 pass 51 52 53 class MBIMComplianceSequenceError(MBIMComplianceError): 54 """ Errors raised by compliance suite sequences. """ 55 pass 56 57 58 class MBIMComplianceAssertionError(MBIMComplianceError): 59 """ Errors raised by compliance suite assertions. """ 60 61 MBIM_ASSERTIONS = { 62 # This key should not be used directly. 63 # Raise |MBIMComplianceGenericAssertionError| instead. 64 'no_code': '', 65 66 # Assertion group: 3.x.x#x 67 'mbim1.0:3.2.1#1': 'Functions that implement both NCM 1.0 and MBIM ' 68 'shall provide two alternate settings for the ' 69 'Communication Interface.', 70 'mbim1.0:3.2.1#2': 'For alternate setting 0 of the Communication ' 71 'Interface of an NCM/MBIM function: interface, ' 72 'functional and endpoint descriptors shall be ' 73 'constructed according to the rules given in ' 74 '[USBNCM10].', 75 'mbim1.0:3.2.1#3': 'For alternate setting 1 of the Communication ' 76 'Interface of an NCM/MBIM function: interface, ' 77 'functional and endpoint descriptors shall be ' 78 'constructed according to the rules given in ' 79 '[MBIM 1.0] section 6.', 80 'mbim1.0:3.2.1#4': 'When alternate setting 0 of the Communiation' 81 'Interface of an NCM/MBIM function is selected, ' 82 'the function shall operator according to the ' 83 'NCM rules given in [USBNCM10].', 84 'mbim1.0:3.2.1#5': 'When alternate setting 1 of the Communiation' 85 'Interface of an NCM/MBIM function is selected, ' 86 'the function shall operator according to the ' 87 'MBIM rules given in [MBIM1.0].', 88 'mbim1.0:3.2.2.1#1': 'If an Interface Association Descriptor is ' 89 'used to form an NCM/MBIM function, its ' 90 'interface class, subclass, and protocol ' 91 'codes shall match those given in alternate ' 92 'setting 0 of the Communication Interface. ', 93 'mbim1.0:3.2.2.4#1': 'Functions that implement both NCM 1.0 and ' 94 'MBIM (an "NCM/MBIM function") shall provide ' 95 'three alternate settings for the Data ' 96 'Interface.', 97 'mbim1.0:3.2.2.4#2': 'For an NCM/MBIM function, the Data Interface ' 98 'descriptors for alternate settings 0 and 1 ' 99 'must have bInterfaceSubClass == 00h, and ' 100 'bInterfaceProtocol == 01h.', 101 'mbim1.0:3.2.2.4#3': 'For an NCM/MBIM function, the Data Interface ' 102 'descriptor for alternate setting 2 must have ' 103 'bInterfaceSubClass == 00h, and ' 104 'bInterfaceProtocol == 02h.', 105 'mbim1.0:3.2.2.4#4': 'For an NCM/MBIM function there must be no ' 106 'endpoints for alternate setting 0 of the ' 107 'Data Interface. For each of the other two ' 108 'alternate settings (1 and 2) there must be ' 109 'exactly two endpoints: one Bulk IN and one ' 110 'Bulk OUT.', 111 112 # Assertion group: 6.x#x 113 'mbim1.0:6.1#1': 'If an Interface Association Descriptor (IAD) is ' 114 'provided for the MBIM function, the IAD and the ' 115 'mandatory CDC Union Functional Descriptor ' 116 'specified for the MBIM function shall group ' 117 'together the same interfaces.', 118 'mbim1.0:6.1#2': 'If an Interface Association Descriptor (IAD) is ' 119 'provided for the MBIM only function, its ' 120 'interface class, subclass, and protocol codes ' 121 'shall match those given in the Communication ' 122 'Interface descriptor.', 123 'mbim1.0:6.3#1': 'The descriptor for alternate setting 0 of the ' 124 'Communication Interface of an MBIM only function ' 125 'shall have bInterfaceClass == 02h, ' 126 'bInterfaceSubClass == 0Eh, and ' 127 'bInterfaceProtocol == 00h.', 128 'mbim1.0:6.3#2': 'MBIM Communication Interface description shall ' 129 'include the following functional descriptors: ' 130 'CDC Header Functional Descriptor, CDC Union ' 131 'Functional Descriptor, and MBIM Functional ' 132 'Descriptor. Refer to Table 6.2 of [USBMBIM10].', 133 'mbim1.0:6.3#3': 'CDC Header Functional Descriptor shall appear ' 134 'before CDC Union Functional Descriptor and ' 135 'before MBIM Functional Descriptor.', 136 'mbim1.0:6.3#4': 'CDC Union Functional Descriptor for an MBIM ' 137 'function shall group together the MBIM ' 138 'Communication Interface and the MBIM Data ' 139 'Interface.', 140 'mbim1.0:6.3#5': 'The class-specific descriptors must be followed ' 141 'by an Interrupt IN endpoint descriptor.', 142 'mbim1.0:6.4#1': 'Field wMaxControlMessage of MBIM Functional ' 143 'Descriptor must not be smaller than 64.', 144 'mbim1.0:6.4#2': 'Field bNumberFilters of MBIM Functional ' 145 'Descriptor must not be smaller than 16.', 146 'mbim1.0:6.4#3': 'Field bMaxFilterSize of MBIM Functional ' 147 'Descriptor must not exceed 192.', 148 'mbim1.0:6.4#4': 'Field wMaxSegmentSize of MBIM Functional ' 149 'Descriptor must not be smaller than 2048.', 150 'mbim1.0:6.4#5': 'Field bFunctionLength of MBIM Functional ' 151 'Descriptor must be 12 representing the size of ' 152 'the descriptor.', 153 'mbim1.0:6.4#6': 'Field bcdMBIMVersion of MBIM Functional ' 154 'Descriptor must be 0x0100 in little endian ' 155 'format.', 156 'mbim1.0:6.4#7': 'Field bmNetworkCapabilities of MBIM Functional ' 157 'Descriptor should have the following bits set to ' 158 'zero: D0, D1, D2, D4, D6 and D7.', 159 'mbim1.0:6.5#1': 'If MBIM Extended Functional Descriptor is ' 160 'provided, it must appear after MBIM Functional ' 161 'Descriptor.', 162 'mbim1.0:6.5#2': 'Field bFunctionLength of MBIM Extended ' 163 'Functional Descriptor must be 8 representing the ' 164 'size of the descriptor.', 165 'mbim1.0:6.5#3': 'Field bcdMBIMEFDVersion of MBIM Extended ' 166 'Functional Descriptor must be 0x0100 in little ' 167 'endian format.', 168 'mbim1.0:6.5#4': 'Field bMaxOutstandingCommandMessages of MBIM ' 169 'Extended Functional Descriptor shall be greater ' 170 'than 0.', 171 'mbim1.0:6.6#1': 'The Data Interface for an MBIM only function ' 172 'shall provide two alternate settings.', 173 'mbim1.0:6.6#2': 'The first alternate setting for the Data ' 174 'Interface of an MBIM only function (the default ' 175 'interface setting, alternate setting 0) shall ' 176 'include no endpoints.', 177 'mbim1.0:6.6#3': 'The second alternate setting for the Data ' 178 'Interface of an MBIM only function (alternate ' 179 'setting 1) is used for normal operation, and ' 180 'shall include one Bulk IN endpoint and one Bulk ' 181 'OUT endpoint.', 182 'mbim1.0:6.6#4': 'For an MBIM only function the Data Interface ' 183 'descriptors for alternate settings 0 and 1 must ' 184 'have bInterfaceSubClass == 00h, and ' 185 'bInterfaceProtocol == 02h. Refer to Table 6.4 of ' 186 '[USBMBIM10].', 187 188 # Assertion Groups: 7.x.x#x 189 'mbim1.0:7#1': 'To distinguish among the data streams, the last ' 190 'character of the dwSignature in the NDP16 header ' 191 'shall be coded with the index SessionId specified' 192 ' by the host in the MBIM_CID_CONNECT. The first ' 193 'three symbols are encoded as ASCII characters in ' 194 'little-endian form plus a last byte in HEX ' 195 '(binary) format: "IPS"<SessionId>.', 196 'mbim1.0:7#3': 'To distinguish among the data streams, the last ' 197 'character of the dwSignature in the NDP32 header ' 198 'shall be coded with the index SessionId specified' 199 ' by the host in the MBIM_CID_CONNECT. The first ' 200 'three symbols are encoded as ASCII characters in ' 201 'little-endian form plus a last byte in HEX ' 202 '(binary) format: "ips"<SessionId>.', 203 204 # Assertion Groups: 8.x.x#x 205 'mbim1.0:8.1.2#2': 'The function must use a separate ' 206 'GET_ENCAPSULATED_RESPONSE transfer for each ' 207 'control message it has to send to the host.', 208 'mbim1.0:8.1.2#3': 'The function must send a RESPONSE_AVAILABLE ' 209 'notification for each available fragment of ' 210 'ENCAPSULATED_RESPONSE to be read from the ' 211 'default pipe.', 212 213 # Assertion Groups: 9.x#x, 9.x.x and 9.x.x#x 214 'mbim1.0:9.1#1': 'For notifications, the TransactionId must be ' 215 'set to 0 by the function.', 216 'mbim1.0:9.1#2': 'MessageLength in MBIM_MESSAGE_HEADER must be >=' 217 ' 0x0C.', 218 'mbim1.0:9.2': 'Function should fragment responses based on ' 219 'MaxControlTransfer value from MBIM_OPEN_MSG.', 220 'mbim1.0:9.3.1#1': 'In case MBIM_OPEN_MSG message is sent to a ' 221 'function that is already opened, the function ' 222 'shall interpret this as that the host and the ' 223 'function are out of synchronization. The ' 224 'function shall then perform the actions ' 225 'dictated by the MBIM_CLOSE_MSG before it ' 226 'performs the actions dictated by this ' 227 'command.The function shall not send the ' 228 'MBIM_CLOSE_DONE when the transition to the ' 229 'Closed state has been completed. Only the ' 230 ' MBIM_OPEN_DONE message is sent upon ' 231 'successful completion of this message.', 232 'mbim1.0:9.3.2#1': 'Between the host\'s sending MBIM_CLOSE_MSG ' 233 'message and the function\'s completing the ' 234 'request (acknowledged with MBIM_CLOSE_DONE), ' 235 'the function shall ignore any MBIM control ' 236 'messages it receives on the control plane or ' 237 'the data on the bulk pipes.', 238 'mbim1.0:9.3.2#2': 'The function shall not send any MBIM control ' 239 'messages on the control plane or data on the ' 240 'bulk pipes after completing ' 241 'MBIM_CLOSE_MSG message (acknowledging it with ' 242 'the MBIM_CLOSE_DONE message) with one ' 243 'exception and that is MBIM_ERROR_NOT_OPENED.', 244 'mbim1.0:9.3.2#3': 'On MBIM_CLOSE_MSG, any active context between ' 245 'the function and the host shall be terminated ', 246 'mbim1.0:9.3.4#2': 'An MBIM_FUNCTION_ERROR_MSG shall not make use ' 247 'of a DataBuffer, so it cannot send any data ' 248 'payload.', 249 'mbim1.0:9.3.4#3': 'MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE shall be ' 250 'sent by the function if it detects a fragmented' 251 ' message out of sequence.', 252 'mbim1.0:9.3.4.2#2': 'For MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE, the' 253 ' TransactionId of the responding message must ' 254 'match the TransactionId in the faulty ' 255 'fragmented sequence.', 256 'mbim1.0:9.3.4.2#3': 'In case of an out of a sequence error, the ' 257 'function shall discard all the packets with ' 258 'the same TransactionId as the faulty message ' 259 'sequence.', 260 'mbim1.0:9.3.4.2#4': 'If the function gets one more message that ' 261 'is out of order for the same TransactionId, it ' 262 'shall send a new error message with the same ' 263 'TransactionId once more.', 264 'mbim1.0:9.4.1#1': 'The function shall respond to the ' 265 'MBIM_OPEN_MSG message with an MBIM_OPEN_DONE ' 266 'message in which the TransactionId must match ' 267 'the TransactionId in the MBIM_OPEN_MSG.', 268 'mbim1.0:9.4.1#2': 'The Status field of MBIM_OPEN_DONE shall be ' 269 'set to MBIM_STATUS_SUCCESS if the function ' 270 'initialized successfully.', 271 'mbim1.0:9.4.2#1': 'The function shall respond to the ' 272 'MBIM_CLOSE_MSG message with an ' 273 'MBIM_CLOSE_DONE message in which the ' 274 'TransactionId must match the TransactionId in ' 275 'the MBIM_CLOSE_MSG.', 276 'mbim1.0:9.4.2#2': 'The Status field of MBIM_CLOSE_DONE shall ' 277 'always be set to MBIM_STATUS_SUCCESS.', 278 'mbim1.0:9.4.3': 'The function shall respond to ' 279 'the MBIM_COMMAND_MSG message with an ' 280 'MBIM_COMMAND_DONE message in which the ' 281 'TransactionId must match the TransactionId in ' 282 'the MBIM_COMMAND_MSG.', 283 'mbim1.0:9.4.5#1': 'If the CID is successful, the function shall ' 284 'set the Status field to MBIM_STATUS_SUCCESS ' 285 'in the MBIM_COMMAND_DONE.', 286 'mbim1.0:9.4.5#2': 'If the function does not implement the CID, ' 287 'then the function shall fail the request with ' 288 'MBIM_STATUS_NO_DEVICE_SUPPORT.', 289 'mbim1.0:9.4.5#3': 'If the Status field returned to the host is ' 290 'not equal to MBIM_STATUS_SUCCESS, the function ' 291 'must set the Information BufferLength to 0, ' 292 'indicating an empty InformationBuffer except ' 293 'the following CIDs: MBIM_CID_REGISTER_STATE, ' 294 'MBIM_CID_PACKET_SERVICE, MBIM_CID_CONNECT, ' 295 'MBIM_CID_SERVICE_ACTIVATION.', 296 'mbim1.0:9.5#1': 'Function should transmit fragmented message to ' 297 'host without intermixing fragments from other ' 298 'messages.', 299 'mbim1.0:10.3#2': 'The function shall reject incoming messages ' 300 'that dont follow the rules for variable-length' 301 ' encoding by setting ' 302 'MBIM_STATUS_INVALID_PARAMETERS as the status ' 303 'code in the MBIM_COMMAND_DONE message.', 304 'mbim1.0:10.5.1.3#1': 'Functions that support CDMA must specify ' 305 'MBIMCtrlCapsCdmaMobileIP or ' 306 'MBIMCtrlCapsCdmaSimpleIP or both flags to ' 307 'inform the host about the type of IP that the ' 308 'function supports.', 309 310 # NCM Assertion group: 3.x.x#x 311 'ncm1.0:3.2.1#1': 'The first four bytes in NTH16 shall be ' 312 '0x484D434E in little-endian format ("NCMH").', 313 'ncm1.0:3.2.1#2': 'wHeaderLength value in NTH16 shall be 0x000C.', 314 'ncm1.0:3.2.1#3': 'wSequence in NTH16 shall be set to zero by the ' 315 'function in the first NTB transferred after ' 316 'every "function reset" event.', 317 'ncm1.0:3.2.1#4': 'wSequence value in NTH16 shall be incremented ' 318 'for every NTB subsequent transfer.', 319 'ncm1.0:3.2.1#5': 'NTB size (IN) shall not exceed dwNtbInMaxSize.', 320 'ncm1.0:3.2.1#6': 'wNdpIndex value in NTH16 must be a multiple of ' 321 '4, and must be >= 0x000C, in little endian.', 322 'ncm1.0:3.2.2#1': 'The first four bytes in NTH32 shall be ' 323 '0x686D636E in little-endian format ("ncmh").', 324 'ncm1.0:3.2.2#2': 'wHeaderLength value in NTH32 shall be 0x0010.', 325 'ncm1.0:3.2.2#3': 'wSequence in NTH32 shall be set to zero by the ' 326 'function in the first NTB transferred after ' 327 'every "function reset" event.', 328 'ncm1.0:3.2.2#4': 'wSequence value in NTH32 shall be incremented ' 329 'for every NTB subsequent transfer.', 330 'ncm1.0:3.2.2#5': 'NTB size (IN) shall not exceed dwNtbInMaxSize.', 331 'ncm1.0:3.2.2#6': 'dwNdpIndex value in NTH32 must be a multiple of' 332 ' 4, and must be >= 0x0010, in little endian.', 333 'ncm1.0:3.3.1#1': 'wLength value in the NDP16 must be a multiple ' 334 'of 4, and must be at least 16d (0x0010).', 335 'ncm1.0:3.3.1#2': 'wDatagramIndex[0] value in NDP16 must be >= ' 336 '0x000C (because it must point past the NTH16).', 337 'ncm1.0:3.3.1#3': 'wDatagramLength[0] value in NDP16 must be >= ' 338 '20d if datagram payload is IPv4 and >= 40d if ' 339 'datagram payload is IPv6.', 340 'ncm1.0:3.3.1#4': 'wDatagramIndex[(wLength-8)/4 - 1] value in ' 341 'NDP16 must be zero.', 342 'ncm1.0:3.3.1#5': 'wDatagramLength[(wLength-8)/4 - 1] value in ' 343 'NDP16 must be zero.', 344 'ncm1.0:3.3.2#1': 'wLength value in the NDP32 must be a multiple ' 345 'of 8, and must be at least 16d (0x0020).', 346 'ncm1.0:3.3.2#2': 'dwDatagramIndex[0] value in NDP32 must be >= ' 347 '0x0010 (because it must point past the NTH32).', 348 'ncm1.0:3.3.2#3': 'dwDatagramLength[0] value in NDP32 must be >= ' 349 '20d if datagram payload is IPv4 and >= 40d if ' 350 'datagram payload is IPv6.', 351 'ncm1.0:3.3.2#4': 'dwDatagramIndex[(wLength-8)/4 - 1] value in ' 352 'NDP32 must be zero.', 353 'ncm1.0:3.3.2#5': 'dwDatagramLength[(wLength-8)/4 - 1] value in ' 354 'NDP32 must be zero.', 355 } 356 357 def __init__(self, assertion_id, error_string=None): 358 """ 359 @param assertion_id: A str that must be a key in the MBIM_ASSERTIONS map 360 defined in this class. 361 @param error_string: An optional str to be appended to the error 362 description. 363 364 For example, 365 MBIMComplianceAssertionError('mbim1.0:3.2.1#1') 366 raises an error associated with assertion [MBIM 1.0]-3.2.1#1 367 368 """ 369 if assertion_id not in self.MBIM_ASSERTIONS: 370 log_and_raise(MBIMComplianceFrameworkError, 371 'Unknown assertion id "%s"' % assertion_id) 372 373 message = '[%s]: %s' % (assertion_id, 374 self.MBIM_ASSERTIONS[assertion_id]) 375 if error_string: 376 message += ': %s' % error_string 377 378 super(MBIMComplianceAssertionError, self).__init__(message) 379 380 381 class MBIMComplianceGenericAssertionError(MBIMComplianceAssertionError): 382 """ Assertion errors that don't map directly to an MBIM assertion. """ 383 def __init__(self, error_string): 384 """ 385 @param error_string: A description of the error. 386 """ 387 super(MBIMComplianceGenericAssertionError, self).__init__( 388 'no_code', 389 error_string) 390 391 392 def log_and_raise(error_class, *args): 393 """ 394 Log and raise an error. 395 396 This function should be used to raise all errors. 397 398 @param error_class: An Exception subclass to raise. 399 @param *args: Arguments to be passed to the error class constructor. 400 @raises: |error_class|. 401 402 """ 403 error_object = error_class(*args) 404 logging.error(error_object) 405 trace = traceback.format_stack() 406 # Get rid of the current frame from trace 407 trace = trace[:len(trace)-1] 408 logging.error('Traceback:\n' + ''.join(trace)) 409 raise error_object 410