examples: mrp_client, fix compiler warning
[profile/ivi/OpenAVB.git] / examples / mrp_client / mrpdhelper.c
1 /******************************************************************************
2
3   Copyright (c) 2012, AudioScience, Inc
4   All rights reserved.
5   
6   Redistribution and use in source and binary forms, with or without 
7   modification, are permitted provided that the following conditions are met:
8   
9    1. Redistributions of source code must retain the above copyright notice, 
10       this list of conditions and the following disclaimer.
11   
12    2. 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 distribution.
15   
16    3. Neither the name of the Intel Corporation nor the names of its 
17       contributors may be used to endorse or promote products derived from 
18       this software without specific prior written permission.
19   
20   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
22   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
23   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
24   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
25   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
26   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
27   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
28   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
29   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   POSSIBILITY OF SUCH DAMAGE.
31
32 ******************************************************************************/
33
34 /******************************************************************************
35 This module implements code that takes the notification strings that MRPD sends
36 and parses them into a machine readable structure.
37 ******************************************************************************/
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <stdint.h>             // for uint8_t etc
42 #ifdef __linux__
43 #include <inttypes.h>
44 #else
45 #define SCNu64       "I64u"
46 #define SCNx64       "I64x"
47 #endif
48
49 #include "mrpdhelper.h"
50
51 struct app_state_to_enum {
52         char *s;
53         enum mrpdhelper_applicant_state value;
54 } mrp_app_state_mapping[12] = {
55         {"VO", mrpdhelper_applicant_state_VO},
56         {"VP", mrpdhelper_applicant_state_VP},
57         {"VN", mrpdhelper_applicant_state_VN},
58         {"AN", mrpdhelper_applicant_state_AN},
59         {"AA", mrpdhelper_applicant_state_AA},
60         {"QA", mrpdhelper_applicant_state_QA},
61         {"LA", mrpdhelper_applicant_state_LA},
62         {"AO", mrpdhelper_applicant_state_AO},
63         {"QO", mrpdhelper_applicant_state_QO},
64         {"AP", mrpdhelper_applicant_state_AP},
65         {"QP", mrpdhelper_applicant_state_QP},
66         {"LO", mrpdhelper_applicant_state_LO}
67 };
68
69
70 static int parse_app_state(char *sz, struct mrpdhelper_notify *n)
71 {
72         int i;
73
74         /* loop over mrp_app_state_mapping struct */
75         for (i=0; i < 12; i++) {
76                 if (strncmp(sz, mrp_app_state_mapping[i].s, 2) == 0) {
77                         n->app_state = mrp_app_state_mapping[i].value;
78                         break;
79                 }
80         }
81         if (n->app_state == mrpdhelper_applicant_state_null)
82                 return -1;
83         else
84                 return 0;
85 }
86
87 static int parse_state(char *sz, struct mrpdhelper_notify *n)
88 {
89         if (strncmp(sz, "IN", 2) == 0) {
90                 n->state = mrpdhelper_state_in;
91         } else if (strncmp(sz, "LV", 3) == 0) {
92                 n->state = mrpdhelper_state_leave;
93         } else if (strncmp(sz, "MT", 3) == 0) {
94                 n->state = mrpdhelper_state_empty;
95         } else {
96                 return -1;
97         }
98         return 0;
99 }
100
101 static int parse_notification(char *sz, struct mrpdhelper_notify *n)
102 {
103         if (strncmp(sz, "NE", 2) == 0) {
104                 n->notify = mrpdhelper_notification_new;
105         } else if (strncmp(sz, "JO", 2) == 0) {
106                 n->notify = mrpdhelper_notification_join;
107         } else if (strncmp(sz, "LE", 2) == 0) {
108                 n->notify = mrpdhelper_notification_leave;
109         } else {
110                 return -1;
111         }
112         return 0;
113 }
114
115 static int parse_registrar(char *sz, struct mrpdhelper_notify *n, char **rpos)
116 {
117         char *r;
118
119         r = strstr(sz, "R=");
120         if (rpos)
121                 *rpos = r;
122         if (!r)
123                 return -1;
124
125         if (sscanf(r, "R=%" SCNx64, &n->registrar) == 1)
126                 return 0;
127         else
128                 return -1;
129 }
130
131 static int parse_mvrp(char *sz, size_t len, struct mrpdhelper_notify *n)
132 {
133         /* format
134            VIN VJO 1234 R=112233445566
135            len = 28
136          */
137         if (len < 28)
138                 return -1;
139
140         if (parse_notification(&sz[1], n) < 0)
141                 return -1;
142
143         if (parse_state(&sz[5], n) < 0)
144                 return -1;
145
146         n->attrib = mrpdhelper_attribtype_mvrp;
147         if (sscanf(&sz[8], "%04x ", &n->u.v.vid) != 1)
148                 return -1;
149         return parse_registrar(sz, n, NULL);
150 }
151
152 static int parse_msrp_string(char *sz, size_t len, struct mrpdhelper_notify *n)
153 {
154         int result;
155
156         sz[len] = 0;
157         switch (sz[0]) {
158         case 'D':
159                 result = sscanf(sz, "D:C=%d,P=%d,V=%04x",
160                                 &n->u.sd.id, &n->u.sd.priority, &n->u.sd.vid);
161                 if (result < 3)
162                         return -1;
163                 n->attrib = mrpdhelper_attribtype_msrp_domain;
164                 break;
165         case 'L':
166                 result = sscanf(sz, "L:D=%d,S=%" SCNx64,
167                                 &n->u.sl.substate, &n->u.sl.id);
168                 if (result < 2)
169                         return -1;
170                 n->attrib = mrpdhelper_attribtype_msrp_listener;
171                 break;
172         case 'T':
173                 result = sscanf(sz,
174                                 "T:S=%" SCNx64
175                                 ",A=%" SCNx64
176                                 ",V=%04x"
177                                 ",Z=%d"
178                                 ",I=%d"
179                                 ",P=%d"
180                                 ",L=%d"
181                                 ",B=%" SCNx64
182                                 ",C=%d",
183                                 &n->u.st.id,
184                                 &n->u.st.dest_mac,
185                                 &n->u.st.vid,
186                                 &n->u.st.max_frame_size,
187                                 &n->u.st.max_interval_frames,
188                                 &n->u.st.priority_and_rank,
189                                 &n->u.st.accum_latency,
190                                 &n->u.st.bridge_id, &n->u.st.failure_code);
191                 if (result < 9)
192                         return -1;
193                 n->attrib = mrpdhelper_attribtype_msrp_talker;
194                 break;
195         default:
196                 return -1;
197
198         }
199         return 0;
200 }
201
202 static int parse_msrp(char *sz, size_t len, struct mrpdhelper_notify *n)
203 {
204         if (parse_notification(&sz[1], n) < 0)
205                 return -1;
206
207         if (parse_msrp_string(&sz[4], len - 4, n) < 0)
208                 return -1;
209
210         return parse_registrar(sz, n, NULL);
211 }
212
213
214 static int parse_msrp_query(char *sz, size_t len, struct mrpdhelper_notify *n)
215 {
216         char *r;
217
218         if (parse_msrp_string(sz, len, n) < 0)
219                 return -1;
220
221         if (parse_registrar(sz, n, &r) < 0)
222                 return -1;
223
224         if (parse_app_state(&r[15], n) < 0)
225                 return -1;
226
227         return parse_state(&r[18], n);
228 }
229
230 static int parse_mmrp(char *sz, size_t len, struct mrpdhelper_notify *n)
231 {
232         /* format
233            MIN MJO M=112233445566 R=112233445566
234            len = 38
235          */
236         if (len < 38)
237                 return -1;
238
239         if (parse_notification(&sz[1], n) < 0)
240                 return -1;
241
242         if (parse_state(&sz[5], n) < 0)
243                 return -1;
244
245         n->attrib = mrpdhelper_attribtype_mvrp;
246         if (sscanf(&sz[8], "M=%" SCNx64, &n->u.m.mac) != 1)
247                 return -1;
248         return parse_registrar(sz, n, NULL);
249 }
250
251 int mrpdhelper_parse_notification(char *sz, size_t len,
252                                   struct mrpdhelper_notify *n)
253 {
254         memset(n, 0, sizeof(*n));
255         switch (sz[0]) {
256         case 'V':
257                 return parse_mvrp(sz, len, n);
258         case 'S':
259                 return parse_msrp(sz, len, n);
260         case 'M':
261                 return parse_mmrp(sz, len, n);
262         case 'L':
263         case 'D':
264         case 'T':
265                 return parse_msrp_query(sz, len, n);
266         default:
267                 return -1;
268         }
269 }
270
271 int mrpdhelper_notify_equal(struct mrpdhelper_notify *n1,
272                             struct mrpdhelper_notify *n2)
273 {
274         if (n1->attrib != n2->attrib)
275                 return 0;
276
277         switch (n1->attrib) {
278         case mrpdhelper_attribtype_mmrp:
279                 if (n1->u.m.mac != n2->u.m.mac)
280                         return 0;
281                 break;
282         case mrpdhelper_attribtype_mvrp:
283                 if (n1->u.v.vid != n2->u.v.vid)
284                         return 0;
285                 break;
286         case mrpdhelper_attribtype_msrp_domain:
287                 if ((n1->u.sd.id != n1->u.sd.id) ||
288                     (n1->u.sd.priority != n1->u.sd.priority) ||
289                     (n1->u.sd.vid != n1->u.sd.vid))
290                         return 0;
291                 break;
292         case mrpdhelper_attribtype_msrp_talker:
293         case mrpdhelper_attribtype_msrp_talker_fail:
294                 if (n1->u.st.id != n2->u.st.id)
295                         return 0;
296                 break;
297         case mrpdhelper_attribtype_msrp_listener:
298         case mrpdhelper_attribtype_msrp_listener_fail:
299                 if (n1->u.sl.id != n2->u.sl.id)
300                         return 0;
301                 break;
302         default:
303                 return 0;
304         }
305         return 1;
306 }