Change IE_METERING timing information from deciseconds to seconds and milliseconds; Fix: AOC-D unit information length; encode AOC-E according to real traces; Add option to disable seconds in time/date IE #4
143
src/isdn/dss1.c
143
src/isdn/dss1.c
|
@ -184,9 +184,9 @@ static void split_3pty(call_t *call)
|
|||
}
|
||||
}
|
||||
|
||||
/* Generate AOC-S facility IE from metering information */
|
||||
/* Send AOC-S facility msg from metering information */
|
||||
#define AOCS_CURRENCY_AMOUNT_PER_UNIT 5
|
||||
static void generate_aocs_fac(call_t *call)
|
||||
static void snd_msg_fac_aocs(call_t *call)
|
||||
{
|
||||
struct l3_msg *l3m;
|
||||
uint8_t fac_ie[256];
|
||||
|
@ -260,33 +260,61 @@ static void generate_aocs_fac(call_t *call)
|
|||
}
|
||||
}
|
||||
|
||||
/* AOC-D timer callback */
|
||||
static void aocd_timer_cb(void *data)
|
||||
/* Send AOC-D facility msg */
|
||||
static void snd_msg_fac_aocd(call_t *call)
|
||||
{
|
||||
struct l3_msg *l3m;
|
||||
uint8_t fac_ie[256];
|
||||
struct asn1_parm fac;
|
||||
|
||||
if(call->isdn_ep->ntmode && call->isdn_ep->aocd && call->metering_info_received) {
|
||||
LOGP(DISDN, LOGL_DEBUG, "Sending AOC-D facility, subTotal units: %d\n", call->metering_total_units);
|
||||
|
||||
memset(&fac, 0, sizeof(fac));
|
||||
fac.Valid = 1;
|
||||
fac.comp = CompInvoke;
|
||||
fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */
|
||||
fac.u.inv.operationValue = Fac_AOCDChargingUnit;
|
||||
fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units;
|
||||
encodeFac(fac_ie, &fac);
|
||||
|
||||
// sending facility
|
||||
l3m = create_l3msg();
|
||||
enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
|
||||
call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m);
|
||||
}
|
||||
}
|
||||
|
||||
/* Encode AOC-E facility */
|
||||
static void enc_ie_fac_aoce(call_t *call, struct l3_msg *l3m)
|
||||
{
|
||||
uint8_t fac_ie[256];
|
||||
struct asn1_parm fac;
|
||||
struct l3_msg *l3m;
|
||||
|
||||
if(call->isdn_ep->ntmode && call->isdn_ep->aocd && call->metering_info_received) {
|
||||
LOGP(DISDN, LOGL_DEBUG, "Attaching AOC-E facility, total units: %d\n", call->metering_total_units);
|
||||
|
||||
memset(&fac, 0, sizeof(fac));
|
||||
fac.Valid = 1;
|
||||
fac.comp = CompInvoke;
|
||||
fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */
|
||||
fac.u.inv.operationValue = Fac_AOCEChargingUnit;
|
||||
fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units;
|
||||
encodeFac(fac_ie, &fac);
|
||||
|
||||
// attach facility
|
||||
enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Metering unit timer callback */
|
||||
static void metering_unit_timer_cb(void *data)
|
||||
{
|
||||
call_t *call = data;
|
||||
|
||||
call->metering_total_units++;
|
||||
|
||||
LOGP(DISDN, LOGL_DEBUG, "Sending next AOC-D facility, total_units=%d\n", call->metering_total_units);
|
||||
|
||||
osmo_timer_schedule(&call->aocd_unit_timer, call->metering_unit_period_decisecs / 10, (call->metering_unit_period_decisecs % 10) * 100000);
|
||||
|
||||
memset(&fac, 0, sizeof(fac));
|
||||
fac.Valid = 1;
|
||||
fac.comp = CompInvoke;
|
||||
fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */
|
||||
fac.u.inv.operationValue = Fac_AOCDChargingUnit;
|
||||
fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units;
|
||||
|
||||
encodeFac(fac_ie, &fac);
|
||||
|
||||
// sending facility
|
||||
l3m = create_l3msg();
|
||||
enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
|
||||
call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m);
|
||||
osmo_timer_schedule(&call->metering_unit_timer, call->metering_unit_period_decisecs / 10, (call->metering_unit_period_decisecs % 10) * 100000);
|
||||
snd_msg_fac_aocd(call);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -461,7 +489,8 @@ void setup_ind(call_t *call, uint32_t pid, struct l3_msg *l3m)
|
|||
|
||||
/* reset AOC information */
|
||||
call->metering_info_received = 0;
|
||||
call->aocd_unit_timer_started = 0;
|
||||
call->metering_unit_timer_started = 0;
|
||||
call->metering_total_units = 0;
|
||||
|
||||
new_state(call, ISDN_STATE_IN_SETUP);
|
||||
|
||||
|
@ -876,11 +905,10 @@ void disconnect_ind(call_t *call, uint32_t pid, struct l3_msg *l3m)
|
|||
/* send message to osmo-cc */
|
||||
osmo_cc_ll_msg(&call->isdn_ep->cc_ep, call->cc_callref, msg);
|
||||
|
||||
/* stop AOC-D timer */
|
||||
if(call->aocd_unit_timer_started)
|
||||
{
|
||||
osmo_timer_del(&call->aocd_unit_timer);
|
||||
call->aocd_unit_timer_started = 0;
|
||||
/* stop AOC-D timer and send AOC-E facility */
|
||||
if(call->metering_unit_timer_started) {
|
||||
osmo_timer_del(&call->metering_unit_timer);
|
||||
call->metering_unit_timer_started = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2110,7 +2138,7 @@ skip_ies:
|
|||
rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs));
|
||||
if(rc >= 0) {
|
||||
call->metering_info_received = 1;
|
||||
generate_aocs_fac(call);
|
||||
snd_msg_fac_aocs(call);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2173,7 +2201,7 @@ void alert_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs));
|
||||
if(rc >= 0) {
|
||||
call->metering_info_received = 1;
|
||||
generate_aocs_fac(call);
|
||||
snd_msg_fac_aocs(call);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2187,8 +2215,6 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
char connected[33];
|
||||
char display[128];
|
||||
int rc;
|
||||
uint8_t fac_ie[256];
|
||||
struct asn1_parm fac;
|
||||
|
||||
/* NT-MODE in setup state we must send PROCEEDING first */
|
||||
if (!call->proceeding_sent && call->isdn_ep->ntmode) {
|
||||
|
@ -2231,7 +2257,7 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
/* date & time, in NT mode only */
|
||||
if (call->isdn_ep->ntmode) {
|
||||
time(¤t_time);
|
||||
enc_ie_date(l3m, current_time, 0);
|
||||
enc_ie_date(l3m, current_time, call->isdn_ep->time_no_sec);
|
||||
}
|
||||
|
||||
/* connected number */
|
||||
|
@ -2253,34 +2279,19 @@ void setup_rsp(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs));
|
||||
if(rc >= 0) {
|
||||
call->metering_info_received = 1;
|
||||
generate_aocs_fac(call);
|
||||
snd_msg_fac_aocs(call);
|
||||
}
|
||||
|
||||
/* AOC-D handling on connect */
|
||||
if(call->isdn_ep->ntmode && call->isdn_ep->aocd && call->metering_info_received && call->metering_connect_units > 0)
|
||||
{
|
||||
LOGP(DISDN, LOGL_DEBUG, "Sending first AOC-D facility, units: %d\n", call->metering_connect_units);
|
||||
if(call->metering_info_received) {
|
||||
call->metering_total_units = call->metering_connect_units;
|
||||
|
||||
memset(&fac, 0, sizeof(fac));
|
||||
fac.Valid = 1;
|
||||
fac.comp = CompInvoke;
|
||||
fac.u.inv.invokeId = 2; /* doesn't matter since no response is expected */
|
||||
fac.u.inv.operationValue = Fac_AOCDChargingUnit;
|
||||
|
||||
fac.u.inv.o.AOCchu.recordedUnits = call->metering_total_units;
|
||||
encodeFac(fac_ie, &fac);
|
||||
|
||||
// sending facility
|
||||
l3m = create_l3msg();
|
||||
enc_ie_facility(l3m, fac_ie + 2, fac_ie[1]);
|
||||
call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_FACILITY, call->l3_pid, l3m);
|
||||
snd_msg_fac_aocd(call);
|
||||
|
||||
if(call->metering_unit_period_decisecs > 0) {
|
||||
LOGP(DISDN, LOGL_DEBUG, "Scheduling AOC-D unit information every %d deciseconds.\n", call->metering_unit_period_decisecs);
|
||||
call->aocd_unit_timer_started = 1;
|
||||
osmo_timer_setup(&call->aocd_unit_timer, aocd_timer_cb, call);
|
||||
osmo_timer_schedule(&call->aocd_unit_timer, call->metering_unit_period_decisecs / 10, (call->metering_unit_period_decisecs % 10) * 100000);
|
||||
LOGP(DISDN, LOGL_DEBUG, "Scheduling metering unit timer every %d deciseconds.\n", call->metering_unit_period_decisecs);
|
||||
call->metering_unit_timer_started = 1;
|
||||
osmo_timer_setup(&call->metering_unit_timer, metering_unit_timer_cb, call);
|
||||
osmo_timer_schedule(&call->metering_unit_timer, call->metering_unit_period_decisecs / 10, (call->metering_unit_period_decisecs % 10) * 100000);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2389,7 +2400,7 @@ void progress_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
rc = osmo_cc_get_ie_metering(msg, 0, &(call->metering_connect_units), &(call->metering_unit_period_decisecs));
|
||||
if(rc >= 0) {
|
||||
call->metering_info_received = 1;
|
||||
generate_aocs_fac(call);
|
||||
snd_msg_fac_aocs(call);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2514,17 +2525,19 @@ void disc_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
enc_ie_display(l3m, display);
|
||||
}
|
||||
|
||||
/* stop AOC-D timer */
|
||||
if(call->aocd_unit_timer_started)
|
||||
{
|
||||
osmo_timer_del(&call->aocd_unit_timer);
|
||||
call->aocd_unit_timer_started = 0;
|
||||
}
|
||||
/* AOC-E */
|
||||
enc_ie_fac_aoce(call, l3m);
|
||||
|
||||
new_state(call, ISDN_STATE_OUT_DISCONNECT);
|
||||
|
||||
/* send message to ISDN */
|
||||
call->isdn_ep->ml3->to_layer3(call->isdn_ep->ml3, MT_DISCONNECT, call->l3_pid, l3m);
|
||||
|
||||
/* stop AOC-D timer and send AOC-E facility */
|
||||
if(call->metering_unit_timer_started) {
|
||||
osmo_timer_del(&call->metering_unit_timer);
|
||||
call->metering_unit_timer_started = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* CC-RELEASE REQUEST */
|
||||
|
@ -2557,6 +2570,9 @@ void rel_req(call_t *call, uint32_t pid, osmo_cc_msg_t *msg)
|
|||
enc_ie_display(l3m, display);
|
||||
}
|
||||
|
||||
/* AOC-E */
|
||||
enc_ie_fac_aoce(call, l3m);
|
||||
|
||||
new_state(call, ISDN_STATE_OUT_RELEASE);
|
||||
|
||||
/* send message to ISDN */
|
||||
|
@ -2729,4 +2745,3 @@ void cc_message(osmo_cc_endpoint_t *ep, uint32_t callref, osmo_cc_msg_t *msg)
|
|||
|
||||
osmo_cc_free_msg(msg);
|
||||
}
|
||||
|
||||
|
|
|
@ -690,7 +690,7 @@ void isdn_destroy(isdn_t *isdn_ep)
|
|||
static void clock_timeout(void *data);
|
||||
|
||||
/* initialization and configuration to isdn interface instance */
|
||||
int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location, int aocd, int aocs)
|
||||
int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location, int aocd, int aocs, int time_no_sec)
|
||||
{
|
||||
int rc;
|
||||
void *mui;
|
||||
|
@ -728,6 +728,7 @@ int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const cha
|
|||
isdn_ep->serving_location = serving_location;
|
||||
isdn_ep->aocd = aocd;
|
||||
isdn_ep->aocs = aocs;
|
||||
isdn_ep->time_no_sec = time_no_sec;
|
||||
|
||||
/* channel selection list */
|
||||
if (channel_out) {
|
||||
|
@ -853,7 +854,7 @@ void call_destroy(call_t *call)
|
|||
free((char *)call->sdp);
|
||||
|
||||
/* remove metering timer, if still active */
|
||||
osmo_timer_del(&call->aocd_unit_timer);
|
||||
osmo_timer_del(&call->metering_unit_timer);
|
||||
|
||||
/* detach */
|
||||
call_p = &call->isdn_ep->call_list;
|
||||
|
|
|
@ -105,10 +105,11 @@ typedef struct isdn {
|
|||
int l1hold;
|
||||
int l2hold;
|
||||
int l2sock;
|
||||
int time_no_sec;
|
||||
void *l2inst;
|
||||
ph_socket_t *ph_socket;
|
||||
pthread_mutex_t upqueue_lock;
|
||||
struct mqueue upqueue;
|
||||
struct mqueue upqueue;
|
||||
int upqueue_initialized;
|
||||
int upqueue_pipe[2];
|
||||
struct osmo_fd upqueue_ofd;
|
||||
|
@ -127,7 +128,7 @@ typedef struct isdn {
|
|||
struct b_timer_inst b_timer_inst[128];
|
||||
uint8_t b_buffer[128][160];
|
||||
int b_buffer_pos[128];
|
||||
unsigned char l2mask[16]; /* 128 bits for each tei */
|
||||
unsigned char l2mask[16]; /* 128 bits for each tei */
|
||||
|
||||
/* bridging */
|
||||
int bridge_possible;
|
||||
|
@ -141,7 +142,7 @@ typedef struct isdn {
|
|||
|
||||
typedef struct call_list {
|
||||
struct call_list *next;
|
||||
isdn_t *isdn_ep;
|
||||
isdn_t *isdn_ep;
|
||||
|
||||
/* mISDN states */
|
||||
uint32_t l3_pid;
|
||||
|
@ -184,8 +185,8 @@ typedef struct call_list {
|
|||
int park_len;
|
||||
uint8_t park_callid[8];
|
||||
/* metering/AOC-D/AOC-S */
|
||||
struct osmo_timer_list aocd_unit_timer;
|
||||
int aocd_unit_timer_started;
|
||||
struct osmo_timer_list metering_unit_timer;
|
||||
int metering_unit_timer_started;
|
||||
int metering_info_received;
|
||||
uint16_t metering_connect_units;
|
||||
uint16_t metering_unit_period_decisecs;
|
||||
|
@ -214,7 +215,7 @@ int open_bchannel_out(call_t *call, unsigned int cmd, int channel, int exclusive
|
|||
/* isdn instance */
|
||||
isdn_t *isdn_create(void);
|
||||
void isdn_destroy(isdn_t *isdn_ep);
|
||||
int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location, int aocd, int aocs);
|
||||
int isdn_initialize(isdn_t *isdn_ep, ph_socket_t *ph_socket, char law, const char *portname, int ntmode, int ptp, int layer1hold, int layer2hold, const char *channel_out, const char *channel_in, const char *timeouts, int tx_delay, int local_tones, int serving_location, int aocd, int aocs, int time_no_sec);
|
||||
int isdn_open(isdn_t *isdn_ep);
|
||||
void isdn_close(isdn_t *isdn_ep);
|
||||
void isdn_add_msn(isdn_t *isdn_ep, const char *msn);
|
||||
|
|
|
@ -48,6 +48,7 @@ static int layer1hold = 0;
|
|||
static int layer2hold = 0;
|
||||
static int aocd = 0;
|
||||
static int aocs = 0;
|
||||
static int time_no_sec = 0;
|
||||
static const char *channel_out = NULL;
|
||||
static const char *channel_in = NULL;
|
||||
static const char *timeouts = NULL;
|
||||
|
@ -131,6 +132,8 @@ static void print_help()
|
|||
printf(" Send AOC-D charging information\n");
|
||||
printf(" --aocs\n");
|
||||
printf(" Send AOC-S charging information\n");
|
||||
printf(" --time-no-seconds\n");
|
||||
printf(" Send date/time IE without seconds\n");
|
||||
printf(" -T --local-tones german | oldgerman | american\n");
|
||||
printf(" Send locally generated tones, if not provided by remote interface.\n");
|
||||
printf(" -D --debug-misdn\n");
|
||||
|
@ -162,6 +165,7 @@ static void print_help()
|
|||
#define OPT_BR_ONLY 267
|
||||
#define OPT_AOCD 268
|
||||
#define OPT_AOCS 269
|
||||
#define OPT_TIME_NO_SEC 270
|
||||
|
||||
static void add_options(void)
|
||||
{
|
||||
|
@ -182,6 +186,7 @@ static void add_options(void)
|
|||
option_add('T', "local-tones", 1);
|
||||
option_add(OPT_AOCD, "aocd", 0);
|
||||
option_add(OPT_AOCS, "aocs", 0);
|
||||
option_add(OPT_TIME_NO_SEC, "time-no-seconds", 0);
|
||||
option_add('D', "debug-misdn", 0);
|
||||
option_add(OPT_SERVING, "serving-location", 1);
|
||||
option_add('B', "bridging", 1);
|
||||
|
@ -253,6 +258,9 @@ static int handle_options(int short_option, int argi, char **argv)
|
|||
case OPT_AOCS:
|
||||
aocs = 1;
|
||||
break;
|
||||
case OPT_TIME_NO_SEC:
|
||||
time_no_sec = 1;
|
||||
break;
|
||||
case 'T':
|
||||
if (!strcasecmp(argv[argi], "american"))
|
||||
local_tones = TONES_TYPE_AMERICAN;
|
||||
|
@ -392,7 +400,7 @@ int main(int argc, char *argv[])
|
|||
isdn_tone_generate_ulaw_samples();
|
||||
|
||||
/* init instance */
|
||||
rc = isdn_initialize(isdn_ep, (misdn_user) ? &ph_drv.ph_socket : NULL, law, portname, ntmode, ptp, layer1hold, layer2hold, channel_out, channel_in, timeouts, tx_delay, local_tones, serving_location, aocd, aocs);
|
||||
rc = isdn_initialize(isdn_ep, (misdn_user) ? &ph_drv.ph_socket : NULL, law, portname, ntmode, ptp, layer1hold, layer2hold, channel_out, channel_in, timeouts, tx_delay, local_tones, serving_location, aocd, aocs, time_no_sec);
|
||||
if (rc) {
|
||||
LOGP(DISDN, LOGL_ERROR, "mISDN initializing failed!\n");
|
||||
goto error;
|
||||
|
|
|
@ -423,14 +423,14 @@ static int encodeAOCDChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
p[i++] = 0x02; // Operation Tag
|
||||
p[i++] = 0x01; // Tag Length
|
||||
p[i++] = Fac_AOCDChargingUnit; // Operation Value
|
||||
p[i++] = 0x30;
|
||||
p[i++] = 0x30; // specificChargingUnits
|
||||
p[i++] = (0x09 + len); // Length
|
||||
p[i++] = 0xa1; // APDU
|
||||
p[i++] = (0x04 + len); // Length
|
||||
p[i++] = 0x30;
|
||||
p[i++] = (0x02 + len);
|
||||
p[i++] = 0x02; // Operation Tag
|
||||
p[i++] = 0x01;
|
||||
p[i++] = 0x30; // recordedUnits
|
||||
p[i++] = (0x02 + len); // Length
|
||||
p[i++] = 0x02; // recordedNumberOfUnits
|
||||
p[i++] = len;
|
||||
|
||||
// Recorded units could take up as much as 3 bytes (0xFFFFFF)
|
||||
p[i] = numberOfUnits & 0xFF;
|
||||
|
@ -441,10 +441,10 @@ static int encodeAOCDChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
i += len;
|
||||
|
||||
p[i++] = 0x82; // Type of charging info
|
||||
p[i++] = 0x01;
|
||||
p[i++] = 0x01; // Length
|
||||
p[i++] = 0x00; // AOC-D so Sub-Total
|
||||
|
||||
p[1] = (AOCD_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length
|
||||
p[1] = i - 2; // IE Payload Length
|
||||
p[4] = p[1] - 3; // Invoke Component Length
|
||||
result = p[1] + 2; // Total Length of IE
|
||||
}
|
||||
|
@ -481,15 +481,16 @@ static int encodeAOCEChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
p[i++] = 0x02; // Operation Tag
|
||||
p[i++] = 0x01; // Tag Length
|
||||
p[i++] = Fac_AOCEChargingUnit; // Operation Value
|
||||
p[i++] = 0xa1; // APDU
|
||||
p[i++] = 0x30;
|
||||
p[i++] = (0x09 + len); // Length
|
||||
p[i++] = 0xa1; // APDU
|
||||
p[i++] = 0x30; // ChargingUnitInfo
|
||||
p[i++] = (0x08 + len); // Length
|
||||
p[i++] = 0x30; // specificChargingUnits
|
||||
p[i++] = (0x06 + len); // Length
|
||||
p[i++] = 0xa1; // Constructor
|
||||
p[i++] = (0x04 + len); // Length
|
||||
p[i++] = 0x30;
|
||||
p[i++] = (0x02 + len);
|
||||
p[i++] = 0x02;
|
||||
p[i++] = 0x02; // AOC-E so Total
|
||||
p[i++] = 0x30; // recordedUnits
|
||||
p[i++] = (0x02 + len); // Length
|
||||
p[i++] = 0x02; // recordedNumberOfUnits
|
||||
p[i++] = len;
|
||||
|
||||
// Recorded units could take up as much as 3 bytes (0xFFFFFF)
|
||||
p[i] = numberOfUnits & 0xFF;
|
||||
|
@ -499,7 +500,7 @@ static int encodeAOCEChargingUnitOperation(__u8 * dest, const struct asn1_parm *
|
|||
p[i+2] = (numberOfUnits >> 16) & 0xFF;
|
||||
i += len;
|
||||
|
||||
p[1] = (AOCE_CHARGE_UNIT_IE_LENGTH + len); // IE Payload Length
|
||||
p[1] = i - 2; // IE Payload Length
|
||||
p[4] = p[1] - 3; // Invoke Component Length
|
||||
|
||||
result = p[1] + 2; // Total Length of IE
|
||||
|
|
Loading…
Reference in New Issue