blob: 2ea6cafac179babca338db466e45c60fab377b87 [file] [log] [blame]
Harald Welte3dcdd202019-03-09 13:06:46 +01001/* (C) 2018-2019 by Harald Welte <laforge@gnumonks.org>
2 *
3 * All Rights Reserved
4 *
5 * SPDX-License-Identifier: GPL-2.0+
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 as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
Harald Welte3dcdd202019-03-09 13:06:46 +010017 */
Harald Welte3aa901d2018-08-13 18:32:36 +020018
19
Harald Welte0eaa0ef2019-03-02 15:12:42 +010020#include <netinet/in.h>
21#include <arpa/inet.h>
22
Kévin Redonff5db6e2018-10-11 17:16:18 +020023#include <asn_application.h>
24#include <der_encoder.h>
Harald Welte3aa901d2018-08-13 18:32:36 +020025
Harald Welteb49ac9c2019-03-09 20:36:07 +010026#include "asn1c_helpers.h"
27
Harald Welte3aa901d2018-08-13 18:32:36 +020028#include <osmocom/core/msgb.h>
29#include <osmocom/rspro/RsproPDU.h>
30
Harald Welte137c4402018-08-17 21:25:56 +020031#include "rspro_util.h"
Harald Welte7293e7b2021-12-08 21:29:11 +010032#include "debug.h"
Harald Welte137c4402018-08-17 21:25:56 +020033
Harald Welte57555aa2018-08-17 22:05:06 +020034#define ASN_ALLOC_COPY(out, in) \
35do { \
36 if (in) { \
37 out = CALLOC(1, sizeof(*in)); \
38 OSMO_ASSERT(out); \
39 memcpy(out, in, sizeof(*in)); \
40 } \
41} while (0)
42
43
Harald Welteb49ac9c2019-03-09 20:36:07 +010044const char *rspro_msgt_name(const RsproPDU_t *pdu)
45{
46 return asn_choice_name(&asn_DEF_RsproPDUchoice, &pdu->msg);
47}
48
Harald Welte3aa901d2018-08-13 18:32:36 +020049struct msgb *rspro_msgb_alloc(void)
50{
51 return msgb_alloc_headroom(1024, 8, "RSPRO");
52}
53
54/*! BER-Encode an RSPRO message into msgb.
55 * \param[in] pdu Structure describing RSPRO PDU. Is freed by this function on success
56 * \returns callee-allocated message buffer containing encoded RSPRO PDU; NULL on error.
57 */
58struct msgb *rspro_enc_msg(RsproPDU_t *pdu)
59{
60 struct msgb *msg = rspro_msgb_alloc();
61 asn_enc_rval_t rval;
62
63 if (!msg)
64 return NULL;
65
Harald Weltefd471192018-09-24 14:51:14 +020066 msg->l2h = msg->data;
Harald Welte6b8d4f82018-08-17 22:06:24 +020067 rval = der_encode_to_buffer(&asn_DEF_RsproPDU, pdu, msgb_data(msg), msgb_tailroom(msg));
Harald Welte3aa901d2018-08-13 18:32:36 +020068 if (rval.encoded < 0) {
Harald Welte7293e7b2021-12-08 21:29:11 +010069 LOGP(DRSPRO, LOGL_ERROR, "Failed to encode %s\n", rval.failed_type->name);
Harald Welte703d6862018-09-24 17:44:50 +020070 msgb_free(msg);
Harald Welte3aa901d2018-08-13 18:32:36 +020071 return NULL;
72 }
Harald Welted5c5c0b2018-08-17 22:04:01 +020073 msgb_put(msg, rval.encoded);
Harald Welte3aa901d2018-08-13 18:32:36 +020074
75 ASN_STRUCT_FREE(asn_DEF_RsproPDU, pdu);
76
77 return msg;
78}
79
Harald Welte573a5b92019-09-12 20:27:58 +020080/* caller must make sure to free msg */
Harald Welte3aa901d2018-08-13 18:32:36 +020081RsproPDU_t *rspro_dec_msg(struct msgb *msg)
82{
Harald Welte9ebbacc2018-09-24 17:43:39 +020083 RsproPDU_t *pdu = NULL;
Harald Welte3aa901d2018-08-13 18:32:36 +020084 asn_dec_rval_t rval;
85
Harald Welte7293e7b2021-12-08 21:29:11 +010086 LOGP(DRSPRO, LOGL_DEBUG, "decoding %s\n", msgb_hexdump(msg));
Harald Welte75852862018-09-24 14:55:34 +020087 rval = ber_decode(NULL, &asn_DEF_RsproPDU, (void **) &pdu, msgb_l2(msg), msgb_l2len(msg));
Harald Welte3aa901d2018-08-13 18:32:36 +020088 if (rval.code != RC_OK) {
Harald Welte7293e7b2021-12-08 21:29:11 +010089 LOGP(DRSPRO, LOGL_ERROR, "Failed to decode: %d. Consumed %zu of %u bytes\n",
Harald Welte75852862018-09-24 14:55:34 +020090 rval.code, rval.consumed, msgb_length(msg));
Harald Welte3aa901d2018-08-13 18:32:36 +020091 return NULL;
92 }
93
Harald Welte3aa901d2018-08-13 18:32:36 +020094 return pdu;
95}
96
Harald Welte3aa901d2018-08-13 18:32:36 +020097static void fill_comp_id(ComponentIdentity_t *out, const struct app_comp_id *in)
98{
Harald Welte137c4402018-08-17 21:25:56 +020099 out->type = in->type;
Harald Welte3aa901d2018-08-13 18:32:36 +0200100 OCTET_STRING_fromString(&out->name, in->name);
101 OCTET_STRING_fromString(&out->software, in->software);
102 OCTET_STRING_fromString(&out->swVersion, in->sw_version);
103 if (strlen(in->hw_manufacturer))
104 out->hwManufacturer = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName,
105 in->hw_manufacturer, -1);
106 if (strlen(in->hw_model))
107 out->hwModel = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_model, -1);
108 if (strlen(in->hw_serial_nr))
109 out->hwSerialNr = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_serial_nr, -1);
110 if (strlen(in->hw_version))
111 out->hwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->hw_version, -1);
112 if (strlen(in->fw_version))
113 out->fwVersion = OCTET_STRING_new_fromBuf(&asn_DEF_ComponentName, in->fw_version, -1);
114}
115
Harald Welte92bd8812019-03-02 14:52:17 +0100116void string_fromOCTET_STRING(char *out, size_t out_size, const OCTET_STRING_t *in)
117{
Harald Weltef5a0fa32019-03-03 15:44:18 +0100118 if (!in) {
Harald Welte92bd8812019-03-02 14:52:17 +0100119 out[0] = '\0';
Harald Weltef5a0fa32019-03-03 15:44:18 +0100120 return;
121 }
Harald Welte92bd8812019-03-02 14:52:17 +0100122 memcpy(out, in->buf, out_size < in->size ? out_size : in->size);
123 if (in->size < out_size)
124 out[in->size] = '\0';
125 else
126 out[out_size-1] = '\0';
127}
128#define string_fromOCTET_STRING_ARRAY(out, in) string_fromOCTET_STRING(out, ARRAY_SIZE(out), in)
129
130
131void rspro_comp_id_retrieve(struct app_comp_id *out, const ComponentIdentity_t *in)
132{
133 memset(out, 0, sizeof(*out));
134 out->type = in->type;
135 string_fromOCTET_STRING_ARRAY(out->name, &in->name);
136 string_fromOCTET_STRING_ARRAY(out->software, &in->software);
137 string_fromOCTET_STRING_ARRAY(out->sw_version, &in->swVersion);
138 string_fromOCTET_STRING_ARRAY(out->hw_manufacturer, in->hwManufacturer);
139 string_fromOCTET_STRING_ARRAY(out->hw_serial_nr, in->hwSerialNr);
140 string_fromOCTET_STRING_ARRAY(out->hw_version, in->hwVersion);
141 string_fromOCTET_STRING_ARRAY(out->fw_version, in->fwVersion);
142}
143
Harald Welte0eaa0ef2019-03-02 15:12:42 +0100144const char *rspro_IpAddr2str(const IpAddress_t *in)
145{
146 static char buf[128];
147
148 switch (in->present) {
149 case IpAddress_PR_ipv4:
150 return inet_ntop(AF_INET, in->choice.ipv4.buf, buf, sizeof(buf));
151 case IpAddress_PR_ipv6:
152 return inet_ntop(AF_INET6, in->choice.ipv6.buf, buf, sizeof(buf));
153 default:
154 return NULL;
155 }
156}
157
Harald Welte3aa901d2018-08-13 18:32:36 +0200158static void fill_ip4_port(IpPort_t *out, uint32_t ip, uint16_t port)
159{
160 uint32_t ip_n = htonl(ip);
161 out->ip.present = IpAddress_PR_ipv4;
162 OCTET_STRING_fromBuf(&out->ip.choice.ipv4, (const char *) &ip_n, 4);
Harald Welte69714122019-03-30 19:16:30 +0100163 out->port = port;
Harald Welte3aa901d2018-08-13 18:32:36 +0200164}
165
166
167RsproPDU_t *rspro_gen_ConnectBankReq(const struct app_comp_id *a_cid,
168 uint16_t bank_id, uint16_t num_slots)
169{
170 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
171 if (!pdu)
172 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200173 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200174 pdu->msg.present = RsproPDUchoice_PR_connectBankReq;
175 fill_comp_id(&pdu->msg.choice.connectBankReq.identity, a_cid);
176 pdu->msg.choice.connectBankReq.bankId = bank_id;
177 pdu->msg.choice.connectBankReq.numberOfSlots = num_slots;
178
179 return pdu;
180}
181
Harald Weltef5a0fa32019-03-03 15:44:18 +0100182RsproPDU_t *rspro_gen_ConnectBankRes(const struct app_comp_id *a_cid, e_ResultCode res)
183{
184 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
185 if (!pdu)
186 return NULL;
187 pdu->version = 2;
188 pdu->msg.present = RsproPDUchoice_PR_connectBankRes;
189 fill_comp_id(&pdu->msg.choice.connectBankRes.identity, a_cid);
190 pdu->msg.choice.connectBankRes.result = res;
191
192 return pdu;
193}
194
Harald Welte57555aa2018-08-17 22:05:06 +0200195RsproPDU_t *rspro_gen_ConnectClientReq(const struct app_comp_id *a_cid, const ClientSlot_t *client)
Harald Welte3aa901d2018-08-13 18:32:36 +0200196{
197 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
198 if (!pdu)
199 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200200 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200201 pdu->msg.present = RsproPDUchoice_PR_connectClientReq;
202 fill_comp_id(&pdu->msg.choice.connectClientReq.identity, a_cid);
Harald Weltec3632a72018-10-14 20:38:34 +0200203 if (client)
204 ASN_ALLOC_COPY(pdu->msg.choice.connectClientReq.clientSlot, client);
Harald Welte3aa901d2018-08-13 18:32:36 +0200205
206 return pdu;
207}
208
Harald Welte10f6c212018-09-24 14:55:55 +0200209RsproPDU_t *rspro_gen_ConnectClientRes(const struct app_comp_id *a_cid, e_ResultCode res)
210{
211 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
212 if (!pdu)
213 return NULL;
214 pdu->version = 2;
215 pdu->tag = 2342;
216 pdu->msg.present = RsproPDUchoice_PR_connectClientRes;
217 fill_comp_id(&pdu->msg.choice.connectClientRes.identity, a_cid);
218 pdu->msg.choice.connectClientRes.result = res;
219
220 return pdu;
221}
222
Harald Welte3aa901d2018-08-13 18:32:36 +0200223RsproPDU_t *rspro_gen_CreateMappingReq(const ClientSlot_t *client, const BankSlot_t *bank)
224{
225 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
226 if (!pdu)
227 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200228 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200229 pdu->msg.present = RsproPDUchoice_PR_createMappingReq;
230 pdu->msg.choice.createMappingReq.client = *client;
231 pdu->msg.choice.createMappingReq.bank = *bank;
232
233 return pdu;
234}
235
Harald Weltec0a4ae42018-10-15 00:44:53 +0200236RsproPDU_t *rspro_gen_CreateMappingRes(e_ResultCode res)
237{
238 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
239 if (!pdu)
240 return NULL;
241 pdu->version = 2;
242 pdu->msg.present = RsproPDUchoice_PR_createMappingRes;
243 pdu->msg.choice.createMappingRes.result = res;
244
245 return pdu;
246}
247
248RsproPDU_t *rspro_gen_RemoveMappingReq(const ClientSlot_t *client, const BankSlot_t *bank)
249{
250 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
251 if (!pdu)
252 return NULL;
253 pdu->version = 2;
254 pdu->msg.present = RsproPDUchoice_PR_removeMappingReq;
255 pdu->msg.choice.removeMappingReq.client = *client;
256 pdu->msg.choice.removeMappingReq.bank = *bank;
257
258 return pdu;
259}
260
261RsproPDU_t *rspro_gen_RemoveMappingRes(e_ResultCode res)
262{
263 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
264 if (!pdu)
265 return NULL;
266 pdu->version = 2;
267 pdu->msg.present = RsproPDUchoice_PR_removeMappingRes;
268 pdu->msg.choice.removeMappingRes.result = res;
269
270 return pdu;
271}
272
Harald Welteeae30c32019-03-30 17:32:37 +0100273RsproPDU_t *rspro_gen_ConfigClientIdReq(const ClientSlot_t *client)
Harald Welte3aa901d2018-08-13 18:32:36 +0200274{
275 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
276 if (!pdu)
277 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200278 pdu->version = 2;
Harald Welted571a3e2019-03-11 22:09:50 +0100279 pdu->msg.present = RsproPDUchoice_PR_configClientIdReq;
280 pdu->msg.choice.configClientIdReq.clientSlot = *client;
Harald Welte3aa901d2018-08-13 18:32:36 +0200281
282 return pdu;
283}
284
Harald Welted571a3e2019-03-11 22:09:50 +0100285RsproPDU_t *rspro_gen_ConfigClientIdRes(e_ResultCode res)
Harald Weltec0097b12019-03-02 14:22:24 +0100286{
287 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
288 if (!pdu)
289 return NULL;
290 pdu->version = 2;
Harald Welted571a3e2019-03-11 22:09:50 +0100291 pdu->msg.present = RsproPDUchoice_PR_configClientIdRes;
292 pdu->msg.choice.configClientIdRes.result = res;
293
294 return pdu;
295}
296
297RsproPDU_t *rspro_gen_ConfigClientBankReq(const BankSlot_t *bank, uint32_t ip, uint16_t port)
298{
299 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
300 if (!pdu)
301 return NULL;
302 pdu->version = 2;
303 pdu->msg.present = RsproPDUchoice_PR_configClientBankReq;
304 pdu->msg.choice.configClientBankReq.bankSlot = *bank;
305 fill_ip4_port(&pdu->msg.choice.configClientBankReq.bankd, ip, port);
306
307 return pdu;
308}
309
310RsproPDU_t *rspro_gen_ConfigClientBankRes(e_ResultCode res)
311{
312 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
313 if (!pdu)
314 return NULL;
315 pdu->version = 2;
316 pdu->msg.present = RsproPDUchoice_PR_configClientBankRes;
317 pdu->msg.choice.configClientBankRes.result = res;
Harald Weltec0097b12019-03-02 14:22:24 +0100318
319 return pdu;
320}
321
Harald Welte3aa901d2018-08-13 18:32:36 +0200322RsproPDU_t *rspro_gen_SetAtrReq(uint16_t client_id, uint16_t slot_nr, const uint8_t *atr,
323 unsigned int atr_len)
324{
325 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
326 if (!pdu)
327 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200328 pdu->version = 2;
Harald Welte3aa901d2018-08-13 18:32:36 +0200329 pdu->msg.present = RsproPDUchoice_PR_setAtrReq;
330 pdu->msg.choice.setAtrReq.slot.clientId = client_id;
331 pdu->msg.choice.setAtrReq.slot.slotNr = slot_nr;
332 OCTET_STRING_fromBuf(&pdu->msg.choice.setAtrReq.atr, (const char *)atr, atr_len);
333
334 return pdu;
335}
Harald Welte5d16b1c2018-09-23 19:25:46 +0200336
Harald Weltefa365592019-03-28 20:28:57 +0100337RsproPDU_t *rspro_gen_SetAtrRes(e_ResultCode res)
338{
339 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
340 if (!pdu)
341 return NULL;
342 pdu->version = 2;
343 pdu->msg.present = RsproPDUchoice_PR_setAtrRes;
344 pdu->msg.choice.setAtrRes.result = res;
345
346 return pdu;
347}
348
Harald Welte5d16b1c2018-09-23 19:25:46 +0200349RsproPDU_t *rspro_gen_TpduModem2Card(const ClientSlot_t *client, const BankSlot_t *bank,
350 const uint8_t *tpdu, unsigned int tpdu_len)
351{
352 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
353 if (!pdu)
354 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200355 pdu->version = 2;
Harald Welte5d16b1c2018-09-23 19:25:46 +0200356 pdu->msg.present = RsproPDUchoice_PR_tpduModemToCard;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200357 OSMO_ASSERT(client);
Harald Welte5d16b1c2018-09-23 19:25:46 +0200358 pdu->msg.choice.tpduModemToCard.fromClientSlot = *client;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200359 OSMO_ASSERT(bank);
Harald Welte5d16b1c2018-09-23 19:25:46 +0200360 pdu->msg.choice.tpduModemToCard.toBankSlot = *bank;
361 /* TODO: flags? */
362 OCTET_STRING_fromBuf(&pdu->msg.choice.tpduModemToCard.data, (const char *)tpdu, tpdu_len);
363
364 return pdu;
365}
366
367RsproPDU_t *rspro_gen_TpduCard2Modem(const BankSlot_t *bank, const ClientSlot_t *client,
368 const uint8_t *tpdu, unsigned int tpdu_len)
369{
370 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
371 if (!pdu)
372 return NULL;
Harald Welte62e3f5f2018-10-15 00:44:25 +0200373 pdu->version = 2;
Harald Welte5d16b1c2018-09-23 19:25:46 +0200374 pdu->msg.present = RsproPDUchoice_PR_tpduCardToModem;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200375 OSMO_ASSERT(bank);
Harald Welte5d16b1c2018-09-23 19:25:46 +0200376 pdu->msg.choice.tpduCardToModem.fromBankSlot = *bank;
Kévin Redon6811e4f2018-10-11 08:37:38 +0200377 OSMO_ASSERT(client)
Harald Welte5d16b1c2018-09-23 19:25:46 +0200378 pdu->msg.choice.tpduCardToModem.toClientSlot = *client;
379 /* TODO: flags? */
380 OCTET_STRING_fromBuf(&pdu->msg.choice.tpduCardToModem.data, (const char *)tpdu, tpdu_len);
381
382 return pdu;
383}
Harald Weltecf8b89a2019-03-11 22:16:22 +0100384
Harald Weltea9bf5c22019-12-16 12:20:53 +0100385RsproPDU_t *rspro_gen_BankSlotStatusInd(const BankSlot_t *bank, const ClientSlot_t *client,
386 bool rst_active, int vcc_present, int clk_active,
387 int card_present)
388{
389 SlotPhysStatus_t *pstatus;
390 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
391 if (!pdu)
392 return NULL;
393 pdu->version = 2;
394 pdu->msg.present = RsproPDUchoice_PR_bankSlotStatusInd;
395 OSMO_ASSERT(bank);
396 pdu->msg.choice.bankSlotStatusInd.fromBankSlot = *bank;
397 OSMO_ASSERT(client)
398 pdu->msg.choice.bankSlotStatusInd.toClientSlot = *client;
399
400 pstatus = &pdu->msg.choice.bankSlotStatusInd.slotPhysStatus;
401 pstatus->resetActive = rst_active ? 1 : 0;
402
403 if (vcc_present >= 0) {
404 pstatus->vccPresent = CALLOC(1, sizeof(BOOLEAN_t));
405 OSMO_ASSERT(pstatus->vccPresent);
406 *pstatus->vccPresent = vcc_present;
407 }
408
409 if (clk_active >= 0) {
410 pstatus->clkActive = CALLOC(1, sizeof(BOOLEAN_t));
411 OSMO_ASSERT(pstatus->clkActive);
412 *pstatus->clkActive = clk_active;
413 }
414
415 if (card_present >= 0) {
416 pstatus->cardPresent = CALLOC(1, sizeof(BOOLEAN_t));
417 OSMO_ASSERT(pstatus->cardPresent);
418 *pstatus->cardPresent = card_present;
419 }
420
421 return pdu;
422}
423
424RsproPDU_t *rspro_gen_ClientSlotStatusInd(const ClientSlot_t *client, const BankSlot_t *bank,
425 bool rst_active, int vcc_present, int clk_active,
426 int card_present)
427{
428 SlotPhysStatus_t *pstatus;
429 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
430 if (!pdu)
431 return NULL;
432 pdu->version = 2;
433 pdu->msg.present = RsproPDUchoice_PR_clientSlotStatusInd;
434 OSMO_ASSERT(client)
435 pdu->msg.choice.clientSlotStatusInd.fromClientSlot = *client;
436 OSMO_ASSERT(bank);
437 pdu->msg.choice.clientSlotStatusInd.toBankSlot = *bank;
438
439 pstatus = &pdu->msg.choice.clientSlotStatusInd.slotPhysStatus;
440 pstatus->resetActive = rst_active ? 1 : 0;
441
442 if (vcc_present >= 0) {
443 pstatus->vccPresent = CALLOC(1, sizeof(BOOLEAN_t));
444 OSMO_ASSERT(pstatus->vccPresent);
445 *pstatus->vccPresent = vcc_present;
446 }
447
448 if (clk_active >= 0) {
449 pstatus->clkActive = CALLOC(1, sizeof(BOOLEAN_t));
450 OSMO_ASSERT(pstatus->clkActive);
451 *pstatus->clkActive = clk_active;
452 }
453
454 if (card_present >= 0) {
455 pstatus->cardPresent = CALLOC(1, sizeof(BOOLEAN_t));
456 OSMO_ASSERT(pstatus->cardPresent);
457 *pstatus->cardPresent = card_present;
458 }
459
460 return pdu;
461}
462
Harald Welte3f966322019-12-04 19:09:58 +0100463RsproPDU_t *rspro_gen_ResetStateReq(void)
464{
465 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
466 if (!pdu)
467 return NULL;
468 pdu->version = 2;
469 pdu->msg.present = RsproPDUchoice_PR_resetStateReq;
470
471 return pdu;
472}
473
474RsproPDU_t *rspro_gen_ResetStateRes(e_ResultCode res)
475{
476 RsproPDU_t *pdu = CALLOC(1, sizeof(*pdu));
477 if (!pdu)
478 return NULL;
479 pdu->version = 2;
480 pdu->msg.present = RsproPDUchoice_PR_resetStateRes;
481 pdu->msg.choice.resetStateRes.result = res;
482
483 return pdu;
484}
485
Harald Welte4e7a2852019-03-17 21:01:50 +0100486e_ResultCode rspro_get_result(const RsproPDU_t *pdu)
487{
488 switch (pdu->msg.present) {
489 case RsproPDUchoice_PR_connectBankRes:
490 return pdu->msg.choice.connectBankRes.result;
491 case RsproPDUchoice_PR_connectClientRes:
492 return pdu->msg.choice.connectClientRes.result;
493 case RsproPDUchoice_PR_createMappingRes:
494 return pdu->msg.choice.createMappingRes.result;
495 case RsproPDUchoice_PR_removeMappingRes:
496 return pdu->msg.choice.removeMappingRes.result;
497 case RsproPDUchoice_PR_configClientIdRes:
498 return pdu->msg.choice.configClientIdRes.result;
499 case RsproPDUchoice_PR_configClientBankRes:
500 return pdu->msg.choice.configClientBankRes.result;
501 case RsproPDUchoice_PR_setAtrRes:
502 return pdu->msg.choice.setAtrRes.result;
Harald Welte3f966322019-12-04 19:09:58 +0100503 case RsproPDUchoice_PR_resetStateRes:
504 return pdu->msg.choice.resetStateRes.result;
Harald Welte4e7a2852019-03-17 21:01:50 +0100505 default:
506 OSMO_ASSERT(0);
507 }
508}
509
Harald Weltecf8b89a2019-03-11 22:16:22 +0100510void rspro2bank_slot(struct bank_slot *out, const BankSlot_t *in)
511{
512 out->bank_id = in->bankId;
513 out->slot_nr = in->slotNr;
514}
515
516void bank_slot2rspro(BankSlot_t *out, const struct bank_slot *in)
517{
518 out->bankId = in->bank_id;
519 out->slotNr = in->slot_nr;
520}
521
522void rspro2client_slot(struct client_slot *out, const ClientSlot_t *in)
523{
524 out->client_id = in->clientId;
525 out->slot_nr = in->slotNr;
526}
527
528void client_slot2rspro(ClientSlot_t *out, const struct client_slot *in)
529{
530 out->clientId = in->client_id;
531 out->slotNr = in->slot_nr;
532}