~awe/phablet-extras/ofono-lp1204683

« back to all changes in this revision

Viewing changes to src/common.c

  • Committer: Bazaar Package Importer
  • Author(s): Andres Salomon
  • Date: 2009-08-15 15:55:11 UTC
  • Revision ID: james.westby@ubuntu.com-20090815155511-frst06dijguhyfi4
Tags: upstream-0.3
Import upstream version 0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *
 
3
 *  oFono - Open Source Telephony
 
4
 *
 
5
 *  Copyright (C) 2008-2009  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 <ctype.h>
 
29
 
 
30
#include <glib.h>
 
31
 
 
32
#include "driver.h"
 
33
#include "common.h"
 
34
 
 
35
struct error_entry {
 
36
        int error;
 
37
        const char *str;
 
38
};
 
39
 
 
40
/* 0-127 from 24.011 Annex E2
 
41
 * 127-255 23.040 Section 9.2.3.22
 
42
 * Rest are from 27.005 Section 3.2.5
 
43
 */
 
44
struct error_entry cms_errors[] = {
 
45
        { 1,    "Unassigned number" },
 
46
        { 8,    "Operator determined barring" },
 
47
        { 10,   "Call barred" },
 
48
        { 21,   "Short message transfer rejected" },
 
49
        { 27,   "Destination out of service" },
 
50
        { 28,   "Unindentified subscriber" },
 
51
        { 29,   "Facility rejected" },
 
52
        { 30,   "Unknown subscriber" },
 
53
        { 38,   "Network out of order" },
 
54
        { 41,   "Temporary failure" },
 
55
        { 42,   "Congestion" },
 
56
        { 47,   "Recources unavailable" },
 
57
        { 50,   "Requested facility not subscribed" },
 
58
        { 69,   "Requested facility not implemented" },
 
59
        { 81,   "Invalid short message transfer reference value" },
 
60
        { 95,   "Invalid message, unspecified" },
 
61
        { 96,   "Invalid mandatory information" },
 
62
        { 97,   "Message type non existent or not implemented" },
 
63
        { 98,   "Message not compatible with short message protocol state" },
 
64
        { 99,   "Information element non-existent or not implemented" },
 
65
        { 111,  "Protocol error, unspecified" },
 
66
        { 127,  "Internetworking error, unspecified" },
 
67
        { 128,  "Telematic internetworking not supported" },
 
68
        { 129,  "Short message type 0 not supported" },
 
69
        { 130,  "Cannot replace short message" },
 
70
        { 143,  "Unspecified TP-PID error" },
 
71
        { 144,  "Data code scheme not supported" },
 
72
        { 145,  "Message class not supported" },
 
73
        { 159,  "Unspecified TP-DCS error" },
 
74
        { 160,  "Command cannot be actioned" },
 
75
        { 161,  "Command unsupported" },
 
76
        { 175,  "Unspecified TP-Command error" },
 
77
        { 176,  "TPDU not supported" },
 
78
        { 192,  "SC busy" },
 
79
        { 193,  "No SC subscription" },
 
80
        { 194,  "SC System failure" },
 
81
        { 195,  "Invalid SME address" },
 
82
        { 196,  "Destination SME barred" },
 
83
        { 197,  "SM Rejected-Duplicate SM" },
 
84
        { 198,  "TP-VPF not supported" },
 
85
        { 199,  "TP-VP not supported" },
 
86
        { 208,  "(U)SIM SMS Storage full" },
 
87
        { 209,  "No SMS Storage capability in SIM" },
 
88
        { 210,  "Error in MS" },
 
89
        { 211,  "Memory capacity exceeded" },
 
90
        { 212,  "Sim application toolkit busy" },
 
91
        { 213,  "SIM data download error" },
 
92
        { 255,  "Unspecified error cause" },
 
93
        { 300,  "ME Failure" },
 
94
        { 301,  "SMS service of ME reserved" },
 
95
        { 302,  "Operation not allowed" },
 
96
        { 303,  "Operation not supported" },
 
97
        { 304,  "Invalid PDU mode parameter" },
 
98
        { 305,  "Invalid Text mode parameter" },
 
99
        { 310,  "(U)SIM not inserted" },
 
100
        { 311,  "(U)SIM PIN required" },
 
101
        { 312,  "PH-(U)SIM PIN required" },
 
102
        { 313,  "(U)SIM failure" },
 
103
        { 314,  "(U)SIM busy" },
 
104
        { 315,  "(U)SIM wrong" },
 
105
        { 316,  "(U)SIM PUK required" },
 
106
        { 317,  "(U)SIM PIN2 required" },
 
107
        { 318,  "(U)SIM PUK2 required" },
 
108
        { 320,  "Memory failure" },
 
109
        { 321,  "Invalid memory index" },
 
110
        { 322,  "Memory full" },
 
111
        { 330,  "SMSC address unknown" },
 
112
        { 331,  "No network service" },
 
113
        { 332,  "Network timeout" },
 
114
        { 340,  "No +CNMA expected" },
 
115
        { 500,  "Unknown error" },
 
116
};
 
117
 
 
118
/* 27.007, Section 9 */
 
119
struct error_entry cme_errors[] = {
 
120
        { 0,    "Phone failure" },
 
121
        { 1,    "No connection to phone" },
 
122
        { 2,    "Phone adapter link reserved" },
 
123
        { 3,    "Operation not allowed" },
 
124
        { 4,    "Operation not supported" },
 
125
        { 5,    "PH_SIM PIN required" },
 
126
        { 6,    "PH_FSIM PIN required" },
 
127
        { 7,    "PH_FSIM PUK required" },
 
128
        { 10,   "SIM not inserted" },
 
129
        { 11,   "SIM PIN required" },
 
130
        { 12,   "SIM PUK required" },
 
131
        { 13,   "SIM failure" },
 
132
        { 14,   "SIM busy" },
 
133
        { 15,   "SIM wrong" },
 
134
        { 16,   "Incorrect password" },
 
135
        { 17,   "SIM PIN2 required" },
 
136
        { 18,   "SIM PUK2 required" },
 
137
        { 20,   "Memory full" },
 
138
        { 21,   "Invalid index" },
 
139
        { 22,   "Not found" },
 
140
        { 23,   "Memory failure" },
 
141
        { 24,   "Text string too long" },
 
142
        { 25,   "Invalid characters in text string" },
 
143
        { 26,   "Dial string too long" },
 
144
        { 27,   "Invalid characters in dial string" },
 
145
        { 30,   "No network service" },
 
146
        { 31,   "Network timeout" },
 
147
        { 32,   "Network not allowed, emergency calls only" },
 
148
        { 40,   "Network personalization PIN required" },
 
149
        { 41,   "Network personalization PUK required" },
 
150
        { 42,   "Network subset personalization PIN required" },
 
151
        { 43,   "Network subset personalization PUK required" },
 
152
        { 44,   "Service provider personalization PIN required" },
 
153
        { 45,   "Service provider personalization PUK required" },
 
154
        { 46,   "Corporate personalization PIN required" },
 
155
        { 47,   "Corporate personalization PUK required" },
 
156
        { 48,   "PH-SIM PUK required" },
 
157
        { 100,  "Unknown error" },
 
158
        { 103,  "Illegal MS" },
 
159
        { 106,  "Illegal ME" },
 
160
        { 107,  "GPRS services not allowed" },
 
161
        { 111,  "PLMN not allowed" },
 
162
        { 112,  "Location area not allowed" },
 
163
        { 113,  "Roaming not allowed in this location area" },
 
164
        { 126,  "Operation temporary not allowed" },
 
165
        { 132,  "Service operation not supported" },
 
166
        { 133,  "Requested service option not subscribed" },
 
167
        { 134,  "Service option temporary out of order" },
 
168
        { 148,  "Unspecified GPRS error" },
 
169
        { 149,  "PDP authentication failure" },
 
170
        { 150,  "Invalid mobile class" },
 
171
        { 256,  "Operation temporarily not allowed" },
 
172
        { 257,  "Call barred" },
 
173
        { 258,  "Phone is busy" },
 
174
        { 259,  "User abort" },
 
175
        { 260,  "Invalid dial string" },
 
176
        { 261,  "SS not executed" },
 
177
        { 262,  "SIM Blocked" },
 
178
        { 263,  "Invalid block" },
 
179
        { 772,  "SIM powered down" },
 
180
};
 
181
 
 
182
/* 24.008 Annex H */
 
183
struct error_entry ceer_errors[] = {
 
184
        { 1,    "Unassigned number" },
 
185
        { 3,    "No route to destination" },
 
186
        { 6,    "Channel unacceptable" },
 
187
        { 8,    "Operator determined barring" },
 
188
        { 16,   "Normal call clearing" },
 
189
        { 17,   "User busy" },
 
190
        { 18,   "No user responding" },
 
191
        { 19,   "User alerting, no answer" },
 
192
        { 21,   "Call rejected" },
 
193
        { 22,   "Number changed" },
 
194
        { 25,   "Pre-emption" },
 
195
        { 26,   "Non-selected user clearing" },
 
196
        { 27,   "Destination out of order" },
 
197
        { 28,   "Invalid number format (incomplete number)" },
 
198
        { 29,   "Facility rejected" },
 
199
        { 30,   "Response to STATUS ENQUIRY" },
 
200
        { 31,   "Normal, unspecified" },
 
201
        { 34,   "No circuit/channel available" },
 
202
        { 38,   "Network out of order" },
 
203
        { 41,   "Temporary failure" },
 
204
        { 42,   "Switching equipment congestion" },
 
205
        { 43,   "Access information discared" },
 
206
        { 44,   "Requested circuit/channel not available" },
 
207
        { 47,   "Resource unavailable (unspecified)" },
 
208
        { 49,   "Quality of service unavailable" },
 
209
        { 50,   "Requested facility not subscribed" },
 
210
        { 55,   "Incoming calls barred within the CUG" },
 
211
        { 57,   "Bearer capability not authorized" },
 
212
        { 58,   "Bearar capability not presently available" },
 
213
        { 63,   "Service or option not available, unspecified" },
 
214
        { 65,   "Bearer service not implemented" },
 
215
        { 68,   "ACM equal to or greater than ACMmax" },
 
216
        { 69,   "Requested facility not implemented" },
 
217
        { 70,   "Only restricted digital information bearer capability is available" },
 
218
        { 79,   "Service or option not implemented, unspecified" },
 
219
        { 81,   "Invalid transaction identifier value" },
 
220
        { 87,   "User not member of CUG" },
 
221
        { 88,   "Incompatible destination" },
 
222
        { 91,   "Invalid transit network selection" },
 
223
        { 95,   "Semantically incorrect message" },
 
224
        { 96,   "Invalid mandatory information"},
 
225
        { 97,   "Message type non-existent or not implemented" },
 
226
        { 98,   "Message type not compatible with protocol state" },
 
227
        { 99,   "Information element non-existent or not implemented" },
 
228
        { 100,  "Conditional IE error" },
 
229
        { 101,  "Message not compatible with protocol state" },
 
230
        { 102,  "Recovery on timer expirty" },
 
231
        { 111,  "Protocol error, unspecified" },
 
232
        { 127,  "Interworking, unspecified" },
 
233
};
 
234
 
 
235
gboolean valid_phone_number_format(const char *number)
 
236
{
 
237
        int len = strlen(number);
 
238
        int begin = 0;
 
239
        int i;
 
240
 
 
241
        if (!len)
 
242
                return FALSE;
 
243
 
 
244
        if (number[0] == '+')
 
245
                begin = 1;
 
246
 
 
247
        if ((len - begin) > OFONO_MAX_PHONE_NUMBER_LENGTH)
 
248
                return FALSE;
 
249
 
 
250
        for (i = begin; i < len; i++) {
 
251
                if (number[i] >= '0' && number[i] <= '9')
 
252
                        continue;
 
253
 
 
254
                if (number[i] == '*' || number[i] == '#')
 
255
                        continue;
 
256
 
 
257
                return FALSE;
 
258
        }
 
259
 
 
260
        return TRUE;
 
261
}
 
262
 
 
263
const char *telephony_error_to_str(const struct ofono_error *error)
 
264
{
 
265
        struct error_entry *e;
 
266
        int maxentries;
 
267
        int i;
 
268
 
 
269
        switch (error->type) {
 
270
        case OFONO_ERROR_TYPE_CME:
 
271
                e = cme_errors;
 
272
                maxentries = sizeof(cme_errors) / sizeof(struct error_entry);
 
273
                break;
 
274
        case OFONO_ERROR_TYPE_CMS:
 
275
                e = cms_errors;
 
276
                maxentries = sizeof(cme_errors) / sizeof(struct error_entry);
 
277
                break;
 
278
        case OFONO_ERROR_TYPE_CEER:
 
279
                e = ceer_errors;
 
280
                maxentries = sizeof(ceer_errors) / sizeof(struct error_entry);
 
281
                break;
 
282
        default:
 
283
                return 0;
 
284
        }
 
285
 
 
286
        for (i = 0; i < maxentries; i++)
 
287
                if (e[i].error == error->error)
 
288
                        return e[i].str;
 
289
 
 
290
        return 0;
 
291
}
 
292
 
 
293
int mmi_service_code_to_bearer_class(int code)
 
294
{
 
295
        int cls = 0;
 
296
 
 
297
        /* Teleservices according to 22.004
 
298
         * 1 - Voice
 
299
         * 2 - SMS
 
300
         * 3,4,5 - Unallocated
 
301
         * 6 - Fax
 
302
         * 7 - All Data Async
 
303
         * 8 - All Data Sync
 
304
         * 12 - Voice Group
 
305
         */
 
306
 
 
307
        switch (code) {
 
308
        /* 22.030: 1 to 6, 12 */
 
309
        case 10:
 
310
                cls = BEARER_CLASS_VOICE | BEARER_CLASS_FAX | BEARER_CLASS_SMS;
 
311
                break;
 
312
        /* 22.030: 1 */
 
313
        case 11:
 
314
                cls = BEARER_CLASS_VOICE;
 
315
                break;
 
316
        /* 22.030: 2-6 */
 
317
        case 12:
 
318
                cls = BEARER_CLASS_SMS | BEARER_CLASS_FAX;
 
319
                break;
 
320
        /* 22.030: 6 */
 
321
        case 13:
 
322
                cls = BEARER_CLASS_FAX;
 
323
                break;
 
324
        /* 22.030: 2 */
 
325
        case 16:
 
326
                cls = BEARER_CLASS_SMS;
 
327
                break;
 
328
        /* TODO: Voice Group Call & Broadcast VGCS & VBS */
 
329
        case 17:
 
330
        case 18:
 
331
                break;
 
332
        /* 22.030: 1, 3 to 6, 12 */
 
333
        case 19:
 
334
                cls = BEARER_CLASS_VOICE | BEARER_CLASS_FAX;
 
335
                break;
 
336
 
 
337
        /* 22.030: 7-11 */
 
338
        /* 22.004 only defines BS 7 (Data Sync) & BS 8 (Data Async) */
 
339
        case 20:
 
340
                cls = BEARER_CLASS_DATA_ASYNC | BEARER_CLASS_DATA_SYNC;
 
341
                break;
 
342
        /* According to 22.030: All Async */
 
343
        case 21:
 
344
        /* According to 22.030: All Data Async */
 
345
        case 25:
 
346
                cls = BEARER_CLASS_DATA_ASYNC;
 
347
                break;
 
348
        /* According to 22.030: All Sync */
 
349
        case 22:
 
350
        /* According to 22.030: All Data Sync */
 
351
        case 24:
 
352
                cls = BEARER_CLASS_DATA_SYNC;
 
353
                break;
 
354
        /* According to 22.030: Telephony & All Sync services */
 
355
        case 26:
 
356
                cls = BEARER_CLASS_VOICE | BEARER_CLASS_DATA_SYNC;
 
357
                break;
 
358
        default:
 
359
                break;
 
360
        }
 
361
 
 
362
        return cls;
 
363
}
 
364
 
 
365
const char *phone_number_to_string(const struct ofono_phone_number *ph)
 
366
{
 
367
        static char buffer[64];
 
368
 
 
369
        if (ph->type == 145 && (strlen(ph->number) > 0) &&
 
370
                        ph->number[0] != '+') {
 
371
                buffer[0] = '+';
 
372
                strncpy(buffer + 1, ph->number, 62);
 
373
                buffer[63] = '\0';
 
374
        } else {
 
375
                strncpy(buffer, ph->number, 63);
 
376
                buffer[63] = '\0';
 
377
        }
 
378
 
 
379
        return buffer;
 
380
}
 
381
 
 
382
void string_to_phone_number(const char *str, struct ofono_phone_number *ph)
 
383
{
 
384
        if (strlen(str) && str[0] == '+') {
 
385
                strcpy(ph->number, str+1);
 
386
                ph->type = 145; /* International */
 
387
        } else {
 
388
                strcpy(ph->number, str);
 
389
                ph->type = 129; /* Local */
 
390
        }
 
391
}
 
392
 
 
393
int valid_ussd_string(const char *str)
 
394
{
 
395
        int len = strlen(str);
 
396
 
 
397
        if (!len)
 
398
                return FALSE;
 
399
 
 
400
        /* It is hard to understand exactly what constitutes a valid USSD string
 
401
         * According to 22.090:
 
402
         * Case a - 1, 2 or 3 digits from the set (*, #) followed by 1X(Y),
 
403
         * where X=any number 0‑4, Y=any number 0‑9, then, optionally "*
 
404
         * followed by any number of any characters", and concluding with #SEND
 
405
         *
 
406
         * Case b - 1, 2 or 3 digits from the set (*, #) followed by 1X(Y),
 
407
         * where X=any number 5‑9, Y=any number 0‑9, then, optionally "*
 
408
         * followed by any number of any characters", and concluding with #SEND
 
409
         *
 
410
         * Case c - 7(Y) SEND, where Y=any number 0‑9
 
411
         *
 
412
         * Case d - All other formats
 
413
         *
 
414
         * According to 22.030 Figure 3.5.3.2 USSD strings can be:
 
415
         *
 
416
         * Supplementary service control
 
417
         * SIM control
 
418
         * Manufacturer defined
 
419
         * Terminated by '#'
 
420
         * Short String - This can be any 2 digit short string.  If the string
 
421
         *                starts with a '1' and no calls are in progress then
 
422
         *                this string is treated as a call setup request
 
423
         *
 
424
         * Everything else is not a valid USSD string
 
425
         */
 
426
 
 
427
        if (len != 2 && str[len-1] != '#')
 
428
                return FALSE;
 
429
 
 
430
        return TRUE;
 
431
}
 
432
 
 
433
const char *ss_control_type_to_string(enum ss_control_type type)
 
434
{
 
435
        switch (type) {
 
436
        case SS_CONTROL_TYPE_ACTIVATION:
 
437
                return "acivation";
 
438
        case SS_CONTROL_TYPE_REGISTRATION:
 
439
                return "registration";
 
440
        case SS_CONTROL_TYPE_QUERY:
 
441
                return "interrogation";
 
442
        case SS_CONTROL_TYPE_DEACTIVATION:
 
443
                return "deactivation";
 
444
        case SS_CONTROL_TYPE_ERASURE:
 
445
                return "erasure";
 
446
        }
 
447
 
 
448
        return NULL;
 
449
}
 
450
 
 
451
#define NEXT_FIELD(str, dest)                   \
 
452
        do {                                    \
 
453
                dest = str;                     \
 
454
                                                \
 
455
                str = strchrnul(str, '*');      \
 
456
                if (*str) {                     \
 
457
                        *str = '\0';            \
 
458
                        str += 1;               \
 
459
                }                               \
 
460
        } while (0)                             \
 
461
 
 
462
/* Note: The str will be modified, so in case of error you should
 
463
 * throw it away and start over
 
464
 */
 
465
gboolean parse_ss_control_string(char *str, int *ss_type,
 
466
                                        char **sc, char **sia,
 
467
                                        char **sib, char **sic,
 
468
                                        char **sid, char **dn)
 
469
{
 
470
        int len = strlen(str);
 
471
        int cur = 0;
 
472
        char *c;
 
473
        unsigned int i;
 
474
        gboolean ret = FALSE;
 
475
 
 
476
        /* Minimum is {*,#}SC# */
 
477
        if (len < 4)
 
478
                goto out;
 
479
 
 
480
        if (str[0] != '*' && str[0] != '#')
 
481
                goto out;
 
482
 
 
483
        cur = 1;
 
484
 
 
485
        if (str[1] != '*' && str[1] != '#' && str[1] > '9' && str[1] < '0')
 
486
                goto out;
 
487
 
 
488
        if (str[0] == '#' && str[1] == '*')
 
489
                goto out;
 
490
 
 
491
        if (str[1] == '#' || str[1] == '*')
 
492
                cur = 2;
 
493
 
 
494
        if (str[0] == '*' && str[1] == '*')
 
495
                *ss_type = SS_CONTROL_TYPE_REGISTRATION;
 
496
        else if (str[0] == '#' && str[1] == '#')
 
497
                *ss_type = SS_CONTROL_TYPE_ERASURE;
 
498
        else if (str[0] == '*' && str[1] == '#')
 
499
                *ss_type = SS_CONTROL_TYPE_QUERY;
 
500
        else if (str[0] == '*')
 
501
                *ss_type = SS_CONTROL_TYPE_ACTIVATION;
 
502
        else
 
503
                *ss_type = SS_CONTROL_TYPE_DEACTIVATION;
 
504
 
 
505
        /* Must have at least one other '#' */
 
506
        c = strrchr(str+cur, '#');
 
507
 
 
508
        if (!c)
 
509
                goto out;
 
510
 
 
511
        *dn = c+1;
 
512
        *c = '\0';
 
513
 
 
514
        if (strlen(*dn) > 0 && !valid_phone_number_format(*dn))
 
515
                goto out;
 
516
 
 
517
        c = str+cur;
 
518
 
 
519
        NEXT_FIELD(c, *sc);
 
520
 
 
521
        /* According to 22.030 SC is 2 or 3 digits, there can be
 
522
         * an optional digit 'n' if this is a call setup string,
 
523
         * however 22.030 does not define any SC of length 3
 
524
         * with an 'n' present
 
525
         */
 
526
        if (strlen(*sc) < 2 || strlen(*sc) > 3)
 
527
                goto out;
 
528
 
 
529
        for (i = 0; i < strlen(*sc); i++)
 
530
                if (!isdigit((*sc)[i]))
 
531
                        goto out;
 
532
 
 
533
        NEXT_FIELD(c, *sia);
 
534
        NEXT_FIELD(c, *sib);
 
535
        NEXT_FIELD(c, *sic);
 
536
        NEXT_FIELD(c, *sid);
 
537
 
 
538
        if (*c == '\0')
 
539
                ret = TRUE;
 
540
 
 
541
out:
 
542
        return ret;
 
543
}
 
544
 
 
545
static const char *bearer_class_lut[] = {
 
546
        "Voice",
 
547
        "Data",
 
548
        "Fax",
 
549
        "Sms",
 
550
        "DataSync",
 
551
        "DataAsync",
 
552
        "DataPad",
 
553
        "DataPacket"
 
554
};
 
555
 
 
556
const char *bearer_class_to_string(enum bearer_class cls)
 
557
{
 
558
        switch (cls) {
 
559
        case BEARER_CLASS_VOICE:
 
560
                return bearer_class_lut[0];
 
561
        case BEARER_CLASS_DATA:
 
562
                return bearer_class_lut[1];
 
563
        case BEARER_CLASS_FAX:
 
564
                return bearer_class_lut[2];
 
565
        case BEARER_CLASS_SMS:
 
566
                return bearer_class_lut[3];
 
567
        case BEARER_CLASS_DATA_SYNC:
 
568
                return bearer_class_lut[4];
 
569
        case BEARER_CLASS_DATA_ASYNC:
 
570
                return bearer_class_lut[5];
 
571
        case BEARER_CLASS_PACKET:
 
572
                return bearer_class_lut[6];
 
573
        case BEARER_CLASS_PAD:
 
574
                return bearer_class_lut[7];
 
575
        case BEARER_CLASS_DEFAULT:
 
576
        case BEARER_CLASS_SS_DEFAULT:
 
577
                break;
 
578
        };
 
579
 
 
580
        return NULL;
 
581
}
 
582
 
 
583
gboolean is_valid_pin(const char *pin)
 
584
{
 
585
        unsigned int i;
 
586
 
 
587
        for (i = 0; i < strlen(pin); i++)
 
588
                if (pin[i] < '0' || pin[i] > '9')
 
589
                        return FALSE;
 
590
 
 
591
        if (i > 8)
 
592
                return FALSE;
 
593
 
 
594
        return TRUE;
 
595
}