xref: /OK3568_Linux_fs/app/forlinx/quectelCM/mbim-cm.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /******************************************************************************
2   @file    mbim-cm.c
3   @brief   MIBIM drivers.
4 
5   DESCRIPTION
6   Connectivity Management Tool for USB network adapter of Quectel wireless cellular modules.
7 
8   INITIALIZATION AND SEQUENCING REQUIREMENTS
9   None.
10 
11   ---------------------------------------------------------------------------
12   Copyright (c) 2016 - 2020 Quectel Wireless Solution, Co., Ltd.  All Rights Reserved.
13   Quectel Wireless Solution Proprietary and Confidential.
14   ---------------------------------------------------------------------------
15 ******************************************************************************/
16 #include <unistd.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <ctype.h>
21 #include <fcntl.h>
22 #include <stddef.h>
23 #include <pthread.h>
24 #include <errno.h>
25 #include <time.h>
26 #include <signal.h>
27 #include <getopt.h>
28 #include <poll.h>
29 #include <sys/time.h>
30 #include <endian.h>
31 #include <time.h>
32 #include <sys/types.h>
33 #include <limits.h>
34 #include <inttypes.h>
35 #include "QMIThread.h"
36 
37 #ifndef htole32
38 #if __BYTE_ORDER == __LITTLE_ENDIAN
39 #define htole16(x) (uint16_t)(x)
40 #define le16toh(x) (uint16_t)(x)
41 #define letoh16(x) (uint16_t)(x)
42 #define htole32(x) (uint32_t)(x)
43 #define le32toh(x) (uint32_t)(x)
44 #define letoh32(x) (uint32_t)(x)
45 #define htole64(x) (uint64_t)(x)
46 #define le64toh(x) (uint64_t)(x)
47 #define letoh64(x) (uint64_t)(x)
48 #else
__bswap16(uint16_t __x)49 static __inline uint16_t __bswap16(uint16_t __x) {
50     return (__x<<8) | (__x>>8);
51 }
52 
__bswap32(uint32_t __x)53 static __inline uint32_t __bswap32(uint32_t __x) {
54     return (__x>>24) | (__x>>8&0xff00) | (__x<<8&0xff0000) | (__x<<24);
55 }
56 
__bswap64(uint64_t __x)57 static __inline uint64_t __bswap64(uint64_t __x) {
58     return (__bswap32(__x)+0ULL<<32) | (__bswap32(__x>>32));
59 }
60 
61 #define htole16(x) __bswap16(x)
62 #define le16toh(x) __bswap16(x)
63 #define letoh16(x) __bswap16(x)
64 #define htole32(x) __bswap32(x)
65 #define le32toh(x) __bswap32(x)
66 #define letoh32(x) __bswap32(x)
67 #define htole64(x) __bswap64(x)
68 #define le64toh(x) __bswap64(x)
69 #define letoh64(x) __bswap64(x)
70 #endif
71 #endif
72 
73 #define mbim_debug dbg_time
74 
75 #define UUID_BASIC_CONNECT "a289cc33-bcbb-8b4f-b6b0-133ec2aae6df"
76 //https://docs.microsoft.com/en-us/windows-hardware/drivers/network/mb-5g-data-class-support
77 #define UUID_BASIC_CONNECT_EXT "3d01dcc5-fef5-4d05-0d3a-bef7058e9aaf"
78 #define UUID_SMS             "533fbeeb-14fe-4467-9f90-33a223e56c3f"
79 #define UUID_USSD             "e550a0c8-5e82-479e-82f7-10abf4c3351f"
80 #define UUID_PHONEBOOK     "4bf38476-1e6a-41db-b1d8-bed289c25bdb"
81 #define UUID_STK             "d8f20131-fcb5-4e17-8602-d6ed3816164c"
82 #define UUID_AUTH             "1d2b5ff7-0aa1-48b2-aa52-50f15767174e"
83 #define UUID_DSS             "c08a26dd-7718-4382-8482-6e0d583c4d0e"
84 #define uuid_ext_qmux "d1a30bc2-f97a-6e43-bf65-c7e24fb0f0d3"
85 #define uuid_mshsd "883b7c26-985f-43fa-9804-27d7fb80959c"
86 #define uuid_qmbe "2d0c12c9-0e6a-495a-915c-8d174fe5d63c"
87 #define UUID_MSFWID "e9f7dea2-feaf-4009-93ce-90a3694103b6"
88 #define uuid_atds "5967bdcc-7fd2-49a2-9f5c-b2e70e527db3"
89 #define uuid_qdu "6427015f-579d-48f5-8c54-f43ed1e76f83"
90 #define UUID_MS_UICC_LOW_LEVEL "c2f6588e-f037-4bc9-8665-f4d44bd09367"
91 #define UUID_MS_SARControl "68223D04-9F6C-4E0F-822D-28441FB72340"
92 #define UUID_VOICEEXTENSIONS	"8d8b9eba-37be-449b-8f1e-61cb034a702e"
93 #define UUID_LIBMBIM_PROXY "838cf7fb-8d0d-4d7f-871e-d71dbefbb39b"
94 
95 #define UUID_MBIMContextTypeInternet "7E5E2A7E-4E6F-7272-736B-656E7E5E2A7E"
96 
97 typedef unsigned char UINT8;
98 typedef unsigned short UINT16;
99 typedef unsigned int UINT32;
100 typedef unsigned long long UINT64;
101 
102 #define STRINGFY(v) #v
103 /* The function name will be _ENUM_NAMEStr */
104 #define enumstrfunc(_ENUM_NAME, _ENUM_MEMS) \
105 static const char *_ENUM_NAME##Str(int _val) { \
106     struct { int val;char *name;} _enumstr[] = { _ENUM_MEMS }; \
107     int idx; for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) { \
108         if (_val == _enumstr[idx].val) return _enumstr[idx].name;} \
109     return STRINGFY(_ENUM_NAME##Unknow); \
110 }
111 
112 #pragma pack(4)
113 typedef enum {
114     MBIM_CID_CMD_TYPE_QUERY = 0,
115     MBIM_CID_CMD_TYPE_SET = 1,
116 } MBIM_CID_CMD_TYPE_E;
117 
118 //Set Query Notification
119 #define UUID_BASIC_CONNECT_CIDs \
120     MBIM_ENUM_HELPER(MBIM_CID_DEVICE_CAPS, 1) \
121     MBIM_ENUM_HELPER(MBIM_CID_SUBSCRIBER_READY_STATUS, 2) \
122     MBIM_ENUM_HELPER(MBIM_CID_RADIO_STATE, 3) \
123     MBIM_ENUM_HELPER(MBIM_CID_PIN, 4) \
124     MBIM_ENUM_HELPER(MBIM_CID_PIN_LIS, 5) \
125     MBIM_ENUM_HELPER(MBIM_CID_HOME_PROVIDER, 6) \
126     MBIM_ENUM_HELPER(MBIM_CID_PREFERRED_PROVIDERS, 7) \
127     MBIM_ENUM_HELPER(MBIM_CID_VISIBLE_PROVIDERS, 8) \
128     MBIM_ENUM_HELPER(MBIM_CID_REGISTER_STATE, 9) \
129     MBIM_ENUM_HELPER(MBIM_CID_PACKET_SERVICE, 10) \
130     MBIM_ENUM_HELPER(MBIM_CID_SIGNAL_STATE, 11) \
131     MBIM_ENUM_HELPER(MBIM_CID_CONNECT, 12) \
132     MBIM_ENUM_HELPER(MBIM_CID_PROVISIONED_CONTEXTS, 13) \
133     MBIM_ENUM_HELPER(MBIM_CID_SERVICE_ACTIVATION, 14) \
134     MBIM_ENUM_HELPER(MBIM_CID_IP_CONFIGURATION, 15) \
135     MBIM_ENUM_HELPER(MBIM_CID_DEVICE_SERVICES, 16) \
136     MBIM_ENUM_HELPER(MBIM_CID_DEVICE_SERVICE_SUBSCRIBE_LIST, 19) \
137     MBIM_ENUM_HELPER(MBIM_CID_PACKET_STATISTICS, 20) \
138     MBIM_ENUM_HELPER(MBIM_CID_NETWORK_IDLE_HINT, 21) \
139     MBIM_ENUM_HELPER(MBIM_CID_EMERGENCY_MODE, 22) \
140     MBIM_ENUM_HELPER(MBIM_CID_IP_PACKET_FILTERS, 23) \
141     MBIM_ENUM_HELPER(MBIM_CID_MULTICARRIER_PROVIDERS, 24)
142 
143 #define MBIM_ENUM_HELPER(k, v) k = v,
144 typedef enum{
145     UUID_BASIC_CONNECT_CIDs
146 } UUID_BASIC_CONNECT_CID_E;
147 #undef MBIM_ENUM_HELPER
148 #define MBIM_ENUM_HELPER(k, v) {k, #k},
149 enumstrfunc(CID2, UUID_BASIC_CONNECT_CIDs);
150 #undef MBIM_ENUM_HELPER
151 
152 static int mbim_ms_version = 1;
153 
154 #define UUID_BASIC_CONNECT_EXT_CIDs \
155     MBIM_ENUM_HELPER(MBIM_CID_MS_PROVISIONED_CONTEXT_V2, 1) \
156     MBIM_ENUM_HELPER(MBIM_CID_MS_NETWORK_BLACKLIST, 2) \
157     MBIM_ENUM_HELPER(MBIM_CID_MS_LTE_ATTACH_CONFIG, 3) \
158     MBIM_ENUM_HELPER(MBIM_CID_MS_LTE_ATTACH_STATUS , 4) \
159     MBIM_ENUM_HELPER(MBIM_CID_MS_SYS_CAPS , 5) \
160     MBIM_ENUM_HELPER(MBIM_CID_MS_DEVICE_CAPS_V2, 6) \
161     MBIM_ENUM_HELPER(MBIM_CID_MS_DEVICE_SLOT_MAPPING, 7) \
162     MBIM_ENUM_HELPER(MBIM_CID_MS_SLOT_INFO_STATUS, 8) \
163     MBIM_ENUM_HELPER(MBIM_CID_MS_PCO, 9) \
164     MBIM_ENUM_HELPER(MBIM_CID_MS_DEVICE_RESET, 10) \
165     MBIM_ENUM_HELPER(MBIM_CID_MS_BASE_STATIONS_INFO, 11) \
166     MBIM_ENUM_HELPER(MBIM_CID_MS_LOCATION_INFO_STATUS, 12) \
167     MBIM_ENUM_HELPER(MBIM_CID_NOT_DEFINED, 13) \
168     MBIM_ENUM_HELPER(MBIM_CID_MS_PIN_EX, 14) \
169     MBIM_ENUM_HELPER(MBIM_CID_MS_VERSION , 15)
170 
171 #define MBIM_ENUM_HELPER(k, v) k = v,
172 typedef enum{
173     UUID_BASIC_CONNECT_EXT_CIDs
174 } UUID_BASIC_CONNECT_EXT_CID_E;
175 #undef MBIM_ENUM_HELPER
176 #define MBIM_ENUM_HELPER(k, v) {k, #k},
177 enumstrfunc(MS_CID2, UUID_BASIC_CONNECT_EXT_CIDs);
178 #undef MBIM_ENUM_HELPER
179 
180 typedef enum {
181     MBIM_CID_SMS_CONFIGURATION = 1, // Y Y Y
182     MBIM_CID_SMS_READ = 2, // N Y Y
183     MBIM_CID_SMS_SEND = 3, // Y N N
184     MBIM_CID_SMS_DELETE = 4, // Y N N
185     MBIM_CID_SMS_MESSAGE_STORE_STATUS = 5, // N Y Y
186 } UUID_SMS_CID_E;
187 
188 typedef enum {
189     MBIM_CID_DSS_CONNECT = 1, // Y N N
190 } UUID_DSS_CID_E;
191 
192 #define MBIM_MSGS \
193     MBIM_ENUM_HELPER(MBIM_OPEN_MSG, 1) \
194     MBIM_ENUM_HELPER(MBIM_CLOSE_MSG, 2) \
195     MBIM_ENUM_HELPER(MBIM_COMMAND_MSG, 3) \
196     MBIM_ENUM_HELPER(MBIM_HOST_ERROR_MSG, 4) \
197     \
198     MBIM_ENUM_HELPER(MBIM_OPEN_DONE, 0x80000001) \
199     MBIM_ENUM_HELPER(MBIM_CLOSE_DONE, 0x80000002) \
200     MBIM_ENUM_HELPER(MBIM_COMMAND_DONE, 0x80000003) \
201     MBIM_ENUM_HELPER(MBIM_FUNCTION_ERROR_MSG, 0x80000004) \
202     MBIM_ENUM_HELPER(MBIM_INDICATE_STATUS_MSG, 0x80000007)
203 
204 #define MBIM_ENUM_HELPER(k, v) k = v,
205 typedef enum{
206     MBIM_MSGS
207 } MBIM_MSG_Type_E;
208 #undef MBIM_ENUM_HELPER
209 #define MBIM_ENUM_HELPER(k, v) {k, #k},
210 enumstrfunc(MBIMMSGType, MBIM_MSGS);
211 #undef MBIM_ENUM_HELPER
212 
213 typedef enum { /*< since=1.10 >*/
214     MBIM_CID_PROXY_CONTROL_UNKNOWN       = 0,
215     MBIM_CID_PROXY_CONTROL_CONFIGURATION = 1
216 } UUID_LIBMBIM_PROXY_CID_E;
217 
218 typedef enum {
219     MBIM_ERROR_TIMEOUT_FRAGMENT = 1,
220     MBIM_ERROR_FRAGMENT_OUT_OF_SEQUENCE = 2,
221     MBIM_ERROR_LENGTH_MISMATCH = 3,
222     MBIM_ERROR_DUPLICATED_TID = 4,
223     MBIM_ERROR_NOT_OPENED = 5,
224     MBIM_ERROR_UNKNOWN = 6,
225     MBIM_ERROR_CANCEL = 7,
226     MBIM_ERROR_MAX_TRANSFER = 8,
227 } MBIM_ERROR_E;
228 
229 typedef enum {
230     MBIM_STATUS_SUCCESS = 0,
231     MBIM_STATUS_BUSY =  1,
232     MBIM_STATUS_FAILURE = 2,
233     MBIM_STATUS_SIM_NOT_INSERTED = 3,
234     MBIM_STATUS_BAD_SIM = 4,
235     MBIM_STATUS_PIN_REQUIRED = 5,
236     MBIM_STATUS_PIN_DISABLED = 6,
237     MBIM_STATUS_NOT_REGISTERED = 7,
238     MBIM_STATUS_PROVIDERS_NOT_FOUND = 8,
239     MBIM_STATUS_NO_DEVICE_SUPPORT = 9,
240     MBIM_STATUS_PROVIDER_NOT_VISIBLE = 10,
241     MBIM_STATUS_DATA_CLASS_NOT_AVAILABL = 11,
242     MBIM_STATUS_PACKET_SERVICE_DETACHED = 12,
243 }  MBIM_STATUS_CODES_E;
244 
245 typedef enum {
246     MBIMPacketServiceActionAttach = 0,
247     MBIMPacketServiceActionDetach = 1,
248 } MBIM_PACKET_SERVICE_ACTION_E;
249 
250 typedef enum {
251     MBIMPacketServiceStateUnknown = 0,
252     MBIMPacketServiceStateAttaching = 1,
253     MBIMPacketServiceStateAttached = 2,
254     MBIMPacketServiceStateDetaching = 3,
255     MBIMPacketServiceStateDetached = 4,
256 } MBIM_PACKET_SERVICE_STATE_E;
257 
MBIMPacketServiceStateStr(int _val)258 static const char *MBIMPacketServiceStateStr(int _val) {
259     struct { int val;char *name;} _enumstr[] = {
260         {MBIMPacketServiceStateUnknown, "Unknown"},
261         {MBIMPacketServiceStateAttaching, "Attaching"},
262         {MBIMPacketServiceStateAttached, "Attached"},
263         {MBIMPacketServiceStateDetaching, "Detaching"},
264         {MBIMPacketServiceStateDetached, "Detached"},
265     };
266     int idx;
267 
268     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
269         if (_val == _enumstr[idx].val)
270             return _enumstr[idx].name;
271     }
272 
273     return "Undefined";
274 };
275 
276 typedef enum {
277     MBIMDataClassNone = 0x0,
278     MBIMDataClassGPRS = 0x1,
279     MBIMDataClassEDGE = 0x2,
280     MBIMDataClassUMTS = 0x4,
281     MBIMDataClassHSDPA = 0x8,
282     MBIMDataClassHSUPA = 0x10,
283     MBIMDataClassLTE = 0x20,
284     MBIMDataClass5G_NSA = 0x40,
285     MBIMDataClass5G_SA = 0x80,
286     MBIMDataClass1XRTT = 0x10000,
287     MBIMDataClass1XEVDO = 0x20000,
288     MBIMDataClass1XEVDORevA = 0x40000,
289     MBIMDataClass1XEVDV = 0x80000,
290     MBIMDataClass3XRTT = 0x100000,
291     MBIMDataClass1XEVDORevB = 0x200000,
292     MBIMDataClassUMB = 0x400000,
293     MBIMDataClassCustom = 0x80000000,
294 } MBIM_DATA_CLASS_E;
295 
MBIMDataClassStr(int _val)296 static const char *MBIMDataClassStr(int _val) {
297     struct { int val;char *name;} _enumstr[] = {
298         {MBIMDataClassNone, "None"},
299         {MBIMDataClassGPRS, "GPRS"},
300         {MBIMDataClassEDGE, "EDGE"},
301         {MBIMDataClassUMTS, "UMTS"},
302         {MBIMDataClassHSDPA, "HSDPA"},
303         {MBIMDataClassHSUPA, "HSUPA"},
304         {MBIMDataClassLTE, "LTE"},
305         {MBIMDataClass5G_NSA, "5G_NSA"},
306         {MBIMDataClass5G_SA, "5G_SA"},
307         {MBIMDataClass1XRTT, "1XRTT"},
308         {MBIMDataClass1XEVDO, "1XEVDO"},
309         {MBIMDataClass1XEVDORevA, "1XEVDORevA"},
310         {MBIMDataClass1XEVDV, "1XEVDV"},
311         {MBIMDataClass3XRTT, "3XRTT"},
312         {MBIMDataClass1XEVDORevB, "1XEVDORevB"},
313         {MBIMDataClassUMB, "UMB"},
314         {MBIMDataClassCustom, "Custom"},
315     };
316     int idx;
317 
318     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
319         if (_val == _enumstr[idx].val)
320             return _enumstr[idx].name;
321     }
322 
323     return "Unknow";
324 };
325 
326 typedef struct {
327     UINT32 NwError;
328     UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E
329     UINT32 HighestAvailableDataClass; //MBIM_DATA_CLASS_E
330     UINT64 UplinkSpeed;
331     UINT64 DownlinkSpeed;
332 } MBIM_PACKET_SERVICE_INFO_T;
333 
334 typedef struct {
335     UINT32 NwError;
336     UINT32 PacketServiceState; //MBIM_PACKET_SERVICE_STATE_E
337     UINT32 CurrentDataClass; //MBIM_DATA_CLASS_E
338     UINT64 UplinkSpeed;
339     UINT64 DownlinkSpeed;
340     UINT32 FrequencyRange;
341 } MBIM_PACKET_SERVICE_INFO_V2_T;
342 
343 typedef enum {
344     MBIMSubscriberReadyStateNotInitialized = 0,
345     MBIMSubscriberReadyStateInitialized = 1,
346     MBIMSubscriberReadyStateSimNotInserted = 2,
347     MBIMSubscriberReadyStateBadSim = 3,
348     MBIMSubscriberReadyStateFailure = 4,
349     MBIMSubscriberReadyStateNotActivated = 5,
350     MBIMSubscriberReadyStateDeviceLocked = 6,
351 }MBIM_SUBSCRIBER_READY_STATE_E;
352 
MBIMSubscriberReadyStateStr(int _val)353 static const char *MBIMSubscriberReadyStateStr(int _val) {
354     struct { int val;char *name;} _enumstr[] = {
355         {MBIMSubscriberReadyStateNotInitialized, "NotInitialized"},
356         {MBIMSubscriberReadyStateInitialized, "Initialized"},
357         {MBIMSubscriberReadyStateSimNotInserted, "NotInserted"},
358         {MBIMSubscriberReadyStateBadSim, "BadSim"},
359         {MBIMSubscriberReadyStateFailure, "Failure"},
360         {MBIMSubscriberReadyStateNotActivated, "NotActivated"},
361         {MBIMSubscriberReadyStateDeviceLocked, "DeviceLocked"},
362     };
363     int idx;
364 
365     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
366         if (_val == _enumstr[idx].val)
367             return _enumstr[idx].name;
368     }
369 
370     return "Undefined";
371 };
372 
373 typedef struct {
374     UINT32 DeviceType; //MBIM_DEVICE_TYPE
375     UINT32 CellularClass; //MBIM_CELLULAR_CLASS
376     UINT32 VoiceClass; //MBIM_VOICE_CLASS
377     UINT32 SimClass; //MBIM_SIM_CLASS
378     UINT32 DataClass; //MBIM_DATA_CLASS
379     UINT32 SmsCaps; //MBIM_SMS_CAPS
380     UINT32 ControlCaps; //MBIM_CTRL_CAPS
381     UINT32 MaxSessions;
382     UINT32 CustomDataClassOffset;
383     UINT32 CustomDataClassSize;
384     UINT32 DeviceIdOffset;
385     UINT32 DeviceIdSize;
386     UINT32 FirmwareInfoOffset;
387     UINT32 FirmwareInfoSize;
388     UINT32 HardwareInfoOffset;
389     UINT32 HardwareInfoSize;
390     UINT8 DataBuffer[0]; //DeviceId FirmwareInfo HardwareInfo
391 } MBIM_DEVICE_CAPS_INFO_T;
392 
393 typedef enum {
394     MBIMRadioOff = 0,
395     MBIMRadioOn = 1,
396 } MBIM_RADIO_SWITCH_STATE_E;
397 
398 typedef struct {
399     MBIM_RADIO_SWITCH_STATE_E RadioState;
400 } MBIM_SET_RADIO_STATE_T;
401 
402 typedef struct {
403     MBIM_RADIO_SWITCH_STATE_E HwRadioState;
404     MBIM_RADIO_SWITCH_STATE_E SwRadioState;
405 } MBIM_RADIO_STATE_INFO_T;
406 
407 typedef enum {
408     MBIMReadyInfoFlagsNone,
409     MBIMReadyInfoFlagsProtectUniqueID,
410 }MBIM_UNIQUE_ID_FLAGS;
411 
412 typedef struct {
413     UINT32 ReadyState;
414     UINT32 SubscriberIdOffset;
415     UINT32 SubscriberIdSize;
416     UINT32 SimIccIdOffset;
417     UINT32 SimIccIdSize;
418     UINT32 ReadyInfo;
419     UINT32 ElementCount;
420     UINT8 *TelephoneNumbersRefList;
421     UINT8 *DataBuffer;
422 } MBIM_SUBSCRIBER_READY_STATUS_T;
423 
424 typedef enum {
425     MBIMRegisterActionAutomatic,
426     MBIMRegisterActionManual,
427 }MBIM_REGISTER_ACTION_E;
428 
429 typedef enum {
430     MBIMRegisterStateUnknown = 0,
431     MBIMRegisterStateDeregistered = 1,
432     MBIMRegisterStateSearching = 2,
433     MBIMRegisterStateHome = 3,
434     MBIMRegisterStateRoaming = 4,
435     MBIMRegisterStatePartner = 5,
436     MBIMRegisterStateDenied = 6,
437 }MBIM_REGISTER_STATE_E;
438 
439 typedef enum {
440     MBIMRegisterModeUnknown = 0,
441     MBIMRegisterModeAutomatic = 1,
442     MBIMRegisterModeManual = 2,
443 }MBIM_REGISTER_MODE_E;
444 
MBIMRegisterStateStr(int _val)445 static const char *MBIMRegisterStateStr(int _val) {
446     struct { int val;char *name;} _enumstr[] ={
447         {MBIMRegisterStateUnknown, "Unknown"},
448         {MBIMRegisterStateDeregistered, "Deregistered"},
449         {MBIMRegisterStateSearching, "Searching"},
450         {MBIMRegisterStateHome, "Home"},
451         {MBIMRegisterStateRoaming, "Roaming"},
452         {MBIMRegisterStatePartner, "Partner"},
453         {MBIMRegisterStateDenied, "Denied"},
454     };
455     int idx;
456 
457     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
458         if (_val == _enumstr[idx].val)
459             return _enumstr[idx].name;
460     }
461 
462     return "Undefined";
463 };
464 
MBIMRegisterModeStr(int _val)465 static const char *MBIMRegisterModeStr(int _val) {
466     struct { int val;char *name;} _enumstr[] = {
467         {MBIMRegisterModeUnknown, "Unknown"},
468         {MBIMRegisterModeAutomatic, "Automatic"},
469         {MBIMRegisterModeManual, "Manual"},
470     };
471     int idx;
472 
473     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
474         if (_val == _enumstr[idx].val)
475             return _enumstr[idx].name;
476     }
477 
478     return "Undefined";
479 };
480 
481 typedef enum {
482     MBIM_REGISTRATION_NONE,
483     MBIM_REGISTRATION_MANUAL_SELECTION_NOT_AVAILABLE,
484     MBIM_REGISTRATION_PACKET_SERVICE_AUTOMATIC_ATTACH,
485 }MBIM_REGISTRATION_FLAGS_E;
486 
487 typedef struct {
488     UINT32 NwError;
489     UINT32 RegisterState; //MBIM_REGISTER_STATE_E
490     UINT32 RegisterMode;
491     UINT32 AvailableDataClasses;
492     UINT32 CurrentCellularClass;
493     UINT32 ProviderIdOffset;
494     UINT32 ProviderIdSize;
495     UINT32 ProviderNameOffset;
496     UINT32 ProviderNameSize;
497     UINT32 RoamingTextOffset;
498     UINT32 RoamingTextSize;
499     UINT32 RegistrationFlag;
500     UINT8 *DataBuffer;
501 } MBIM_REGISTRATION_STATE_INFO_T;
502 
503 typedef struct {
504     UINT32 NwError;
505     UINT32 RegisterState; //MBIM_REGISTER_STATE_E
506     UINT32 RegisterMode;
507     UINT32 AvailableDataClasses;
508     UINT32 CurrentCellularClass;
509     UINT32 ProviderIdOffset;
510     UINT32 ProviderIdSize;
511     UINT32 ProviderNameOffset;
512     UINT32 ProviderNameSize;
513     UINT32 RoamingTextOffset;
514     UINT32 RoamingTextSize;
515     UINT32 RegistrationFlag;
516     UINT32 PreferredDataClass;
517     UINT8 *DataBuffer;
518 } MBIM_REGISTRATION_STATE_INFO_V2_T;
519 
520 typedef struct {
521     UINT32 MessageType; //Specifies the MBIM message type.
522     UINT32 MessageLength; //Specifies the total length of this MBIM message in bytes.
523     /* Specifies the MBIM message id value.  This value is used to match host sent messages with function responses.
524     This value must be unique among all outstanding transactions.
525     For notifications, the TransactionId must be set to 0 by the function */
526     UINT32 TransactionId;
527 } MBIM_MESSAGE_HEADER;
528 
529 typedef struct {
530     UINT32 TotalFragments; //this field indicates how many fragments there are intotal.
531     UINT32 CurrentFragment; //This field indicates which fragment this message is.  Values are 0 to TotalFragments?\1
532 } MBIM_FRAGMENT_HEADER;
533 
534 typedef struct {
535     MBIM_MESSAGE_HEADER MessageHeader;
536     UINT32 MaxControlTransfer;
537 } MBIM_OPEN_MSG_T;
538 
539 typedef struct {
540     MBIM_MESSAGE_HEADER MessageHeader;
541     UINT32 Status;
542 } MBIM_OPEN_DONE_T;
543 
544 typedef struct {
545     MBIM_MESSAGE_HEADER MessageHeader;
546 } MBIM_CLOSE_MSG_T;
547 
548 typedef struct {
549     MBIM_MESSAGE_HEADER MessageHeader;
550     UINT32 Status;
551 } MBIM_CLOSE_DONE_T;
552 
553 typedef struct {
554     UINT8 uuid[16];
555 } UUID_T;
556 
557 typedef struct {
558     MBIM_MESSAGE_HEADER MessageHeader;
559     MBIM_FRAGMENT_HEADER FragmentHeader;
560     UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies.
561     UINT32 CID; //Specifies the CID that identifies the parameter being queried for
562     UINT32 CommandType; //0 for a query operation, 1 for a Set operation
563     UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented.
564     UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID
565 } MBIM_COMMAND_MSG_T;
566 
567 typedef struct {
568     MBIM_MESSAGE_HEADER MessageHeader;
569     MBIM_FRAGMENT_HEADER FragmentHeader;
570     UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies.
571     UINT32 CID; //Specifies the CID that identifies the parameter being queried for
572     UINT32 Status;
573     UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented.
574     UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID
575 } MBIM_COMMAND_DONE_T;
576 
577 typedef struct {
578     MBIM_MESSAGE_HEADER MessageHeader;
579     UINT32 ErrorStatusCode;
580 } MBIM_HOST_ERROR_MSG_T;
581 
582 typedef struct {
583     MBIM_MESSAGE_HEADER MessageHeader;
584     UINT32 ErrorStatusCode;
585 } MBIM_FUNCTION_ERROR_MSG_T;
586 
587 typedef struct {
588     MBIM_MESSAGE_HEADER MessageHeader;
589     MBIM_FRAGMENT_HEADER FragmentHeader;
590     UUID_T DeviceServiceId; //A 16 byte UUID that identifies the device service the following CID value applies.
591     UINT32 CID; //Specifies the CID that identifies the parameter being queried for
592     UINT32 InformationBufferLength; //Size of the Total InformationBuffer, may be larger than current message if fragmented.
593     UINT8 InformationBuffer[0]; //Data supplied to device specific to the CID
594 } MBIM_INDICATE_STATUS_MSG_T;
595 
596 typedef struct {
597     UINT32 offset;
598     UINT32 size;
599 } OL_PAIR_LIST;
600 
601 typedef struct {
602     UUID_T DeviceServiceId;
603     UINT32 DssPayload;
604     UINT32 MaxDssInstances;
605     UINT32 CidCount;
606     UINT32 CidList[];
607 } MBIM_DEVICE_SERVICE_ELEMENT_T;
608 
609 typedef struct {
610     UINT32 DeviceServicesCount;
611     UINT32 MaxDssSessions;
612     OL_PAIR_LIST DeviceServicesRefList[];
613 } MBIM_DEVICE_SERVICES_INFO_T;
614 
615 typedef enum {
616     MBIMActivationCommandDeactivate = 0,
617     MBIMActivationCommandActivate = 1,
618 } MBIM_ACTIVATION_COMMAND_E;
619 
620 typedef enum {
621     MBIMCompressionNone =  0,
622     MBIMCompressionEnable =  1,
623 } MBIM_COMPRESSION_E;
624 
625 typedef enum {
626     MBIMAuthProtocolNone = 0,
627     MBIMAuthProtocolPap = 1,
628     MBIMAuthProtocolChap = 2,
629     MBIMAuthProtocolMsChapV2 = 3,
630 } MBIM_AUTH_PROTOCOL_E;
631 
632 #define MBIMContextIPTypes \
633     MBIM_ENUM_HELPER(MBIMContextIPTypeDefault, 0) \
634     MBIM_ENUM_HELPER(MBIMContextIPTypeIPv4, 1) \
635     MBIM_ENUM_HELPER(MBIMContextIPTypeIPv6, 2) \
636     MBIM_ENUM_HELPER(MBIMContextIPTypeIPv4v6, 3) \
637     MBIM_ENUM_HELPER(MBIMContextIPTypeIPv4AndIPv6, 4)
638 
639 #define MBIM_ENUM_HELPER(k, v) k = v,
640 typedef enum {
641     MBIMContextIPTypes
642 } MBIM_CONTEXT_IP_TYPE_E;
643 #undef MBIM_ENUM_HELPER
644 #define MBIM_ENUM_HELPER(k, v) {k, #k},
645 enumstrfunc(MBIMContextIPType, MBIMContextIPTypes);
646 #undef MBIM_ENUM_HELPER
647 
648 typedef enum {
649     MBIMActivationStateUnknown = 0,
650         MBIMActivationStateActivated = 1,
651         MBIMActivationStateActivating = 2,
652         MBIMActivationStateDeactivated = 3,
653         MBIMActivationStateDeactivating = 4,
654 } MBIM_ACTIVATION_STATE_E;
655 
656 typedef enum {
657     MBIMVoiceCallStateNone = 0,
658         MBIMVoiceCallStateInProgress = 1,
659         MBIMVoiceCallStateHangUp = 2,
660 } MBIM_VOICECALL_STATE_E;
661 
MBIMActivationStateStr(int _val)662 static const char *MBIMActivationStateStr(int _val) {
663     struct { int val;char *name;} _enumstr[] = {
664         {MBIMActivationStateUnknown, "Unknown"},
665         {MBIMActivationStateActivated, "Activated"},
666         {MBIMActivationStateActivating, "Activating"},
667         {MBIMActivationStateDeactivated, "Deactivated"},
668         {MBIMActivationStateDeactivating, "Deactivating"},
669     };
670     int idx;
671 
672     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
673         if (_val == _enumstr[idx].val)
674             return _enumstr[idx].name;
675     }
676 
677     return "Undefined";
678 };
679 
MBIMVoiceCallStateStr(int _val)680 static const char *MBIMVoiceCallStateStr(int _val) {
681     struct { int val;char *name;} _enumstr[] = {
682         {MBIMVoiceCallStateNone, "None"},
683         {MBIMVoiceCallStateInProgress, "InProgress"},
684         {MBIMVoiceCallStateHangUp, "HangUp"},
685     };
686     int idx;
687 
688     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
689         if (_val == _enumstr[idx].val)
690         return _enumstr[idx].name;
691     }
692 
693     return "Undefined";
694 };
695 
696 typedef struct {
697     UINT32 SessionId;
698     UINT32 ActivationCommand; //MBIM_ACTIVATION_COMMAND_E
699     UINT32 AccessStringOffset;
700     UINT32 AccessStringSize;
701     UINT32 UserNameOffset;
702     UINT32 UserNameSize;
703     UINT32 PasswordOffset;
704     UINT32 PasswordSize;
705     UINT32 Compression; //MBIM_COMPRESSION_E
706     UINT32 AuthProtocol; //MBIM_AUTH_PROTOCOL_E
707     UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E
708     UUID_T ContextType;
709     UINT8 DataBuffer[0];  /* apn, username, password */
710 } MBIM_SET_CONNECT_T;
711 
712 typedef struct {
713     UINT32 SessionId;
714     UINT32 ActivationState; //MBIM_ACTIVATION_STATE_E
715     UINT32 VoiceCallState;
716     UINT32 IPType; //MBIM_CONTEXT_IP_TYPE_E
717     UUID_T ContextType;
718     UINT32 NwError;
719 } MBIM_CONNECT_T;
720 
721 typedef struct {
722     UINT32 OnLinkPrefixLength;
723     UINT8 IPv4Address[4];
724 } MBIM_IPV4_ELEMENT_T;
725 
726 typedef struct {
727     UINT32 OnLinkPrefixLength;
728     UINT8 IPv6Address[16];
729 } MBIM_IPV6_ELEMENT_T;
730 
731 typedef struct {
732     UINT32 SessionId;
733     UINT32 IPv4ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU
734     UINT32 IPv6ConfigurationAvailable; //bit0~Address, bit1~gateway, bit2~DNS, bit3~MTU
735     UINT32 IPv4AddressCount;
736     UINT32 IPv4AddressOffset;
737     UINT32 IPv6AddressCount;
738     UINT32 IPv6AddressOffset;
739     UINT32 IPv4GatewayOffset;
740     UINT32 IPv6GatewayOffset;
741     UINT32 IPv4DnsServerCount;
742     UINT32 IPv4DnsServerOffset;
743     UINT32 IPv6DnsServerCount;
744     UINT32 IPv6DnsServerOffset;
745     UINT32 IPv4Mtu;
746     UINT32 IPv6Mtu;
747     UINT8 DataBuffer[];
748 } MBIM_IP_CONFIGURATION_INFO_T;
749 
750 typedef struct {
751     UINT32 RSRP;
752     UINT32 SNR;
753     UINT32 RSRPThreshold;
754     UINT32 SNRThreshold;
755     UINT32 SystemType;
756 } MBIM_RSRP_SNR_INFO_T;
757 
758 typedef struct {
759     UINT32 Elementcount;
760     MBIM_RSRP_SNR_INFO_T RsrpSnr[0];
761 } MBIM_RSRP_SNR_T;
762 
763 typedef struct {
764     UINT32 Rssi;
765     UINT32 ErrorRate;
766     UINT32 SignalStrengthInterval;
767     UINT32 RssiThreshold;
768     UINT32 ErrorRateThreshold;
769 } MBIM_SIGNAL_STATE_INFO_T;
770 
771 typedef struct {
772     UINT32 Rssi;
773     UINT32 ErrorRate;
774     UINT32 SignalStrengthInterval;
775     UINT32 RssiThreshold;
776     UINT32 ErrorRateThreshold;
777     UINT32 RsrpSnrOffset;
778     UINT32 RsrpSnrSize;
779     UINT8 DataBuffer[];
780 } MBIM_SIGNAL_STATE_INFO_V2_T;
781 
782 typedef struct {
783     UINT32 SignalStrengthInterval;
784     UINT32 RssiThreshold;
785     UINT32 ErrorRateThreshold;
786 } MBIM_SET_SIGNAL_STATE_T;
787 
788 typedef struct {
789     UINT32 DevicePathOffset;
790     UINT32 DevicePathSize;
791     UINT32 Timeout;
792     UINT8 DataBuffer[];
793 } MBIM_LIBQMI_PROXY_CONFIG_T;
794 
795 #pragma pack()
796 
797 static pthread_t s_tid_reader = 0;
798 static int mbim_verbose = 0;
799 static UINT32 TransactionId = 1;
800 static unsigned mbim_default_timeout  = 30000;
801 static const char *mbim_apn = NULL;
802 static const char *mbim_user = NULL;
803 static const char *mbim_passwd = NULL;
804 static int mbim_iptype = MBIMContextIPTypeDefault;
805 static int mbim_auth = MBIMAuthProtocolNone;
806 static int mbim_sessionID = 0;
807 static int mbim_fd = -1;
808 static MBIM_MESSAGE_HEADER *mbim_pRequest;
809 static MBIM_MESSAGE_HEADER *mbim_pResponse;
810 
str2uuid(const char * str)811 static const UUID_T * str2uuid(const char *str) {
812     static UUID_T uuid;
813     UINT32 d[16];
814     char tmp[16*2+4+1];
815     unsigned i = 0;
816 
817     while (str[i]) {
818         tmp[i] = tolower(str[i]);
819         i++;
820     }
821     tmp[i] = '\0';
822 
823     sscanf(tmp, "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
824         &d[0], &d[1], &d[2], &d[3], &d[4], &d[5], &d[6], &d[7],
825         &d[8], &d[9], &d[10], &d[11], &d[12], &d[13], &d[14], &d[15]);
826 
827     for (i = 0; i < 16; i++) {
828         uuid.uuid[i] = d[i]&0xFF;
829     }
830 
831     return &uuid;
832 }
833 
wchar2char(const char * src,size_t src_size,char * dst,size_t dst_len)834 static void wchar2char(const char *src, size_t src_size, char *dst, size_t dst_len) {
835     size_t i;
836 
837     for (i = 0; i < (dst_len-1) && i < (src_size/2); i++)
838         dst[i] = src[i*2];
839     dst[i] = 0;
840 }
841 
char2wchar(const char * src,size_t src_len,uint8_t * dst,size_t dst_len)842 static size_t char2wchar(const char *src, size_t src_len, uint8_t *dst, size_t dst_len) {
843     size_t i;
844 
845     if (src_len > (dst_len/2))
846         src_len = (dst_len/2);
847 
848     for (i = 0; i < src_len; i++) {
849         *dst++ = *src++;
850         *dst++ = 0;
851     }
852 
853     return i*2;
854 }
855 
856 #define mbim_alloc( _size)  malloc(_size)
857 #define mbim_free(_mem) do { if (_mem) { free(_mem); _mem = NULL;}} while(0)
858 
859 static int mbim_open_state = 0;
860 static MBIM_SUBSCRIBER_READY_STATE_E ReadyState = MBIMSubscriberReadyStateNotInitialized;
861 static MBIM_REGISTER_STATE_E RegisterState = MBIMRegisterStateUnknown;
862 static MBIM_PACKET_SERVICE_STATE_E PacketServiceState = MBIMPacketServiceStateUnknown;
863 static MBIM_ACTIVATION_STATE_E ActivationState = MBIMActivationStateUnknown;
864 static MBIM_SUBSCRIBER_READY_STATE_E oldReadyState = MBIMSubscriberReadyStateNotInitialized;
865 static MBIM_REGISTER_STATE_E oldRegisterState = MBIMRegisterStateUnknown;
866 static MBIM_PACKET_SERVICE_STATE_E oldPacketServiceState = MBIMPacketServiceStateUnknown;
867 static MBIM_ACTIVATION_STATE_E oldActivationState = MBIMActivationStateUnknown;
868 static int mbim_update_state(void);
869 
mbim2qmi_ipv4addr(uint32_t addr)870 static __inline uint32_t mbim2qmi_ipv4addr(uint32_t addr) {
871     return (addr>>24) | (addr>>8&0xff00) | (addr<<8&0xff0000) | (addr<<24);
872 }
873 
mbim2qmi_ipv6addr(const unsigned char * src,unsigned char * dst)874 static __inline void mbim2qmi_ipv6addr(const unsigned char *src, unsigned char *dst) {
875     int i;
876 
877     for (i = 0; i < 16 ; i++) {
878         dst[i] = src[i];
879     }
880 }
881 
compose_open_command(UINT32 MaxControlTransfer)882 static MBIM_MESSAGE_HEADER *compose_open_command(UINT32 MaxControlTransfer)
883 {
884     MBIM_OPEN_MSG_T *pRequest = (MBIM_OPEN_MSG_T *)mbim_alloc(sizeof(MBIM_OPEN_MSG_T));
885 
886     if(!pRequest)
887         return NULL;
888 
889     pRequest->MessageHeader.MessageType = htole32(MBIM_OPEN_MSG);
890     pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_COMMAND_MSG_T));
891     pRequest->MessageHeader.TransactionId = htole32(TransactionId++);
892     pRequest->MaxControlTransfer = htole32(MaxControlTransfer);
893 
894     return &pRequest->MessageHeader;
895 }
896 
compose_close_command(void)897 static MBIM_MESSAGE_HEADER *compose_close_command(void)
898 {
899     MBIM_CLOSE_MSG_T *pRequest = (MBIM_CLOSE_MSG_T *)mbim_alloc(sizeof(MBIM_CLOSE_MSG_T));
900 
901     if(!pRequest)
902         return NULL;
903 
904     pRequest->MessageHeader.MessageType = htole32(MBIM_CLOSE_MSG);
905     pRequest->MessageHeader.MessageLength = htole32(sizeof(MBIM_CLOSE_MSG_T));
906     pRequest->MessageHeader.TransactionId = htole32(TransactionId++);
907 
908     return &pRequest->MessageHeader;
909 }
910 
compose_basic_connect_command(UINT32 CID,UINT32 CommandType,void * pInformationBuffer,UINT32 InformationBufferLength)911 static MBIM_MESSAGE_HEADER *compose_basic_connect_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength)
912 {
913     MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)mbim_alloc(sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength);
914 
915     if (!pRequest)
916         return NULL;
917 
918     pRequest->MessageHeader.MessageType = htole32(MBIM_COMMAND_MSG);
919     pRequest->MessageHeader.MessageLength = htole32((sizeof(MBIM_COMMAND_MSG_T) + InformationBufferLength));
920     pRequest->MessageHeader.TransactionId = htole32(TransactionId++);
921 
922     pRequest->FragmentHeader.TotalFragments = htole32(1);
923     pRequest->FragmentHeader.CurrentFragment= htole32(0);
924 
925     memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16);
926 
927     pRequest->CID = htole32(CID);
928     pRequest->CommandType = htole32(CommandType);
929     if (InformationBufferLength && pInformationBuffer) {
930         pRequest->InformationBufferLength = htole32(InformationBufferLength);
931         memcpy(pRequest->InformationBuffer, pInformationBuffer, InformationBufferLength);
932     } else {
933         pRequest->InformationBufferLength = htole32(0);
934     }
935 
936     return &pRequest->MessageHeader;
937 }
938 
compose_basic_connect_ext_command(UINT32 CID,UINT32 CommandType,void * pInformationBuffer,UINT32 InformationBufferLength)939 static MBIM_MESSAGE_HEADER *compose_basic_connect_ext_command(UINT32 CID, UINT32 CommandType, void *pInformationBuffer, UINT32 InformationBufferLength)
940 {
941     MBIM_COMMAND_MSG_T *pRequest = (MBIM_COMMAND_MSG_T *)compose_basic_connect_command(CID, CommandType, pInformationBuffer, InformationBufferLength);
942 
943     if (!pRequest)
944         return NULL;
945 
946     memcpy(pRequest->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16);
947 
948     return &pRequest->MessageHeader;
949 }
950 
uuid2str(const UUID_T * pUUID)951 static const char * uuid2str(const UUID_T *pUUID) {
952     static char str[16*2+4+1];
953     const UINT8 *d = pUUID->uuid;
954 
955     snprintf(str, sizeof(str), "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
956         d[0], d[1], d[2], d[3], d[4], d[5], d[6], d[7],
957         d[8], d[9], d[10], d[11], d[12], d[13], d[14], d[15]);
958 
959     return str;
960 }
961 
DeviceServiceId2str(const UUID_T * pUUID)962 static const char *DeviceServiceId2str(const UUID_T *pUUID) {
963     const char *str = uuid2str(pUUID);
964 
965     struct { char *val;char *name;} _enumstr[] = {
966         {UUID_BASIC_CONNECT, "UUID_BASIC_CONNECT"},
967         {UUID_BASIC_CONNECT_EXT, "UUID_BASIC_CONNECT_EXT"},
968         {UUID_SMS, "UUID_SMS"},
969         {UUID_USSD, "UUID_USSD"},
970         {UUID_PHONEBOOK, "UUID_PHONEBOOK"},
971         {UUID_STK, "UUID_STK"},
972         {UUID_AUTH, "UUID_AUTH"},
973         {UUID_DSS, "UUID_DSS"},
974         {uuid_ext_qmux, "uuid_ext_qmux"},
975         {uuid_mshsd, "uuid_mshsd"},
976         {uuid_qmbe, "uuid_qmbe"},
977         {UUID_MSFWID, "UUID_MSFWID"},
978         {uuid_atds, "uuid_atds"},
979         {uuid_qdu, "uuid_qdu"},
980         {UUID_MS_UICC_LOW_LEVEL, "UUID_MS_UICC_LOW_LEVEL"},
981         {UUID_MS_SARControl, "UUID_MS_SARControl"},
982         {UUID_VOICEEXTENSIONS, "UUID_VOICEEXTENSIONS"},
983         {UUID_LIBMBIM_PROXY, "UUID_LIBMBIM_PROXY"},
984     };
985     int idx;
986 
987     for (idx = 0; idx < (int)(sizeof(_enumstr)/sizeof(_enumstr[0])); idx++) {
988         if (!strcasecmp(str, _enumstr[idx].val))
989             return _enumstr[idx].name;
990     }
991 
992     return str;
993 }
994 
mbim_get_segment(void * _pMsg,UINT32 offset,UINT32 len)995 static const char *mbim_get_segment(void *_pMsg, UINT32 offset, UINT32 len)
996 {
997     int idx;
998     static char buff[256] = {'\0'};
999     UINT8 *pMsg = (UINT8*)_pMsg;
1000 
1001     for (idx = 0; idx < (int)(len/2); idx++)
1002         buff[idx] = pMsg[offset+idx*2];
1003     buff[idx] = '\0';
1004     return buff;
1005 }
1006 
mbim_dump_header(MBIM_MESSAGE_HEADER * pMsg,const char * direction)1007 static void mbim_dump_header(MBIM_MESSAGE_HEADER *pMsg, const char *direction) {
1008     mbim_debug("%s Header:", direction);
1009     mbim_debug("%s MessageLength = %u", direction, le32toh(pMsg->MessageLength));
1010     mbim_debug("%s MessageType =  %s (0x%08x)", direction, MBIMMSGTypeStr(le32toh(pMsg->MessageType)), le32toh(pMsg->MessageType));
1011     mbim_debug("%s TransactionId = %u", direction, le32toh(pMsg->TransactionId));
1012     mbim_debug("%s Contents:", direction);
1013 }
1014 
mbim_dump_command_msg(MBIM_COMMAND_MSG_T * pCmdMsg,const char * direction)1015 static void mbim_dump_command_msg(MBIM_COMMAND_MSG_T *pCmdMsg, const char *direction) {
1016     mbim_debug("%s DeviceServiceId = %s (%s)", direction, DeviceServiceId2str(&pCmdMsg->DeviceServiceId), uuid2str(&pCmdMsg->DeviceServiceId));
1017     mbim_debug("%s CID = %s (%u)", direction, CID2Str(le32toh(pCmdMsg->CID)), le32toh(pCmdMsg->CID));
1018     mbim_debug("%s CommandType = %s (%u)", direction, le32toh(pCmdMsg->CommandType) ? "set" : "query", le32toh(pCmdMsg->CommandType));
1019     mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdMsg->InformationBufferLength));
1020 }
1021 
mbim_dump_command_done(MBIM_COMMAND_DONE_T * pCmdDone,const char * direction)1022 static void mbim_dump_command_done(MBIM_COMMAND_DONE_T *pCmdDone, const char *direction) {
1023     mbim_debug("%s DeviceServiceId = %s (%s)", direction, DeviceServiceId2str(&pCmdDone->DeviceServiceId), uuid2str(&pCmdDone->DeviceServiceId));
1024     mbim_debug("%s CID = %s (%u)", direction, CID2Str(le32toh(pCmdDone->CID)), le32toh(pCmdDone->CID));
1025     mbim_debug("%s Status = %u", direction, le32toh(pCmdDone->Status));
1026     mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pCmdDone->InformationBufferLength));
1027 }
1028 
mbim_dump_indicate_msg(MBIM_INDICATE_STATUS_MSG_T * pIndMsg,const char * direction)1029 static void mbim_dump_indicate_msg(MBIM_INDICATE_STATUS_MSG_T *pIndMsg, const char *direction) {
1030     mbim_debug("%s DeviceServiceId = %s (%s)", direction, DeviceServiceId2str(&pIndMsg->DeviceServiceId), uuid2str(&pIndMsg->DeviceServiceId));
1031     if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16))
1032         mbim_debug("%s CID = %s (%u)", direction, MS_CID2Str(le32toh(pIndMsg->CID)), le32toh(pIndMsg->CID));
1033     else
1034         mbim_debug("%s CID = %s (%u)", direction, CID2Str(le32toh(pIndMsg->CID)), le32toh(pIndMsg->CID));
1035     mbim_debug("%s InformationBufferLength = %u", direction, le32toh(pIndMsg->InformationBufferLength));
1036 }
1037 
mbim_dump_connect(MBIM_CONNECT_T * pInfo,const char * direction)1038 static void mbim_dump_connect(MBIM_CONNECT_T *pInfo, const char *direction) {
1039     mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId));
1040     mbim_debug("%s ActivationState = %s (%u)", direction, MBIMActivationStateStr(le32toh(pInfo->ActivationState)), le32toh(pInfo->ActivationState));
1041     mbim_debug("%s IPType = %s", direction, MBIMContextIPTypeStr(le32toh(pInfo->IPType)));
1042     mbim_debug("%s VoiceCallState = %s", direction, MBIMVoiceCallStateStr(le32toh(pInfo->VoiceCallState)));
1043     mbim_debug("%s ContextType = %s", direction, uuid2str(&pInfo->ContextType));
1044     mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError));
1045 }
1046 
mbim_dump_signal_state(MBIM_SIGNAL_STATE_INFO_T * pInfo,const char * direction)1047 static void mbim_dump_signal_state(MBIM_SIGNAL_STATE_INFO_T *pInfo, const char *direction)
1048 {
1049     mbim_debug("%s Rssi = %u", direction, le32toh(pInfo->Rssi));
1050     mbim_debug("%s ErrorRate = %u", direction, le32toh(pInfo->ErrorRate));
1051     mbim_debug("%s SignalStrengthInterval = %u", direction, le32toh(pInfo->SignalStrengthInterval));
1052     mbim_debug("%s RssiThreshold = %u", direction, le32toh(pInfo->RssiThreshold));
1053     mbim_debug("%s ErrorRateThreshold = %u", direction, le32toh(pInfo->ErrorRateThreshold));
1054 }
1055 
mbim_dump_packet_service(MBIM_PACKET_SERVICE_INFO_T * pInfo,const char * direction)1056 static void mbim_dump_packet_service(MBIM_PACKET_SERVICE_INFO_T *pInfo, const char *direction)
1057 {
1058     mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError));
1059     mbim_debug("%s PacketServiceState = %s", direction, MBIMPacketServiceStateStr(le32toh(pInfo->PacketServiceState)));
1060     mbim_debug("%s HighestAvailableDataClass = %s", direction, MBIMDataClassStr(le32toh(pInfo->HighestAvailableDataClass)));
1061     mbim_debug("%s UplinkSpeed = %ld", direction, (long)le64toh(pInfo->UplinkSpeed));
1062     mbim_debug("%s DownlinkSpeed = %ld", direction, (long)le64toh(pInfo->DownlinkSpeed));
1063 }
1064 
mbim_dump_subscriber_status(MBIM_SUBSCRIBER_READY_STATUS_T * pInfo,const char * direction)1065 static void mbim_dump_subscriber_status(MBIM_SUBSCRIBER_READY_STATUS_T *pInfo, const char *direction)
1066 {
1067     mbim_debug("%s ReadyState = %s", direction, MBIMSubscriberReadyStateStr(le32toh(pInfo->ReadyState)));
1068     mbim_debug("%s SIMICCID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize)));
1069     mbim_debug("%s SubscriberID = %s", direction, mbim_get_segment(pInfo, le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize)));
1070     /* maybe more than one number */
1071     uint32_t idx;
1072     for (idx = 0; idx < le32toh(pInfo->ElementCount); idx++) {
1073         UINT32 offset = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[0];
1074         UINT32 length = ((UINT32*)((UINT8*)pInfo+offsetof(MBIM_SUBSCRIBER_READY_STATUS_T, TelephoneNumbersRefList)))[1];
1075         mbim_debug("%s Number = %s", direction, mbim_get_segment(pInfo, le32toh(offset), le32toh(length)));
1076     }
1077 }
1078 
mbim_dump_regiester_status(MBIM_REGISTRATION_STATE_INFO_T * pInfo,const char * direction)1079 static void mbim_dump_regiester_status(MBIM_REGISTRATION_STATE_INFO_T *pInfo, const char *direction)
1080 {
1081     mbim_debug("%s NwError = %u", direction, le32toh(pInfo->NwError));
1082     mbim_debug("%s RegisterState = %s", direction, MBIMRegisterStateStr(le32toh(pInfo->RegisterState)));
1083     mbim_debug("%s RegisterMode = %s", direction, MBIMRegisterModeStr(le32toh(pInfo->RegisterMode)));
1084 }
1085 
mbim_dump_ipconfig(MBIM_IP_CONFIGURATION_INFO_T * pInfo,const char * direction)1086 static void mbim_dump_ipconfig(MBIM_IP_CONFIGURATION_INFO_T *pInfo, const char *direction)
1087 {
1088     UINT8 prefix = 0, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL;
1089 
1090     mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId));
1091     mbim_debug("%s IPv4ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv4ConfigurationAvailable));
1092     mbim_debug("%s IPv6ConfigurationAvailable = 0x%x", direction, le32toh(pInfo->IPv6ConfigurationAvailable));
1093     mbim_debug("%s IPv4AddressCount = 0x%x", direction, le32toh(pInfo->IPv4AddressCount));
1094     mbim_debug("%s IPv4AddressOffset = 0x%x", direction, le32toh(pInfo->IPv4AddressOffset));
1095     mbim_debug("%s IPv6AddressCount = 0x%x", direction, le32toh(pInfo->IPv6AddressCount));
1096     mbim_debug("%s IPv6AddressOffset = 0x%x", direction, le32toh(pInfo->IPv6AddressOffset));
1097 
1098     /* IPv4 */
1099     if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) {
1100         MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1101         prefix = le32toh(pAddress->OnLinkPrefixLength);
1102         ipv4 = pAddress->IPv4Address;
1103         mbim_debug("%s IPv4 = %u.%u.%u.%u/%u", direction, ipv4[0], ipv4[1], ipv4[2], ipv4[3], prefix);
1104     }
1105     if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2) {
1106         gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1107         mbim_debug("%s gw = %u.%u.%u.%u", direction, gw[0], gw[1], gw[2], gw[3]);
1108     }
1109     if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x3) {
1110         dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset) -sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1111         mbim_debug("%s dns1 = %u.%u.%u.%u", direction, dns1[0], dns1[1], dns1[2], dns1[3]);
1112         if (le32toh(pInfo->IPv4DnsServerCount) == 2) {
1113             dns2 = dns1 + 4;
1114             mbim_debug("%s dns2 = %u.%u.%u.%u", direction, dns2[0], dns2[1], dns2[2], dns2[3]);
1115         }
1116     }
1117     if (le32toh(pInfo->IPv4Mtu)) mbim_debug("%s ipv4 mtu = %u", direction, le32toh(pInfo->IPv4Mtu));
1118 
1119     /* IPv6 */
1120     if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) {
1121         MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1122         prefix = le32toh(pAddress->OnLinkPrefixLength);
1123         ipv6 = pAddress->IPv6Address;
1124         mbim_debug("%s IPv6 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x/%d", \
1125             direction, ipv6[0], ipv6[1], ipv6[2], ipv6[3], ipv6[4], ipv6[5], ipv6[6], ipv6[7], \
1126             ipv6[8], ipv6[9], ipv6[10], ipv6[11], ipv6[12], ipv6[13], ipv6[14], ipv6[15], prefix);
1127     }
1128     if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2) {
1129         gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1130         mbim_debug("%s gw = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \
1131             direction, gw[0], gw[1], gw[2], gw[3], gw[4], gw[5], gw[6], gw[7], \
1132             gw[8], gw[9], gw[10], gw[11], gw[12], gw[13], gw[14], gw[15]);
1133     }
1134     if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x3) {
1135         dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1136         mbim_debug("%s dns1 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \
1137             direction, dns1[0], dns1[1], dns1[2], dns1[3], dns1[4], dns1[5], dns1[6], dns1[7], \
1138             dns1[8], dns1[9], dns1[10], dns1[11], dns1[12], dns1[13], dns1[14], dns1[15]);
1139         if (le32toh(pInfo->IPv6DnsServerCount) == 2) {
1140             dns2 = dns1 + 16;
1141             mbim_debug("%s dns2 = %02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x:%02x%02x", \
1142                 direction, dns2[0], dns2[1], dns2[2], dns2[3], dns1[4], dns1[5], dns1[6], dns1[7],
1143                 dns2[8], dns2[9], dns2[10], dns2[11], dns2[12], dns2[13], dns2[14], dns2[15]);
1144         }
1145     }
1146     if (le32toh(pInfo->IPv6Mtu)) mbim_debug("%s ipv6 mtu = %u", direction, le32toh(pInfo->IPv6Mtu));
1147 }
1148 
mbim_dump(MBIM_MESSAGE_HEADER * pMsg,int mbim_verbose)1149 static void mbim_dump(MBIM_MESSAGE_HEADER *pMsg, int mbim_verbose) {
1150     unsigned char *data = (unsigned char *)pMsg;
1151     const char *direction = (le32toh(pMsg->MessageType) & 0x80000000) ? "<" : ">";
1152 
1153     if (!mbim_verbose)
1154         return;
1155 
1156     if (mbim_verbose) {
1157         unsigned i;
1158         static char *_tmp = NULL;
1159 
1160         if (!_tmp)
1161             _tmp = (char *)malloc(4096);
1162 
1163         if (_tmp) {
1164             _tmp[0] = (le32toh(pMsg->MessageType) & 0x80000000) ? '<' : '>';
1165             _tmp[1] = '\0';
1166             for (i = 0; i < le32toh(pMsg->MessageLength) && i < 4096; i++)
1167                 snprintf(_tmp + strlen(_tmp), 4096 - strlen(_tmp), "%02X:", data[i]);
1168             mbim_debug("%s", _tmp);
1169         }
1170     }
1171 
1172     mbim_dump_header(pMsg, direction);
1173 
1174     switch (le32toh(pMsg->MessageType)) {
1175     case MBIM_OPEN_MSG: {
1176         MBIM_OPEN_MSG_T *pOpenMsg = (MBIM_OPEN_MSG_T *)pMsg;
1177         mbim_debug("%s MaxControlTransfer = %u", direction, le32toh(pOpenMsg->MaxControlTransfer));
1178     }
1179     break;
1180     case MBIM_OPEN_DONE: {
1181         MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsg;
1182         mbim_debug("%s Status = %u", direction, le32toh(pOpenDone->Status));
1183     }
1184     break;
1185     case MBIM_CLOSE_MSG: {
1186 
1187     }
1188     break;
1189     case MBIM_CLOSE_DONE: {
1190         MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsg;
1191         mbim_debug("%s Status = %u", direction, le32toh(pCloseDone->Status));
1192     }
1193     break;
1194     case MBIM_COMMAND_MSG: {
1195         MBIM_COMMAND_MSG_T *pCmdMsg = (MBIM_COMMAND_MSG_T *)pMsg;
1196 
1197         mbim_dump_command_msg(pCmdMsg, direction);
1198         if (!memcmp(pCmdMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) {
1199             switch (le32toh(pCmdMsg->CID)) {
1200                case  MBIM_CID_CONNECT: {
1201                     MBIM_SET_CONNECT_T *pInfo = (MBIM_SET_CONNECT_T *)pCmdMsg->InformationBuffer;
1202                     mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId));
1203                 }
1204                 break;
1205                 case MBIM_CID_IP_CONFIGURATION: {
1206                     MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdMsg->InformationBuffer;
1207                     mbim_debug("%s SessionId = %u", direction, le32toh(pInfo->SessionId));
1208                 }
1209                 break;
1210                 default:
1211                 break;
1212             }
1213         }
1214     }
1215     break;
1216     case MBIM_COMMAND_DONE: {
1217         MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsg;
1218 
1219         mbim_dump_command_done(pCmdDone, direction);
1220         if (le32toh(pCmdDone->InformationBufferLength) == 0)
1221             return;
1222 
1223         if (!memcmp(pCmdDone->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) {
1224             switch (le32toh(pCmdDone->CID)) {
1225                 case MBIM_CID_CONNECT: {
1226                 MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer;
1227                 mbim_dump_connect(pInfo, direction);
1228                 }
1229                 break;
1230                 case MBIM_CID_IP_CONFIGURATION: {
1231                     //MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer;
1232                     //mbim_dump_ipconfig(pInfo, direction);
1233                 }
1234                 break;
1235                 case MBIM_CID_PACKET_SERVICE: {
1236                     MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer;
1237                     mbim_dump_packet_service(pInfo, direction);
1238                 }
1239                 break;
1240                 case MBIM_CID_SUBSCRIBER_READY_STATUS: {
1241                     MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer;
1242                     mbim_dump_subscriber_status(pInfo, direction);
1243                 }
1244                 break;
1245                 case MBIM_CID_REGISTER_STATE: {
1246                     MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer;
1247                     mbim_dump_regiester_status(pInfo, direction);
1248                 }
1249                 break;
1250                 default:
1251                 break;
1252             }
1253         }
1254     }
1255     break;
1256     case MBIM_INDICATE_STATUS_MSG: {
1257         MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pMsg;
1258 
1259         mbim_dump_indicate_msg(pIndMsg, direction);
1260         if (le32toh(pIndMsg->InformationBufferLength) == 0)
1261             return;
1262 
1263         if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16)) {
1264             switch (le32toh(pIndMsg->CID)) {
1265                 case MBIM_CID_CONNECT: {
1266                     MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer;
1267                     mbim_dump_connect(pInfo, direction);
1268                 }
1269                 break;
1270                 case MBIM_CID_SIGNAL_STATE: {
1271                     MBIM_SIGNAL_STATE_INFO_T *pInfo = (MBIM_SIGNAL_STATE_INFO_T *)pIndMsg->InformationBuffer;
1272                     mbim_dump_signal_state(pInfo, direction);
1273                 }
1274                 break;
1275                 case MBIM_CID_SUBSCRIBER_READY_STATUS: {
1276                     MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer;
1277                     mbim_dump_subscriber_status(pInfo, direction);
1278                 }
1279                 break;
1280                 case MBIM_CID_REGISTER_STATE: {
1281                     MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer;
1282                     mbim_dump_regiester_status(pInfo, direction);
1283                 }
1284                 break;
1285                 case MBIM_CID_PACKET_SERVICE: {
1286                     MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer;
1287                     mbim_dump_packet_service(pInfo, direction);
1288                 }
1289                 break;
1290                 default:
1291                 break;
1292             }
1293         }
1294         else if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT_EXT), 16)) {
1295         }
1296     }
1297     break;
1298     case MBIM_FUNCTION_ERROR_MSG: {
1299         MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T*)pMsg;
1300         mbim_debug("%s ErrorStatusCode = %u", direction, le32toh(pErrMsg->ErrorStatusCode));
1301     }
1302     break;
1303     default:
1304     break;
1305     }
1306 }
1307 
mbim_recv_command(MBIM_MESSAGE_HEADER * pResponse,unsigned size)1308 static void mbim_recv_command(MBIM_MESSAGE_HEADER *pResponse, unsigned size)
1309 {
1310     (void)size;
1311     pthread_mutex_lock(&cm_command_mutex);
1312 
1313     if (pResponse)
1314         mbim_dump(pResponse, mbim_verbose);
1315 
1316     if (pResponse == NULL) {
1317         pthread_cond_signal(&cm_command_cond);
1318     }
1319     else if (mbim_pRequest && le32toh(mbim_pRequest->TransactionId) == le32toh(pResponse->TransactionId)) {
1320         mbim_pResponse = mbim_alloc(le32toh(pResponse->MessageLength));
1321         if (mbim_pResponse)
1322             memcpy(mbim_pResponse, pResponse, le32toh(pResponse->MessageLength));
1323         pthread_cond_signal(&cm_command_cond);
1324     }
1325     else if (le32toh(pResponse->MessageType) ==  MBIM_INDICATE_STATUS_MSG) {
1326         MBIM_INDICATE_STATUS_MSG_T *pIndMsg = (MBIM_INDICATE_STATUS_MSG_T *)pResponse;
1327 
1328         if (!memcmp(pIndMsg->DeviceServiceId.uuid, str2uuid(UUID_BASIC_CONNECT), 16))
1329         {
1330             switch (le32toh(pIndMsg->CID)) {
1331                 case MBIM_CID_SUBSCRIBER_READY_STATUS: {
1332                     MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pIndMsg->InformationBuffer;
1333                     if (oldReadyState != le32toh(pInfo->ReadyState))
1334                         qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
1335                 }
1336                 break;
1337                 case MBIM_CID_REGISTER_STATE: {
1338                     MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pIndMsg->InformationBuffer;
1339                     if (oldRegisterState != le32toh(pInfo->RegisterState))
1340                         qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
1341                 }
1342                 break;
1343                 case MBIM_CID_PACKET_SERVICE: {
1344                     MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pIndMsg->InformationBuffer;
1345                     MBIM_PACKET_SERVICE_STATE_E state = le32toh(pInfo->PacketServiceState);
1346 
1347                     if (oldPacketServiceState != state
1348                             && (1 || MBIMPacketServiceStateAttached == state || MBIMPacketServiceStateDetached == state))
1349                         qmidevice_send_event_to_main(RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED);
1350                 }
1351                 break;
1352                 case MBIM_CID_CONNECT: {
1353                     MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pIndMsg->InformationBuffer;
1354                     if (pInfo->SessionId == (uint32_t)mbim_sessionID) {
1355                         MBIM_ACTIVATION_STATE_E state = le32toh(pInfo->ActivationState);
1356 
1357                         if (oldActivationState != state
1358                             && (1 || MBIMActivationStateActivated == state || MBIMActivationStateDeactivated == state))
1359                             qmidevice_send_event_to_main(RIL_UNSOL_DATA_CALL_LIST_CHANGED);
1360                     }
1361                 }
1362                 break;
1363                 default:
1364                 break;
1365             }
1366         }
1367     }
1368 
1369     pthread_mutex_unlock(&cm_command_mutex);
1370 }
1371 
mbim_send_command(MBIM_MESSAGE_HEADER * pRequest,MBIM_COMMAND_DONE_T ** ppCmdDone,unsigned msecs)1372 static int mbim_send_command(MBIM_MESSAGE_HEADER *pRequest, MBIM_COMMAND_DONE_T **ppCmdDone, unsigned msecs) {
1373     int ret;
1374 
1375     if (ppCmdDone)
1376          *ppCmdDone = NULL;
1377 
1378     if (mbim_fd <= 0)
1379         return -ENODEV;
1380 
1381    if (s_tid_reader == 0)
1382       return -EINVAL;
1383 
1384     if (!pRequest)
1385         return -ENOMEM;
1386 
1387     pthread_mutex_lock(&cm_command_mutex);
1388 
1389     if (pRequest) {
1390         if (pRequest->TransactionId == (0xFFFFFF + 1)) { //mbim-proxy need 0xFF000000 to indicat client
1391             TransactionId = 1;
1392             pRequest->TransactionId = htole32(TransactionId++);
1393         }
1394         mbim_dump(pRequest, mbim_verbose);
1395     }
1396 
1397     mbim_pRequest = pRequest;
1398     mbim_pResponse = NULL;
1399 
1400     ret = write(mbim_fd, pRequest, le32toh(pRequest->MessageLength));
1401 
1402     if (ret > 0 && (uint32_t)ret == le32toh(pRequest->MessageLength)) {
1403         ret = pthread_cond_timeout_np(&cm_command_cond, &cm_command_mutex, msecs);
1404         if (!ret) {
1405             if (mbim_pResponse && ppCmdDone) {
1406                 *ppCmdDone = (MBIM_COMMAND_DONE_T *)mbim_pResponse;
1407             }
1408         }
1409     } else {
1410         mbim_debug("%s pthread_cond_timeout_np=%d", __func__, ret);
1411     }
1412 
1413     mbim_pRequest = mbim_pResponse = NULL;
1414 
1415     pthread_mutex_unlock(&cm_command_mutex);
1416 
1417     return ret;
1418 }
1419 
mbim_proxy_read(int fd,MBIM_MESSAGE_HEADER * pResponse,size_t size)1420 static ssize_t mbim_proxy_read (int fd, MBIM_MESSAGE_HEADER *pResponse, size_t size) {
1421     ssize_t nreads;
1422 
1423     nreads = read(fd, pResponse, sizeof(MBIM_MESSAGE_HEADER));
1424     if (nreads == sizeof(MBIM_MESSAGE_HEADER) && le32toh(pResponse->MessageLength) <= size) {
1425         nreads += read(fd, pResponse+1, le32toh(pResponse->MessageLength) - sizeof(MBIM_MESSAGE_HEADER));
1426     }
1427 
1428     return nreads;
1429 }
1430 
mbim_read_thread(void * param)1431 static void * mbim_read_thread(void *param) {
1432     PROFILE_T *profile = (PROFILE_T *)param;
1433     const char *cdc_wdm = (const char *)profile->qmichannel;
1434     int wait_for_request_quit = 0;
1435 
1436     mbim_verbose = debug_qmi;
1437     s_tid_reader = pthread_self();
1438 
1439     if (profile->qmap_mode > 1 && profile->qmapnet_adapter[0]) {
1440         if (!profile->proxy[0])
1441              sprintf(profile->proxy, "%s", QUECTEL_MBIM_PROXY);
1442         mbim_sessionID = profile->pdp;
1443     }
1444 
1445     if (profile->proxy[0]) {
1446         mbim_fd = cm_open_proxy(profile->proxy);
1447     }
1448     else {
1449         mbim_fd = cm_open_dev(cdc_wdm);
1450     }
1451 
1452     if (mbim_fd <= 0) {
1453         mbim_debug("fail to open (%s), errno: %d (%s)", cdc_wdm, errno, strerror(errno));
1454         goto __quit;
1455     }
1456 
1457     dbg_time("cdc_wdm_fd = %d", mbim_fd);
1458 
1459     qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_CONNECTED);
1460 
1461     while (mbim_fd > 0) {
1462         struct pollfd pollfds[] = {{mbim_fd, POLLIN, 0}, {qmidevice_control_fd[1], POLLIN, 0}};
1463         int ne, ret, nevents = 2;
1464 
1465         ret = poll(pollfds, nevents, wait_for_request_quit ? 1000 : -1);
1466 
1467         if (ret == 0 && wait_for_request_quit) {
1468             break;
1469         }
1470 
1471         if (ret < 0) {
1472             mbim_debug("%s poll=%d, errno: %d (%s)", __func__, ret, errno, strerror(errno));
1473             break;
1474         }
1475 
1476         for (ne = 0; ne < nevents; ne++) {
1477             int fd = pollfds[ne].fd;
1478             short revents = pollfds[ne].revents;
1479 
1480             if (revents & (POLLERR | POLLHUP | POLLNVAL)) {
1481                 mbim_debug("%s poll err/hup/inval", __func__);
1482                 mbim_debug("epoll fd = %d, events = 0x%04x", fd, revents);
1483                 if (revents & (POLLERR | POLLHUP | POLLNVAL))
1484                 goto __quit;
1485             }
1486 
1487             if ((revents & POLLIN) == 0)
1488                 continue;
1489 
1490             if (mbim_fd == fd) {
1491                 ssize_t nreads;
1492                 MBIM_MESSAGE_HEADER *pResponse = (MBIM_MESSAGE_HEADER *) cm_recv_buf;
1493 
1494                 if (profile->proxy[0])
1495                     nreads = mbim_proxy_read(fd, pResponse, sizeof(cm_recv_buf));
1496                 else
1497                     nreads = read(fd, pResponse, sizeof(cm_recv_buf));
1498 
1499                 if (nreads <= 0) {
1500                     mbim_debug("%s read=%d errno: %d (%s)",  __func__, (int)nreads, errno, strerror(errno));
1501                     break;
1502                 }
1503 
1504                 mbim_recv_command(pResponse, nreads);
1505             }
1506             else if (fd == qmidevice_control_fd[1]) {
1507                 int triger_event;
1508                 if (read(fd, &triger_event, sizeof(triger_event)) == sizeof(triger_event)) {
1509                     //mbim_debug("triger_event = 0x%x", triger_event);
1510                     switch (triger_event) {
1511                         case RIL_REQUEST_QUIT:
1512                             goto __quit;
1513                         break;
1514                         case SIG_EVENT_STOP:
1515                             wait_for_request_quit = 1;
1516                         break;
1517                         default:
1518                         break;
1519                     }
1520                 }
1521             }
1522         }
1523     }
1524 
1525 __quit:
1526     if (mbim_fd != -1) { close(mbim_fd); mbim_fd = -1; }
1527     mbim_recv_command(NULL, 0);
1528     qmidevice_send_event_to_main(RIL_INDICATE_DEVICE_DISCONNECTED);
1529     mbim_debug("%s exit", __func__);
1530     s_tid_reader = 0;
1531 
1532     return NULL;
1533 }
1534 
mbim_status_code(MBIM_MESSAGE_HEADER * pMsgHdr)1535 static int mbim_status_code(MBIM_MESSAGE_HEADER *pMsgHdr) {
1536     int status = 0;
1537 
1538     if (!pMsgHdr)
1539         return 0;
1540 
1541     switch (le32toh(pMsgHdr->MessageType)) {
1542         case MBIM_OPEN_DONE: {
1543             MBIM_OPEN_DONE_T *pOpenDone = (MBIM_OPEN_DONE_T *)pMsgHdr;
1544             status = le32toh(pOpenDone->Status);
1545         }
1546         break;
1547         case MBIM_CLOSE_DONE: {
1548             MBIM_CLOSE_DONE_T *pCloseDone = (MBIM_CLOSE_DONE_T *)pMsgHdr;
1549             status = le32toh(pCloseDone->Status);
1550         }
1551         break;
1552         case MBIM_COMMAND_DONE: {
1553             MBIM_COMMAND_DONE_T *pCmdDone = (MBIM_COMMAND_DONE_T *)pMsgHdr;
1554             status = le32toh(pCmdDone->Status);
1555         }
1556         break;
1557         case MBIM_FUNCTION_ERROR_MSG: {
1558             MBIM_FUNCTION_ERROR_MSG_T *pErrMsg = (MBIM_FUNCTION_ERROR_MSG_T *)pMsgHdr;
1559             status = le32toh(pErrMsg->ErrorStatusCode);
1560             if (status == MBIM_ERROR_NOT_OPENED)
1561                 mbim_open_state = 0; //EM06ELAR03A05M4G when suspend/resume, may get this error
1562         }
1563         break;
1564         default:
1565         break;
1566     }
1567 
1568     return status;
1569 }
1570 
1571 #define mbim_check_err(err, pRequest, pCmdDone) do { \
1572     int _status = mbim_status_code(pCmdDone ? &pCmdDone->MessageHeader : NULL); \
1573     if (err || _status || !pCmdDone) { \
1574         if (pCmdDone) { mbim_dump(&pCmdDone->MessageHeader, (mbim_verbose == 0)); } \
1575         mbim_free(pRequest); mbim_free(pCmdDone); \
1576         mbim_debug("%s:%d err=%d, Status=%d", __func__, __LINE__, err, _status); \
1577         if (err) return err; if (_status) return _status; return 8888; \
1578     } \
1579 } while(0)
1580 
1581 /*
1582  * MBIM device can be open repeatly without error
1583  * So, we can call the function, no matter it have been opened or not
1584  */
mbim_open_device(uint32_t MaxControlTransfer)1585 static int mbim_open_device(uint32_t MaxControlTransfer) {
1586     MBIM_MESSAGE_HEADER *pRequest = NULL;
1587     MBIM_OPEN_DONE_T *pOpenDone = NULL;
1588     int err = 0;
1589 
1590     mbim_debug("%s()", __func__);
1591     pRequest = compose_open_command(MaxControlTransfer);
1592     err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pOpenDone, 2*1000);
1593     mbim_check_err(err, pRequest, pOpenDone);
1594 
1595     err = le32toh(pOpenDone->Status);
1596     mbim_free(pRequest); mbim_free(pOpenDone);
1597 
1598     return err;
1599 }
1600 
mbim_close_device(void)1601 static int mbim_close_device(void) {
1602     MBIM_MESSAGE_HEADER *pRequest = NULL;
1603     MBIM_CLOSE_DONE_T *pCloseDone = NULL;
1604     int err = 0;
1605 
1606     mbim_debug("%s()", __func__);
1607     pRequest = compose_close_command();
1608     err = mbim_send_command(pRequest, (MBIM_COMMAND_DONE_T **)&pCloseDone, mbim_default_timeout);
1609     mbim_check_err(err, pRequest, pCloseDone);
1610 
1611     err = le32toh(pCloseDone->Status);
1612     mbim_free(pRequest); mbim_free(pCloseDone);
1613 
1614     return err;
1615 }
1616 
mbim_query_connect(int sessionID)1617 static int mbim_query_connect(int sessionID) {
1618     MBIM_MESSAGE_HEADER *pRequest = NULL;
1619     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1620     MBIM_SET_CONNECT_T set_connect;
1621     int err;
1622 
1623     if (ActivationState != MBIMActivationStateActivated  || mbim_verbose)
1624         mbim_debug("%s(sessionID=%d)", __func__, sessionID); //avoid two many log
1625     set_connect.SessionId = htole32(sessionID);
1626     pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_QUERY, &set_connect, sizeof(set_connect));
1627     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1628     mbim_check_err(err, pRequest, pCmdDone);
1629 
1630     if (le32toh(pCmdDone->InformationBufferLength))
1631     {
1632         MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer;
1633         ActivationState = le32toh(pInfo->ActivationState);
1634         mbim_update_state();
1635     }
1636     mbim_free(pRequest); mbim_free(pCmdDone);
1637     return err;
1638 }
1639 
mbim_ms_version_query(void)1640 static int mbim_ms_version_query(void) {
1641     MBIM_MESSAGE_HEADER *pRequest = NULL;
1642     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1643     int err;
1644 
1645     struct _bc_ext_version {
1646             UINT8 ver_minor;
1647             UINT8 ver_major;
1648             UINT8 ext_ver_minor;
1649             UINT8 ext_ver_major;
1650     } __attribute__ ((packed)) bc_ext_version;
1651 
1652     bc_ext_version.ver_major = 1;
1653     bc_ext_version.ver_minor = 0;
1654     bc_ext_version.ext_ver_major = 2;
1655     bc_ext_version.ext_ver_minor = 0;
1656 
1657     pRequest = compose_basic_connect_ext_command(MBIM_CID_MS_VERSION, MBIM_CID_CMD_TYPE_QUERY, &bc_ext_version, sizeof(bc_ext_version));
1658     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1659     mbim_check_err(err, pRequest, pCmdDone);
1660 
1661     if (le32toh(pCmdDone->InformationBufferLength)) {
1662         struct _bc_ext_version *pInfo = (struct _bc_ext_version *)pCmdDone->InformationBuffer;
1663         //mbim_debug("%s ext_rel_ver major=%d, minor=%d", __func__, pInfo->ext_ver_major, pInfo->ext_ver_minor);
1664         mbim_ms_version = pInfo->ext_ver_major;
1665     }
1666 
1667     mbim_free(pRequest); mbim_free(pCmdDone);
1668     return err;
1669 }
1670 
mbim_device_services_query(void)1671 static int mbim_device_services_query(void) {
1672     MBIM_MESSAGE_HEADER *pRequest = NULL;
1673     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1674     int err;
1675     int mbim_v2_support = 0;
1676 
1677     mbim_debug("%s()", __func__);
1678     pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_SERVICES, MBIM_CID_CMD_TYPE_QUERY, NULL, 0);
1679     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1680     mbim_check_err(err, pRequest, pCmdDone);
1681 
1682     if (pCmdDone->InformationBufferLength) {
1683          MBIM_DEVICE_SERVICES_INFO_T *pInfo = (MBIM_DEVICE_SERVICES_INFO_T *)pCmdDone->InformationBuffer;
1684          UINT32 i;
1685 
1686         for (i = 0; i < le32toh(pInfo->DeviceServicesCount) ; i++) {
1687             //UINT32 size = pInfo->DeviceServicesRefList[i].size;
1688             UINT32 offset = le32toh(pInfo->DeviceServicesRefList[i].offset);
1689             MBIM_DEVICE_SERVICE_ELEMENT_T *pSrvEle = (MBIM_DEVICE_SERVICE_ELEMENT_T *)((void *)pInfo + offset);
1690 
1691             if (!strcasecmp(UUID_BASIC_CONNECT_EXT, uuid2str(&pSrvEle->DeviceServiceId))) {
1692                 UINT32 cid = 0;
1693 
1694                 for (cid = 0; cid < le32toh(pSrvEle->CidCount); cid++) {
1695                   if (MBIM_CID_MS_VERSION == le32toh(pSrvEle->CidList[cid])) {
1696                         mbim_v2_support = 1;
1697                     }
1698                 }
1699             }
1700         }
1701     }
1702     mbim_free(pRequest); mbim_free(pCmdDone);
1703 
1704     if (mbim_v2_support) {
1705         mbim_ms_version_query();
1706     }
1707 
1708     return err;
1709 }
1710 
mbim_device_caps_query(PROFILE_T * profile)1711 static int mbim_device_caps_query(PROFILE_T *profile) {
1712     MBIM_MESSAGE_HEADER *pRequest = NULL;
1713     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1714     int err;
1715 
1716     mbim_debug("%s()", __func__);
1717     pRequest = compose_basic_connect_command(MBIM_CID_DEVICE_CAPS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0);
1718     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1719     mbim_check_err(err, pRequest, pCmdDone);
1720 
1721     if (le32toh(pCmdDone->InformationBufferLength)) {
1722          MBIM_DEVICE_CAPS_INFO_T *pInfo = (MBIM_DEVICE_CAPS_INFO_T *)pCmdDone->InformationBuffer;
1723          char tmp[32];
1724 
1725          if (le32toh(pInfo->DeviceIdOffset) && le32toh(pInfo->DeviceIdSize)) {
1726             wchar2char((const char *)pInfo + le32toh(pInfo->DeviceIdOffset), le32toh(pInfo->DeviceIdSize), tmp, sizeof(tmp));
1727             mbim_debug("DeviceId:     %s", tmp);
1728          }
1729          if (le32toh(pInfo->FirmwareInfoOffset) && le32toh(pInfo->FirmwareInfoSize)) {
1730             wchar2char((const char *)pInfo + le32toh(pInfo->FirmwareInfoOffset), le32toh(pInfo->FirmwareInfoSize), tmp, sizeof(tmp));
1731             strncpy(profile->BaseBandVersion, tmp, sizeof(profile->BaseBandVersion));
1732             mbim_debug("FirmwareInfo: %s", tmp);
1733          }
1734          if (le32toh(pInfo->HardwareInfoOffset) && le32toh(pInfo->HardwareInfoSize)) {
1735             wchar2char((const char *)pInfo + le32toh(pInfo->HardwareInfoOffset), le32toh(pInfo->HardwareInfoSize), tmp, sizeof(tmp));
1736             mbim_debug("HardwareInfo: %s", tmp);
1737          }
1738     }
1739     mbim_free(pRequest); mbim_free(pCmdDone);
1740     return err;
1741 }
1742 
1743 #if 0
1744 static int mbim_radio_state_query(void) {
1745     MBIM_MESSAGE_HEADER *pRequest = NULL;
1746     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1747     int err;
1748 
1749     mbim_debug("%s()", __func__);
1750     pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0);
1751     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1752     mbim_check_err(err, pRequest, pCmdDone);
1753 
1754     if (pCmdDone->InformationBufferLength) {
1755          MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer;
1756         mbim_debug("HwRadioState: %d, SwRadioState: %d", pInfo->HwRadioState, pInfo->SwRadioState);
1757     }
1758     mbim_free(pRequest); mbim_free(pCmdDone);
1759     return err;
1760 }
1761 #endif
1762 
mbim_set_radio_state(MBIM_RADIO_SWITCH_STATE_E RadioState)1763 static int mbim_set_radio_state(MBIM_RADIO_SWITCH_STATE_E RadioState) {
1764     MBIM_MESSAGE_HEADER *pRequest = NULL;
1765     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1766     UINT32 value = htole32(RadioState);
1767     int err;
1768 
1769     mbim_debug("%s( %d )", __func__, RadioState);
1770     pRequest = compose_basic_connect_command(MBIM_CID_RADIO_STATE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value));
1771     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1772     mbim_check_err(err, pRequest, pCmdDone);
1773 
1774     if (le32toh(pCmdDone->InformationBufferLength)) {
1775          MBIM_RADIO_STATE_INFO_T *pInfo = (MBIM_RADIO_STATE_INFO_T *)pCmdDone->InformationBuffer;
1776         mbim_debug("HwRadioState: %d, SwRadioState: %d", le32toh(pInfo->HwRadioState), le32toh(pInfo->SwRadioState));
1777     }
1778     mbim_free(pRequest); mbim_free(pCmdDone);
1779     return err;
1780 }
1781 
mbim_subscriber_status_query(void)1782 static int mbim_subscriber_status_query(void) {
1783     MBIM_MESSAGE_HEADER *pRequest = NULL;
1784     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1785     int err;
1786 
1787     mbim_debug("%s()", __func__);
1788     pRequest = compose_basic_connect_command(MBIM_CID_SUBSCRIBER_READY_STATUS, MBIM_CID_CMD_TYPE_QUERY, NULL, 0);
1789     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1790     mbim_check_err(err, pRequest, pCmdDone);
1791 
1792     if (le32toh(pCmdDone->InformationBufferLength)) {
1793          MBIM_SUBSCRIBER_READY_STATUS_T *pInfo = (MBIM_SUBSCRIBER_READY_STATUS_T *)pCmdDone->InformationBuffer;
1794          char tmp[32];
1795 
1796         wchar2char((const char *)pInfo + le32toh(pInfo->SubscriberIdOffset), le32toh(pInfo->SubscriberIdSize), tmp, sizeof(tmp));
1797         mbim_debug("SubscriberId: %s", tmp);
1798         wchar2char((const char *)pInfo + le32toh(pInfo->SimIccIdOffset), le32toh(pInfo->SimIccIdSize), tmp, sizeof(tmp));
1799         mbim_debug("SimIccId:     %s", tmp);
1800         ReadyState = le32toh(pInfo->ReadyState);
1801         mbim_update_state();
1802     }
1803     mbim_free(pRequest); mbim_free(pCmdDone);
1804     return err;
1805 }
1806 
mbim_register_state_query(void)1807 static int mbim_register_state_query(void) {
1808     MBIM_MESSAGE_HEADER *pRequest = NULL;
1809     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1810     int err;
1811 
1812     mbim_debug("%s()", __func__);
1813     pRequest = compose_basic_connect_command(MBIM_CID_REGISTER_STATE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0);
1814     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1815     mbim_check_err(err, pRequest, pCmdDone);
1816 
1817     if (le32toh(pCmdDone->InformationBufferLength)) {
1818         MBIM_REGISTRATION_STATE_INFO_T *pInfo = (MBIM_REGISTRATION_STATE_INFO_T *)pCmdDone->InformationBuffer;;
1819         RegisterState = le32toh(pInfo->RegisterState);
1820         mbim_update_state();
1821     }
1822     mbim_free(pRequest); mbim_free(pCmdDone);
1823     return err;
1824 }
1825 
mbim_packet_service_query(void)1826 static int mbim_packet_service_query(void) {
1827     MBIM_MESSAGE_HEADER *pRequest = NULL;
1828     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1829     int err;
1830 
1831     mbim_debug("%s()", __func__);
1832     pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_QUERY, NULL, 0);
1833     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1834     mbim_check_err(err, pRequest, pCmdDone);
1835 
1836     if (le32toh(pCmdDone->InformationBufferLength)) {
1837         MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer;
1838         PacketServiceState = le32toh(pInfo->PacketServiceState);
1839         mbim_update_state();
1840 
1841         if (le32toh(pCmdDone->InformationBufferLength) == sizeof(MBIM_PACKET_SERVICE_INFO_V2_T)) {
1842             MBIM_PACKET_SERVICE_INFO_V2_T *pInfo = (MBIM_PACKET_SERVICE_INFO_V2_T *)pCmdDone->InformationBuffer;
1843             mbim_debug("CurrentDataClass = %s", MBIMDataClassStr(le32toh(pInfo->CurrentDataClass)));
1844         }
1845     }
1846     mbim_free(pRequest); mbim_free(pCmdDone);
1847     return err;
1848 }
1849 
mbim_packet_service_set(MBIM_PACKET_SERVICE_ACTION_E action)1850 static int mbim_packet_service_set(MBIM_PACKET_SERVICE_ACTION_E action) {
1851     MBIM_MESSAGE_HEADER *pRequest = NULL;
1852     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1853     UINT32 value = htole32(action);
1854     int err;
1855 
1856     mbim_debug("%s()", __func__);
1857     pRequest = compose_basic_connect_command(MBIM_CID_PACKET_SERVICE, MBIM_CID_CMD_TYPE_SET, &value, sizeof(value));
1858     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1859     mbim_check_err(err, pRequest, pCmdDone);
1860 
1861     if (le32toh(pCmdDone->InformationBufferLength)) {
1862         MBIM_PACKET_SERVICE_INFO_T *pInfo = (MBIM_PACKET_SERVICE_INFO_T *)pCmdDone->InformationBuffer;
1863         PacketServiceState = le32toh(pInfo->PacketServiceState);
1864         mbim_update_state();
1865     }
1866     mbim_free(pRequest); mbim_free(pCmdDone);
1867     return err;
1868 }
1869 
1870 #define _align_32(len) {len += (len % 4) ? (4 - (len % 4)) : 0;}
mbim_populate_connect_data(MBIM_SET_CONNECT_T ** connect_req_ptr)1871 static int mbim_populate_connect_data(MBIM_SET_CONNECT_T **connect_req_ptr) {
1872     int offset;
1873     int buflen = 0;
1874 
1875     if (mbim_apn && strlen(mbim_apn) > 0) buflen += 2*strlen(mbim_apn) ;
1876     _align_32(buflen);
1877     if (mbim_user && strlen(mbim_user) > 0) buflen += 2*strlen(mbim_user);
1878     _align_32(buflen);
1879     if (mbim_passwd && strlen(mbim_passwd) > 0) buflen += 2*strlen(mbim_passwd);
1880     _align_32(buflen);
1881 
1882     *connect_req_ptr = (MBIM_SET_CONNECT_T*)malloc(sizeof(MBIM_SET_CONNECT_T) + buflen);
1883     if (! *connect_req_ptr) {
1884         mbim_debug("not enough memory\n");
1885         return -1;
1886     }
1887     memset(*connect_req_ptr, 0, sizeof(MBIM_SET_CONNECT_T) + buflen);
1888 
1889     offset = 0;
1890     if (mbim_apn && strlen(mbim_apn) > 0) {
1891         (*connect_req_ptr)->AccessStringSize = htole32(2*strlen(mbim_apn));
1892         (*connect_req_ptr)->AccessStringOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T));
1893         offset = char2wchar(mbim_apn, strlen(mbim_apn), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset);
1894         _align_32(offset);
1895     }
1896 
1897     if (mbim_user && strlen(mbim_user) > 0) {
1898         (*connect_req_ptr)->UserNameSize = htole32(2*strlen(mbim_user));
1899         (*connect_req_ptr)->UserNameOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T));
1900         offset = char2wchar(mbim_user, strlen(mbim_user), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset);
1901         _align_32(offset);
1902     }
1903 
1904     if (mbim_passwd && strlen(mbim_passwd) > 0) {
1905         (*connect_req_ptr)->PasswordSize = htole32(2*strlen(mbim_passwd));
1906         (*connect_req_ptr)->PasswordOffset = htole32(offset + sizeof(MBIM_SET_CONNECT_T));
1907         offset = char2wchar(mbim_passwd, strlen(mbim_passwd), &(*connect_req_ptr)->DataBuffer[offset], buflen - offset);
1908     }
1909 
1910     return buflen;
1911 }
1912 
mbim_set_connect(int onoff,int sessionID)1913 static int mbim_set_connect(int onoff, int sessionID) {
1914     MBIM_MESSAGE_HEADER *pRequest = NULL;
1915     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1916     MBIM_SET_CONNECT_T *set_connect = NULL;
1917     int err;
1918 
1919     mbim_debug("%s(onoff=%d, sessionID=%d)", __func__, onoff, sessionID);
1920     /* alloc memory then populate APN USERNAME PASSWORD */
1921     int buflen = mbim_populate_connect_data(&set_connect);
1922     if (buflen < 0) {
1923         return ENOMEM;
1924      }
1925 
1926     set_connect->SessionId = htole32(sessionID);
1927     if (onoff == 0)
1928         set_connect->ActivationCommand = htole32(MBIMActivationCommandDeactivate);
1929     else
1930         set_connect->ActivationCommand = htole32(MBIMActivationCommandActivate);
1931 
1932     set_connect->Compression = htole32(MBIMCompressionNone);
1933     set_connect->AuthProtocol = htole32(mbim_auth);
1934     set_connect->IPType = htole32(mbim_iptype);
1935     memcpy(set_connect->ContextType.uuid, str2uuid(UUID_MBIMContextTypeInternet), 16);
1936 
1937     pRequest = compose_basic_connect_command(MBIM_CID_CONNECT, MBIM_CID_CMD_TYPE_SET, set_connect, sizeof(MBIM_SET_CONNECT_T) + buflen);
1938     mbim_free(set_connect);
1939     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout*10);
1940     mbim_check_err(err, pRequest, pCmdDone);
1941 
1942     if (le32toh(pCmdDone->InformationBufferLength)) {
1943         MBIM_CONNECT_T *pInfo = (MBIM_CONNECT_T *)pCmdDone->InformationBuffer;
1944         ActivationState = le32toh(pInfo->ActivationState);
1945         mbim_update_state();
1946     }
1947 
1948     mbim_free(pRequest); mbim_free(pCmdDone);
1949     return err;
1950 }
1951 
mbim_ip_config(PROFILE_T * profile,int sessionID)1952 static int mbim_ip_config(PROFILE_T *profile, int sessionID) {
1953     MBIM_MESSAGE_HEADER *pRequest = NULL;
1954     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
1955     MBIM_IP_CONFIGURATION_INFO_T ip_info;
1956     int err;
1957 
1958     if (profile->ipv4.Address == 0 || mbim_verbose)
1959         mbim_debug("%s(sessionID=%d)", __func__, sessionID);
1960     ip_info.SessionId = htole32(sessionID);
1961     pRequest = compose_basic_connect_command(MBIM_CID_IP_CONFIGURATION, MBIM_CID_CMD_TYPE_QUERY, &ip_info, sizeof(ip_info));
1962     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
1963     mbim_check_err(err, pRequest, pCmdDone);
1964 
1965     if (le32toh(pCmdDone->InformationBufferLength)) {
1966         UINT8 prefix, *ipv4=NULL, *ipv6=NULL, *gw=NULL, *dns1=NULL, *dns2=NULL;
1967         UINT32 mtu = 1500;
1968         MBIM_IP_CONFIGURATION_INFO_T *pInfo = (MBIM_IP_CONFIGURATION_INFO_T *)pCmdDone->InformationBuffer;
1969 
1970         /* IPv4 network configration */
1971         if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x1) {
1972             MBIM_IPV4_ELEMENT_T *pAddress = (MBIM_IPV4_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1973             prefix = le32toh(pAddress->OnLinkPrefixLength);
1974             ipv4 = pAddress->IPv4Address;
1975 
1976             if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x2)
1977                 gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1978 
1979             if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x4) {
1980                 dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv4DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
1981                 if (le32toh(pInfo->IPv4DnsServerCount) == 2)
1982                     dns2 = dns1 + 4;
1983             }
1984 
1985             if (le32toh(pInfo->IPv4ConfigurationAvailable)&0x8)
1986                 mtu =  le32toh(pInfo->IPv4Mtu);
1987 
1988             if (profile->ipv4.Address != mbim2qmi_ipv4addr(*(uint32_t *)ipv4) || mbim_verbose) {
1989                 mbim_dump_ipconfig(pInfo, "<");
1990                 profile->ipv4.Address = mbim2qmi_ipv4addr(*(uint32_t *)ipv4);
1991             }
1992             profile->ipv4.Gateway = mbim2qmi_ipv4addr(*(uint32_t *)gw);
1993             profile->ipv4.SubnetMask = mbim2qmi_ipv4addr(0xFFFFFFFF>>(32-prefix)<<(32-prefix));
1994             profile->ipv4.DnsPrimary = mbim2qmi_ipv4addr(*(uint32_t *)dns1);
1995             profile->ipv4.DnsSecondary = mbim2qmi_ipv4addr(*(uint32_t *)dns2);
1996             profile->ipv4.Mtu = mbim2qmi_ipv4addr(mtu);
1997         }
1998 
1999         /* IPv6 network configration */
2000         if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x1) {
2001             MBIM_IPV6_ELEMENT_T *pAddress = (MBIM_IPV6_ELEMENT_T *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6AddressOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
2002             prefix = le32toh(pAddress->OnLinkPrefixLength);
2003             ipv6 = pAddress->IPv6Address;
2004 
2005             if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x2)
2006                 gw = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6GatewayOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
2007 
2008             if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x4) {
2009                 dns1 = (UINT8 *)(&pInfo->DataBuffer[le32toh(pInfo->IPv6DnsServerOffset)-sizeof(MBIM_IP_CONFIGURATION_INFO_T)]);
2010                 if (le32toh(pInfo->IPv6DnsServerCount) == 2)
2011                     dns2 = dns1 + 16;
2012             }
2013 
2014             if (le32toh(pInfo->IPv6ConfigurationAvailable)&0x8)
2015                 mtu =  le32toh(pInfo->IPv6Mtu);
2016 
2017             mbim2qmi_ipv6addr(ipv6, profile->ipv6.Address);
2018             mbim2qmi_ipv6addr(gw, profile->ipv6.Gateway);
2019             mbim2qmi_ipv6addr(dns1, profile->ipv6.DnsPrimary);
2020             mbim2qmi_ipv6addr(dns2, profile->ipv6.DnsSecondary);
2021             profile->ipv6.PrefixLengthIPAddr = prefix;
2022             profile->ipv6.PrefixLengthGateway = prefix;
2023             profile->ipv6.Mtu = mbim2qmi_ipv4addr(mtu);
2024         }
2025     }
2026     return err;
2027 }
2028 
mbim_proxy_configure(const char * dev)2029 int mbim_proxy_configure(const char *dev) {
2030     MBIM_MESSAGE_HEADER *pRequest = NULL;
2031     MBIM_COMMAND_DONE_T *pCmdDone = NULL;
2032     MBIM_LIBQMI_PROXY_CONFIG_T *cfg;
2033     int err;
2034 
2035     pRequest = compose_basic_connect_command(
2036                                                     MBIM_CID_PROXY_CONTROL_CONFIGURATION,
2037                                                     MBIM_CID_CMD_TYPE_SET,
2038                                                     NULL,
2039                                                     sizeof(*cfg) + strlen(dev)*2);
2040     if (pRequest) {
2041         memcpy(((MBIM_COMMAND_MSG_T *)pRequest)->DeviceServiceId.uuid, str2uuid(UUID_LIBMBIM_PROXY), 16);
2042         cfg = (MBIM_LIBQMI_PROXY_CONFIG_T *)((MBIM_COMMAND_MSG_T *)pRequest)->InformationBuffer;
2043 
2044         cfg->DevicePathOffset = sizeof(*cfg);
2045         cfg->DevicePathSize = char2wchar(dev, strlen(dev), cfg->DataBuffer, strlen(dev)*2);
2046         cfg->Timeout = 15;
2047     }
2048 
2049     err = mbim_send_command(pRequest, &pCmdDone, mbim_default_timeout);
2050     mbim_check_err(err, pRequest, pCmdDone);
2051 
2052     mbim_free(pRequest); mbim_free(pCmdDone);
2053     return err;
2054 }
2055 
mbim_update_state(void)2056 static int mbim_update_state(void) {
2057     int chages = 0;
2058 
2059     if (oldReadyState != ReadyState) {
2060         mbim_debug("SubscriberReadyState %s -> %s ", MBIMSubscriberReadyStateStr(oldReadyState), MBIMSubscriberReadyStateStr(ReadyState));
2061         oldReadyState = ReadyState; chages++;
2062     }
2063     if (oldRegisterState != RegisterState) {
2064         mbim_debug("RegisterState %s -> %s ", MBIMRegisterStateStr(oldRegisterState), MBIMRegisterStateStr(RegisterState));
2065         oldRegisterState = RegisterState; chages++;
2066     }
2067     if (oldPacketServiceState != PacketServiceState) {
2068         mbim_debug("PacketServiceState %s -> %s ", MBIMPacketServiceStateStr(oldPacketServiceState), MBIMPacketServiceStateStr(PacketServiceState));
2069         oldPacketServiceState = PacketServiceState; chages++;
2070     }
2071     if (oldActivationState != ActivationState) {
2072         mbim_debug("ActivationState %s -> %s ", MBIMActivationStateStr(oldActivationState), MBIMActivationStateStr(ActivationState));
2073         oldActivationState = ActivationState; chages++;
2074     }
2075 
2076     return chages;
2077 }
2078 
mbim_init(PROFILE_T * profile)2079 static int mbim_init(PROFILE_T *profile) {
2080     int retval;
2081     int t = 0;
2082 
2083     if (profile->proxy[0] && !strcmp(profile->proxy, LIBMBIM_PROXY)) {
2084         retval = mbim_proxy_configure(profile->qmichannel);
2085         if (retval) goto exit;
2086     }
2087 
2088     while (t++ < 10) {
2089         retval = mbim_open_device(4096);
2090         if (retval != ETIMEDOUT)
2091             break;
2092     }
2093     if (retval) goto exit;
2094     retval = mbim_device_caps_query(profile);
2095     if (retval) goto exit;
2096     mbim_update_state();
2097     retval = mbim_device_services_query();
2098     if (retval) goto exit;
2099     mbim_update_state();
2100     retval = mbim_set_radio_state(MBIMRadioOn);
2101     if (retval) goto exit;
2102     mbim_update_state();
2103 
2104     return 0;
2105 
2106 exit:
2107     return retval;
2108 }
2109 
mbim_deinit(void)2110 static int mbim_deinit(void) {
2111     mbim_close_device();
2112 
2113     return 0;
2114 }
2115 
2116 const struct qmi_device_ops mbim_dev_ops = {
2117     .init = mbim_init,
2118     .deinit = mbim_deinit,
2119     .read = mbim_read_thread,
2120 };
2121 
requestBaseBandVersion(PROFILE_T * profile)2122 static int requestBaseBandVersion(PROFILE_T *profile) {
2123     (void)profile;
2124     return 0;
2125 }
2126 
requestGetSIMStatus(SIM_Status * pSIMStatus)2127 static int requestGetSIMStatus(SIM_Status *pSIMStatus)
2128 {
2129     int retval;
2130 
2131     *pSIMStatus = SIM_ABSENT;
2132     retval = mbim_subscriber_status_query();
2133     if (retval)
2134         goto exit;
2135     mbim_update_state();
2136 
2137      switch(ReadyState) {
2138         case MBIMSubscriberReadyStateNotInitialized: *pSIMStatus = SIM_NOT_READY; break;
2139         case MBIMSubscriberReadyStateInitialized: *pSIMStatus = SIM_READY; break;
2140         case MBIMSubscriberReadyStateSimNotInserted: *pSIMStatus = SIM_ABSENT; break;
2141         case MBIMSubscriberReadyStateBadSim: *pSIMStatus = SIM_BAD; break;
2142         case MBIMSubscriberReadyStateFailure: *pSIMStatus = SIM_ABSENT; break;
2143         case MBIMSubscriberReadyStateNotActivated: *pSIMStatus = SIM_ABSENT; break;
2144         case MBIMSubscriberReadyStateDeviceLocked: *pSIMStatus = SIM_PIN; break;
2145         default: *pSIMStatus = SIM_ABSENT; break;
2146     }
2147 
2148 exit:
2149     return retval;
2150 }
2151 
requestRegistrationState(UCHAR * pPSAttachedState)2152 static int requestRegistrationState(UCHAR *pPSAttachedState) {
2153     int retval;
2154 
2155     *pPSAttachedState = 0;
2156     retval = mbim_register_state_query();
2157     if (retval)
2158         goto exit;
2159     mbim_update_state();
2160 
2161     switch (RegisterState) {
2162         case MBIMRegisterStateUnknown: *pPSAttachedState = 0; break;
2163         case MBIMRegisterStateDeregistered: *pPSAttachedState = 0; break;
2164         case MBIMRegisterStateSearching: *pPSAttachedState = 0; break;
2165         case MBIMRegisterStateHome: *pPSAttachedState = 1; break;
2166         case MBIMRegisterStateRoaming: *pPSAttachedState = 1; break;
2167         case MBIMRegisterStatePartner: *pPSAttachedState = 0; break;
2168         case MBIMRegisterStateDenied: *pPSAttachedState = 0; break;
2169         default: *pPSAttachedState = 0; break;
2170     }
2171 
2172     if (*pPSAttachedState == 0)
2173         goto exit;
2174 
2175     retval =  mbim_packet_service_query();
2176     if (retval)
2177         goto exit;
2178 
2179     switch (PacketServiceState) {
2180         case MBIMPacketServiceStateUnknown: *pPSAttachedState = 0; break;
2181         case MBIMPacketServiceStateAttaching: *pPSAttachedState = 0; break;
2182         case MBIMPacketServiceStateAttached: *pPSAttachedState = 1; break;
2183         case MBIMPacketServiceStateDetaching: *pPSAttachedState = 0; break;
2184         case MBIMPacketServiceStateDetached: *pPSAttachedState = 0; break;
2185         default: *pPSAttachedState = 0; break;
2186     }
2187 
2188     if (*pPSAttachedState == 0)
2189         mbim_packet_service_set(MBIMPacketServiceActionAttach);
2190 
2191 exit:
2192     return retval;
2193 }
2194 
requestSetupDataCall(PROFILE_T * profile,int curIpFamily)2195 static int requestSetupDataCall(PROFILE_T *profile, int curIpFamily) {
2196     int retval;
2197 
2198     (void)curIpFamily;
2199 
2200     if (profile->apn)
2201         mbim_apn = profile->apn;
2202     if (profile->user)
2203         mbim_user = profile->user;
2204     if (profile->password)
2205         mbim_passwd = profile->password;
2206     if (profile->auth)
2207         mbim_auth = profile->auth;
2208     if (profile->enable_ipv4)
2209         mbim_iptype = MBIMContextIPTypeIPv4;
2210     if (profile->enable_ipv6)
2211         mbim_iptype = MBIMContextIPTypeIPv6;
2212     if (profile->enable_ipv4 && profile->enable_ipv6)
2213         mbim_iptype = MBIMContextIPTypeIPv4AndIPv6;
2214 
2215     retval = mbim_set_connect(1, mbim_sessionID);
2216     if (retval)
2217         goto exit;
2218 
2219 exit:
2220     return retval;
2221 }
2222 
requestQueryDataCall(UCHAR * pConnectionStatus,int curIpFamily)2223 static int requestQueryDataCall(UCHAR  *pConnectionStatus, int curIpFamily) {
2224     int retval;
2225 
2226     (void)curIpFamily;
2227 
2228     *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED;
2229 
2230     retval = mbim_query_connect(mbim_sessionID);
2231     if (retval)
2232         goto exit;
2233 
2234     switch(ActivationState) {
2235         case MBIMActivationStateUnknown: *pConnectionStatus = QWDS_PKT_DATA_UNKNOW; break;
2236         case MBIMActivationStateActivated: *pConnectionStatus = QWDS_PKT_DATA_CONNECTED; break;
2237         case MBIMActivationStateActivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break;
2238         case MBIMActivationStateDeactivated: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break;
2239         case MBIMActivationStateDeactivating: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break;
2240         default: *pConnectionStatus = QWDS_PKT_DATA_DISCONNECTED; break;
2241     }
2242 
2243 exit:
2244     return retval;
2245 }
2246 
requestDeactivateDefaultPDP(PROFILE_T * profile,int curIpFamily)2247 static int requestDeactivateDefaultPDP(PROFILE_T *profile, int curIpFamily) {
2248     int retval;
2249 
2250     (void)profile;
2251     (void)curIpFamily;
2252 
2253     retval = mbim_set_connect(0, mbim_sessionID);
2254     if (retval)
2255         goto exit;
2256 
2257 exit:
2258     return retval;
2259 }
2260 
requestGetIPAddress(PROFILE_T * profile,int curIpFamily)2261 static int requestGetIPAddress(PROFILE_T *profile, int curIpFamily) {
2262     int retval;
2263 
2264     (void)curIpFamily;
2265     retval = mbim_ip_config(profile, mbim_sessionID);
2266     if (retval)
2267         goto exit;
2268 
2269 exit:
2270     return retval;
2271 }
2272 
2273 const struct request_ops mbim_request_ops = {
2274     .requestBaseBandVersion = requestBaseBandVersion,
2275     .requestGetSIMStatus = requestGetSIMStatus,
2276     .requestRegistrationState = requestRegistrationState,
2277     .requestSetupDataCall = requestSetupDataCall,
2278     .requestQueryDataCall = requestQueryDataCall,
2279     .requestDeactivateDefaultPDP = requestDeactivateDefaultPDP,
2280     .requestGetIPAddress = requestGetIPAddress,
2281 };
2282 
2283