Added Linux example and updated release notes
[keystone-rtos/rm-lld.git] / test / k2k / armv7 / linux / rm_server.c
1 /*
2  * Copyright (C) 2013 Texas Instruments Incorporated - http://www.ti.com/
3  *
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *    Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *    Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *    Neither the name of Texas Instruments Incorporated nor the names of
18  *    its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
34 /* Standard includes */
35 #include <stdio.h>
36 #include <errno.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <sys/mman.h>
40 #include <sys/stat.h>
41 #include <fcntl.h>
42 #include <time.h>
44 /* Socket Includes */
45 #include "sockutils.h"
46 #include "sockrmmsg.h"
48 /* RM includes */
49 #include <ti/drv/rm/rm.h>
50 #include <ti/drv/rm/rm_transport.h>
52 #define error_msg printf
53 #define info_msg  printf
55 /* Socket timeout */
56 #define SERVER_SOCK_TIMEOUT_USEC     (500)
58 /* Seconds since last request to print resources */
59 #define SECONDS_SINCE_LAST_REQUEST   (5)
61 /* Error checking macro */
62 #define ERROR_CHECK(checkVal, resultVal, rmInstName, printMsg)            \
63     if (resultVal != checkVal) {                                          \
64         char errorMsgToPrint[] = printMsg;                                \
65         printf("%s : ", rmInstName);                                      \
66         printf("%s with error code : %d\n", errorMsgToPrint, resultVal);  \
67         exit(EXIT_FAILURE);                                               \
68     }
70 /* RM registered transport mapping structure */
71 typedef struct trans_map_entry_s {
72     /* Registered RM transport handle */
73     Rm_TransportHandle        trans_handle;
74     /* Remote socket tied to the transport handle */
75     sock_name_t              *remote_sock;
76     /* Next entry in the transport map */
77     struct trans_map_entry_s *n;
78 } trans_map_entry_t;
80 /**********************************************************************
81  ********************** Global Variables ******************************
82  **********************************************************************/
83 /* RM Server instance name (must match with RM Global Resource List (GRL) and policies */
84 char   server_name[RM_NAME_MAX_CHARS] = "RM_Server";
86 sock_h server_sock = NULL;
88 /**********************************************************************
89  ************************** Server Functions **************************
90  **********************************************************************/
91  
92 Rm_Packet *transportAlloc(Rm_AppTransportHandle appTransport, uint32_t pktSize, Rm_PacketHandle *pktHandle)
93 {
94     Rm_Packet *rm_pkt = NULL;
96     rm_pkt = calloc(1, sizeof(*rm_pkt));
97     if (!rm_pkt) {
98         error_msg("can't malloc for RM send message (err: %s)\n",
99                   strerror(errno));
100         return (NULL);
101     }
102     rm_pkt->pktLenBytes = pktSize;
103     *pktHandle = rm_pkt;
105     return(rm_pkt);
108 void transportFree (Rm_Packet *rm_pkt)
110     uint32_t pkt_size = rm_pkt->pktLenBytes;
111     int32_t  status;
113     if (rm_pkt) {
114         free (rm_pkt);
115     }         
118 int32_t transportSend (Rm_AppTransportHandle appTransport, Rm_PacketHandle pktHandle)
120     sock_name_t *client_sock_name = (sock_name_t *)appTransport;
121     Rm_Packet   *rm_pkt = (Rm_Packet *)pktHandle;
122     
123     if (sock_send(server_sock, (char *)rm_pkt, (int) rm_pkt->pktLenBytes, client_sock_name)) {
124         error_msg("send data failed\n");
125     }
126  
127     return (0);
130 int main(int argc, char *argv[])
132     int                 fd;
133     time_t              old_time;
134     struct stat         file_stat;
135     char               *grl_addr;
136     char               *linux_dtb_addr;
137     char               *policy_addr;
138     Rm_Handle           server_h;
139     Rm_InitCfg          rm_init_cfg;
140     Rm_TransportCfg     rm_trans_cfg;
141     int32_t             rm_result;
142     trans_map_entry_t  *trans_map = NULL;
143     trans_map_entry_t  *new_map_entry;
144     trans_map_entry_t  *map_index;
145     int                 retval;
146     int                 length = 0;
147     sock_name_t         serv_sock_name;
148     sock_name_t         client_sock_addr;
149     Rm_Packet          *rm_pkt = NULL;
150     struct sockaddr_un  client_addr;
151     struct timeval      tv = {0, SERVER_SOCK_TIMEOUT_USEC};    
152     char                rm_socket_name[] = RM_SERVER_SOCKET_NAME;
154     if ((argc < 3) || (argc > 4))
155     {
156         error_msg("Invalid number of input arguments\n");
157         exit(EXIT_FAILURE);        
158     }
160     /* mmap the GRL */
161     fd = open(argv[1], O_RDONLY);
162     if (fd == -1) {
163         error_msg("Error opening GRL\n");
164         exit(EXIT_FAILURE);
165     }
166     /* Obtain file size */
167     if (fstat(fd, &file_stat) == -1) {
168         error_msg("Error getting GRL size\n");
169         exit(EXIT_FAILURE);
170     }
171     grl_addr = mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
172     if (grl_addr == MAP_FAILED) {
173         error_msg("mmap of GRL failed\n");
174         exit(EXIT_FAILURE);
175     }
177     /* mmap the Global Policy */
178     fd = open(argv[2], O_RDONLY);
179     if (fd == -1) {
180         error_msg("Error opening Global Policy\n");
181         exit(EXIT_FAILURE);
182     }
183     /* Obtain file size */
184     if (fstat(fd, &file_stat) == -1) {
185         error_msg("Error getting Global Policy size\n");
186         exit(EXIT_FAILURE);
187     }
188     policy_addr = mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
189     if (policy_addr == MAP_FAILED) {
190         error_msg("mmap of Global Policy failed\n");
191         exit(EXIT_FAILURE);
192     }
194     if (argc == 4){
195         /* mmap (Example) Linux DTB */
196         fd = open(argv[3], O_RDONLY);
197         if (fd == -1) {
198             error_msg("Error opening Linux DTB\n");
199             exit(EXIT_FAILURE);
200         }
201         /* Obtain file size */
202         if (fstat(fd, &file_stat) == -1) {
203             error_msg("Error getting Linux DTB size\n");
204             exit(EXIT_FAILURE);
205         }
206         linux_dtb_addr = mmap(NULL, file_stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
207         if (linux_dtb_addr == MAP_FAILED) {
208             error_msg("mmap of Linux DTB failed\n");
209             exit(EXIT_FAILURE);
210         }
211     }
213     /* Create the Server instance */
214     memset(&rm_init_cfg, 0, sizeof(rm_init_cfg));
215     rm_init_cfg.instName = server_name;
216     rm_init_cfg.instType = Rm_instType_SERVER;
217     rm_init_cfg.instCfg.serverCfg.globalResourceList = (void *)grl_addr;
218     rm_init_cfg.instCfg.serverCfg.linuxDtb = (void *)linux_dtb_addr;
219     rm_init_cfg.instCfg.serverCfg.globalPolicy = (void *)policy_addr;
220     server_h = Rm_init(&rm_init_cfg, &rm_result);
221     ERROR_CHECK(RM_OK, rm_result, server_name, "Initialization failed\n");
223     printf("\n\nInitialized %s\n\n", server_name);
225     Rm_resourceStatus(server_h, 1);
226     
227     serv_sock_name.type = sock_name_e;
228     serv_sock_name.s.name = rm_socket_name;
229     server_sock = sock_open (&serv_sock_name);
231     old_time = time(NULL);
232     info_msg("Begin waiting for messages from Clients\n");
234     while(1) {
236         if ((time(NULL) - old_time) > SECONDS_SINCE_LAST_REQUEST) {
237             Rm_resourceStatus(server_h, 1);
238             old_time = time(NULL);
239         }
241         retval = sock_wait(server_sock, &length, &tv, -1);
242         if (retval == -2) {
243             goto loop_continue;
244         }
245         else if (retval < 0) {
246             error_msg("Error in reading from socket\n");
247             goto loop_continue;
248         }
250         if (length < sizeof(rm_pkt)) {
251             error_msg("invalid RM message length %d\n", length);
252             goto loop_continue;
253         }
254         rm_pkt = calloc(1, length);
255         if (!rm_pkt) {
256             error_msg("can't malloc for recv'd RM message (err: %s)\n",
257                       strerror(errno));
258             goto loop_continue;
259         }
261         client_sock_addr.type = sock_addr_e;
262         client_sock_addr.s.addr = &client_addr;
263         retval = sock_recv(server_sock, (char *)rm_pkt, length, &client_sock_addr);
264         if (retval != length) {
265             error_msg("recv RM pkt failed from socket, received = %d, expected = %d\n",
266                       retval, length);
267             goto loop_continue;
268         }
270         info_msg("received RM pkt of size %d bytes from %s\n", length, client_sock_addr.s.addr->sun_path);
272         map_index = trans_map;
273         while(map_index != NULL) {
274             if (strncmp(map_index->remote_sock->s.addr->sun_path,
275                         client_addr.sun_path, 
276                         sizeof(client_addr.sun_path)) == 0) {
277                 break;
278             }
279             map_index = map_index->n;
280         }
282         if (!map_index) {
283             new_map_entry = calloc(1, sizeof(*new_map_entry));
284             new_map_entry->remote_sock = calloc(1, sizeof(sock_name_t));
285             new_map_entry->remote_sock->s.addr = calloc(1, sizeof(struct sockaddr_un));
286             new_map_entry->remote_sock->type = sock_addr_e;
287             memcpy(new_map_entry->remote_sock->s.addr, &client_addr, sizeof(struct sockaddr_un));
288                         
289             /* Register the Client with the Server instance */
290             rm_trans_cfg.rmHandle = server_h;
291             rm_trans_cfg.appTransportHandle = (Rm_AppTransportHandle)new_map_entry->remote_sock;
292             rm_trans_cfg.remoteInstType = Rm_instType_CLIENT;
293             rm_trans_cfg.transportCallouts.rmAllocPkt = transportAlloc;
294             rm_trans_cfg.transportCallouts.rmSendPkt = transportSend;
295             new_map_entry->trans_handle = Rm_transportRegister(&rm_trans_cfg, &rm_result);
297             new_map_entry->n = NULL;
299             if (trans_map == NULL) {
300                 trans_map = new_map_entry;
301             }
302             else {
303                 map_index = trans_map;
305                 while(map_index->n != NULL) {
306                     map_index = map_index->n;
307                 }
308                 map_index->n = new_map_entry;
309             }
311             map_index = new_map_entry;
312         }
314         /* Provide packet to RM Server for processing */       
315         if (rm_result = Rm_receivePacket(map_index->trans_handle, rm_pkt)) {
316             printf("RM failed to process received packet: %d\n", rm_result);
317         }
318         transportFree(rm_pkt);
319         old_time = time(NULL);
320 loop_continue:
321         /* Cleanups */
322         length = 0;    
323         memset(&client_sock_addr, 0, sizeof(sock_name_t));
324         memset(&client_addr, 0, sizeof(struct sockaddr_un));
325     }