comparison src/g23m-gprs/sm/sm_mm_output_handler.c @ 183:219afcfc6250

src/g23m-gprs: initial import from TCS3.2/LoCosto
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 13 Oct 2016 04:24:13 +0000
parents
children
comparison
equal deleted inserted replaced
182:f02d0a0e1849 183:219afcfc6250
1 /*----------------------------------------------------------------------------
2 | Project : 3G PS
3 | Module : SM
4 +-----------------------------------------------------------------------------
5 | Copyright 2003 Texas Instruments.
6 | All rights reserved.
7 |
8 | This file is confidential and a trade secret of Texas
9 | Instruments .
10 | The receipt of or possession of this file does not convey
11 | any rights to reproduce or disclose its contents or to
12 | manufacture, use, or sell anything it may describe, in
13 | whole, or in part, without the specific written consent of
14 | Texas Instruments.
15 +-----------------------------------------------------------------------------
16 | Purpose: Output functions for primitives from SM to the MM entity.
17 | For design details, see:
18 | 8010.908 SM Detailed Specification
19 +---------------------------------------------------------------------------*/
20
21 /*==== DECLARATION CONTROL =================================================*/
22
23 /*==== INCLUDES ============================================================*/
24
25 #include "sm.h"
26 #include "message.h"
27 #include "ccdapi.h"
28
29 #include "sm_mm_output_handler.h"
30 #include "sm_qos.h"
31 #include "sm_tft.h"
32
33 /*==== CONSTS ===============================================================*/
34
35 /*==== TYPES ================================================================*/
36
37 /*==== LOCALS ===============================================================*/
38
39 #define SM_MM_SEND_MSG(c,e,s,M) sm_mm_send_msg(c,e,s,BSIZE_##M##)
40
41 /*==== PRIVATE FUNCTIONS ====================================================*/
42
43 /*
44 +------------------------------------------------------------------------------
45 | Function : sm_set_ti_pd
46 +------------------------------------------------------------------------------
47 | Description : Prepend TI and PD to an outgoing air interface message
48 |
49 | Parameters : ti, pd
50 |
51 +------------------------------------------------------------------------------
52 */
53 static void sm_set_ti_pd(U8 ti, T_MSGBUF *msg)
54 {
55 U8 ti_flag = ti & SM_TI_FLAG;
56 U8 msg_type = msg->buf[msg->o_buf >> 3];
57
58 /* Check for extended ti */
59 if ( (ti & SM_TI_MASK) > (U8)SM_MAX_NON_EXT_TI) { /* TRUE == Extended TI */
60 /* Value assigned to variable to shut up Visual C */
61 U8 ti_msb = ti_flag | 0x70 | PD_SM;
62 U8 ti_lsb = ti & 127 | 0x80; /* TI EXT must be 1 [3G 24.007, 11.2.3.1.3] */
63
64 /* Insert extended ti flag + PD in first octet, and ti value in octet 2 */
65 (void)ccd_codeByte(msg->buf, (U16)(msg->o_buf-16), (U16)8, ti_msb);
66 (void)ccd_codeByte(msg->buf, (U16)(msg->o_buf-8), (U16)8, ti_lsb);
67 msg->l_buf += 16;
68 msg->o_buf -= 16;
69
70 (void)TRACE_EVENT_P8("L3 HDR: 0x%02x [0x%02x] 0x%02x {ti_flag=%d, "
71 "ti=%d, pd=%d, ext_ti=%d, msg_type=0x%02x}",
72 msg->buf[msg->o_buf >> 3],
73 msg->buf[(msg->o_buf >> 3) + 1],
74 msg->buf[(msg->o_buf >> 3) + 2],
75 (ti_flag != (U8)0 ? 1 : 0),
76 ti, PD_SM, ti_lsb, msg_type);
77 } else { /* (ti & SM_TI_MASK) <= SM_MAX_NON_EXT_TI: Non-extended TI */
78 /* Value assigned to variable to shut up Visual C */
79 U8 ti_val = ti_flag | ((ti & SM_TI_NON_EXT_MASK) << 4) | PD_SM;
80
81 /* Insert non-extended ti value in msg */
82 (void)ccd_codeByte(msg->buf, (USHORT)(msg->o_buf-8), (U16)8, ti_val);
83 msg->l_buf += 8;
84 msg->o_buf -= 8;
85
86 (void)TRACE_EVENT_P6("L3 HDR: 0x%02x [] 0x%02x {ti_flag=%d, "
87 "ti=%d, pd=%d, msg_type=0x%02x}",
88 msg->buf[msg->o_buf >> 3],
89 msg->buf[(msg->o_buf >> 3) + 1],
90 (ti_flag != (U8)0 ? 1 : 0), ti, PD_SM, msg_type);
91 }
92 }
93
94 static U8 sm_mmpm_establish_cause(struct T_SM_CONTEXT_DATA *context)
95 {
96 T_PS_tc traffic_class;
97
98 if (context != NULL) {
99 /*
100 * Call QoS helper function to extract requested traffic class QoS
101 * parameter from the requested QoS parameters for this context/NSAPI.
102 */
103 traffic_class = (T_PS_tc)sm_qos_get_traffic_class(context);
104
105 switch (traffic_class) {
106 case PS_TC_CONV:
107 return (U8)MMPM_CAUSE_ESTABL_ORIG_CONVERSATIONAL;
108 case PS_TC_STREAM:
109 return (U8)MMPM_CAUSE_ESTABL_ORIG_STREAMING;
110 case PS_TC_INTER:
111 return (U8)MMPM_CAUSE_ESTABL_ORIG_INTERACTIVE;
112 case PS_TC_BG:
113 return (U8)MMPM_CAUSE_ESTABL_ORIG_BACKGROUND;
114 default:
115 /* For subscribed QoS, high priority signalling is used by default. */
116 return (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING;
117 }
118 } else {
119 return (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING;
120 }
121 }
122
123 static U8 sm_cause_ps_to_air(T_CAUSE_ps_cause *cause)
124 {
125 switch (cause->ctrl_value) {
126 case CAUSE_is_from_nwsm:
127 return (U8)cause->value.nwsm_cause;
128 default:
129 (void)TRACE_ERROR("Causes not from M_SM not supported yet!");
130 return (U8)cause->value.nwsm_cause;
131 }
132 }
133
134 /*
135 +------------------------------------------------------------------------------
136 | Function : send_mmpm_unitdata_req
137 +------------------------------------------------------------------------------
138 | Description : Call CCD to code AIM and send MMPM_UNITDATA_REQ primitive.
139 |
140 | Parameters : ti - Transaction identifier
141 | est_cause - establish cause (for MM)
142 | prim - Formatted air interface message
143 +------------------------------------------------------------------------------
144 */
145 static void send_mmpm_unitdata_req(U8 ti, U8 est_cause,
146 /*@null@*/struct T_SM_CONTEXT_DATA *context,
147 /*@only@*/ /*@null@*/
148 T_MMPM_UNITDATA_REQ *prim)
149 {
150 (void)TRACE_FUNCTION("send_mmpm_unitdata_req");
151
152 TRACE_ASSERT (prim != NULL);
153
154 if (prim EQ NULL)
155 return;
156
157 /* Originating entity is SM */
158 prim->org_entity = (U8)NAS_ORG_ENTITY_SM;
159
160 /* Add establish cause and PDP context status elements */
161 prim->v_establish_cause = (U8)TRUE;
162 prim->establish_cause = est_cause;
163
164 prim->v_nsapi_set = (U8)TRUE;
165 prim->nsapi_set = sm_get_pdp_context_status();
166
167 if (ccd_codeMsg((U8)CCDENT_SM, (U8)UPLINK, (T_MSGBUF *)&prim->sdu,
168 _decodedMsg, (U8)NOT_PRESENT_8BIT) != (U8)ccdOK) {
169 /*
170 * Error Handling
171 */
172 (void)TRACE_ERROR( "Error in outgoing message" ) ;
173 sm_pfree(prim);
174 } else {
175 /*
176 * Add TI and PD to air interface message
177 * Note: "sm_set_ti_pd" updates SDU length and offset according
178 * to TI size (i.e. whether extended TIs are needed)
179 */
180 sm_set_ti_pd(ti, (T_MSGBUF *)&prim->sdu);
181
182 if (context != NULL) {
183 /* Store coded message for retransmission etc. */
184 sm_allocate_and_copy_coded_msg(context, est_cause, &prim->sdu);
185 }
186
187 /* No sending primitives if SM is suspended or not attached
188 * - resume will cause retransmission */
189 if (!sm_is_suspended() && sm_is_attached()) {
190 (void)PSEND(hCommMM, prim);
191 } else {
192 (void)TRACE_EVENT( "Primitive NOT sent to GMM. SM is suspended or GPRS not attached" );
193 sm_pfree(prim);
194 }
195 }
196 }
197
198 /*
199 +------------------------------------------------------------------------------
200 | Function : sm_mm_send_msg
201 +------------------------------------------------------------------------------
202 | Description : Send message using MM. Codes message using CCD, stores it
203 | for retransmission, and sends it (unless SM is suspended).
204 |
205 | Parameters : context - Context data
206 | est_cause - establish cause (for MM)
207 | msg_bitlen - Maximum message bit length
208 +------------------------------------------------------------------------------
209 */
210 static void sm_mm_send_msg(struct T_SM_CONTEXT_DATA *context, U8 est_cause,
211 BOOL store_coded_msg, int msg_bitlen)
212 {
213 (void)TRACE_FUNCTION("sm_mm_send_msg");
214
215 {
216 T_MMPM_UNITDATA_REQ *mmpm_unitdata_req;
217
218 mmpm_unitdata_req = (T_MMPM_UNITDATA_REQ *)
219 vsi_c_new_sdu(SIZ(T_MMPM_UNITDATA_REQ), MMPM_UNITDATA_REQ,
220 (U16)msg_bitlen, offsetof(T_MMPM_UNITDATA_REQ, sdu), /*lint -e413*/
221 ENCODE_OFFSET FILE_LINE_MACRO);
222
223 TRACE_ASSERT(mmpm_unitdata_req != NULL);
224
225 send_mmpm_unitdata_req(context->ti, est_cause,
226 (store_coded_msg ? context : NULL),
227 mmpm_unitdata_req);
228 }
229 }
230
231 /*==== PUBLIC FUNCTIONS =====================================================*/
232
233 /*
234 +------------------------------------------------------------------------------
235 | Function : resend_msg
236 +------------------------------------------------------------------------------
237 | Description : Resend previously coded message
238 |
239 | Parameters : ti - Transaction identifier
240 | est_cause - establish cause (for MM)
241 +------------------------------------------------------------------------------
242 */
243 void resend_msg(struct T_SM_CONTEXT_DATA *context)
244 {
245 T_sdu *message = context->coded_msg;
246
247 (void)TRACE_FUNCTION("resend_msg");
248
249 /* Send nothing if SM is suspended or not attached */
250 if (sm_is_suspended() || !sm_is_attached())
251 {
252 return;
253 }
254
255 if (message != NULL)
256 {
257 T_MMPM_UNITDATA_REQ *prim;
258
259 prim = (T_MMPM_UNITDATA_REQ *)
260 vsi_c_new_sdu(SIZ(T_MMPM_UNITDATA_REQ), MMPM_UNITDATA_REQ,
261 message->l_buf, offsetof(T_MMPM_UNITDATA_REQ, sdu), /*lint -e413*/
262 ENCODE_OFFSET FILE_LINE_MACRO);
263
264 TRACE_ASSERT (prim != NULL);
265
266 if (prim EQ NULL)
267 return;
268
269 prim->sdu.l_buf = message->l_buf;
270 memcpy(&prim->sdu.buf[(prim->sdu.o_buf >> 3)], message->buf,
271 (size_t)(message->l_buf >> 3));
272
273 /* Originating entity is SM */
274 prim->org_entity = (U8)NAS_ORG_ENTITY_SM;
275
276 /* Add establish cause and PDP context status elements */
277 prim->v_establish_cause = (U8)TRUE;
278 prim->establish_cause = (U8)message->o_buf;
279
280 prim->v_nsapi_set = (U8)TRUE;
281 prim->nsapi_set = sm_get_pdp_context_status();
282
283 (void)PSEND(hCommMM, prim);
284 }
285 }
286
287 /*
288 +------------------------------------------------------------------------------
289 | Function : send_mmpm_pdp_context_status_req
290 +------------------------------------------------------------------------------
291 | Description : Allocate, pack and send MMPM_PDP_CONTEXT_STATUS_REQ primitive.
292 |
293 | Parameters : None
294 +------------------------------------------------------------------------------
295 */
296 void send_mmpm_pdp_context_status_req(void)
297 {
298 (void)TRACE_FUNCTION("send_mmpm_pdp_context_status_req");
299 {
300 PALLOC(prim, MMPM_PDP_CONTEXT_STATUS_REQ);
301
302 TRACE_ASSERT(prim != NULL);
303 /*lint -e613 (Possible use of null pointer 'prim' in left argument to operator '->') */
304 prim->nsapi_set = sm_get_pdp_context_status();
305
306 (void)PSEND(hCommMM, prim);
307 /*lint +e613 (Possible use of null pointer 'prim' in left argument to operator '->') */
308 }
309 }
310
311 /* Air Interface Message formatting functions */
312 void send_msg_activate_pdp_context_request(struct T_SM_CONTEXT_DATA *context)
313 {
314 int addr_len;
315 MCAST(msg, ACTIVATE_PDP_CONTEXT_REQUEST);
316
317 (void)TRACE_FUNCTION("send_msg_activate_pdp_context_request");
318
319 msg->msg_type = (U8)ACTIVATE_PDP_CONTEXT_REQUEST;
320 msg->nsapi.nsapi_val = context->nsapi;
321
322 msg->llc_sapi.sapi = (U8)PS_SAPI_3;
323
324 /*
325 * Assign air message QoS parameters from SMREG parameters. Release conversion included.
326 */
327 sm_qos_convert_to_aim(&context->requested_qos,
328 &msg->qos, sm_get_current_nw_release());
329
330 switch (context->pdp_type) {
331 case SMREG_PDP_PPP:
332 msg->address.pdp_type_org = (U8)M_SM_ETSI_ORG;
333 msg->address.pdp_type_no = (U8)M_SM_PPP_TYPE;
334 break;
335 case SMREG_PDP_IPV6:
336 msg->address.pdp_type_org = (U8)M_SM_IETF_ORG;
337 msg->address.pdp_type_no = (U8)M_SM_IP6_TYPE;
338 break;
339 case SMREG_PDP_IPV4:
340 msg->address.pdp_type_org = (U8)M_SM_IETF_ORG;
341 msg->address.pdp_type_no = (U8)M_SM_IP4_TYPE;
342 break;
343 case SMREG_PDP_EMPTY:
344 default:
345 msg->address.pdp_type_org = (U8)M_SM_PDP_MT;
346 msg->address.pdp_type_no = (U8)0;
347 }
348
349 switch (context->requested_address.ctrl_ip_address) {
350 case NAS_is_ipv4:
351 addr_len = NAS_SIZE_IPv4_ADDR;
352 break;
353 case NAS_is_ipv6:
354 addr_len = NAS_SIZE_IPv6_ADDR;
355 break;
356 case NAS_is_ip_not_present: /* No IP address requested == dynamic IP */
357 default:
358 addr_len = 0;
359 break;
360 }
361 msg->address.c_add_info = (U8)addr_len;
362 memcpy(&msg->address.add_info,
363 &context->requested_address.ip_address,
364 (size_t)addr_len);
365
366 /*
367 * Access Point Name.
368 */
369 if (context->apn != NULL && context->apn->c_apn_buf > (U8)0) {
370 msg->v_apn = (U8)TRUE;
371 msg->apn.c_apn_value = context->apn->c_apn_buf;
372 memcpy(msg->apn.apn_value,
373 context->apn->apn_buf,
374 (size_t)context->apn->c_apn_buf);
375 } else {
376 msg->v_apn = (U8)FALSE;
377 msg->apn.c_apn_value = (U8)0;
378 }
379
380 /*
381 * Protocol configuration options.
382 */
383 if (context->requested_pco != NULL &&
384 context->requested_pco->c_pco_value > (U8)0) {
385 msg->v_pco = (U8)TRUE;
386 msg->pco.c_pco_value = context->requested_pco->c_pco_value;
387 memcpy(msg->pco.pco_value,
388 context->requested_pco->pco_value,
389 (size_t)context->requested_pco->c_pco_value);
390 } else {
391 msg->v_pco = (U8)FALSE;
392 }
393
394 SM_MM_SEND_MSG(context, sm_mmpm_establish_cause(context),
395 TRUE, ACTIVATE_PDP_CONTEXT_REQUEST);
396 }
397
398 void send_msg_activate_secondary_pdp_context_request(struct T_SM_CONTEXT_DATA *context)
399 {
400 MCAST(msg, ACTIVATE_SECONDARY_PDP_CONTEXT_REQUEST);
401
402 (void)TRACE_FUNCTION("send_msg_activate_secondary_pdp_context_request");
403
404 msg->msg_type = (U8)ACTIVATE_SECONDARY_PDP_CONTEXT_REQUEST;
405 msg->nsapi.nsapi_val = (U8)context->nsapi;
406
407 msg->llc_sapi.sapi = (U8)PS_SAPI_3;
408
409 /*
410 * Assign air message QoS parameters from SMREG parameters. Release conversion included.
411 */
412 sm_qos_convert_to_aim(&context->requested_qos,
413 &msg->qos, sm_get_current_nw_release());
414
415 if (context->requested_tft.ptr_tft_pf != NULL)
416 {
417 msg->v_tft = (U8)TRUE;
418 sm_tft_convert_to_aim(context, &msg->tft);
419 } else {
420 msg->v_tft = (U8)FALSE;
421 }
422
423 SM_MM_SEND_MSG(context, sm_mmpm_establish_cause(context),
424 TRUE, ACTIVATE_SECONDARY_PDP_CONTEXT_REQUEST);
425 }
426
427 void send_msg_deactivate_pdp_context_accept(struct T_SM_CONTEXT_DATA *context)
428 {
429 MCAST(msg, DEACTIVATE_PDP_CONTEXT_ACCEPT);
430
431 (void)TRACE_FUNCTION("send_msg_deactivate_pdp_context_accept");
432
433 msg->msg_type = (U8)DEACTIVATE_PDP_CONTEXT_ACCEPT;
434
435 SM_MM_SEND_MSG(context, (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING,
436 FALSE, DEACTIVATE_PDP_CONTEXT_ACCEPT);
437 }
438
439 void send_msg_deactivate_pdp_context_request(struct T_SM_CONTEXT_DATA *context, /*@partial@*/T_CAUSE_ps_cause *cause, BOOL tear_down)
440 {
441 MCAST(msg, DEACTIVATE_PDP_CONTEXT_REQUEST);
442
443 (void)TRACE_FUNCTION("send_msg_deactivate_pdp_context_request");
444
445 msg->msg_type = (U8)DEACTIVATE_PDP_CONTEXT_REQUEST;
446
447 msg->sm_cause.sm_cause_val = sm_cause_ps_to_air(cause);
448
449 if (tear_down) {
450 msg->v_tear_down = (U8)TRUE;
451 msg->tear_down.tear_down_flag = (U8)1;
452 } else {
453 msg->v_tear_down = (U8)FALSE;
454 }
455
456 SM_MM_SEND_MSG(context, (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING,
457 TRUE, DEACTIVATE_PDP_CONTEXT_REQUEST);
458 }
459
460 void send_msg_modify_pdp_context_accept(struct T_SM_CONTEXT_DATA *context)
461 {
462 MCAST(msg, U_MODIFY_PDP_CONTEXT_ACCEPT);
463
464 (void)TRACE_FUNCTION("send_msg_modify_pdp_context_accept");
465
466 msg->msg_type = (U8)U_MODIFY_PDP_CONTEXT_ACCEPT;
467
468 SM_MM_SEND_MSG(context, (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING,
469 FALSE, U_MODIFY_PDP_CONTEXT_ACCEPT);
470 }
471
472 void send_msg_modify_pdp_context_request(struct T_SM_CONTEXT_DATA *context)
473 {
474 MCAST(msg, U_MODIFY_PDP_CONTEXT_REQUEST);
475
476 (void)TRACE_FUNCTION("send_msg_modify_pdp_context_request");
477
478 msg->msg_type = (U8)U_MODIFY_PDP_CONTEXT_REQUEST;
479
480 if (context->sapi != (U8)PS_SAPI_0) {
481 msg->v_llc_sapi = (U8)TRUE;
482 msg->llc_sapi.sapi = (U8)context->sapi;
483 } else {
484 msg->v_llc_sapi = (U8)FALSE;
485 }
486
487 if (sm_qos_is_requested_qos_present(context)) {
488 msg->v_qos = (U8)TRUE;
489 /* Assign air message QoS parameters from SMREG parameters. Release conversion included. */
490 sm_qos_convert_to_aim(&context->requested_qos,
491 &msg->qos, sm_get_current_nw_release());
492 } else {
493 msg->v_qos = (U8)FALSE;
494 }
495
496 if (sm_tft_more_to_modify(context))
497 {
498 msg->v_tft = (U8)TRUE;
499 sm_tft_convert_to_aim(context, &msg->tft);
500 } else {
501 msg->v_tft = (U8)FALSE;
502 }
503
504 SM_MM_SEND_MSG(context, (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING,
505 TRUE, U_MODIFY_PDP_CONTEXT_REQUEST);
506 }
507
508 void send_msg_request_pdp_context_activation_reject(struct T_SM_CONTEXT_DATA *context, /*@partial@*/T_CAUSE_ps_cause *cause)
509 {
510 MCAST(msg, REQUEST_PDP_CONTEXT_ACTIVATION_REJECT);
511
512 (void)TRACE_FUNCTION("send_msg_request_pdp_context_activation_reject");
513
514 msg->msg_type = (U8)REQUEST_PDP_CONTEXT_ACTIVATION_REJECT;
515 msg->sm_cause.sm_cause_val = (U8)sm_cause_ps_to_air(cause);
516 {
517 /* This message must ALWAYS have TI flag set, as it is a reply to the network. */
518 U8 ti = context->ti | SM_TI_FLAG;
519 PALLOC_MSG(mmpm_unitdata_req, MMPM_UNITDATA_REQ, REQUEST_PDP_CONTEXT_ACTIVATION_REJECT);
520
521 send_mmpm_unitdata_req(ti, (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING,
522 NULL, mmpm_unitdata_req);
523 }
524 }
525
526 void send_msg_sm_status(U8 ti, /*@partial@*/T_CAUSE_ps_cause *cause)
527 {
528 MCAST(msg, SM_STATUS);
529
530 (void)TRACE_FUNCTION("send_msg_sm_status");
531
532 msg->msg_type = (U8)SM_STATUS;
533 msg->sm_cause.sm_cause_val = sm_cause_ps_to_air(cause);
534 {
535 PALLOC_MSG(mmpm_unitdata_req, MMPM_UNITDATA_REQ, SM_STATUS);
536
537 send_mmpm_unitdata_req(ti, (U8)MMPM_CAUSE_ESTABL_ORIG_HIGH_PRIO_SIGNALLING,
538 NULL, mmpm_unitdata_req);
539 }
540 }
541
542 /*==== END OF FILE ==========================================================*/