sms: Use __ofono_atom_find
[platform/upstream/ofono.git] / src / common.c
1 /*
2  *
3  *  oFono - Open Source Telephony
4  *
5  *  Copyright (C) 2008-2011  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #define _GNU_SOURCE
27 #include <string.h>
28 #include <errno.h>
29
30 #include <glib.h>
31
32 #include <ofono/types.h>
33 #include "common.h"
34 #include "util.h"
35
36 struct error_entry {
37         int error;
38         const char *str;
39 };
40
41 /*
42  * 0-127 from 24.011 Annex E2
43  * 127-255 23.040 Section 9.2.3.22
44  * Rest are from 27.005 Section 3.2.5
45  */
46 struct error_entry cms_errors[] = {
47         { 1,    "Unassigned number" },
48         { 8,    "Operator determined barring" },
49         { 10,   "Call barred" },
50         { 21,   "Short message transfer rejected" },
51         { 27,   "Destination out of service" },
52         { 28,   "Unindentified subscriber" },
53         { 29,   "Facility rejected" },
54         { 30,   "Unknown subscriber" },
55         { 38,   "Network out of order" },
56         { 41,   "Temporary failure" },
57         { 42,   "Congestion" },
58         { 47,   "Recources unavailable" },
59         { 50,   "Requested facility not subscribed" },
60         { 69,   "Requested facility not implemented" },
61         { 81,   "Invalid short message transfer reference value" },
62         { 95,   "Invalid message, unspecified" },
63         { 96,   "Invalid mandatory information" },
64         { 97,   "Message type non existent or not implemented" },
65         { 98,   "Message not compatible with short message protocol state" },
66         { 99,   "Information element non-existent or not implemented" },
67         { 111,  "Protocol error, unspecified" },
68         { 127,  "Internetworking error, unspecified" },
69         { 128,  "Telematic internetworking not supported" },
70         { 129,  "Short message type 0 not supported" },
71         { 130,  "Cannot replace short message" },
72         { 143,  "Unspecified TP-PID error" },
73         { 144,  "Data code scheme not supported" },
74         { 145,  "Message class not supported" },
75         { 159,  "Unspecified TP-DCS error" },
76         { 160,  "Command cannot be actioned" },
77         { 161,  "Command unsupported" },
78         { 175,  "Unspecified TP-Command error" },
79         { 176,  "TPDU not supported" },
80         { 192,  "SC busy" },
81         { 193,  "No SC subscription" },
82         { 194,  "SC System failure" },
83         { 195,  "Invalid SME address" },
84         { 196,  "Destination SME barred" },
85         { 197,  "SM Rejected-Duplicate SM" },
86         { 198,  "TP-VPF not supported" },
87         { 199,  "TP-VP not supported" },
88         { 208,  "(U)SIM SMS Storage full" },
89         { 209,  "No SMS Storage capability in SIM" },
90         { 210,  "Error in MS" },
91         { 211,  "Memory capacity exceeded" },
92         { 212,  "Sim application toolkit busy" },
93         { 213,  "SIM data download error" },
94         { 255,  "Unspecified error cause" },
95         { 300,  "ME Failure" },
96         { 301,  "SMS service of ME reserved" },
97         { 302,  "Operation not allowed" },
98         { 303,  "Operation not supported" },
99         { 304,  "Invalid PDU mode parameter" },
100         { 305,  "Invalid Text mode parameter" },
101         { 310,  "(U)SIM not inserted" },
102         { 311,  "(U)SIM PIN required" },
103         { 312,  "PH-(U)SIM PIN required" },
104         { 313,  "(U)SIM failure" },
105         { 314,  "(U)SIM busy" },
106         { 315,  "(U)SIM wrong" },
107         { 316,  "(U)SIM PUK required" },
108         { 317,  "(U)SIM PIN2 required" },
109         { 318,  "(U)SIM PUK2 required" },
110         { 320,  "Memory failure" },
111         { 321,  "Invalid memory index" },
112         { 322,  "Memory full" },
113         { 330,  "SMSC address unknown" },
114         { 331,  "No network service" },
115         { 332,  "Network timeout" },
116         { 340,  "No +CNMA expected" },
117         { 500,  "Unknown error" },
118 };
119
120 /* 27.007, Section 9 */
121 struct error_entry cme_errors[] = {
122         { 0,    "Phone failure" },
123         { 1,    "No connection to phone" },
124         { 2,    "Phone adapter link reserved" },
125         { 3,    "Operation not allowed" },
126         { 4,    "Operation not supported" },
127         { 5,    "PH_SIM PIN required" },
128         { 6,    "PH_FSIM PIN required" },
129         { 7,    "PH_FSIM PUK required" },
130         { 10,   "SIM not inserted" },
131         { 11,   "SIM PIN required" },
132         { 12,   "SIM PUK required" },
133         { 13,   "SIM failure" },
134         { 14,   "SIM busy" },
135         { 15,   "SIM wrong" },
136         { 16,   "Incorrect password" },
137         { 17,   "SIM PIN2 required" },
138         { 18,   "SIM PUK2 required" },
139         { 20,   "Memory full" },
140         { 21,   "Invalid index" },
141         { 22,   "Not found" },
142         { 23,   "Memory failure" },
143         { 24,   "Text string too long" },
144         { 25,   "Invalid characters in text string" },
145         { 26,   "Dial string too long" },
146         { 27,   "Invalid characters in dial string" },
147         { 30,   "No network service" },
148         { 31,   "Network timeout" },
149         { 32,   "Network not allowed, emergency calls only" },
150         { 40,   "Network personalization PIN required" },
151         { 41,   "Network personalization PUK required" },
152         { 42,   "Network subset personalization PIN required" },
153         { 43,   "Network subset personalization PUK required" },
154         { 44,   "Service provider personalization PIN required" },
155         { 45,   "Service provider personalization PUK required" },
156         { 46,   "Corporate personalization PIN required" },
157         { 47,   "Corporate personalization PUK required" },
158         { 48,   "PH-SIM PUK required" },
159         { 100,  "Unknown error" },
160         { 103,  "Illegal MS" },
161         { 106,  "Illegal ME" },
162         { 107,  "GPRS services not allowed" },
163         { 111,  "PLMN not allowed" },
164         { 112,  "Location area not allowed" },
165         { 113,  "Roaming not allowed in this location area" },
166         { 126,  "Operation temporary not allowed" },
167         { 132,  "Service operation not supported" },
168         { 133,  "Requested service option not subscribed" },
169         { 134,  "Service option temporary out of order" },
170         { 148,  "Unspecified GPRS error" },
171         { 149,  "PDP authentication failure" },
172         { 150,  "Invalid mobile class" },
173         { 256,  "Operation temporarily not allowed" },
174         { 257,  "Call barred" },
175         { 258,  "Phone is busy" },
176         { 259,  "User abort" },
177         { 260,  "Invalid dial string" },
178         { 261,  "SS not executed" },
179         { 262,  "SIM Blocked" },
180         { 263,  "Invalid block" },
181         { 772,  "SIM powered down" },
182 };
183
184 /* 24.008 Annex H */
185 struct error_entry ceer_errors[] = {
186         { 1,    "Unassigned number" },
187         { 3,    "No route to destination" },
188         { 6,    "Channel unacceptable" },
189         { 8,    "Operator determined barring" },
190         { 16,   "Normal call clearing" },
191         { 17,   "User busy" },
192         { 18,   "No user responding" },
193         { 19,   "User alerting, no answer" },
194         { 21,   "Call rejected" },
195         { 22,   "Number changed" },
196         { 25,   "Pre-emption" },
197         { 26,   "Non-selected user clearing" },
198         { 27,   "Destination out of order" },
199         { 28,   "Invalid number format (incomplete number)" },
200         { 29,   "Facility rejected" },
201         { 30,   "Response to STATUS ENQUIRY" },
202         { 31,   "Normal, unspecified" },
203         { 34,   "No circuit/channel available" },
204         { 38,   "Network out of order" },
205         { 41,   "Temporary failure" },
206         { 42,   "Switching equipment congestion" },
207         { 43,   "Access information discared" },
208         { 44,   "Requested circuit/channel not available" },
209         { 47,   "Resource unavailable (unspecified)" },
210         { 49,   "Quality of service unavailable" },
211         { 50,   "Requested facility not subscribed" },
212         { 55,   "Incoming calls barred within the CUG" },
213         { 57,   "Bearer capability not authorized" },
214         { 58,   "Bearar capability not presently available" },
215         { 63,   "Service or option not available, unspecified" },
216         { 65,   "Bearer service not implemented" },
217         { 68,   "ACM equal to or greater than ACMmax" },
218         { 69,   "Requested facility not implemented" },
219         { 70,   "Only restricted digital information bearer capability is available" },
220         { 79,   "Service or option not implemented, unspecified" },
221         { 81,   "Invalid transaction identifier value" },
222         { 87,   "User not member of CUG" },
223         { 88,   "Incompatible destination" },
224         { 91,   "Invalid transit network selection" },
225         { 95,   "Semantically incorrect message" },
226         { 96,   "Invalid mandatory information"},
227         { 97,   "Message type non-existent or not implemented" },
228         { 98,   "Message type not compatible with protocol state" },
229         { 99,   "Information element non-existent or not implemented" },
230         { 100,  "Conditional IE error" },
231         { 101,  "Message not compatible with protocol state" },
232         { 102,  "Recovery on timer expirty" },
233         { 111,  "Protocol error, unspecified" },
234         { 127,  "Interworking, unspecified" },
235 };
236
237 gboolean valid_number_format(const char *number, int length)
238 {
239         int len = strlen(number);
240         int begin = 0;
241         int i;
242
243         if (!len)
244                 return FALSE;
245
246         if (number[0] == '+')
247                 begin = 1;
248
249         if (begin == len)
250                 return FALSE;
251
252         if ((len - begin) > length)
253                 return FALSE;
254
255         for (i = begin; i < len; i++) {
256                 if (number[i] >= '0' && number[i] <= '9')
257                         continue;
258
259                 if (number[i] == '*' || number[i] == '#')
260                         continue;
261
262                 return FALSE;
263         }
264
265         return TRUE;
266 }
267
268 /*
269  * According to 3GPP TS 24.011 or 3GPP TS 31.102, some
270  * addresses (or numbers), like Service Centre address,
271  * Destination address, or EFADN (Abbreviated dialling numbers),
272  * are up 20 digits.
273  */
274 gboolean valid_phone_number_format(const char *number)
275 {
276         return valid_number_format(number, 20);
277 }
278
279 gboolean valid_long_phone_number_format(const char *number)
280 {
281         return valid_number_format(number, OFONO_MAX_PHONE_NUMBER_LENGTH);
282 }
283
284 gboolean valid_cdma_phone_number_format(const char *number)
285 {
286         int len = strlen(number);
287         int i;
288
289         if (!len)
290                 return FALSE;
291
292         if (len > OFONO_CDMA_MAX_PHONE_NUMBER_LENGTH)
293                 return FALSE;
294
295         for (i = 0; i < len; i++) {
296                 if (number[i] >= '0' && number[i] <= '9')
297                         continue;
298
299                 if (number[i] == '*' || number[i] == '#')
300                         continue;
301
302                 return FALSE;
303         }
304
305         return TRUE;
306 }
307
308 const char *telephony_error_to_str(const struct ofono_error *error)
309 {
310         struct error_entry *e;
311         int maxentries;
312         int i;
313
314         switch (error->type) {
315         case OFONO_ERROR_TYPE_CME:
316                 e = cme_errors;
317                 maxentries = sizeof(cme_errors) / sizeof(struct error_entry);
318                 break;
319         case OFONO_ERROR_TYPE_CMS:
320                 e = cms_errors;
321                 maxentries = sizeof(cms_errors) / sizeof(struct error_entry);
322                 break;
323         case OFONO_ERROR_TYPE_CEER:
324                 e = ceer_errors;
325                 maxentries = sizeof(ceer_errors) / sizeof(struct error_entry);
326                 break;
327         default:
328                 return "Unknown error type";
329         }
330
331         for (i = 0; i < maxentries; i++)
332                 if (e[i].error == error->error)
333                         return e[i].str;
334
335         return "Unknown error";
336 }
337
338 int mmi_service_code_to_bearer_class(int code)
339 {
340         int cls = 0;
341
342         /*
343          * Teleservices according to 22.004
344          * 1 - Voice
345          * 2 - SMS
346          * 3,4,5 - Unallocated
347          * 6 - Fax
348          * 7 - All Data Async
349          * 8 - All Data Sync
350          * 12 - Voice Group
351          */
352
353         switch (code) {
354         /* 22.030: 1 to 6, 12 */
355         case 10:
356                 cls = BEARER_CLASS_VOICE | BEARER_CLASS_FAX | BEARER_CLASS_SMS;
357                 break;
358         /* 22.030: 1 */
359         case 11:
360                 cls = BEARER_CLASS_VOICE;
361                 break;
362         /* 22.030: 2-6 */
363         case 12:
364                 cls = BEARER_CLASS_SMS | BEARER_CLASS_FAX;
365                 break;
366         /* 22.030: 6 */
367         case 13:
368                 cls = BEARER_CLASS_FAX;
369                 break;
370         /* 22.030: 2 */
371         case 16:
372                 cls = BEARER_CLASS_SMS;
373                 break;
374         /* TODO: Voice Group Call & Broadcast VGCS & VBS */
375         case 17:
376         case 18:
377                 break;
378         /* 22.030: 1, 3 to 6, 12 */
379         case 19:
380                 cls = BEARER_CLASS_VOICE | BEARER_CLASS_FAX;
381                 break;
382         /*
383          * 22.030: 7-11
384          * 22.004 only defines BS 7 (Data Sync) & BS 8 (Data Async)
385          * and PAD and Packet bearer services are deprecated.  Still,
386          * AT modems rely on these to differentiate between sending
387          * a 'All Sync' or 'All Data Sync' message types.  In theory
388          * both message types cover the same bearer services, but we
389          * must still send these for conformance reasons.
390          */
391         case 20:
392                 cls = BEARER_CLASS_DATA_ASYNC | BEARER_CLASS_DATA_SYNC |
393                         BEARER_CLASS_PAD | BEARER_CLASS_PACKET;
394                 break;
395         /* According to 22.030: All Async (7) */
396         case 21:
397                 cls = BEARER_CLASS_DATA_ASYNC | BEARER_CLASS_PAD;
398                 break;
399         /* According to 22.030: All Data Async (7)*/
400         case 25:
401                 cls = BEARER_CLASS_DATA_ASYNC;
402                 break;
403         /* According to 22.030: All Sync (8) */
404         case 22:
405                 cls = BEARER_CLASS_DATA_SYNC | BEARER_CLASS_PACKET;
406                 break;
407         /* According to 22.030: All Data Sync (8) */
408         case 24:
409                 cls = BEARER_CLASS_DATA_SYNC;
410                 break;
411         /* According to 22.030: Telephony & All Sync services (1, 8) */
412         case 26:
413                 cls = BEARER_CLASS_VOICE | BEARER_CLASS_DATA_SYNC |
414                         BEARER_CLASS_PACKET;
415                 break;
416         default:
417                 break;
418         }
419
420         return cls;
421 }
422
423 const char *phone_number_to_string(const struct ofono_phone_number *ph)
424 {
425         static char buffer[OFONO_MAX_PHONE_NUMBER_LENGTH + 2];
426
427         if (ph->type == 145 && (strlen(ph->number) > 0) &&
428                         ph->number[0] != '+') {
429                 buffer[0] = '+';
430                 strncpy(buffer + 1, ph->number, OFONO_MAX_PHONE_NUMBER_LENGTH);
431                 buffer[OFONO_MAX_PHONE_NUMBER_LENGTH + 1] = '\0';
432         } else {
433                 strncpy(buffer, ph->number, OFONO_MAX_PHONE_NUMBER_LENGTH + 1);
434                 buffer[OFONO_MAX_PHONE_NUMBER_LENGTH + 1] = '\0';
435         }
436
437         return buffer;
438 }
439
440 void string_to_phone_number(const char *str, struct ofono_phone_number *ph)
441 {
442         if (str[0] == '+') {
443                 strcpy(ph->number, str+1);
444                 ph->type = 145; /* International */
445         } else {
446                 strcpy(ph->number, str);
447                 ph->type = 129; /* Local */
448         }
449 }
450
451 const char *cdma_phone_number_to_string(
452                                 const struct ofono_cdma_phone_number *ph)
453 {
454         static char buffer[OFONO_CDMA_MAX_PHONE_NUMBER_LENGTH + 1];
455
456         strncpy(buffer, ph->number, OFONO_CDMA_MAX_PHONE_NUMBER_LENGTH);
457         buffer[OFONO_CDMA_MAX_PHONE_NUMBER_LENGTH] = '\0';
458
459         return buffer;
460 }
461
462 void string_to_cdma_phone_number(const char *str,
463                                         struct ofono_cdma_phone_number *ph)
464 {
465         strcpy(ph->number, str);
466 }
467
468 gboolean valid_ussd_string(const char *str, gboolean call_in_progress)
469 {
470         int len = strlen(str);
471
472         if (!len)
473                 return FALSE;
474
475         /*
476          * Return true if an MMI input string is to be sent as USSD.
477          *
478          * According to 3GPP TS 22.030, after checking the well-known
479          * supplementary service control, SIM control and manufacturer
480          * defined control codes, the terminal should check if the input
481          * should be sent as USSD according to the following rules:
482          *
483          * 1) Terminated by '#'
484          * 2) A short string of 1 or 2 digits
485          *
486          * As an exception, if a 2 digit string starts with a '1' and
487          * there are no calls in progress then this string is treated as
488          * a call setup request instead.
489          */
490
491         if (str[len-1] == '#')
492                 return TRUE;
493
494         if (!call_in_progress && len == 2 && str[0] != '1')
495                 return FALSE;
496
497         if (len <= 2)
498                 return TRUE;
499
500         return FALSE;
501 }
502
503 const char *ss_control_type_to_string(enum ss_control_type type)
504 {
505         switch (type) {
506         case SS_CONTROL_TYPE_ACTIVATION:
507                 return "activation";
508         case SS_CONTROL_TYPE_REGISTRATION:
509                 return "registration";
510         case SS_CONTROL_TYPE_QUERY:
511                 return "interrogation";
512         case SS_CONTROL_TYPE_DEACTIVATION:
513                 return "deactivation";
514         case SS_CONTROL_TYPE_ERASURE:
515                 return "erasure";
516         }
517
518         return NULL;
519 }
520
521 #define NEXT_FIELD(str, dest)                   \
522         do {                                    \
523                 dest = str;                     \
524                                                 \
525                 str = strchrnul(str, '*');      \
526                 if (*str) {                     \
527                         *str = '\0';            \
528                         str += 1;               \
529                 }                               \
530         } while (0)                             \
531
532 /*
533  * Note: The str will be modified, so in case of error you should
534  * throw it away and start over
535  */
536 gboolean parse_ss_control_string(char *str, int *ss_type,
537                                         char **sc, char **sia,
538                                         char **sib, char **sic,
539                                         char **sid, char **dn)
540 {
541         int len = strlen(str);
542         int cur = 0;
543         char *c;
544         unsigned int i;
545         gboolean ret = FALSE;
546
547         /* Minimum is {*,#}SC# */
548         if (len < 4)
549                 goto out;
550
551         if (str[0] != '*' && str[0] != '#')
552                 goto out;
553
554         cur = 1;
555
556         if (str[1] != '*' && str[1] != '#' && str[1] > '9' && str[1] < '0')
557                 goto out;
558
559         if (str[0] == '#' && str[1] == '*')
560                 goto out;
561
562         if (str[1] == '#' || str[1] == '*')
563                 cur = 2;
564
565         if (str[0] == '*' && str[1] == '*')
566                 *ss_type = SS_CONTROL_TYPE_REGISTRATION;
567         else if (str[0] == '#' && str[1] == '#')
568                 *ss_type = SS_CONTROL_TYPE_ERASURE;
569         else if (str[0] == '*' && str[1] == '#')
570                 *ss_type = SS_CONTROL_TYPE_QUERY;
571         else if (str[0] == '*')
572                 *ss_type = SS_CONTROL_TYPE_ACTIVATION;
573         else
574                 *ss_type = SS_CONTROL_TYPE_DEACTIVATION;
575
576         /* Must have at least one other '#' */
577         c = strrchr(str+cur, '#');
578
579         if (c == NULL)
580                 goto out;
581
582         *dn = c+1;
583         *c = '\0';
584
585         if (strlen(*dn) > 0 && !valid_phone_number_format(*dn))
586                 goto out;
587
588         c = str+cur;
589
590         NEXT_FIELD(c, *sc);
591
592         /*
593          * According to 22.030 SC is 2 or 3 digits, there can be
594          * an optional digit 'n' if this is a call setup string,
595          * however 22.030 does not define any SC of length 3
596          * with an 'n' present
597          */
598         if (strlen(*sc) < 2 || strlen(*sc) > 3)
599                 goto out;
600
601         for (i = 0; i < strlen(*sc); i++)
602                 if (!g_ascii_isdigit((*sc)[i]))
603                         goto out;
604
605         NEXT_FIELD(c, *sia);
606         NEXT_FIELD(c, *sib);
607         NEXT_FIELD(c, *sic);
608         NEXT_FIELD(c, *sid);
609
610         if (*c == '\0')
611                 ret = TRUE;
612
613 out:
614         return ret;
615 }
616
617 static const char *bearer_class_lut[] = {
618         "Voice",
619         "Data",
620         "Fax",
621         "Sms",
622         "DataSync",
623         "DataAsync",
624         "DataPad",
625         "DataPacket"
626 };
627
628 const char *bearer_class_to_string(enum bearer_class cls)
629 {
630         switch (cls) {
631         case BEARER_CLASS_VOICE:
632                 return bearer_class_lut[0];
633         case BEARER_CLASS_DATA:
634                 return bearer_class_lut[1];
635         case BEARER_CLASS_FAX:
636                 return bearer_class_lut[2];
637         case BEARER_CLASS_SMS:
638                 return bearer_class_lut[3];
639         case BEARER_CLASS_DATA_SYNC:
640                 return bearer_class_lut[4];
641         case BEARER_CLASS_DATA_ASYNC:
642                 return bearer_class_lut[5];
643         case BEARER_CLASS_PACKET:
644                 return bearer_class_lut[6];
645         case BEARER_CLASS_PAD:
646                 return bearer_class_lut[7];
647         case BEARER_CLASS_DEFAULT:
648         case BEARER_CLASS_SS_DEFAULT:
649                 break;
650         };
651
652         return NULL;
653 }
654
655 const char *registration_status_to_string(int status)
656 {
657         switch (status) {
658         case NETWORK_REGISTRATION_STATUS_NOT_REGISTERED:
659                 return "unregistered";
660         case NETWORK_REGISTRATION_STATUS_REGISTERED:
661                 return "registered";
662         case NETWORK_REGISTRATION_STATUS_SEARCHING:
663                 return "searching";
664         case NETWORK_REGISTRATION_STATUS_DENIED:
665                 return "denied";
666         case NETWORK_REGISTRATION_STATUS_UNKNOWN:
667                 return "unknown";
668         case NETWORK_REGISTRATION_STATUS_ROAMING:
669                 return "roaming";
670         }
671
672         return "";
673 }
674
675 const char *registration_tech_to_string(int tech)
676 {
677         switch (tech) {
678         case ACCESS_TECHNOLOGY_GSM:
679                 return "gsm";
680         case ACCESS_TECHNOLOGY_GSM_COMPACT:
681                 return "gsm";
682         case ACCESS_TECHNOLOGY_UTRAN:
683                 return "umts";
684         case ACCESS_TECHNOLOGY_GSM_EGPRS:
685                 return "edge";
686         case ACCESS_TECHNOLOGY_UTRAN_HSDPA:
687                 return "hspa";
688         case ACCESS_TECHNOLOGY_UTRAN_HSUPA:
689                 return "hspa";
690         case ACCESS_TECHNOLOGY_UTRAN_HSDPA_HSUPA:
691                 return "hspa";
692         case ACCESS_TECHNOLOGY_EUTRAN:
693                 return "lte";
694         default:
695                 return "";
696         }
697 }
698
699 gboolean is_valid_apn(const char *apn)
700 {
701         int i;
702         int last_period = 0;
703
704         if (apn[0] == '.' || apn[0] == '\0')
705                 return FALSE;
706
707         for (i = 0; apn[i] != '\0'; i++) {
708                 if (g_ascii_isalnum(apn[i]))
709                         continue;
710
711                 if (apn[i] == '-')
712                         continue;
713
714                 if (apn[i] == '.' && (i - last_period) > 1) {
715                         last_period = i;
716                         continue;
717                 }
718
719                 return FALSE;
720         }
721
722         return TRUE;
723 }
724
725 const char *ofono_uuid_to_str(const struct ofono_uuid *uuid)
726 {
727         static char buf[OFONO_SHA1_UUID_LEN * 2 + 1];
728
729         return encode_hex_own_buf(uuid->uuid, OFONO_SHA1_UUID_LEN, 0, buf);
730 }
731
732 void ofono_call_init(struct ofono_call *call)
733 {
734         memset(call, 0, sizeof(struct ofono_call));
735         call->cnap_validity = CNAP_VALIDITY_NOT_AVAILABLE;
736         call->clip_validity = CLIP_VALIDITY_NOT_AVAILABLE;
737 }