1*042d53a7SEvalZero /*
2*042d53a7SEvalZero * Licensed to the Apache Software Foundation (ASF) under one
3*042d53a7SEvalZero * or more contributor license agreements. See the NOTICE file
4*042d53a7SEvalZero * distributed with this work for additional information
5*042d53a7SEvalZero * regarding copyright ownership. The ASF licenses this file
6*042d53a7SEvalZero * to you under the Apache License, Version 2.0 (the
7*042d53a7SEvalZero * "License"); you may not use this file except in compliance
8*042d53a7SEvalZero * with the License. You may obtain a copy of the License at
9*042d53a7SEvalZero *
10*042d53a7SEvalZero * http://www.apache.org/licenses/LICENSE-2.0
11*042d53a7SEvalZero *
12*042d53a7SEvalZero * Unless required by applicable law or agreed to in writing,
13*042d53a7SEvalZero * software distributed under the License is distributed on an
14*042d53a7SEvalZero * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15*042d53a7SEvalZero * KIND, either express or implied. See the License for the
16*042d53a7SEvalZero * specific language governing permissions and limitations
17*042d53a7SEvalZero * under the License.
18*042d53a7SEvalZero */
19*042d53a7SEvalZero
20*042d53a7SEvalZero #include <string.h>
21*042d53a7SEvalZero #include <stdlib.h>
22*042d53a7SEvalZero #include <limits.h>
23*042d53a7SEvalZero #include <stdarg.h>
24*042d53a7SEvalZero #include <errno.h>
25*042d53a7SEvalZero #include <assert.h>
26*042d53a7SEvalZero #include "host/ble_hs.h"
27*042d53a7SEvalZero #include "host/ble_uuid.h"
28*042d53a7SEvalZero #include "host/ble_eddystone.h"
29*042d53a7SEvalZero #include "cmd.h"
30*042d53a7SEvalZero #include "btshell.h"
31*042d53a7SEvalZero
32*042d53a7SEvalZero #include "nimble/npl_shell.h"
33*042d53a7SEvalZero
34*042d53a7SEvalZero #define CMD_MAX_ARGS 16
35*042d53a7SEvalZero
36*042d53a7SEvalZero static char *cmd_args[CMD_MAX_ARGS][2];
37*042d53a7SEvalZero static int cmd_num_args;
38*042d53a7SEvalZero
39*042d53a7SEvalZero int
parse_arg_find_idx(const char * key)40*042d53a7SEvalZero parse_arg_find_idx(const char *key)
41*042d53a7SEvalZero {
42*042d53a7SEvalZero int i;
43*042d53a7SEvalZero
44*042d53a7SEvalZero for (i = 0; i < cmd_num_args; i++) {
45*042d53a7SEvalZero if (strcmp(cmd_args[i][0], key) == 0) {
46*042d53a7SEvalZero return i;
47*042d53a7SEvalZero }
48*042d53a7SEvalZero }
49*042d53a7SEvalZero
50*042d53a7SEvalZero return -1;
51*042d53a7SEvalZero }
52*042d53a7SEvalZero
53*042d53a7SEvalZero char *
parse_arg_peek(const char * key)54*042d53a7SEvalZero parse_arg_peek(const char *key)
55*042d53a7SEvalZero {
56*042d53a7SEvalZero int i;
57*042d53a7SEvalZero
58*042d53a7SEvalZero for (i = 0; i < cmd_num_args; i++) {
59*042d53a7SEvalZero if (strcmp(cmd_args[i][0], key) == 0) {
60*042d53a7SEvalZero return cmd_args[i][1];
61*042d53a7SEvalZero }
62*042d53a7SEvalZero }
63*042d53a7SEvalZero
64*042d53a7SEvalZero return NULL;
65*042d53a7SEvalZero }
66*042d53a7SEvalZero
67*042d53a7SEvalZero char *
parse_arg_extract(const char * key)68*042d53a7SEvalZero parse_arg_extract(const char *key)
69*042d53a7SEvalZero {
70*042d53a7SEvalZero int i;
71*042d53a7SEvalZero
72*042d53a7SEvalZero for (i = 0; i < cmd_num_args; i++) {
73*042d53a7SEvalZero if (strcmp(cmd_args[i][0], key) == 0) {
74*042d53a7SEvalZero /* Erase parameter. */
75*042d53a7SEvalZero cmd_args[i][0][0] = '\0';
76*042d53a7SEvalZero
77*042d53a7SEvalZero return cmd_args[i][1];
78*042d53a7SEvalZero }
79*042d53a7SEvalZero }
80*042d53a7SEvalZero
81*042d53a7SEvalZero return NULL;
82*042d53a7SEvalZero }
83*042d53a7SEvalZero
84*042d53a7SEvalZero /**
85*042d53a7SEvalZero * Determines which number base to use when parsing the specified numeric
86*042d53a7SEvalZero * string. This just avoids base '0' so that numbers don't get interpreted as
87*042d53a7SEvalZero * octal.
88*042d53a7SEvalZero */
89*042d53a7SEvalZero static int
parse_arg_long_base(char * sval)90*042d53a7SEvalZero parse_arg_long_base(char *sval)
91*042d53a7SEvalZero {
92*042d53a7SEvalZero if (sval[0] == '0' && sval[1] == 'x') {
93*042d53a7SEvalZero return 0;
94*042d53a7SEvalZero } else {
95*042d53a7SEvalZero return 10;
96*042d53a7SEvalZero }
97*042d53a7SEvalZero }
98*042d53a7SEvalZero
99*042d53a7SEvalZero long
parse_long_bounds(char * sval,long min,long max,int * out_status)100*042d53a7SEvalZero parse_long_bounds(char *sval, long min, long max, int *out_status)
101*042d53a7SEvalZero {
102*042d53a7SEvalZero char *endptr;
103*042d53a7SEvalZero long lval;
104*042d53a7SEvalZero
105*042d53a7SEvalZero lval = strtol(sval, &endptr, parse_arg_long_base(sval));
106*042d53a7SEvalZero if (sval[0] != '\0' && *endptr == '\0' &&
107*042d53a7SEvalZero lval >= min && lval <= max) {
108*042d53a7SEvalZero
109*042d53a7SEvalZero *out_status = 0;
110*042d53a7SEvalZero return lval;
111*042d53a7SEvalZero }
112*042d53a7SEvalZero
113*042d53a7SEvalZero *out_status = EINVAL;
114*042d53a7SEvalZero return 0;
115*042d53a7SEvalZero }
116*042d53a7SEvalZero
117*042d53a7SEvalZero long
parse_arg_long_bounds_peek(char * name,long min,long max,int * out_status)118*042d53a7SEvalZero parse_arg_long_bounds_peek(char *name, long min, long max, int *out_status)
119*042d53a7SEvalZero {
120*042d53a7SEvalZero char *sval;
121*042d53a7SEvalZero
122*042d53a7SEvalZero sval = parse_arg_peek(name);
123*042d53a7SEvalZero if (sval == NULL) {
124*042d53a7SEvalZero *out_status = ENOENT;
125*042d53a7SEvalZero return 0;
126*042d53a7SEvalZero }
127*042d53a7SEvalZero return parse_long_bounds(sval, min, max, out_status);
128*042d53a7SEvalZero }
129*042d53a7SEvalZero
130*042d53a7SEvalZero long
parse_arg_long_bounds(char * name,long min,long max,int * out_status)131*042d53a7SEvalZero parse_arg_long_bounds(char *name, long min, long max, int *out_status)
132*042d53a7SEvalZero {
133*042d53a7SEvalZero char *sval;
134*042d53a7SEvalZero
135*042d53a7SEvalZero sval = parse_arg_extract(name);
136*042d53a7SEvalZero if (sval == NULL) {
137*042d53a7SEvalZero *out_status = ENOENT;
138*042d53a7SEvalZero return 0;
139*042d53a7SEvalZero }
140*042d53a7SEvalZero return parse_long_bounds(sval, min, max, out_status);
141*042d53a7SEvalZero }
142*042d53a7SEvalZero
143*042d53a7SEvalZero long
parse_arg_long_bounds_dflt(char * name,long min,long max,long dflt,int * out_status)144*042d53a7SEvalZero parse_arg_long_bounds_dflt(char *name, long min, long max,
145*042d53a7SEvalZero long dflt, int *out_status)
146*042d53a7SEvalZero {
147*042d53a7SEvalZero long val;
148*042d53a7SEvalZero int rc;
149*042d53a7SEvalZero
150*042d53a7SEvalZero val = parse_arg_long_bounds(name, min, max, &rc);
151*042d53a7SEvalZero if (rc == ENOENT) {
152*042d53a7SEvalZero rc = 0;
153*042d53a7SEvalZero val = dflt;
154*042d53a7SEvalZero }
155*042d53a7SEvalZero
156*042d53a7SEvalZero *out_status = rc;
157*042d53a7SEvalZero
158*042d53a7SEvalZero return val;
159*042d53a7SEvalZero }
160*042d53a7SEvalZero
161*042d53a7SEvalZero uint64_t
parse_arg_uint64_bounds(char * name,uint64_t min,uint64_t max,int * out_status)162*042d53a7SEvalZero parse_arg_uint64_bounds(char *name, uint64_t min, uint64_t max, int *out_status)
163*042d53a7SEvalZero {
164*042d53a7SEvalZero char *endptr;
165*042d53a7SEvalZero char *sval;
166*042d53a7SEvalZero uint64_t lval;
167*042d53a7SEvalZero
168*042d53a7SEvalZero sval = parse_arg_extract(name);
169*042d53a7SEvalZero if (sval == NULL) {
170*042d53a7SEvalZero *out_status = ENOENT;
171*042d53a7SEvalZero return 0;
172*042d53a7SEvalZero }
173*042d53a7SEvalZero
174*042d53a7SEvalZero lval = strtoull(sval, &endptr, parse_arg_long_base(sval));
175*042d53a7SEvalZero if (sval[0] != '\0' && *endptr == '\0' &&
176*042d53a7SEvalZero lval >= min && lval <= max) {
177*042d53a7SEvalZero
178*042d53a7SEvalZero *out_status = 0;
179*042d53a7SEvalZero return lval;
180*042d53a7SEvalZero }
181*042d53a7SEvalZero
182*042d53a7SEvalZero *out_status = EINVAL;
183*042d53a7SEvalZero return 0;
184*042d53a7SEvalZero }
185*042d53a7SEvalZero
186*042d53a7SEvalZero long
parse_arg_long(char * name,int * out_status)187*042d53a7SEvalZero parse_arg_long(char *name, int *out_status)
188*042d53a7SEvalZero {
189*042d53a7SEvalZero return parse_arg_long_bounds(name, LONG_MIN, LONG_MAX, out_status);
190*042d53a7SEvalZero }
191*042d53a7SEvalZero
192*042d53a7SEvalZero uint8_t
parse_arg_bool(char * name,int * out_status)193*042d53a7SEvalZero parse_arg_bool(char *name, int *out_status)
194*042d53a7SEvalZero {
195*042d53a7SEvalZero return parse_arg_long_bounds(name, 0, 1, out_status);
196*042d53a7SEvalZero }
197*042d53a7SEvalZero
198*042d53a7SEvalZero uint8_t
parse_arg_bool_dflt(char * name,uint8_t dflt,int * out_status)199*042d53a7SEvalZero parse_arg_bool_dflt(char *name, uint8_t dflt, int *out_status)
200*042d53a7SEvalZero {
201*042d53a7SEvalZero return parse_arg_long_bounds_dflt(name, 0, 1, dflt, out_status);
202*042d53a7SEvalZero }
203*042d53a7SEvalZero
204*042d53a7SEvalZero uint8_t
parse_arg_uint8(char * name,int * out_status)205*042d53a7SEvalZero parse_arg_uint8(char *name, int *out_status)
206*042d53a7SEvalZero {
207*042d53a7SEvalZero return parse_arg_long_bounds(name, 0, UINT8_MAX, out_status);
208*042d53a7SEvalZero }
209*042d53a7SEvalZero
210*042d53a7SEvalZero uint16_t
parse_arg_uint16(char * name,int * out_status)211*042d53a7SEvalZero parse_arg_uint16(char *name, int *out_status)
212*042d53a7SEvalZero {
213*042d53a7SEvalZero return parse_arg_long_bounds(name, 0, UINT16_MAX, out_status);
214*042d53a7SEvalZero }
215*042d53a7SEvalZero
216*042d53a7SEvalZero uint16_t
parse_arg_uint16_peek(char * name,int * out_status)217*042d53a7SEvalZero parse_arg_uint16_peek(char *name, int *out_status)
218*042d53a7SEvalZero {
219*042d53a7SEvalZero return parse_arg_long_bounds_peek(name, 0, UINT16_MAX, out_status);
220*042d53a7SEvalZero }
221*042d53a7SEvalZero
222*042d53a7SEvalZero uint32_t
parse_arg_uint32(char * name,int * out_status)223*042d53a7SEvalZero parse_arg_uint32(char *name, int *out_status)
224*042d53a7SEvalZero {
225*042d53a7SEvalZero return parse_arg_uint64_bounds(name, 0, UINT32_MAX, out_status);
226*042d53a7SEvalZero }
227*042d53a7SEvalZero
228*042d53a7SEvalZero uint64_t
parse_arg_uint64(char * name,int * out_status)229*042d53a7SEvalZero parse_arg_uint64(char *name, int *out_status)
230*042d53a7SEvalZero {
231*042d53a7SEvalZero return parse_arg_uint64_bounds(name, 0, UINT64_MAX, out_status);
232*042d53a7SEvalZero }
233*042d53a7SEvalZero
234*042d53a7SEvalZero uint8_t
parse_arg_uint8_dflt(char * name,uint8_t dflt,int * out_status)235*042d53a7SEvalZero parse_arg_uint8_dflt(char *name, uint8_t dflt, int *out_status)
236*042d53a7SEvalZero {
237*042d53a7SEvalZero uint8_t val;
238*042d53a7SEvalZero int rc;
239*042d53a7SEvalZero
240*042d53a7SEvalZero val = parse_arg_uint8(name, &rc);
241*042d53a7SEvalZero if (rc == ENOENT) {
242*042d53a7SEvalZero val = dflt;
243*042d53a7SEvalZero rc = 0;
244*042d53a7SEvalZero }
245*042d53a7SEvalZero
246*042d53a7SEvalZero *out_status = rc;
247*042d53a7SEvalZero return val;
248*042d53a7SEvalZero }
249*042d53a7SEvalZero
250*042d53a7SEvalZero uint16_t
parse_arg_uint16_dflt(char * name,uint16_t dflt,int * out_status)251*042d53a7SEvalZero parse_arg_uint16_dflt(char *name, uint16_t dflt, int *out_status)
252*042d53a7SEvalZero {
253*042d53a7SEvalZero uint16_t val;
254*042d53a7SEvalZero int rc;
255*042d53a7SEvalZero
256*042d53a7SEvalZero val = parse_arg_uint16(name, &rc);
257*042d53a7SEvalZero if (rc == ENOENT) {
258*042d53a7SEvalZero val = dflt;
259*042d53a7SEvalZero rc = 0;
260*042d53a7SEvalZero }
261*042d53a7SEvalZero
262*042d53a7SEvalZero *out_status = rc;
263*042d53a7SEvalZero return val;
264*042d53a7SEvalZero }
265*042d53a7SEvalZero
266*042d53a7SEvalZero uint32_t
parse_arg_uint32_dflt(char * name,uint32_t dflt,int * out_status)267*042d53a7SEvalZero parse_arg_uint32_dflt(char *name, uint32_t dflt, int *out_status)
268*042d53a7SEvalZero {
269*042d53a7SEvalZero uint32_t val;
270*042d53a7SEvalZero int rc;
271*042d53a7SEvalZero
272*042d53a7SEvalZero val = parse_arg_uint32(name, &rc);
273*042d53a7SEvalZero if (rc == ENOENT) {
274*042d53a7SEvalZero val = dflt;
275*042d53a7SEvalZero rc = 0;
276*042d53a7SEvalZero }
277*042d53a7SEvalZero
278*042d53a7SEvalZero *out_status = rc;
279*042d53a7SEvalZero return val;
280*042d53a7SEvalZero }
281*042d53a7SEvalZero
282*042d53a7SEvalZero const struct kv_pair *
parse_kv_find(const struct kv_pair * kvs,char * name)283*042d53a7SEvalZero parse_kv_find(const struct kv_pair *kvs, char *name)
284*042d53a7SEvalZero {
285*042d53a7SEvalZero const struct kv_pair *kv;
286*042d53a7SEvalZero int i;
287*042d53a7SEvalZero
288*042d53a7SEvalZero for (i = 0; kvs[i].key != NULL; i++) {
289*042d53a7SEvalZero kv = kvs + i;
290*042d53a7SEvalZero if (strcmp(name, kv->key) == 0) {
291*042d53a7SEvalZero return kv;
292*042d53a7SEvalZero }
293*042d53a7SEvalZero }
294*042d53a7SEvalZero
295*042d53a7SEvalZero return NULL;
296*042d53a7SEvalZero }
297*042d53a7SEvalZero
298*042d53a7SEvalZero int
parse_arg_kv(char * name,const struct kv_pair * kvs,int * out_status)299*042d53a7SEvalZero parse_arg_kv(char *name, const struct kv_pair *kvs, int *out_status)
300*042d53a7SEvalZero {
301*042d53a7SEvalZero const struct kv_pair *kv;
302*042d53a7SEvalZero char *sval;
303*042d53a7SEvalZero
304*042d53a7SEvalZero sval = parse_arg_extract(name);
305*042d53a7SEvalZero if (sval == NULL) {
306*042d53a7SEvalZero *out_status = ENOENT;
307*042d53a7SEvalZero return -1;
308*042d53a7SEvalZero }
309*042d53a7SEvalZero
310*042d53a7SEvalZero kv = parse_kv_find(kvs, sval);
311*042d53a7SEvalZero if (kv == NULL) {
312*042d53a7SEvalZero *out_status = EINVAL;
313*042d53a7SEvalZero return -1;
314*042d53a7SEvalZero }
315*042d53a7SEvalZero
316*042d53a7SEvalZero *out_status = 0;
317*042d53a7SEvalZero return kv->val;
318*042d53a7SEvalZero }
319*042d53a7SEvalZero
320*042d53a7SEvalZero int
parse_arg_kv_dflt(char * name,const struct kv_pair * kvs,int def_val,int * out_status)321*042d53a7SEvalZero parse_arg_kv_dflt(char *name, const struct kv_pair *kvs, int def_val,
322*042d53a7SEvalZero int *out_status)
323*042d53a7SEvalZero {
324*042d53a7SEvalZero int val;
325*042d53a7SEvalZero int rc;
326*042d53a7SEvalZero
327*042d53a7SEvalZero val = parse_arg_kv(name, kvs, &rc);
328*042d53a7SEvalZero if (rc == ENOENT) {
329*042d53a7SEvalZero rc = 0;
330*042d53a7SEvalZero val = def_val;
331*042d53a7SEvalZero }
332*042d53a7SEvalZero
333*042d53a7SEvalZero *out_status = rc;
334*042d53a7SEvalZero
335*042d53a7SEvalZero return val;
336*042d53a7SEvalZero }
337*042d53a7SEvalZero
338*042d53a7SEvalZero
339*042d53a7SEvalZero static int
parse_arg_byte_stream_delim(char * sval,char * delims,int max_len,uint8_t * dst,int * out_len)340*042d53a7SEvalZero parse_arg_byte_stream_delim(char *sval, char *delims, int max_len,
341*042d53a7SEvalZero uint8_t *dst, int *out_len)
342*042d53a7SEvalZero {
343*042d53a7SEvalZero unsigned long ul;
344*042d53a7SEvalZero char *endptr;
345*042d53a7SEvalZero char *token;
346*042d53a7SEvalZero int i;
347*042d53a7SEvalZero
348*042d53a7SEvalZero i = 0;
349*042d53a7SEvalZero for (token = strtok(sval, delims);
350*042d53a7SEvalZero token != NULL;
351*042d53a7SEvalZero token = strtok(NULL, delims)) {
352*042d53a7SEvalZero
353*042d53a7SEvalZero if (i >= max_len) {
354*042d53a7SEvalZero return EINVAL;
355*042d53a7SEvalZero }
356*042d53a7SEvalZero
357*042d53a7SEvalZero ul = strtoul(token, &endptr, 16);
358*042d53a7SEvalZero if (sval[0] == '\0' || *endptr != '\0' || ul > UINT8_MAX) {
359*042d53a7SEvalZero return -1;
360*042d53a7SEvalZero }
361*042d53a7SEvalZero
362*042d53a7SEvalZero dst[i] = ul;
363*042d53a7SEvalZero i++;
364*042d53a7SEvalZero }
365*042d53a7SEvalZero
366*042d53a7SEvalZero *out_len = i;
367*042d53a7SEvalZero
368*042d53a7SEvalZero return 0;
369*042d53a7SEvalZero }
370*042d53a7SEvalZero
371*042d53a7SEvalZero int
parse_arg_byte_stream(char * name,int max_len,uint8_t * dst,int * out_len)372*042d53a7SEvalZero parse_arg_byte_stream(char *name, int max_len, uint8_t *dst, int *out_len)
373*042d53a7SEvalZero {
374*042d53a7SEvalZero char *sval;
375*042d53a7SEvalZero
376*042d53a7SEvalZero sval = parse_arg_extract(name);
377*042d53a7SEvalZero if (sval == NULL) {
378*042d53a7SEvalZero return ENOENT;
379*042d53a7SEvalZero }
380*042d53a7SEvalZero
381*042d53a7SEvalZero return parse_arg_byte_stream_delim(sval, ":-", max_len, dst, out_len);
382*042d53a7SEvalZero }
383*042d53a7SEvalZero
384*042d53a7SEvalZero int
parse_arg_byte_stream_exact_length(char * name,uint8_t * dst,int len)385*042d53a7SEvalZero parse_arg_byte_stream_exact_length(char *name, uint8_t *dst, int len)
386*042d53a7SEvalZero {
387*042d53a7SEvalZero int actual_len;
388*042d53a7SEvalZero int rc;
389*042d53a7SEvalZero
390*042d53a7SEvalZero rc = parse_arg_byte_stream(name, len, dst, &actual_len);
391*042d53a7SEvalZero if (rc != 0) {
392*042d53a7SEvalZero return rc;
393*042d53a7SEvalZero }
394*042d53a7SEvalZero
395*042d53a7SEvalZero if (actual_len != len) {
396*042d53a7SEvalZero return EINVAL;
397*042d53a7SEvalZero }
398*042d53a7SEvalZero
399*042d53a7SEvalZero return 0;
400*042d53a7SEvalZero }
401*042d53a7SEvalZero
402*042d53a7SEvalZero static void
parse_reverse_bytes(uint8_t * bytes,int len)403*042d53a7SEvalZero parse_reverse_bytes(uint8_t *bytes, int len)
404*042d53a7SEvalZero {
405*042d53a7SEvalZero uint8_t tmp;
406*042d53a7SEvalZero int i;
407*042d53a7SEvalZero
408*042d53a7SEvalZero for (i = 0; i < len / 2; i++) {
409*042d53a7SEvalZero tmp = bytes[i];
410*042d53a7SEvalZero bytes[i] = bytes[len - i - 1];
411*042d53a7SEvalZero bytes[len - i - 1] = tmp;
412*042d53a7SEvalZero }
413*042d53a7SEvalZero }
414*042d53a7SEvalZero
415*042d53a7SEvalZero int
parse_arg_mac(char * name,uint8_t * dst)416*042d53a7SEvalZero parse_arg_mac(char *name, uint8_t *dst)
417*042d53a7SEvalZero {
418*042d53a7SEvalZero int rc;
419*042d53a7SEvalZero
420*042d53a7SEvalZero rc = parse_arg_byte_stream_exact_length(name, dst, 6);
421*042d53a7SEvalZero if (rc != 0) {
422*042d53a7SEvalZero return rc;
423*042d53a7SEvalZero }
424*042d53a7SEvalZero
425*042d53a7SEvalZero parse_reverse_bytes(dst, 6);
426*042d53a7SEvalZero
427*042d53a7SEvalZero return 0;
428*042d53a7SEvalZero }
429*042d53a7SEvalZero
430*042d53a7SEvalZero int
parse_arg_uuid(char * str,ble_uuid_any_t * uuid)431*042d53a7SEvalZero parse_arg_uuid(char *str, ble_uuid_any_t *uuid)
432*042d53a7SEvalZero {
433*042d53a7SEvalZero uint16_t uuid16;
434*042d53a7SEvalZero uint8_t val[16];
435*042d53a7SEvalZero int len;
436*042d53a7SEvalZero int rc;
437*042d53a7SEvalZero
438*042d53a7SEvalZero uuid16 = parse_arg_uint16_peek(str, &rc);
439*042d53a7SEvalZero switch (rc) {
440*042d53a7SEvalZero case ENOENT:
441*042d53a7SEvalZero parse_arg_extract(str);
442*042d53a7SEvalZero return ENOENT;
443*042d53a7SEvalZero
444*042d53a7SEvalZero case 0:
445*042d53a7SEvalZero len = 2;
446*042d53a7SEvalZero val[0] = uuid16;
447*042d53a7SEvalZero val[1] = uuid16 >> 8;
448*042d53a7SEvalZero parse_arg_extract(str);
449*042d53a7SEvalZero break;
450*042d53a7SEvalZero
451*042d53a7SEvalZero default:
452*042d53a7SEvalZero len = 16;
453*042d53a7SEvalZero rc = parse_arg_byte_stream_exact_length(str, val, 16);
454*042d53a7SEvalZero if (rc != 0) {
455*042d53a7SEvalZero return EINVAL;
456*042d53a7SEvalZero }
457*042d53a7SEvalZero parse_reverse_bytes(val, 16);
458*042d53a7SEvalZero break;
459*042d53a7SEvalZero }
460*042d53a7SEvalZero
461*042d53a7SEvalZero rc = ble_uuid_init_from_buf(uuid, val, len);
462*042d53a7SEvalZero if (rc != 0) {
463*042d53a7SEvalZero return EINVAL;
464*042d53a7SEvalZero } else {
465*042d53a7SEvalZero return 0;
466*042d53a7SEvalZero }
467*042d53a7SEvalZero }
468*042d53a7SEvalZero
469*042d53a7SEvalZero int
parse_arg_all(int argc,char ** argv)470*042d53a7SEvalZero parse_arg_all(int argc, char **argv)
471*042d53a7SEvalZero {
472*042d53a7SEvalZero char *key;
473*042d53a7SEvalZero char *val;
474*042d53a7SEvalZero int i;
475*042d53a7SEvalZero
476*042d53a7SEvalZero cmd_num_args = 0;
477*042d53a7SEvalZero
478*042d53a7SEvalZero for (i = 0; i < argc; i++) {
479*042d53a7SEvalZero key = strtok(argv[i], "=");
480*042d53a7SEvalZero val = strtok(NULL, "=");
481*042d53a7SEvalZero
482*042d53a7SEvalZero if (key != NULL && val != NULL) {
483*042d53a7SEvalZero if (strlen(key) == 0) {
484*042d53a7SEvalZero console_printf("Error: invalid argument: %s\n", argv[i]);
485*042d53a7SEvalZero return -1;
486*042d53a7SEvalZero }
487*042d53a7SEvalZero
488*042d53a7SEvalZero if (cmd_num_args >= CMD_MAX_ARGS) {
489*042d53a7SEvalZero console_printf("Error: too many arguments");
490*042d53a7SEvalZero return -1;
491*042d53a7SEvalZero }
492*042d53a7SEvalZero
493*042d53a7SEvalZero cmd_args[cmd_num_args][0] = key;
494*042d53a7SEvalZero cmd_args[cmd_num_args][1] = val;
495*042d53a7SEvalZero cmd_num_args++;
496*042d53a7SEvalZero }
497*042d53a7SEvalZero }
498*042d53a7SEvalZero
499*042d53a7SEvalZero return 0;
500*042d53a7SEvalZero }
501*042d53a7SEvalZero
502*042d53a7SEvalZero int
parse_eddystone_url(char * full_url,uint8_t * out_scheme,char * out_body,uint8_t * out_body_len,uint8_t * out_suffix)503*042d53a7SEvalZero parse_eddystone_url(char *full_url, uint8_t *out_scheme, char *out_body,
504*042d53a7SEvalZero uint8_t *out_body_len, uint8_t *out_suffix)
505*042d53a7SEvalZero {
506*042d53a7SEvalZero static const struct {
507*042d53a7SEvalZero char *s;
508*042d53a7SEvalZero uint8_t scheme;
509*042d53a7SEvalZero } schemes[] = {
510*042d53a7SEvalZero { "http://www.", BLE_EDDYSTONE_URL_SCHEME_HTTP_WWW },
511*042d53a7SEvalZero { "https://www.", BLE_EDDYSTONE_URL_SCHEME_HTTPS_WWW },
512*042d53a7SEvalZero { "http://", BLE_EDDYSTONE_URL_SCHEME_HTTP },
513*042d53a7SEvalZero { "https://", BLE_EDDYSTONE_URL_SCHEME_HTTPS },
514*042d53a7SEvalZero };
515*042d53a7SEvalZero
516*042d53a7SEvalZero static const struct {
517*042d53a7SEvalZero char *s;
518*042d53a7SEvalZero uint8_t code;
519*042d53a7SEvalZero } suffixes[] = {
520*042d53a7SEvalZero { ".com/", BLE_EDDYSTONE_URL_SUFFIX_COM_SLASH },
521*042d53a7SEvalZero { ".org/", BLE_EDDYSTONE_URL_SUFFIX_ORG_SLASH },
522*042d53a7SEvalZero { ".edu/", BLE_EDDYSTONE_URL_SUFFIX_EDU_SLASH },
523*042d53a7SEvalZero { ".net/", BLE_EDDYSTONE_URL_SUFFIX_NET_SLASH },
524*042d53a7SEvalZero { ".info/", BLE_EDDYSTONE_URL_SUFFIX_INFO_SLASH },
525*042d53a7SEvalZero { ".biz/", BLE_EDDYSTONE_URL_SUFFIX_BIZ_SLASH },
526*042d53a7SEvalZero { ".gov/", BLE_EDDYSTONE_URL_SUFFIX_GOV_SLASH },
527*042d53a7SEvalZero { ".com", BLE_EDDYSTONE_URL_SUFFIX_COM },
528*042d53a7SEvalZero { ".org", BLE_EDDYSTONE_URL_SUFFIX_ORG },
529*042d53a7SEvalZero { ".edu", BLE_EDDYSTONE_URL_SUFFIX_EDU },
530*042d53a7SEvalZero { ".net", BLE_EDDYSTONE_URL_SUFFIX_NET },
531*042d53a7SEvalZero { ".info", BLE_EDDYSTONE_URL_SUFFIX_INFO },
532*042d53a7SEvalZero { ".biz", BLE_EDDYSTONE_URL_SUFFIX_BIZ },
533*042d53a7SEvalZero { ".gov", BLE_EDDYSTONE_URL_SUFFIX_GOV },
534*042d53a7SEvalZero };
535*042d53a7SEvalZero
536*042d53a7SEvalZero char *prefix;
537*042d53a7SEvalZero char *suffix;
538*042d53a7SEvalZero int full_url_len;
539*042d53a7SEvalZero int prefix_len;
540*042d53a7SEvalZero int suffix_len;
541*042d53a7SEvalZero int suffix_idx;
542*042d53a7SEvalZero int rc;
543*042d53a7SEvalZero int i;
544*042d53a7SEvalZero
545*042d53a7SEvalZero full_url_len = strlen(full_url);
546*042d53a7SEvalZero
547*042d53a7SEvalZero rc = BLE_HS_EINVAL;
548*042d53a7SEvalZero for (i = 0; i < sizeof schemes / sizeof schemes[0]; i++) {
549*042d53a7SEvalZero prefix = schemes[i].s;
550*042d53a7SEvalZero prefix_len = strlen(schemes[i].s);
551*042d53a7SEvalZero
552*042d53a7SEvalZero if (full_url_len >= prefix_len &&
553*042d53a7SEvalZero memcmp(full_url, prefix, prefix_len) == 0) {
554*042d53a7SEvalZero
555*042d53a7SEvalZero *out_scheme = i;
556*042d53a7SEvalZero rc = 0;
557*042d53a7SEvalZero break;
558*042d53a7SEvalZero }
559*042d53a7SEvalZero }
560*042d53a7SEvalZero if (rc != 0) {
561*042d53a7SEvalZero return rc;
562*042d53a7SEvalZero }
563*042d53a7SEvalZero
564*042d53a7SEvalZero rc = BLE_HS_EINVAL;
565*042d53a7SEvalZero for (i = 0; i < sizeof suffixes / sizeof suffixes[0]; i++) {
566*042d53a7SEvalZero suffix = suffixes[i].s;
567*042d53a7SEvalZero suffix_len = strlen(suffixes[i].s);
568*042d53a7SEvalZero
569*042d53a7SEvalZero suffix_idx = full_url_len - suffix_len;
570*042d53a7SEvalZero if (suffix_idx >= prefix_len &&
571*042d53a7SEvalZero memcmp(full_url + suffix_idx, suffix, suffix_len) == 0) {
572*042d53a7SEvalZero
573*042d53a7SEvalZero *out_suffix = i;
574*042d53a7SEvalZero rc = 0;
575*042d53a7SEvalZero break;
576*042d53a7SEvalZero }
577*042d53a7SEvalZero }
578*042d53a7SEvalZero if (rc != 0) {
579*042d53a7SEvalZero *out_suffix = BLE_EDDYSTONE_URL_SUFFIX_NONE;
580*042d53a7SEvalZero *out_body_len = full_url_len - prefix_len;
581*042d53a7SEvalZero } else {
582*042d53a7SEvalZero *out_body_len = full_url_len - prefix_len - suffix_len;
583*042d53a7SEvalZero }
584*042d53a7SEvalZero
585*042d53a7SEvalZero memcpy(out_body, full_url + prefix_len, *out_body_len);
586*042d53a7SEvalZero
587*042d53a7SEvalZero return 0;
588*042d53a7SEvalZero }
589