1 /* -*- Mode: C; tab-width:2 -*- */
2 /* ex: set ts=2 shiftwidth=2 softtabstop=2 cindent: */
4 * Copyright (c) 2003 The Regents of the University of California.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above
13 * copyright notice, this list of conditions and the following
14 * disclaimer in the documentation and/or other materials provided
15 * with the distribution.
16 * 3. All advertising materials mentioning features or use of this
17 * software must display the following acknowledgement:
18 * This product includes software developed by Networked &
19 * Embedded Systems Lab at UCLA
20 * 4. Neither the name of the University nor that of the Laboratory
21 * may be used to endorse or promote products derived from this
22 * software without specific prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
25 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
26 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
27 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS
28 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * $Id: message_net.c,v 1.36 2006/12/17 00:51:01 simonhan Exp $
40 * @brief Message handling routines for network
41 * @author Simon Han (simonhan@cs.ucla.edu)
42 * @brief General Message Dispatcher (Handles diverse links)
43 * @author Ram Kumar {ram@ee.ucla.edu}
46 #include <message_queue.h>
49 #include <message_types.h>
52 #include <sos_sched.h>
54 #include <sos_logging.h>
56 #ifdef SOS_USE_PREEMPTION
60 #if defined (SOS_UART_CHANNEL)
62 #include <sos_uart_mgr.h>
65 #if defined (SOS_I2C_CHANNEL)
67 #include <sos_i2c_mgr.h>
70 typedef int8_t (*routing_func_t
)(func_cb_ptr cb
, Message
*m
);
71 static int8_t no_router(func_cb_ptr p
, Message
*msg
);
72 //-------------------------------------------------------------------------------
73 // STATIC FUNCTION DECLARATIONS
74 //-------------------------------------------------------------------------------
75 static int8_t sos_msg_dispatch(Message
* m
);
76 static inline void msg_change_endian(Message
* e
);
77 static bool sos_msg_find_right_link(Message
*m
);
78 static int8_t routing_handler(void *state
, Message
*msg
);
80 #ifndef SOS_USE_PREEMPTION
81 static sos_module_t routing_module
;
84 #ifdef SOS_USE_PREEMPTION
85 static func_cb_ptr
*routing_func_ptr
;
87 static func_cb_ptr routing_func_ptr
[1];
90 static mod_header_t mod_header SOS_MODULE_HEADER
=
92 mod_id
: KER_ROUTING_PID
,
93 #ifdef SOS_USE_PREEMPTION
94 state_size
: sizeof(func_cb_ptr
),
100 module_handler
: routing_handler
,
103 {no_router
, "czv1", RUNTIME_PID
, RUNTIME_FID
},
107 static int8_t no_router(func_cb_ptr p
, Message
*msg
)
111 static int8_t routing_handler(void *state
, Message
*msg
)
116 //-------------------------------------------------------------------------------
117 // FUNCTION IMPLEMENTATIONS
118 //-------------------------------------------------------------------------------
119 // Fix the endian-ness of the message header
120 static inline void msg_change_endian(Message
* e
){
121 e
->daddr
= ehtons(e
->daddr
);
122 e
->saddr
= ehtons(e
->saddr
);
125 // Create a deep copy of the message
127 #if defined(SOS_UART_CHANNEL) || defined(SOS_I2C_CHANNEL) || defined(SOS_SPI_CHANNEL)
128 static Message
* msg_duplicate(Message
* m
){
131 mcopy
= msg_create();
132 if (NULL
== mcopy
) return NULL
;
133 d
= (uint8_t*)ker_malloc(m
->len
, KER_SCHED_PID
);
134 if ((NULL
== d
) && (0 != m
->len
)){
138 memcpy(mcopy
, m
, sizeof(Message
));
140 mcopy
->flag
|= SOS_MSG_RELEASE
;
141 memcpy(mcopy
->data
, m
->data
, m
->len
);
146 // NULL Link - Simply free the message
147 static void null_link_msg_alloc(Message
* m
){
153 //-------------------------------------------------------------------------------
155 //-------------------------------------------------------------------------------
156 // Copies message header and sends out the message
157 int8_t post(Message
*e
){
158 Message
*m
= msg_create();
160 if(flag_msg_release(e
->flag
)) {
167 // deep copy the header
170 // Transfer the memory
173 e
->flag
&= ~SOS_MSG_RELEASE
;
177 return sos_msg_dispatch(m
);
180 //-------------------------------------------------------------------------------
182 //-------------------------------------------------------------------------------
183 // Post a message over any link as specified by the flag
184 int8_t post_link(sos_pid_t did
, sos_pid_t sid
,
185 uint8_t type
, uint8_t len
,
186 void *data
, uint16_t flag
,
190 Message
*m
= msg_create();
192 if (flag_msg_release(flag
)){
198 // Fill out message header
202 m
->saddr
= node_address
;
205 m
->data
= (uint8_t*)data
;
207 #ifdef SOS_USE_PREEMPTION
208 // assign priority based on did
209 m
->priority
= get_module_priority(did
);
213 return sos_msg_dispatch(m
);
217 //-----------------------------------------------------------------------------
218 // SOS Find Right link
219 //-----------------------------------------------------------------------------
220 static bool sos_msg_find_right_link(Message
*m
)
222 bool link_found
= false;
224 // try to figure out the right link
225 #ifdef SOS_UART_CHANNEL
226 if (check_uart_address(m
->daddr
) == SOS_OK
) {
227 m
->flag
|= SOS_MSG_UART_IO
;
230 m
->flag
&= ~SOS_MSG_UART_IO
;
233 m
->flag
&= ~SOS_MSG_UART_IO
;
236 #ifdef SOS_I2C_CHANNEL
237 if (check_i2c_address(m
->daddr
) == SOS_OK
) {
238 m
->flag
|= SOS_MSG_I2C_IO
;
241 m
->flag
&= ~SOS_MSG_I2C_IO
;
244 m
->flag
&= ~SOS_MSG_I2C_IO
;
247 if(link_found
== false) {
248 m
->flag
|= SOS_MSG_RADIO_IO
;
250 m
->flag
&= ~SOS_MSG_RADIO_IO
;
255 //--------------------------------------------------------------------------------
256 // SOS Message Dispatcher
257 //--------------------------------------------------------------------------------
258 static int8_t sos_msg_dispatch(Message
* m
)
260 #if defined(SOS_RADIO_CHANNEL) || defined(SOS_UART_CHANNEL) || defined(SOS_I2C_CHANNEL) || defined(SOS_SPI_CHANNEL)
261 Message
* mcopy
[NUM_IO_LINKS
] = {NULL
};
262 uint8_t msg_count
= 0;
266 if (node_address
== m
->daddr
){
268 ker_log( SOS_LOG_POST_NET
, m
->sid
, m
->daddr
);
272 #if !defined(SOS_UART_CHANNEL) && !defined(SOS_I2C_CHANNEL) && !defined(SOS_RADIO_CHANNEL) && !defined(SOS_SPI_CHANNEL)
273 null_link_msg_alloc(m
);
277 if( m
->daddr
!= BCAST_ADDRESS
&& flag_msg_raw(m
->flag
) == 0 ) {
279 // Not using raw message, send to the routing layer first
280 if( sos_msg_find_right_link(m
) == false ) {
281 ret
= SOS_CALL(routing_func_ptr
[0], routing_func_t
, m
);
282 if( ret
== ( SOS_OK
+ 1 )) {
283 // Forward to the link layer (don't generate senddone)
286 } else if( ret
== SOS_OK
) {
288 msg_send_senddone( m
, true, KER_ROUTING_PID
);
294 if (flag_msg_link_auto(m
->flag
) && m
->daddr
!= BCAST_ADDRESS
) {
295 sos_msg_find_right_link(m
);
298 if ((m
->flag
& SOS_MSG_ALL_LINK_IO
) == 0) {
299 null_link_msg_alloc(m
);
303 // Pre-allocate the message copies to allow for
304 // an atomic NOMEM failure
305 #ifdef SOS_RADIO_CHANNEL
306 if (flag_msg_from_radio(m
->flag
)){
307 mcopy
[SOS_RADIO_LINK_ID
] = m
;
312 #ifdef SOS_UART_CHANNEL
313 if( flag_msg_from_uart(m
->flag
) ) {
315 mcopy
[SOS_UART_LINK_ID
] = m
;
317 mcopy
[SOS_UART_LINK_ID
] = msg_duplicate(m
);
318 if (NULL
== mcopy
[SOS_UART_LINK_ID
]) goto dispatch_cleanup
;
319 mcopy
[SOS_UART_LINK_ID
]->flag
&= ~SOS_MSG_RELIABLE
;
325 #ifdef SOS_I2C_CHANNEL
326 if (flag_msg_from_i2c(m
->flag
)) {
328 mcopy
[SOS_I2C_LINK_ID
] = m
;
330 mcopy
[SOS_I2C_LINK_ID
] = msg_duplicate(m
);
331 if (NULL
== mcopy
[SOS_I2C_LINK_ID
]) goto dispatch_cleanup
;
332 mcopy
[SOS_I2C_LINK_ID
]->flag
&= ~SOS_MSG_RELIABLE
;
338 #ifdef SOS_SPI_CHANNEL
339 if (flag_msg_from_spi(m
->flag
)) {
341 mcopy
[SOS_SPI_LINK_ID
] = m
;
343 mcopy
[SOS_SPI_LINK_ID
] = msg_duplicate(m
);
344 if (NULL
== mcopy
[SOS_SPI_LINK_ID
]) goto dispatch_cleanup
;
345 mcopy
[SOS_SPI_LINK_ID
]->flag
&= ~SOS_MSG_RELIABLE
;
351 // Deliver to monitor only once
352 monitor_deliver_outgoing_msg_to_monitor(m
);
355 #ifdef SOS_RADIO_CHANNEL
356 if (NULL
!= mcopy
[SOS_RADIO_LINK_ID
]){
357 msg_change_endian(mcopy
[SOS_RADIO_LINK_ID
]);
358 SOS_RADIO_LINK_DISPATCH(mcopy
[SOS_RADIO_LINK_ID
]);
359 ker_log( SOS_LOG_POST_NET
, mcopy
[SOS_RADIO_LINK_ID
]->sid
, mcopy
[SOS_RADIO_LINK_ID
]->daddr
);
364 #ifdef SOS_UART_CHANNEL
365 if (NULL
!= mcopy
[SOS_UART_LINK_ID
]){
366 msg_change_endian(mcopy
[SOS_UART_LINK_ID
]);
367 SOS_UART_LINK_DISPATCH(mcopy
[SOS_UART_LINK_ID
]);
372 #ifdef SOS_I2C_CHANNEL
373 if (NULL
!= mcopy
[SOS_I2C_LINK_ID
]){
374 msg_change_endian(mcopy
[SOS_I2C_LINK_ID
]);
375 SOS_I2C_LINK_DISPATCH(mcopy
[SOS_I2C_LINK_ID
]);
380 #ifdef SOS_SPI_CHANNEL
381 if (NULL
!= mcopy
[SOS_SPI_LINK_ID
]){
382 msg_change_endian(mcopy
[SOS_SPI_LINK_ID
]);
383 SOS_SPI_LINK_DISPATCH(mcopy
[SOS_SPI_LINK_ID
]);
389 #if defined(SOS_UART_CHANNEL) || defined(SOS_I2C_CHANNEL) || defined(SOS_SPI_CHANNEL)
393 for (i
= 0 ; i
< NUM_IO_LINKS
; i
++){
394 if (NULL
!= mcopy
[i
]){
395 msg_dispose(mcopy
[i
]);
398 DEBUG("----------------Cleaning up-----------\n");
404 //============================================================================
406 //============================================================================
408 int8_t ker_sys_post_link(sos_pid_t dst_mod_id
, uint8_t type
,
409 uint8_t size
, void *data
, uint16_t flag
, uint16_t dst_node_addr
)
411 sos_pid_t my_id
= ker_get_current_pid();
413 if( post_link(dst_mod_id
, my_id
, type
, size
, data
, flag
, dst_node_addr
) != SOS_OK
) {
414 return ker_mod_panic(my_id
);
419 int8_t ker_sys_routing_register( uint8_t fid
)
421 sos_pid_t sub_id
= ker_get_current_pid();
423 if(ker_fntable_subscribe(KER_ROUTING_PID
, sub_id
, fid
, 0) != SOS_OK
) {
429 void routing_init( void )
431 #ifdef SOS_USE_PREEMPTION
432 ker_register_module(sos_get_header_address(mod_header
));
433 routing_func_ptr
= ker_get_module_state(KER_SENSOR_PID
);
435 sched_register_kernel_module( &routing_module
, sos_get_header_address(mod_header
), routing_func_ptr
);