1 /*
2 * libpri: An implementation of Primary Rate ISDN
3 *
4 * Copyright (C) 2009 Digium, Inc.
5 *
6 * Richard Mudgett <rmudgett@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2 as published by the
16 * Free Software Foundation. See the LICENSE file included with
17 * this program for more details.
18 *
19 * In addition, when this program is distributed with Asterisk in
20 * any form that would qualify as a 'combined work' or as a
21 * 'derivative work' (but not mere aggregation), you can redistribute
22 * and/or modify the combination under the terms of the license
23 * provided with that copy of Asterisk, instead of the license
24 * terms granted here.
25 */
26
27 /*!
28 * \file
29 * \brief ROSE Advice Of Charge (AOC) operations
30 *
31 * Advice of Charge (AOC) supplementary service EN 300 182-1
32 *
33 * \author Richard Mudgett <rmudgett@digium.com>
34 */
35
36
37 #include "compat.h"
38 #include "libpri.h"
39 #include "pri_internal.h"
40 #include "rose.h"
41 #include "rose_internal.h"
42 #include "asn1.h"
43
44
45 /* ------------------------------------------------------------------- */
46
47 /*!
48 * \internal
49 * \brief Encode the Time type.
50 *
51 * \param ctrl D channel controller for diagnostic messages or global options.
52 * \param pos Starting position to encode ASN.1 component.
53 * \param end End of ASN.1 encoding data buffer.
54 * \param tag Component tag to identify the encoded component.
55 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
56 * tags it otherwise.
57 * \param time Time information to encode.
58 *
59 * \retval Start of the next ASN.1 component to encode on success.
60 * \retval NULL on error.
61 */
rose_enc_etsi_AOC_Time(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCTime * time)62 static unsigned char *rose_enc_etsi_AOC_Time(struct pri *ctrl, unsigned char *pos,
63 unsigned char *end, unsigned tag, const struct roseEtsiAOCTime *time)
64 {
65 unsigned char *seq_len;
66
67 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
68
69 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
70 time->length));
71 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2, time->scale));
72
73 ASN1_CONSTRUCTED_END(seq_len, pos, end);
74
75 return pos;
76 }
77
78 /*!
79 * \internal
80 * \brief Encode the Amount type.
81 *
82 * \param ctrl D channel controller for diagnostic messages or global options.
83 * \param pos Starting position to encode ASN.1 component.
84 * \param end End of ASN.1 encoding data buffer.
85 * \param tag Component tag to identify the encoded component.
86 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
87 * tags it otherwise.
88 * \param amount Amount information to encode.
89 *
90 * \retval Start of the next ASN.1 component to encode on success.
91 * \retval NULL on error.
92 */
rose_enc_etsi_AOC_Amount(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCAmount * amount)93 static unsigned char *rose_enc_etsi_AOC_Amount(struct pri *ctrl, unsigned char *pos,
94 unsigned char *end, unsigned tag, const struct roseEtsiAOCAmount *amount)
95 {
96 unsigned char *seq_len;
97
98 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
99
100 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
101 amount->currency));
102 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
103 amount->multiplier));
104
105 ASN1_CONSTRUCTED_END(seq_len, pos, end);
106
107 return pos;
108 }
109
110 /*!
111 * \internal
112 * \brief Encode the RecordedCurrency type.
113 *
114 * \param ctrl D channel controller for diagnostic messages or global options.
115 * \param pos Starting position to encode ASN.1 component.
116 * \param end End of ASN.1 encoding data buffer.
117 * \param tag Component tag to identify the encoded component.
118 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
119 * tags it otherwise.
120 * \param recorded Recorded currency information to encode.
121 *
122 * \retval Start of the next ASN.1 component to encode on success.
123 * \retval NULL on error.
124 */
rose_enc_etsi_AOC_RecordedCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCRecordedCurrency * recorded)125 static unsigned char *rose_enc_etsi_AOC_RecordedCurrency(struct pri *ctrl,
126 unsigned char *pos, unsigned char *end, unsigned tag,
127 const struct roseEtsiAOCRecordedCurrency *recorded)
128 {
129 unsigned char *seq_len;
130
131 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
132
133 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
134 recorded->currency, sizeof(recorded->currency) - 1));
135 ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
136 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &recorded->amount));
137
138 ASN1_CONSTRUCTED_END(seq_len, pos, end);
139
140 return pos;
141 }
142
143 /*!
144 * \internal
145 * \brief Encode the DurationCurrency type.
146 *
147 * \param ctrl D channel controller for diagnostic messages or global options.
148 * \param pos Starting position to encode ASN.1 component.
149 * \param end End of ASN.1 encoding data buffer.
150 * \param tag Component tag to identify the encoded component.
151 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
152 * tags it otherwise.
153 * \param duration Duration currency information to encode.
154 *
155 * \retval Start of the next ASN.1 component to encode on success.
156 * \retval NULL on error.
157 */
rose_enc_etsi_AOC_DurationCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCDurationCurrency * duration)158 static unsigned char *rose_enc_etsi_AOC_DurationCurrency(struct pri *ctrl,
159 unsigned char *pos, unsigned char *end, unsigned tag,
160 const struct roseEtsiAOCDurationCurrency *duration)
161 {
162 unsigned char *seq_len;
163
164 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
165
166 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
167 duration->currency, sizeof(duration->currency) - 1));
168 ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
169 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &duration->amount));
170 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
171 duration->charging_type));
172 ASN1_CALL(pos, rose_enc_etsi_AOC_Time(ctrl, pos, end,
173 ASN1_CLASS_CONTEXT_SPECIFIC | 4, &duration->time));
174 if (duration->granularity_present) {
175 ASN1_CALL(pos, rose_enc_etsi_AOC_Time(ctrl, pos, end,
176 ASN1_CLASS_CONTEXT_SPECIFIC | 5, &duration->granularity));
177 }
178
179 ASN1_CONSTRUCTED_END(seq_len, pos, end);
180
181 return pos;
182 }
183
184 /*!
185 * \internal
186 * \brief Encode the FlatRateCurrency type.
187 *
188 * \param ctrl D channel controller for diagnostic messages or global options.
189 * \param pos Starting position to encode ASN.1 component.
190 * \param end End of ASN.1 encoding data buffer.
191 * \param tag Component tag to identify the encoded component.
192 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
193 * tags it otherwise.
194 * \param flat_rate Flat rate currency information to encode.
195 *
196 * \retval Start of the next ASN.1 component to encode on success.
197 * \retval NULL on error.
198 */
rose_enc_etsi_AOC_FlatRateCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCFlatRateCurrency * flat_rate)199 static unsigned char *rose_enc_etsi_AOC_FlatRateCurrency(struct pri *ctrl,
200 unsigned char *pos, unsigned char *end, unsigned tag,
201 const struct roseEtsiAOCFlatRateCurrency *flat_rate)
202 {
203 unsigned char *seq_len;
204
205 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
206
207 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
208 flat_rate->currency, sizeof(flat_rate->currency) - 1));
209 ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
210 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &flat_rate->amount));
211
212 ASN1_CONSTRUCTED_END(seq_len, pos, end);
213
214 return pos;
215 }
216
217 /*!
218 * \internal
219 * \brief Encode the VolumeRateCurrency type.
220 *
221 * \param ctrl D channel controller for diagnostic messages or global options.
222 * \param pos Starting position to encode ASN.1 component.
223 * \param end End of ASN.1 encoding data buffer.
224 * \param tag Component tag to identify the encoded component.
225 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
226 * tags it otherwise.
227 * \param volume_rate Volume rate currency information to encode.
228 *
229 * \retval Start of the next ASN.1 component to encode on success.
230 * \retval NULL on error.
231 */
rose_enc_etsi_AOC_VolumeRateCurrency(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCVolumeRateCurrency * volume_rate)232 static unsigned char *rose_enc_etsi_AOC_VolumeRateCurrency(struct pri *ctrl,
233 unsigned char *pos, unsigned char *end, unsigned tag,
234 const struct roseEtsiAOCVolumeRateCurrency *volume_rate)
235 {
236 unsigned char *seq_len;
237
238 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
239
240 ASN1_CALL(pos, asn1_enc_string_max(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1,
241 volume_rate->currency, sizeof(volume_rate->currency) - 1));
242 ASN1_CALL(pos, rose_enc_etsi_AOC_Amount(ctrl, pos, end,
243 ASN1_CLASS_CONTEXT_SPECIFIC | 2, &volume_rate->amount));
244 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
245 volume_rate->unit));
246
247 ASN1_CONSTRUCTED_END(seq_len, pos, end);
248
249 return pos;
250 }
251
252 /*!
253 * \internal
254 * \brief Encode the AOCSCurrencyInfo type.
255 *
256 * \param ctrl D channel controller for diagnostic messages or global options.
257 * \param pos Starting position to encode ASN.1 component.
258 * \param end End of ASN.1 encoding data buffer.
259 * \param tag Component tag to identify the encoded component.
260 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
261 * tags it otherwise.
262 * \param currency_info Currency information record to encode.
263 *
264 * \retval Start of the next ASN.1 component to encode on success.
265 * \retval NULL on error.
266 */
rose_enc_etsi_AOCSCurrencyInfo(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCSCurrencyInfo * currency_info)267 static unsigned char *rose_enc_etsi_AOCSCurrencyInfo(struct pri *ctrl,
268 unsigned char *pos, unsigned char *end, unsigned tag,
269 const struct roseEtsiAOCSCurrencyInfo *currency_info)
270 {
271 unsigned char *seq_len;
272
273 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
274
275 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
276 currency_info->charged_item));
277
278 switch (currency_info->currency_type) {
279 case 0: /* specialChargingCode */
280 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
281 currency_info->u.special_charging_code));
282 break;
283 case 1: /* durationCurrency */
284 ASN1_CALL(pos, rose_enc_etsi_AOC_DurationCurrency(ctrl, pos, end,
285 ASN1_CLASS_CONTEXT_SPECIFIC | 1, ¤cy_info->u.duration));
286 break;
287 case 2: /* flatRateCurrency */
288 ASN1_CALL(pos, rose_enc_etsi_AOC_FlatRateCurrency(ctrl, pos, end,
289 ASN1_CLASS_CONTEXT_SPECIFIC | 2, ¤cy_info->u.flat_rate));
290 break;
291 case 3: /* volumeRateCurrency */
292 ASN1_CALL(pos, rose_enc_etsi_AOC_VolumeRateCurrency(ctrl, pos, end,
293 ASN1_CLASS_CONTEXT_SPECIFIC | 3, ¤cy_info->u.volume_rate));
294 break;
295 case 4: /* freeOfCharge */
296 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 4));
297 break;
298 case 5: /* currencyInfoNotAvailable */
299 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 5));
300 break;
301 default:
302 ASN1_ENC_ERROR(ctrl, "Unknown currency type");
303 return NULL;
304 }
305
306 ASN1_CONSTRUCTED_END(seq_len, pos, end);
307
308 return pos;
309 }
310
311 /*!
312 * \internal
313 * \brief Encode the AOCSCurrencyInfoList type.
314 *
315 * \param ctrl D channel controller for diagnostic messages or global options.
316 * \param pos Starting position to encode ASN.1 component.
317 * \param end End of ASN.1 encoding data buffer.
318 * \param tag Component tag to identify the encoded component.
319 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
320 * tags it otherwise.
321 * \param currency_info Currency information list to encode.
322 *
323 * \retval Start of the next ASN.1 component to encode on success.
324 * \retval NULL on error.
325 */
rose_enc_etsi_AOCSCurrencyInfoList(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCSCurrencyInfoList * currency_info)326 static unsigned char *rose_enc_etsi_AOCSCurrencyInfoList(struct pri *ctrl,
327 unsigned char *pos, unsigned char *end, unsigned tag,
328 const struct roseEtsiAOCSCurrencyInfoList *currency_info)
329 {
330 unsigned index;
331 unsigned char *seq_len;
332
333 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
334
335 for (index = 0; index < currency_info->num_records; ++index) {
336 ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
337 ¤cy_info->list[index]));
338 }
339
340 ASN1_CONSTRUCTED_END(seq_len, pos, end);
341
342 return pos;
343 }
344
345 /*!
346 * \internal
347 * \brief Encode the RecordedUnits type.
348 *
349 * \param ctrl D channel controller for diagnostic messages or global options.
350 * \param pos Starting position to encode ASN.1 component.
351 * \param end End of ASN.1 encoding data buffer.
352 * \param tag Component tag to identify the encoded component.
353 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
354 * tags it otherwise.
355 * \param recorded Recorded units information record to encode.
356 *
357 * \retval Start of the next ASN.1 component to encode on success.
358 * \retval NULL on error.
359 */
rose_enc_etsi_AOC_RecordedUnits(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCRecordedUnits * recorded)360 static unsigned char *rose_enc_etsi_AOC_RecordedUnits(struct pri *ctrl,
361 unsigned char *pos, unsigned char *end, unsigned tag,
362 const struct roseEtsiAOCRecordedUnits *recorded)
363 {
364 unsigned char *seq_len;
365
366 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
367
368 if (recorded->not_available) {
369 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
370 } else {
371 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
372 recorded->number_of_units));
373 }
374
375 if (recorded->type_of_unit_present) {
376 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
377 recorded->type_of_unit));
378 }
379
380 ASN1_CONSTRUCTED_END(seq_len, pos, end);
381
382 return pos;
383 }
384
385 /*!
386 * \internal
387 * \brief Encode the RecordedUnitsList type.
388 *
389 * \param ctrl D channel controller for diagnostic messages or global options.
390 * \param pos Starting position to encode ASN.1 component.
391 * \param end End of ASN.1 encoding data buffer.
392 * \param tag Component tag to identify the encoded component.
393 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
394 * tags it otherwise.
395 * \param recorded_info Recorded units information list to encode.
396 *
397 * \retval Start of the next ASN.1 component to encode on success.
398 * \retval NULL on error.
399 */
rose_enc_etsi_AOC_RecordedUnitsList(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCRecordedUnitsList * recorded_info)400 static unsigned char *rose_enc_etsi_AOC_RecordedUnitsList(struct pri *ctrl,
401 unsigned char *pos, unsigned char *end, unsigned tag,
402 const struct roseEtsiAOCRecordedUnitsList *recorded_info)
403 {
404 unsigned index;
405 unsigned char *seq_len;
406
407 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
408
409 for (index = 0; index < recorded_info->num_records; ++index) {
410 ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnits(ctrl, pos, end, ASN1_TAG_SEQUENCE,
411 &recorded_info->list[index]));
412 }
413
414 ASN1_CONSTRUCTED_END(seq_len, pos, end);
415
416 return pos;
417 }
418
419 /*!
420 * \internal
421 * \brief Encode the ChargingAssociation type.
422 *
423 * \param ctrl D channel controller for diagnostic messages or global options.
424 * \param pos Starting position to encode ASN.1 component.
425 * \param end End of ASN.1 encoding data buffer.
426 * \param charging Charging association information to encode.
427 *
428 * \retval Start of the next ASN.1 component to encode on success.
429 * \retval NULL on error.
430 */
rose_enc_etsi_AOC_ChargingAssociation(struct pri * ctrl,unsigned char * pos,unsigned char * end,const struct roseEtsiAOCChargingAssociation * charging)431 static unsigned char *rose_enc_etsi_AOC_ChargingAssociation(struct pri *ctrl,
432 unsigned char *pos, unsigned char *end,
433 const struct roseEtsiAOCChargingAssociation *charging)
434 {
435 unsigned char *explicit_len;
436
437 switch (charging->type) {
438 case 0: /* charge_identifier */
439 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER, charging->id));
440 break;
441 case 1: /* charged_number */
442 /* EXPLICIT tag */
443 ASN1_CONSTRUCTED_BEGIN(explicit_len, pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 0);
444 ASN1_CALL(pos, rose_enc_PartyNumber(ctrl, pos, end, &charging->number));
445 ASN1_CONSTRUCTED_END(explicit_len, pos, end);
446 break;
447 default:
448 ASN1_ENC_ERROR(ctrl, "Unknown ChargingAssociation type");
449 return NULL;
450 }
451
452 return pos;
453 }
454
455 /*!
456 * \internal
457 * \brief Encode the AOCECurrencyInfo type.
458 *
459 * \param ctrl D channel controller for diagnostic messages or global options.
460 * \param pos Starting position to encode ASN.1 component.
461 * \param end End of ASN.1 encoding data buffer.
462 * \param tag Component tag to identify the encoded component.
463 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
464 * tags it otherwise.
465 * \param currency_info Currency information to encode.
466 *
467 * \retval Start of the next ASN.1 component to encode on success.
468 * \retval NULL on error.
469 */
rose_enc_etsi_AOCECurrencyInfo(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCECurrencyInfo * currency_info)470 static unsigned char *rose_enc_etsi_AOCECurrencyInfo(struct pri *ctrl,
471 unsigned char *pos, unsigned char *end, unsigned tag,
472 const struct roseEtsiAOCECurrencyInfo *currency_info)
473 {
474 unsigned char *seq_len;
475 unsigned char *specific_seq_len;
476
477 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
478
479 if (currency_info->free_of_charge) {
480 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
481 } else {
482 ASN1_CONSTRUCTED_BEGIN(specific_seq_len, pos, end, ASN1_TAG_SEQUENCE);
483
484 ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedCurrency(ctrl, pos, end,
485 ASN1_CLASS_CONTEXT_SPECIFIC | 1, ¤cy_info->specific.recorded));
486
487 if (currency_info->specific.billing_id_present) {
488 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
489 currency_info->specific.billing_id));
490 }
491
492 ASN1_CONSTRUCTED_END(specific_seq_len, pos, end);
493 }
494
495 if (currency_info->charging_association_present) {
496 ASN1_CALL(pos, rose_enc_etsi_AOC_ChargingAssociation(ctrl, pos, end,
497 ¤cy_info->charging_association));
498 }
499
500 ASN1_CONSTRUCTED_END(seq_len, pos, end);
501
502 return pos;
503 }
504
505 /*!
506 * \internal
507 * \brief Encode the AOCEChargingUnitInfo type.
508 *
509 * \param ctrl D channel controller for diagnostic messages or global options.
510 * \param pos Starting position to encode ASN.1 component.
511 * \param end End of ASN.1 encoding data buffer.
512 * \param tag Component tag to identify the encoded component.
513 * The tag should be ASN1_TAG_SEQUENCE unless the caller implicitly
514 * tags it otherwise.
515 * \param charging_unit Charging unit information to encode.
516 *
517 * \retval Start of the next ASN.1 component to encode on success.
518 * \retval NULL on error.
519 */
rose_enc_etsi_AOCEChargingUnitInfo(struct pri * ctrl,unsigned char * pos,unsigned char * end,unsigned tag,const struct roseEtsiAOCEChargingUnitInfo * charging_unit)520 static unsigned char *rose_enc_etsi_AOCEChargingUnitInfo(struct pri *ctrl,
521 unsigned char *pos, unsigned char *end, unsigned tag,
522 const struct roseEtsiAOCEChargingUnitInfo *charging_unit)
523 {
524 unsigned char *seq_len;
525 unsigned char *specific_seq_len;
526
527 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, tag);
528
529 if (charging_unit->free_of_charge) {
530 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
531 } else {
532 ASN1_CONSTRUCTED_BEGIN(specific_seq_len, pos, end, ASN1_TAG_SEQUENCE);
533
534 ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnitsList(ctrl, pos, end,
535 ASN1_CLASS_CONTEXT_SPECIFIC | 1, &charging_unit->specific.recorded));
536
537 if (charging_unit->specific.billing_id_present) {
538 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
539 charging_unit->specific.billing_id));
540 }
541
542 ASN1_CONSTRUCTED_END(specific_seq_len, pos, end);
543 }
544
545 if (charging_unit->charging_association_present) {
546 ASN1_CALL(pos, rose_enc_etsi_AOC_ChargingAssociation(ctrl, pos, end,
547 &charging_unit->charging_association));
548 }
549
550 ASN1_CONSTRUCTED_END(seq_len, pos, end);
551
552 return pos;
553 }
554
555 /*!
556 * \brief Encode the ChargingRequest invoke facility ie arguments.
557 *
558 * \param ctrl D channel controller for diagnostic messages or global options.
559 * \param pos Starting position to encode ASN.1 component.
560 * \param end End of ASN.1 encoding data buffer.
561 * \param args Arguments to encode in the buffer.
562 *
563 * \retval Start of the next ASN.1 component to encode on success.
564 * \retval NULL on error.
565 */
rose_enc_etsi_ChargingRequest_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)566 unsigned char *rose_enc_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned char *pos,
567 unsigned char *end, const union rose_msg_invoke_args *args)
568 {
569 return asn1_enc_int(pos, end, ASN1_TYPE_ENUMERATED,
570 args->etsi.ChargingRequest.charging_case);
571 }
572
573 /*!
574 * \brief Encode the ChargingRequest result facility ie arguments.
575 *
576 * \param ctrl D channel controller for diagnostic messages or global options.
577 * \param pos Starting position to encode ASN.1 component.
578 * \param end End of ASN.1 encoding data buffer.
579 * \param args Arguments to encode in the buffer.
580 *
581 * \retval Start of the next ASN.1 component to encode on success.
582 * \retval NULL on error.
583 */
rose_enc_etsi_ChargingRequest_RES(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_result_args * args)584 unsigned char *rose_enc_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned char *pos,
585 unsigned char *end, const union rose_msg_result_args *args)
586 {
587 switch (args->etsi.ChargingRequest.type) {
588 case 0: /* currency_info_list */
589 ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
590 ASN1_TAG_SEQUENCE, &args->etsi.ChargingRequest.u.currency_info));
591 break;
592 case 1: /* special_arrangement_info */
593 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
594 args->etsi.ChargingRequest.u.special_arrangement));
595 break;
596 case 2: /* charging_info_follows */
597 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
598 break;
599 default:
600 ASN1_ENC_ERROR(ctrl, "Unknown ChargingRequst type");
601 return NULL;
602 }
603
604 return pos;
605 }
606
607 /*!
608 * \brief Encode the AOCSCurrency invoke facility ie arguments.
609 *
610 * \param ctrl D channel controller for diagnostic messages or global options.
611 * \param pos Starting position to encode ASN.1 component.
612 * \param end End of ASN.1 encoding data buffer.
613 * \param args Arguments to encode in the buffer.
614 *
615 * \retval Start of the next ASN.1 component to encode on success.
616 * \retval NULL on error.
617 */
rose_enc_etsi_AOCSCurrency_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)618 unsigned char *rose_enc_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned char *pos,
619 unsigned char *end, const union rose_msg_invoke_args *args)
620 {
621 switch (args->etsi.AOCSCurrency.type) {
622 case 0: /* charge_not_available */
623 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
624 break;
625 case 1: /* currency_info_list */
626 if (args->etsi.AOCSCurrency.currency_info.num_records) {
627 ASN1_CALL(pos, rose_enc_etsi_AOCSCurrencyInfoList(ctrl, pos, end,
628 ASN1_TAG_SEQUENCE, &args->etsi.AOCSCurrency.currency_info));
629 } else {
630 /* There were no records so encode as charge_not_available */
631 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
632 }
633 break;
634 default:
635 ASN1_ENC_ERROR(ctrl, "Unknown AOCSCurrency type");
636 return NULL;
637 }
638
639 return pos;
640 }
641
642 /*!
643 * \brief Encode the AOCSSpecialArr invoke facility ie arguments.
644 *
645 * \param ctrl D channel controller for diagnostic messages or global options.
646 * \param pos Starting position to encode ASN.1 component.
647 * \param end End of ASN.1 encoding data buffer.
648 * \param args Arguments to encode in the buffer.
649 *
650 * \retval Start of the next ASN.1 component to encode on success.
651 * \retval NULL on error.
652 */
rose_enc_etsi_AOCSSpecialArr_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)653 unsigned char *rose_enc_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned char *pos,
654 unsigned char *end, const union rose_msg_invoke_args *args)
655 {
656 switch (args->etsi.AOCSSpecialArr.type) {
657 case 0: /* charge_not_available */
658 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
659 break;
660 case 1: /* special_arrangement_info */
661 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_TYPE_INTEGER,
662 args->etsi.AOCSSpecialArr.special_arrangement));
663 break;
664 default:
665 ASN1_ENC_ERROR(ctrl, "Unknown AOCSSpecialArr type");
666 return NULL;
667 }
668
669 return pos;
670 }
671
672 /*!
673 * \brief Encode the AOCDCurrency invoke facility ie arguments.
674 *
675 * \param ctrl D channel controller for diagnostic messages or global options.
676 * \param pos Starting position to encode ASN.1 component.
677 * \param end End of ASN.1 encoding data buffer.
678 * \param args Arguments to encode in the buffer.
679 *
680 * \retval Start of the next ASN.1 component to encode on success.
681 * \retval NULL on error.
682 */
rose_enc_etsi_AOCDCurrency_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)683 unsigned char *rose_enc_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned char *pos,
684 unsigned char *end, const union rose_msg_invoke_args *args)
685 {
686 const struct roseEtsiAOCDCurrency_ARG *aoc_d;
687 unsigned char *seq_len;
688
689 aoc_d = &args->etsi.AOCDCurrency;
690 switch (aoc_d->type) {
691 case 0: /* charge_not_available */
692 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
693 break;
694 case 1: /* free_of_charge */
695 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
696 break;
697 case 2: /* specific_currency */
698 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
699
700 ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedCurrency(ctrl, pos, end,
701 ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_d->specific.recorded));
702 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
703 aoc_d->specific.type_of_charging_info));
704 if (aoc_d->specific.billing_id_present) {
705 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
706 aoc_d->specific.billing_id));
707 }
708
709 ASN1_CONSTRUCTED_END(seq_len, pos, end);
710 break;
711 default:
712 ASN1_ENC_ERROR(ctrl, "Unknown AOCDCurrency type");
713 return NULL;
714 }
715
716 return pos;
717 }
718
719 /*!
720 * \brief Encode the AOCDChargingUnit invoke facility ie arguments.
721 *
722 * \param ctrl D channel controller for diagnostic messages or global options.
723 * \param pos Starting position to encode ASN.1 component.
724 * \param end End of ASN.1 encoding data buffer.
725 * \param args Arguments to encode in the buffer.
726 *
727 * \retval Start of the next ASN.1 component to encode on success.
728 * \retval NULL on error.
729 */
rose_enc_etsi_AOCDChargingUnit_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)730 unsigned char *rose_enc_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
731 unsigned char *end, const union rose_msg_invoke_args *args)
732 {
733 const struct roseEtsiAOCDChargingUnit_ARG *aoc_d;
734 unsigned char *seq_len;
735
736 aoc_d = &args->etsi.AOCDChargingUnit;
737 switch (aoc_d->type) {
738 case 0: /* charge_not_available */
739 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
740 break;
741 case 1: /* free_of_charge */
742 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 1));
743 break;
744 case 2: /* specific_charging_units */
745 ASN1_CONSTRUCTED_BEGIN(seq_len, pos, end, ASN1_TAG_SEQUENCE);
746
747 ASN1_CALL(pos, rose_enc_etsi_AOC_RecordedUnitsList(ctrl, pos, end,
748 ASN1_CLASS_CONTEXT_SPECIFIC | 1, &aoc_d->specific.recorded));
749 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 2,
750 aoc_d->specific.type_of_charging_info));
751 if (aoc_d->specific.billing_id_present) {
752 ASN1_CALL(pos, asn1_enc_int(pos, end, ASN1_CLASS_CONTEXT_SPECIFIC | 3,
753 aoc_d->specific.billing_id));
754 }
755
756 ASN1_CONSTRUCTED_END(seq_len, pos, end);
757 break;
758 default:
759 ASN1_ENC_ERROR(ctrl, "Unknown AOCDChargingUnit type");
760 return NULL;
761 }
762
763 return pos;
764 }
765
766 /*!
767 * \brief Encode the AOCECurrency invoke facility ie arguments.
768 *
769 * \param ctrl D channel controller for diagnostic messages or global options.
770 * \param pos Starting position to encode ASN.1 component.
771 * \param end End of ASN.1 encoding data buffer.
772 * \param args Arguments to encode in the buffer.
773 *
774 * \retval Start of the next ASN.1 component to encode on success.
775 * \retval NULL on error.
776 */
rose_enc_etsi_AOCECurrency_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)777 unsigned char *rose_enc_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned char *pos,
778 unsigned char *end, const union rose_msg_invoke_args *args)
779 {
780 switch (args->etsi.AOCECurrency.type) {
781 case 0: /* charge_not_available */
782 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
783 break;
784 case 1: /* currency_info */
785 ASN1_CALL(pos, rose_enc_etsi_AOCECurrencyInfo(ctrl, pos, end, ASN1_TAG_SEQUENCE,
786 &args->etsi.AOCECurrency.currency_info));
787 break;
788 default:
789 ASN1_ENC_ERROR(ctrl, "Unknown AOCECurrency type");
790 return NULL;
791 }
792
793 return pos;
794 }
795
796 /*!
797 * \brief Encode the AOCEChargingUnit invoke facility ie arguments.
798 *
799 * \param ctrl D channel controller for diagnostic messages or global options.
800 * \param pos Starting position to encode ASN.1 component.
801 * \param end End of ASN.1 encoding data buffer.
802 * \param args Arguments to encode in the buffer.
803 *
804 * \retval Start of the next ASN.1 component to encode on success.
805 * \retval NULL on error.
806 */
rose_enc_etsi_AOCEChargingUnit_ARG(struct pri * ctrl,unsigned char * pos,unsigned char * end,const union rose_msg_invoke_args * args)807 unsigned char *rose_enc_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned char *pos,
808 unsigned char *end, const union rose_msg_invoke_args *args)
809 {
810 switch (args->etsi.AOCEChargingUnit.type) {
811 case 0: /* charge_not_available */
812 ASN1_CALL(pos, asn1_enc_null(pos, end, ASN1_TYPE_NULL));
813 break;
814 case 1: /* charging_unit */
815 ASN1_CALL(pos, rose_enc_etsi_AOCEChargingUnitInfo(ctrl, pos, end,
816 ASN1_TAG_SEQUENCE, &args->etsi.AOCEChargingUnit.charging_unit));
817 break;
818 default:
819 ASN1_ENC_ERROR(ctrl, "Unknown AOCEChargingUnit type");
820 return NULL;
821 }
822
823 return pos;
824 }
825
826 /*!
827 * \internal
828 * \brief Decode the Time type.
829 *
830 * \param ctrl D channel controller for diagnostic messages or global options.
831 * \param name Field name
832 * \param tag Component tag that identified this production.
833 * \param pos Starting position of the ASN.1 component length.
834 * \param end End of ASN.1 decoding data buffer.
835 * \param time Parameter storage to fill.
836 *
837 * \retval Start of the next ASN.1 component on success.
838 * \retval NULL on error.
839 */
rose_dec_etsi_AOC_Time(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCTime * time)840 static const unsigned char *rose_dec_etsi_AOC_Time(struct pri *ctrl, const char *name,
841 unsigned tag, const unsigned char *pos, const unsigned char *end,
842 struct roseEtsiAOCTime *time)
843 {
844 int32_t value;
845 int length;
846 int seq_offset;
847 const unsigned char *seq_end;
848
849 if (ctrl->debug & PRI_DEBUG_APDU) {
850 pri_message(ctrl, " %s Time %s\n", name, asn1_tag2str(tag));
851 }
852 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
853 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
854
855 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
856 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
857 ASN1_CALL(pos, asn1_dec_int(ctrl, "lengthOfTimeUnit", tag, pos, seq_end, &value));
858 time->length = value;
859
860 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
861 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
862 ASN1_CALL(pos, asn1_dec_int(ctrl, "scale", tag, pos, seq_end, &value));
863 time->scale = value;
864
865 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
866
867 return pos;
868 }
869
870 /*!
871 * \internal
872 * \brief Decode the Amount type.
873 *
874 * \param ctrl D channel controller for diagnostic messages or global options.
875 * \param name Field name
876 * \param tag Component tag that identified this production.
877 * \param pos Starting position of the ASN.1 component length.
878 * \param end End of ASN.1 decoding data buffer.
879 * \param amount Parameter storage to fill.
880 *
881 * \retval Start of the next ASN.1 component on success.
882 * \retval NULL on error.
883 */
rose_dec_etsi_AOC_Amount(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCAmount * amount)884 static const unsigned char *rose_dec_etsi_AOC_Amount(struct pri *ctrl, const char *name,
885 unsigned tag, const unsigned char *pos, const unsigned char *end,
886 struct roseEtsiAOCAmount *amount)
887 {
888 int32_t value;
889 int length;
890 int seq_offset;
891 const unsigned char *seq_end;
892
893 if (ctrl->debug & PRI_DEBUG_APDU) {
894 pri_message(ctrl, " %s Amount %s\n", name, asn1_tag2str(tag));
895 }
896 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
897 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
898
899 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
900 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
901 ASN1_CALL(pos, asn1_dec_int(ctrl, "currencyAmount", tag, pos, seq_end, &value));
902 amount->currency = value;
903
904 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
905 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
906 ASN1_CALL(pos, asn1_dec_int(ctrl, "multiplier", tag, pos, seq_end, &value));
907 amount->multiplier = value;
908
909 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
910
911 return pos;
912 }
913
914 /*!
915 * \internal
916 * \brief Decode the RecordedCurrency type.
917 *
918 * \param ctrl D channel controller for diagnostic messages or global options.
919 * \param name Field name
920 * \param tag Component tag that identified this production.
921 * \param pos Starting position of the ASN.1 component length.
922 * \param end End of ASN.1 decoding data buffer.
923 * \param recorded Parameter storage to fill.
924 *
925 * \retval Start of the next ASN.1 component on success.
926 * \retval NULL on error.
927 */
rose_dec_etsi_AOC_RecordedCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCRecordedCurrency * recorded)928 static const unsigned char *rose_dec_etsi_AOC_RecordedCurrency(struct pri *ctrl,
929 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
930 struct roseEtsiAOCRecordedCurrency *recorded)
931 {
932 int length;
933 int seq_offset;
934 const unsigned char *seq_end;
935 size_t str_len;
936
937 if (ctrl->debug & PRI_DEBUG_APDU) {
938 pri_message(ctrl, " %s RecordedCurrency %s\n", name, asn1_tag2str(tag));
939 }
940 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
941 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
942
943 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
944 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
945 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "rCurrency", tag, pos, seq_end,
946 sizeof(recorded->currency), recorded->currency, &str_len));
947
948 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
949 ASN1_CHECK_TAG(ctrl, tag, tag,
950 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
951 ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "rAmount", tag, pos, seq_end,
952 &recorded->amount));
953
954 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
955
956 return pos;
957 }
958
959 /*!
960 * \internal
961 * \brief Decode the DurationCurrency type.
962 *
963 * \param ctrl D channel controller for diagnostic messages or global options.
964 * \param name Field name
965 * \param tag Component tag that identified this production.
966 * \param pos Starting position of the ASN.1 component length.
967 * \param end End of ASN.1 decoding data buffer.
968 * \param duration Parameter storage to fill.
969 *
970 * \retval Start of the next ASN.1 component on success.
971 * \retval NULL on error.
972 */
rose_dec_etsi_AOC_DurationCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCDurationCurrency * duration)973 static const unsigned char *rose_dec_etsi_AOC_DurationCurrency(struct pri *ctrl,
974 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
975 struct roseEtsiAOCDurationCurrency *duration)
976 {
977 int32_t value;
978 int length;
979 int seq_offset;
980 const unsigned char *seq_end;
981 size_t str_len;
982
983 if (ctrl->debug & PRI_DEBUG_APDU) {
984 pri_message(ctrl, " %s DurationCurrency %s\n", name, asn1_tag2str(tag));
985 }
986 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
987 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
988
989 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
990 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
991 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "dCurrency", tag, pos, seq_end,
992 sizeof(duration->currency), duration->currency, &str_len));
993
994 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
995 ASN1_CHECK_TAG(ctrl, tag, tag,
996 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
997 ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "dAmount", tag, pos, seq_end,
998 &duration->amount));
999
1000 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1001 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
1002 ASN1_CALL(pos, asn1_dec_int(ctrl, "dChargingType", tag, pos, seq_end, &value));
1003 duration->charging_type = value;
1004
1005 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1006 ASN1_CHECK_TAG(ctrl, tag, tag,
1007 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 4);
1008 ASN1_CALL(pos, rose_dec_etsi_AOC_Time(ctrl, "dTime", tag, pos, seq_end,
1009 &duration->time));
1010
1011 if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1012 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1013 ASN1_CHECK_TAG(ctrl, tag, tag,
1014 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 5);
1015 ASN1_CALL(pos, rose_dec_etsi_AOC_Time(ctrl, "dGranularity", tag, pos, seq_end,
1016 &duration->granularity));
1017 duration->granularity_present = 1;
1018 } else {
1019 duration->granularity_present = 0;
1020 }
1021
1022 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1023
1024 return pos;
1025 }
1026
1027 /*!
1028 * \internal
1029 * \brief Decode the FlatRateCurrency type.
1030 *
1031 * \param ctrl D channel controller for diagnostic messages or global options.
1032 * \param name Field name
1033 * \param tag Component tag that identified this production.
1034 * \param pos Starting position of the ASN.1 component length.
1035 * \param end End of ASN.1 decoding data buffer.
1036 * \param flat_rate Parameter storage to fill.
1037 *
1038 * \retval Start of the next ASN.1 component on success.
1039 * \retval NULL on error.
1040 */
rose_dec_etsi_AOC_FlatRateCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCFlatRateCurrency * flat_rate)1041 static const unsigned char *rose_dec_etsi_AOC_FlatRateCurrency(struct pri *ctrl,
1042 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1043 struct roseEtsiAOCFlatRateCurrency *flat_rate)
1044 {
1045 int length;
1046 int seq_offset;
1047 const unsigned char *seq_end;
1048 size_t str_len;
1049
1050 if (ctrl->debug & PRI_DEBUG_APDU) {
1051 pri_message(ctrl, " %s FlatRateCurrency %s\n", name, asn1_tag2str(tag));
1052 }
1053 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1054 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1055
1056 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1057 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
1058 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "fRCurrency", tag, pos, seq_end,
1059 sizeof(flat_rate->currency), flat_rate->currency, &str_len));
1060
1061 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1062 ASN1_CHECK_TAG(ctrl, tag, tag,
1063 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
1064 ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "fRAmount", tag, pos, seq_end,
1065 &flat_rate->amount));
1066
1067 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1068
1069 return pos;
1070 }
1071
1072 /*!
1073 * \internal
1074 * \brief Decode the VolumeRateCurrency type.
1075 *
1076 * \param ctrl D channel controller for diagnostic messages or global options.
1077 * \param name Field name
1078 * \param tag Component tag that identified this production.
1079 * \param pos Starting position of the ASN.1 component length.
1080 * \param end End of ASN.1 decoding data buffer.
1081 * \param volume_rate Parameter storage to fill.
1082 *
1083 * \retval Start of the next ASN.1 component on success.
1084 * \retval NULL on error.
1085 */
rose_dec_etsi_AOC_VolumeRateCurrency(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCVolumeRateCurrency * volume_rate)1086 static const unsigned char *rose_dec_etsi_AOC_VolumeRateCurrency(struct pri *ctrl,
1087 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1088 struct roseEtsiAOCVolumeRateCurrency *volume_rate)
1089 {
1090 int32_t value;
1091 int length;
1092 int seq_offset;
1093 const unsigned char *seq_end;
1094 size_t str_len;
1095
1096 if (ctrl->debug & PRI_DEBUG_APDU) {
1097 pri_message(ctrl, " %s VolumeRateCurrency %s\n", name, asn1_tag2str(tag));
1098 }
1099 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1100 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1101
1102 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1103 ASN1_CHECK_TAG(ctrl, tag & ~ASN1_PC_MASK, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 1);
1104 ASN1_CALL(pos, asn1_dec_string_max(ctrl, "vRCurrency", tag, pos, seq_end,
1105 sizeof(volume_rate->currency), volume_rate->currency, &str_len));
1106
1107 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1108 ASN1_CHECK_TAG(ctrl, tag, tag,
1109 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2);
1110 ASN1_CALL(pos, rose_dec_etsi_AOC_Amount(ctrl, "vRAmount", tag, pos, seq_end,
1111 &volume_rate->amount));
1112
1113 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1114 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
1115 ASN1_CALL(pos, asn1_dec_int(ctrl, "vRVolumeUnit", tag, pos, seq_end, &value));
1116 volume_rate->unit = value;
1117
1118 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1119
1120 return pos;
1121 }
1122
1123 /*!
1124 * \internal
1125 * \brief Decode the AOCSCurrencyInfo type.
1126 *
1127 * \param ctrl D channel controller for diagnostic messages or global options.
1128 * \param name Field name
1129 * \param tag Component tag that identified this production.
1130 * \param pos Starting position of the ASN.1 component length.
1131 * \param end End of ASN.1 decoding data buffer.
1132 * \param currency_info Parameter storage to fill.
1133 *
1134 * \retval Start of the next ASN.1 component on success.
1135 * \retval NULL on error.
1136 */
rose_dec_etsi_AOCSCurrencyInfo(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCSCurrencyInfo * currency_info)1137 static const unsigned char *rose_dec_etsi_AOCSCurrencyInfo(struct pri *ctrl,
1138 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1139 struct roseEtsiAOCSCurrencyInfo *currency_info)
1140 {
1141 int32_t value;
1142 int length;
1143 int seq_offset;
1144 const unsigned char *seq_end;
1145
1146 if (ctrl->debug & PRI_DEBUG_APDU) {
1147 pri_message(ctrl, " %s AOCSCurrencyInfo %s\n", name, asn1_tag2str(tag));
1148 }
1149 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1150 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1151
1152 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1153 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
1154 ASN1_CALL(pos, asn1_dec_int(ctrl, "chargedItem", tag, pos, seq_end, &value));
1155 currency_info->charged_item = value;
1156
1157 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1158 switch (tag) {
1159 case ASN1_TYPE_INTEGER:
1160 currency_info->currency_type = 0; /* specialChargingCode */
1161 ASN1_CALL(pos, asn1_dec_int(ctrl, "specialChargingCode", tag, pos, seq_end,
1162 &value));
1163 currency_info->u.special_charging_code = value;
1164 break;
1165 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1:
1166 currency_info->currency_type = 1; /* durationCurrency */
1167 ASN1_CALL(pos, rose_dec_etsi_AOC_DurationCurrency(ctrl, "durationCurrency", tag,
1168 pos, seq_end, ¤cy_info->u.duration));
1169 break;
1170 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 2:
1171 currency_info->currency_type = 2; /* flatRateCurrency */
1172 ASN1_CALL(pos, rose_dec_etsi_AOC_FlatRateCurrency(ctrl, "flatRateCurrency", tag,
1173 pos, seq_end, ¤cy_info->u.flat_rate));
1174 break;
1175 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 3:
1176 currency_info->currency_type = 3; /* volumeRateCurrency */
1177 ASN1_CALL(pos, rose_dec_etsi_AOC_VolumeRateCurrency(ctrl, "volumeRateCurrency",
1178 tag, pos, seq_end, ¤cy_info->u.volume_rate));
1179 break;
1180 case ASN1_CLASS_CONTEXT_SPECIFIC | 4:
1181 currency_info->currency_type = 4; /* freeOfCharge */
1182 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
1183 break;
1184 case ASN1_CLASS_CONTEXT_SPECIFIC | 5:
1185 currency_info->currency_type = 5; /* currencyInfoNotAvailable */
1186 ASN1_CALL(pos, asn1_dec_null(ctrl, "currencyInfoNotAvailable", tag, pos,
1187 seq_end));
1188 break;
1189 default:
1190 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1191 return NULL;
1192 }
1193
1194 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1195
1196 return pos;
1197 }
1198
1199 /*!
1200 * \internal
1201 * \brief Decode the AOCSCurrencyInfoList type.
1202 *
1203 * \param ctrl D channel controller for diagnostic messages or global options.
1204 * \param name Field name
1205 * \param tag Component tag that identified this production.
1206 * \param pos Starting position of the ASN.1 component length.
1207 * \param end End of ASN.1 decoding data buffer.
1208 * \param currency_info Parameter storage to fill.
1209 *
1210 * \retval Start of the next ASN.1 component on success.
1211 * \retval NULL on error.
1212 */
rose_dec_etsi_AOCSCurrencyInfoList(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCSCurrencyInfoList * currency_info)1213 static const unsigned char *rose_dec_etsi_AOCSCurrencyInfoList(struct pri *ctrl,
1214 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1215 struct roseEtsiAOCSCurrencyInfoList *currency_info)
1216 {
1217 int length;
1218 int seq_offset;
1219 const unsigned char *seq_end;
1220
1221 if (ctrl->debug & PRI_DEBUG_APDU) {
1222 pri_message(ctrl, " %s AOCSCurrencyInfoList %s\n", name, asn1_tag2str(tag));
1223 }
1224 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1225 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1226
1227 currency_info->num_records = 0;
1228 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1229 if (currency_info->num_records < ARRAY_LEN(currency_info->list)) {
1230 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1231 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1232 ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfo(ctrl, "listEntry", tag, pos,
1233 seq_end, ¤cy_info->list[currency_info->num_records]));
1234 ++currency_info->num_records;
1235 } else {
1236 /* Too many records */
1237 return NULL;
1238 }
1239 }
1240
1241 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1242
1243 return pos;
1244 }
1245
1246 /*!
1247 * \internal
1248 * \brief Decode the RecordedUnits type.
1249 *
1250 * \param ctrl D channel controller for diagnostic messages or global options.
1251 * \param name Field name
1252 * \param tag Component tag that identified this production.
1253 * \param pos Starting position of the ASN.1 component length.
1254 * \param end End of ASN.1 decoding data buffer.
1255 * \param recorded Parameter storage to fill.
1256 *
1257 * \retval Start of the next ASN.1 component on success.
1258 * \retval NULL on error.
1259 */
rose_dec_etsi_AOC_RecordedUnits(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCRecordedUnits * recorded)1260 static const unsigned char *rose_dec_etsi_AOC_RecordedUnits(struct pri *ctrl,
1261 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1262 struct roseEtsiAOCRecordedUnits *recorded)
1263 {
1264 int32_t value;
1265 int length;
1266 int seq_offset;
1267 const unsigned char *seq_end;
1268
1269 if (ctrl->debug & PRI_DEBUG_APDU) {
1270 pri_message(ctrl, " %s RecordedUnits %s\n", name, asn1_tag2str(tag));
1271 }
1272 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1273 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1274
1275 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1276 switch (tag) {
1277 case ASN1_TYPE_INTEGER:
1278 recorded->not_available = 0;
1279 ASN1_CALL(pos, asn1_dec_int(ctrl, "recordedNumberOfUnits", tag, pos, seq_end,
1280 &value));
1281 recorded->number_of_units = value;
1282 break;
1283 case ASN1_TYPE_NULL:
1284 recorded->not_available = 1;
1285 recorded->number_of_units = 0;
1286 ASN1_CALL(pos, asn1_dec_null(ctrl, "notAvailable", tag, pos, seq_end));
1287 break;
1288 default:
1289 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1290 return NULL;
1291 }
1292
1293 if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1294 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1295 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_INTEGER);
1296 ASN1_CALL(pos, asn1_dec_int(ctrl, "recordedTypeOfUnits", tag, pos, seq_end,
1297 &value));
1298 recorded->type_of_unit = value;
1299 recorded->type_of_unit_present = 1;
1300 } else {
1301 recorded->type_of_unit_present = 0;
1302 }
1303
1304 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1305
1306 return pos;
1307 }
1308
1309 /*!
1310 * \internal
1311 * \brief Decode the RecordedUnitsList type.
1312 *
1313 * \param ctrl D channel controller for diagnostic messages or global options.
1314 * \param name Field name
1315 * \param tag Component tag that identified this production.
1316 * \param pos Starting position of the ASN.1 component length.
1317 * \param end End of ASN.1 decoding data buffer.
1318 * \param recorded_info Parameter storage to fill.
1319 *
1320 * \retval Start of the next ASN.1 component on success.
1321 * \retval NULL on error.
1322 */
rose_dec_etsi_AOC_RecordedUnitsList(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCRecordedUnitsList * recorded_info)1323 static const unsigned char *rose_dec_etsi_AOC_RecordedUnitsList(struct pri *ctrl,
1324 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1325 struct roseEtsiAOCRecordedUnitsList *recorded_info)
1326 {
1327 int length;
1328 int seq_offset;
1329 const unsigned char *seq_end;
1330
1331 if (ctrl->debug & PRI_DEBUG_APDU) {
1332 pri_message(ctrl, " %s RecordedUnitsList %s\n", name, asn1_tag2str(tag));
1333 }
1334 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1335 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1336
1337 recorded_info->num_records = 0;
1338 while (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1339 if (recorded_info->num_records < ARRAY_LEN(recorded_info->list)) {
1340 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1341 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TAG_SEQUENCE);
1342 ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnits(ctrl, "listEntry", tag, pos,
1343 seq_end, &recorded_info->list[recorded_info->num_records]));
1344 ++recorded_info->num_records;
1345 } else {
1346 /* Too many records */
1347 return NULL;
1348 }
1349 }
1350
1351 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1352
1353 return pos;
1354 }
1355
1356 /*!
1357 * \internal
1358 * \brief Decode the ChargingAssociation type.
1359 *
1360 * \param ctrl D channel controller for diagnostic messages or global options.
1361 * \param name Field name
1362 * \param tag Component tag that identified this production.
1363 * \param pos Starting position of the ASN.1 component length.
1364 * \param end End of ASN.1 decoding data buffer.
1365 * \param charging Parameter storage to fill.
1366 *
1367 * \retval Start of the next ASN.1 component on success.
1368 * \retval NULL on error.
1369 */
rose_dec_etsi_AOC_ChargingAssociation(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCChargingAssociation * charging)1370 static const unsigned char *rose_dec_etsi_AOC_ChargingAssociation(struct pri *ctrl,
1371 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1372 struct roseEtsiAOCChargingAssociation *charging)
1373 {
1374 int32_t value;
1375 int length;
1376 int explicit_offset;
1377 const unsigned char *explicit_end;
1378
1379 if (ctrl->debug & PRI_DEBUG_APDU) {
1380 pri_message(ctrl, " %s ChargingAssociation\n", name);
1381 }
1382 switch (tag) {
1383 case ASN1_TYPE_INTEGER:
1384 charging->type = 0; /* charge_identifier */
1385 ASN1_CALL(pos, asn1_dec_int(ctrl, "chargeIdentifier", tag, pos, end, &value));
1386 charging->id = value;
1387 break;
1388 case ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 0:
1389 charging->type = 1; /* charged_number */
1390
1391 /* Remove EXPLICIT tag */
1392 if (ctrl->debug & PRI_DEBUG_APDU) {
1393 pri_message(ctrl, " Explicit %s\n", asn1_tag2str(tag));
1394 }
1395 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1396 ASN1_END_SETUP(explicit_end, explicit_offset, length, pos, end);
1397
1398 ASN1_CALL(pos, asn1_dec_tag(pos, explicit_end, &tag));
1399 ASN1_CALL(pos, rose_dec_PartyNumber(ctrl, "chargedNumber", tag, pos,
1400 explicit_end, &charging->number));
1401
1402 ASN1_END_FIXUP(ctrl, pos, explicit_offset, explicit_end, end);
1403 break;
1404 default:
1405 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1406 return NULL;
1407 }
1408
1409 return pos;
1410 }
1411
1412 /*!
1413 * \internal
1414 * \brief Decode the AOCECurrencyInfo type.
1415 *
1416 * \param ctrl D channel controller for diagnostic messages or global options.
1417 * \param name Field name
1418 * \param tag Component tag that identified this production.
1419 * \param pos Starting position of the ASN.1 component length.
1420 * \param end End of ASN.1 decoding data buffer.
1421 * \param currency_info Parameter storage to fill.
1422 *
1423 * \retval Start of the next ASN.1 component on success.
1424 * \retval NULL on error.
1425 */
rose_dec_etsi_AOCECurrencyInfo(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCECurrencyInfo * currency_info)1426 static const unsigned char *rose_dec_etsi_AOCECurrencyInfo(struct pri *ctrl,
1427 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1428 struct roseEtsiAOCECurrencyInfo *currency_info)
1429 {
1430 int32_t value;
1431 int length;
1432 int seq_offset;
1433 int specific_offset;
1434 const unsigned char *seq_end;
1435 const unsigned char *specific_end;
1436
1437 if (ctrl->debug & PRI_DEBUG_APDU) {
1438 pri_message(ctrl, " %s AOCECurrencyInfo %s\n", name, asn1_tag2str(tag));
1439 }
1440 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1441 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1442
1443 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1444 switch (tag) {
1445 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
1446 currency_info->free_of_charge = 1;
1447 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
1448 break;
1449 case ASN1_TAG_SEQUENCE:
1450 currency_info->free_of_charge = 0;
1451 if (ctrl->debug & PRI_DEBUG_APDU) {
1452 pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
1453 }
1454 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1455 ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
1456
1457 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1458 ASN1_CHECK_TAG(ctrl, tag, tag,
1459 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
1460 ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
1461 pos, specific_end, ¤cy_info->specific.recorded));
1462
1463 if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
1464 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1465 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
1466 ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, specific_end,
1467 &value));
1468 currency_info->specific.billing_id = value;
1469 currency_info->specific.billing_id_present = 1;
1470 } else {
1471 currency_info->specific.billing_id_present = 0;
1472 }
1473
1474 ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
1475 break;
1476 default:
1477 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1478 return NULL;
1479 }
1480
1481 if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1482 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1483 ASN1_CALL(pos, rose_dec_etsi_AOC_ChargingAssociation(ctrl, "chargingAssociation",
1484 tag, pos, seq_end, ¤cy_info->charging_association));
1485 currency_info->charging_association_present = 1;
1486 } else {
1487 currency_info->charging_association_present = 0;
1488 }
1489
1490 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1491
1492 return pos;
1493 }
1494
1495 /*!
1496 * \internal
1497 * \brief Decode the AOCEChargingUnitInfo type.
1498 *
1499 * \param ctrl D channel controller for diagnostic messages or global options.
1500 * \param name Field name
1501 * \param tag Component tag that identified this production.
1502 * \param pos Starting position of the ASN.1 component length.
1503 * \param end End of ASN.1 decoding data buffer.
1504 * \param charging_unit Parameter storage to fill.
1505 *
1506 * \retval Start of the next ASN.1 component on success.
1507 * \retval NULL on error.
1508 */
rose_dec_etsi_AOCEChargingUnitInfo(struct pri * ctrl,const char * name,unsigned tag,const unsigned char * pos,const unsigned char * end,struct roseEtsiAOCEChargingUnitInfo * charging_unit)1509 static const unsigned char *rose_dec_etsi_AOCEChargingUnitInfo(struct pri *ctrl,
1510 const char *name, unsigned tag, const unsigned char *pos, const unsigned char *end,
1511 struct roseEtsiAOCEChargingUnitInfo *charging_unit)
1512 {
1513 int32_t value;
1514 int length;
1515 int seq_offset;
1516 int specific_offset;
1517 const unsigned char *seq_end;
1518 const unsigned char *specific_end;
1519
1520 if (ctrl->debug & PRI_DEBUG_APDU) {
1521 pri_message(ctrl, " %s AOCEChargingUnitInfo %s\n", name, asn1_tag2str(tag));
1522 }
1523 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1524 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1525
1526 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1527 switch (tag) {
1528 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
1529 charging_unit->free_of_charge = 1;
1530 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, seq_end));
1531 break;
1532 case ASN1_TAG_SEQUENCE:
1533 charging_unit->free_of_charge = 0;
1534 if (ctrl->debug & PRI_DEBUG_APDU) {
1535 pri_message(ctrl, " specificChargingUnits %s\n", asn1_tag2str(tag));
1536 }
1537 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1538 ASN1_END_SETUP(specific_end, specific_offset, length, pos, seq_end);
1539
1540 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1541 ASN1_CHECK_TAG(ctrl, tag, tag,
1542 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
1543 ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnitsList(ctrl, "recordedUnitsList",
1544 tag, pos, specific_end, &charging_unit->specific.recorded));
1545
1546 if (pos < specific_end && *pos != ASN1_INDEF_TERM) {
1547 ASN1_CALL(pos, asn1_dec_tag(pos, specific_end, &tag));
1548 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
1549 ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, specific_end,
1550 &value));
1551 charging_unit->specific.billing_id = value;
1552 charging_unit->specific.billing_id_present = 1;
1553 } else {
1554 charging_unit->specific.billing_id_present = 0;
1555 }
1556
1557 ASN1_END_FIXUP(ctrl, pos, specific_offset, specific_end, seq_end);
1558 break;
1559 default:
1560 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1561 return NULL;
1562 }
1563
1564 if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1565 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1566 ASN1_CALL(pos, rose_dec_etsi_AOC_ChargingAssociation(ctrl, "chargingAssociation",
1567 tag, pos, seq_end, &charging_unit->charging_association));
1568 charging_unit->charging_association_present = 1;
1569 } else {
1570 charging_unit->charging_association_present = 0;
1571 }
1572
1573 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1574
1575 return pos;
1576 }
1577
1578 /*!
1579 * \brief Decode the ChargingRequest invoke argument parameters.
1580 *
1581 * \param ctrl D channel controller for diagnostic messages or global options.
1582 * \param tag Component tag that identified this structure.
1583 * \param pos Starting position of the ASN.1 component length.
1584 * \param end End of ASN.1 decoding data buffer.
1585 * \param args Arguments to fill in from the decoded buffer.
1586 *
1587 * \retval Start of the next ASN.1 component on success.
1588 * \retval NULL on error.
1589 */
rose_dec_etsi_ChargingRequest_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1590 const unsigned char *rose_dec_etsi_ChargingRequest_ARG(struct pri *ctrl, unsigned tag,
1591 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1592 {
1593 int32_t value;
1594
1595 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_TYPE_ENUMERATED);
1596 ASN1_CALL(pos, asn1_dec_int(ctrl, "chargingCase", tag, pos, end, &value));
1597 args->etsi.ChargingRequest.charging_case = value;
1598
1599 return pos;
1600 }
1601
1602 /*!
1603 * \brief Decode the ChargingRequest result parameters.
1604 *
1605 * \param ctrl D channel controller for diagnostic messages or global options.
1606 * \param tag Component tag that identified this structure.
1607 * \param pos Starting position of the ASN.1 component length.
1608 * \param end End of ASN.1 decoding data buffer.
1609 * \param args Arguments to fill in from the decoded buffer.
1610 *
1611 * \retval Start of the next ASN.1 component on success.
1612 * \retval NULL on error.
1613 */
rose_dec_etsi_ChargingRequest_RES(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_result_args * args)1614 const unsigned char *rose_dec_etsi_ChargingRequest_RES(struct pri *ctrl, unsigned tag,
1615 const unsigned char *pos, const unsigned char *end, union rose_msg_result_args *args)
1616 {
1617 struct roseEtsiChargingRequest_RES *charging_request;
1618 int32_t value;
1619
1620 charging_request = &args->etsi.ChargingRequest;
1621 switch (tag) {
1622 case ASN1_TAG_SEQUENCE:
1623 charging_request->type = 0; /* currency_info_list */
1624 ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfoList(ctrl, "currencyList", tag, pos,
1625 end, &charging_request->u.currency_info));
1626 break;
1627 case ASN1_TYPE_INTEGER:
1628 charging_request->type = 1; /* special_arrangement_info */
1629 ASN1_CALL(pos, asn1_dec_int(ctrl, "specialArrangement", tag, pos, end, &value));
1630 charging_request->u.special_arrangement = value;
1631 break;
1632 case ASN1_TYPE_NULL:
1633 charging_request->type = 2; /* charging_info_follows */
1634 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargingInfoFollows", tag, pos, end));
1635 break;
1636 default:
1637 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1638 return NULL;
1639 }
1640
1641 return pos;
1642 }
1643
1644 /*!
1645 * \brief Decode the AOCSCurrency invoke argument parameters.
1646 *
1647 * \param ctrl D channel controller for diagnostic messages or global options.
1648 * \param tag Component tag that identified this structure.
1649 * \param pos Starting position of the ASN.1 component length.
1650 * \param end End of ASN.1 decoding data buffer.
1651 * \param args Arguments to fill in from the decoded buffer.
1652 *
1653 * \retval Start of the next ASN.1 component on success.
1654 * \retval NULL on error.
1655 */
rose_dec_etsi_AOCSCurrency_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1656 const unsigned char *rose_dec_etsi_AOCSCurrency_ARG(struct pri *ctrl, unsigned tag,
1657 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1658 {
1659 struct roseEtsiAOCSCurrency_ARG *aoc_s;
1660
1661 aoc_s = &args->etsi.AOCSCurrency;
1662 switch (tag) {
1663 case ASN1_TYPE_NULL:
1664 aoc_s->type = 0; /* charge_not_available */
1665 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
1666 break;
1667 case ASN1_TAG_SEQUENCE:
1668 aoc_s->type = 1; /* currency_info_list */
1669 ASN1_CALL(pos, rose_dec_etsi_AOCSCurrencyInfoList(ctrl, "currencyInfo", tag, pos,
1670 end, &aoc_s->currency_info));
1671 break;
1672 default:
1673 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1674 return NULL;
1675 }
1676
1677 return pos;
1678 }
1679
1680 /*!
1681 * \brief Decode the AOCSSpecialArr invoke argument parameters.
1682 *
1683 * \param ctrl D channel controller for diagnostic messages or global options.
1684 * \param tag Component tag that identified this structure.
1685 * \param pos Starting position of the ASN.1 component length.
1686 * \param end End of ASN.1 decoding data buffer.
1687 * \param args Arguments to fill in from the decoded buffer.
1688 *
1689 * \retval Start of the next ASN.1 component on success.
1690 * \retval NULL on error.
1691 */
rose_dec_etsi_AOCSSpecialArr_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1692 const unsigned char *rose_dec_etsi_AOCSSpecialArr_ARG(struct pri *ctrl, unsigned tag,
1693 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1694 {
1695 struct roseEtsiAOCSSpecialArr_ARG *aoc_s;
1696 int32_t value;
1697
1698 aoc_s = &args->etsi.AOCSSpecialArr;
1699 switch (tag) {
1700 case ASN1_TYPE_NULL:
1701 aoc_s->type = 0; /* charge_not_available */
1702 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
1703 break;
1704 case ASN1_TYPE_INTEGER:
1705 aoc_s->type = 1; /* special_arrangement_info */
1706 ASN1_CALL(pos, asn1_dec_int(ctrl, "specialArrangement", tag, pos, end, &value));
1707 aoc_s->special_arrangement = value;
1708 break;
1709 default:
1710 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1711 return NULL;
1712 }
1713
1714 return pos;
1715 }
1716
1717 /*!
1718 * \brief Decode the AOCDCurrency invoke argument parameters.
1719 *
1720 * \param ctrl D channel controller for diagnostic messages or global options.
1721 * \param tag Component tag that identified this structure.
1722 * \param pos Starting position of the ASN.1 component length.
1723 * \param end End of ASN.1 decoding data buffer.
1724 * \param args Arguments to fill in from the decoded buffer.
1725 *
1726 * \retval Start of the next ASN.1 component on success.
1727 * \retval NULL on error.
1728 */
rose_dec_etsi_AOCDCurrency_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1729 const unsigned char *rose_dec_etsi_AOCDCurrency_ARG(struct pri *ctrl, unsigned tag,
1730 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1731 {
1732 struct roseEtsiAOCDCurrency_ARG *aoc_d;
1733 int length;
1734 int seq_offset;
1735 const unsigned char *seq_end;
1736 int32_t value;
1737
1738 aoc_d = &args->etsi.AOCDCurrency;
1739 switch (tag) {
1740 case ASN1_TYPE_NULL:
1741 aoc_d->type = 0; /* charge_not_available */
1742 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
1743 break;
1744 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
1745 aoc_d->type = 1; /* free_of_charge */
1746 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, end));
1747 break;
1748 case ASN1_TAG_SEQUENCE:
1749 aoc_d->type = 2; /* specific_currency */
1750
1751 if (ctrl->debug & PRI_DEBUG_APDU) {
1752 pri_message(ctrl, " specificCurrency %s\n", asn1_tag2str(tag));
1753 }
1754 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1755 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1756
1757 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1758 ASN1_CHECK_TAG(ctrl, tag, tag,
1759 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
1760 ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedCurrency(ctrl, "recordedCurrency", tag,
1761 pos, seq_end, &aoc_d->specific.recorded));
1762
1763 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1764 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
1765 ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfChargingInfo", tag, pos, seq_end,
1766 &value));
1767 aoc_d->specific.type_of_charging_info = value;
1768
1769 if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1770 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1771 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
1772 ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, seq_end, &value));
1773 aoc_d->specific.billing_id = value;
1774 aoc_d->specific.billing_id_present = 1;
1775 } else {
1776 aoc_d->specific.billing_id_present = 0;
1777 }
1778
1779 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1780 break;
1781 default:
1782 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1783 return NULL;
1784 }
1785
1786 return pos;
1787 }
1788
1789 /*!
1790 * \brief Decode the AOCDChargingUnit invoke argument parameters.
1791 *
1792 * \param ctrl D channel controller for diagnostic messages or global options.
1793 * \param tag Component tag that identified this structure.
1794 * \param pos Starting position of the ASN.1 component length.
1795 * \param end End of ASN.1 decoding data buffer.
1796 * \param args Arguments to fill in from the decoded buffer.
1797 *
1798 * \retval Start of the next ASN.1 component on success.
1799 * \retval NULL on error.
1800 */
rose_dec_etsi_AOCDChargingUnit_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1801 const unsigned char *rose_dec_etsi_AOCDChargingUnit_ARG(struct pri *ctrl, unsigned tag,
1802 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1803 {
1804 struct roseEtsiAOCDChargingUnit_ARG *aoc_d;
1805 int length;
1806 int seq_offset;
1807 const unsigned char *seq_end;
1808 int32_t value;
1809
1810 aoc_d = &args->etsi.AOCDChargingUnit;
1811 switch (tag) {
1812 case ASN1_TYPE_NULL:
1813 aoc_d->type = 0; /* charge_not_available */
1814 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
1815 break;
1816 case ASN1_CLASS_CONTEXT_SPECIFIC | 1:
1817 aoc_d->type = 1; /* free_of_charge */
1818 ASN1_CALL(pos, asn1_dec_null(ctrl, "freeOfCharge", tag, pos, end));
1819 break;
1820 case ASN1_TAG_SEQUENCE:
1821 aoc_d->type = 2; /* specific_charging_units */
1822
1823 if (ctrl->debug & PRI_DEBUG_APDU) {
1824 pri_message(ctrl, " specificChargingUnits %s\n", asn1_tag2str(tag));
1825 }
1826 ASN1_CALL(pos, asn1_dec_length(pos, end, &length));
1827 ASN1_END_SETUP(seq_end, seq_offset, length, pos, end);
1828
1829 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1830 ASN1_CHECK_TAG(ctrl, tag, tag,
1831 ASN1_CLASS_CONTEXT_SPECIFIC | ASN1_PC_CONSTRUCTED | 1);
1832 ASN1_CALL(pos, rose_dec_etsi_AOC_RecordedUnitsList(ctrl, "recordedUnitsList",
1833 tag, pos, seq_end, &aoc_d->specific.recorded));
1834
1835 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1836 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 2);
1837 ASN1_CALL(pos, asn1_dec_int(ctrl, "typeOfChargingInfo", tag, pos, seq_end,
1838 &value));
1839 aoc_d->specific.type_of_charging_info = value;
1840
1841 if (pos < seq_end && *pos != ASN1_INDEF_TERM) {
1842 ASN1_CALL(pos, asn1_dec_tag(pos, seq_end, &tag));
1843 ASN1_CHECK_TAG(ctrl, tag, tag, ASN1_CLASS_CONTEXT_SPECIFIC | 3);
1844 ASN1_CALL(pos, asn1_dec_int(ctrl, "billingId", tag, pos, seq_end, &value));
1845 aoc_d->specific.billing_id = value;
1846 aoc_d->specific.billing_id_present = 1;
1847 } else {
1848 aoc_d->specific.billing_id_present = 0;
1849 }
1850
1851 ASN1_END_FIXUP(ctrl, pos, seq_offset, seq_end, end);
1852 break;
1853 default:
1854 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1855 return NULL;
1856 }
1857
1858 return pos;
1859 }
1860
1861 /*!
1862 * \brief Decode the AOCECurrency invoke argument parameters.
1863 *
1864 * \param ctrl D channel controller for diagnostic messages or global options.
1865 * \param tag Component tag that identified this structure.
1866 * \param pos Starting position of the ASN.1 component length.
1867 * \param end End of ASN.1 decoding data buffer.
1868 * \param args Arguments to fill in from the decoded buffer.
1869 *
1870 * \retval Start of the next ASN.1 component on success.
1871 * \retval NULL on error.
1872 */
rose_dec_etsi_AOCECurrency_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1873 const unsigned char *rose_dec_etsi_AOCECurrency_ARG(struct pri *ctrl, unsigned tag,
1874 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1875 {
1876 struct roseEtsiAOCECurrency_ARG *aoc_e;
1877
1878 aoc_e = &args->etsi.AOCECurrency;
1879 switch (tag) {
1880 case ASN1_TYPE_NULL:
1881 aoc_e->type = 0; /* charge_not_available */
1882 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
1883 break;
1884 case ASN1_TAG_SEQUENCE:
1885 aoc_e->type = 1; /* currency_info */
1886 ASN1_CALL(pos, rose_dec_etsi_AOCECurrencyInfo(ctrl, "currencyInfo", tag, pos,
1887 end, &aoc_e->currency_info));
1888 break;
1889 default:
1890 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1891 return NULL;
1892 }
1893
1894 return pos;
1895 }
1896
1897 /*!
1898 * \brief Decode the AOCEChargingUnit invoke argument parameters.
1899 *
1900 * \param ctrl D channel controller for diagnostic messages or global options.
1901 * \param tag Component tag that identified this structure.
1902 * \param pos Starting position of the ASN.1 component length.
1903 * \param end End of ASN.1 decoding data buffer.
1904 * \param args Arguments to fill in from the decoded buffer.
1905 *
1906 * \retval Start of the next ASN.1 component on success.
1907 * \retval NULL on error.
1908 */
rose_dec_etsi_AOCEChargingUnit_ARG(struct pri * ctrl,unsigned tag,const unsigned char * pos,const unsigned char * end,union rose_msg_invoke_args * args)1909 const unsigned char *rose_dec_etsi_AOCEChargingUnit_ARG(struct pri *ctrl, unsigned tag,
1910 const unsigned char *pos, const unsigned char *end, union rose_msg_invoke_args *args)
1911 {
1912 struct roseEtsiAOCEChargingUnit_ARG *aoc_e;
1913
1914 aoc_e = &args->etsi.AOCEChargingUnit;
1915 switch (tag) {
1916 case ASN1_TYPE_NULL:
1917 aoc_e->type = 0; /* charge_not_available */
1918 ASN1_CALL(pos, asn1_dec_null(ctrl, "chargeNotAvailable", tag, pos, end));
1919 break;
1920 case ASN1_TAG_SEQUENCE:
1921 aoc_e->type = 1; /* charging_unit */
1922 ASN1_CALL(pos, rose_dec_etsi_AOCEChargingUnitInfo(ctrl, "chargingUnitInfo", tag,
1923 pos, end, &aoc_e->charging_unit));
1924 break;
1925 default:
1926 ASN1_DID_NOT_EXPECT_TAG(ctrl, tag);
1927 return NULL;
1928 }
1929
1930 return pos;
1931 }
1932
1933 /* ------------------------------------------------------------------- */
1934 /* end rose_etsi_aoc.c */
1935