initial commit
This commit is contained in:
598
lib/amb1_sdk/common/utilities/cJSON.c
Normal file
598
lib/amb1_sdk/common/utilities/cJSON.c
Normal file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
/* cJSON */
|
||||
/* JSON parser in C. */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <float.h>
|
||||
#include <limits.h>
|
||||
#include <ctype.h>
|
||||
#include "cJSON.h"
|
||||
|
||||
static const char *ep;
|
||||
|
||||
const char *cJSON_GetErrorPtr(void) {return ep;}
|
||||
|
||||
#define sprintf rtl_sprintf
|
||||
|
||||
static int cJSON_strcasecmp(const char *s1,const char *s2)
|
||||
{
|
||||
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
|
||||
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
|
||||
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
|
||||
}
|
||||
|
||||
static void *(*cJSON_malloc)(size_t sz) = malloc;
|
||||
static void (*cJSON_free)(void *ptr) = free;
|
||||
|
||||
static char* cJSON_strdup(const char* str)
|
||||
{
|
||||
size_t len;
|
||||
char* copy;
|
||||
|
||||
len = strlen(str) + 1;
|
||||
if (!(copy = (char*)cJSON_malloc(len))) return 0;
|
||||
memcpy(copy,str,len);
|
||||
return copy;
|
||||
}
|
||||
|
||||
void cJSON_InitHooks(cJSON_Hooks* hooks)
|
||||
{
|
||||
if (!hooks) { /* Reset hooks */
|
||||
cJSON_malloc = malloc;
|
||||
cJSON_free = free;
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
|
||||
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
|
||||
}
|
||||
|
||||
/* Internal constructor. */
|
||||
static cJSON *cJSON_New_Item(void)
|
||||
{
|
||||
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
|
||||
if (node) memset(node,0,sizeof(cJSON));
|
||||
return node;
|
||||
}
|
||||
|
||||
/* Delete a cJSON structure. */
|
||||
void cJSON_Delete(cJSON *c)
|
||||
{
|
||||
cJSON *next;
|
||||
while (c)
|
||||
{
|
||||
next=c->next;
|
||||
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
|
||||
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
|
||||
if (c->string) cJSON_free(c->string);
|
||||
cJSON_free(c);
|
||||
c=next;
|
||||
}
|
||||
}
|
||||
|
||||
/* Parse the input text to generate a number, and populate the result into item. */
|
||||
const char *parse_number(cJSON *item,const char *num)
|
||||
{
|
||||
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
|
||||
|
||||
if (*num=='-') sign=-1,num++; /* Has sign? */
|
||||
if (*num=='0') num++; /* is zero */
|
||||
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
|
||||
if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
|
||||
if (*num=='e' || *num=='E') /* Exponent? */
|
||||
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
|
||||
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
|
||||
}
|
||||
|
||||
n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
|
||||
|
||||
item->valuedouble=n;
|
||||
item->valueint=(int)n;
|
||||
item->type=cJSON_Number;
|
||||
return num;
|
||||
}
|
||||
|
||||
/* Render the number nicely from the given item into a string. */
|
||||
static char *print_number(cJSON *item)
|
||||
{
|
||||
char *str;
|
||||
double d=item->valuedouble;
|
||||
if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
|
||||
{
|
||||
str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
|
||||
if (str) sprintf(str,"%d",item->valueint);
|
||||
}
|
||||
else
|
||||
{
|
||||
str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
|
||||
if (str)
|
||||
{
|
||||
if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
|
||||
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
|
||||
else sprintf(str,"%f",d);
|
||||
}
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
static unsigned parse_hex4(const char *str)
|
||||
{
|
||||
unsigned h=0;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
h=h<<4;str++;
|
||||
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
|
||||
return h;
|
||||
}
|
||||
|
||||
/* Parse the input text into an unescaped cstring, and populate item. */
|
||||
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
|
||||
static const char *parse_string(cJSON *item,const char *str)
|
||||
{
|
||||
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
|
||||
if (*str!='\"') {ep=str;return 0;} /* not a string! */
|
||||
|
||||
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
|
||||
|
||||
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
|
||||
if (!out) return 0;
|
||||
|
||||
ptr=str+1;ptr2=out;
|
||||
while (*ptr!='\"' && *ptr)
|
||||
{
|
||||
if (*ptr!='\\') *ptr2++=*ptr++;
|
||||
else
|
||||
{
|
||||
ptr++;
|
||||
switch (*ptr)
|
||||
{
|
||||
case 'b': *ptr2++='\b'; break;
|
||||
case 'f': *ptr2++='\f'; break;
|
||||
case 'n': *ptr2++='\n'; break;
|
||||
case 'r': *ptr2++='\r'; break;
|
||||
case 't': *ptr2++='\t'; break;
|
||||
case 'u': /* transcode utf16 to utf8. */
|
||||
uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
|
||||
|
||||
if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
|
||||
|
||||
if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
|
||||
{
|
||||
if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
|
||||
uc2=parse_hex4(ptr+3);ptr+=6;
|
||||
if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
|
||||
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
|
||||
}
|
||||
|
||||
len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
|
||||
|
||||
switch (len) {
|
||||
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
|
||||
case 1: *--ptr2 =(uc | firstByteMark[len]);
|
||||
}
|
||||
ptr2+=len;
|
||||
break;
|
||||
default: *ptr2++=*ptr; break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
*ptr2=0;
|
||||
if (*ptr=='\"') ptr++;
|
||||
item->valuestring=out;
|
||||
item->type=cJSON_String;
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/* Render the cstring provided to an escaped version that can be printed. */
|
||||
static char *print_string_ptr(const char *str)
|
||||
{
|
||||
const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
|
||||
|
||||
if (!str) return cJSON_strdup("");
|
||||
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
|
||||
|
||||
out=(char*)cJSON_malloc(len+3);
|
||||
if (!out) return 0;
|
||||
|
||||
ptr2=out;ptr=str;
|
||||
*ptr2++='\"';
|
||||
while (*ptr)
|
||||
{
|
||||
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
|
||||
else
|
||||
{
|
||||
*ptr2++='\\';
|
||||
switch (token=*ptr++)
|
||||
{
|
||||
case '\\': *ptr2++='\\'; break;
|
||||
case '\"': *ptr2++='\"'; break;
|
||||
case '\b': *ptr2++='b'; break;
|
||||
case '\f': *ptr2++='f'; break;
|
||||
case '\n': *ptr2++='n'; break;
|
||||
case '\r': *ptr2++='r'; break;
|
||||
case '\t': *ptr2++='t'; break;
|
||||
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
|
||||
}
|
||||
}
|
||||
}
|
||||
*ptr2++='\"';*ptr2++=0;
|
||||
return out;
|
||||
}
|
||||
/* Invote print_string_ptr (which is useful) on an item. */
|
||||
static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
|
||||
|
||||
/* Predeclare these prototypes. */
|
||||
static const char *parse_value(cJSON *item,const char *value);
|
||||
static char *print_value(cJSON *item,int depth,int fmt);
|
||||
static const char *parse_array(cJSON *item,const char *value);
|
||||
static char *print_array(cJSON *item,int depth,int fmt);
|
||||
static const char *parse_object(cJSON *item,const char *value);
|
||||
static char *print_object(cJSON *item,int depth,int fmt);
|
||||
|
||||
/* Utility to jump whitespace and cr/lf */
|
||||
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
|
||||
|
||||
/* Parse an object - create a new root, and populate. */
|
||||
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
|
||||
{
|
||||
const char *end=0;
|
||||
cJSON *c=cJSON_New_Item();
|
||||
ep=0;
|
||||
if (!c) return 0; /* memory fail */
|
||||
|
||||
end=parse_value(c,skip(value));
|
||||
if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
|
||||
|
||||
/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
|
||||
if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
|
||||
if (return_parse_end) *return_parse_end=end;
|
||||
return c;
|
||||
}
|
||||
/* Default options for cJSON_Parse */
|
||||
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
|
||||
|
||||
/* Render a cJSON item/entity/structure to text. */
|
||||
char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
|
||||
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
|
||||
|
||||
/* Parser core - when encountering text, process appropriately. */
|
||||
static const char *parse_value(cJSON *item,const char *value)
|
||||
{
|
||||
if (!value) return 0; /* Fail on null. */
|
||||
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
|
||||
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
|
||||
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
|
||||
if (*value=='\"') { return parse_string(item,value); }
|
||||
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
|
||||
if (*value=='[') { return parse_array(item,value); }
|
||||
if (*value=='{') { return parse_object(item,value); }
|
||||
|
||||
ep=value;return 0; /* failure. */
|
||||
}
|
||||
|
||||
/* Render a value to text. */
|
||||
static char *print_value(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char *out=0;
|
||||
if (!item) return 0;
|
||||
switch ((item->type)&255)
|
||||
{
|
||||
case cJSON_NULL: out=cJSON_strdup("null"); break;
|
||||
case cJSON_False: out=cJSON_strdup("false");break;
|
||||
case cJSON_True: out=cJSON_strdup("true"); break;
|
||||
case cJSON_Number: out=print_number(item);break;
|
||||
case cJSON_String: out=print_string(item);break;
|
||||
case cJSON_Array: out=print_array(item,depth,fmt);break;
|
||||
case cJSON_Object: out=print_object(item,depth,fmt);break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Build an array from input text. */
|
||||
static const char *parse_array(cJSON *item,const char *value)
|
||||
{
|
||||
cJSON *child;
|
||||
if (*value!='[') {ep=value;return 0;} /* not an array! */
|
||||
|
||||
item->type=cJSON_Array;
|
||||
value=skip(value+1);
|
||||
if (*value==']') return value+1; /* empty array. */
|
||||
|
||||
item->child=child=cJSON_New_Item();
|
||||
if (!item->child) return 0; /* memory fail */
|
||||
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
|
||||
while (*value==',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
|
||||
child->next=new_item;new_item->prev=child;child=new_item;
|
||||
value=skip(parse_value(child,skip(value+1)));
|
||||
if (!value) return 0; /* memory fail */
|
||||
}
|
||||
|
||||
if (*value==']') return value+1; /* end of array */
|
||||
ep=value;return 0; /* malformed. */
|
||||
}
|
||||
|
||||
/* Render an array to text */
|
||||
static char *print_array(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char **entries;
|
||||
char *out=0,*ptr,*ret;int len=5;
|
||||
cJSON *child=item->child;
|
||||
int numentries=0,i=0,fail=0;
|
||||
|
||||
/* How many entries in the array? */
|
||||
while (child) numentries++,child=child->next;
|
||||
/* Explicitly handle numentries==0 */
|
||||
if (!numentries)
|
||||
{
|
||||
out=(char*)cJSON_malloc(3);
|
||||
if (out) strcpy(out,"[]");
|
||||
return out;
|
||||
}
|
||||
/* Allocate an array to hold the values for each */
|
||||
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!entries) return 0;
|
||||
memset(entries,0,numentries*sizeof(char*));
|
||||
/* Retrieve all the results: */
|
||||
child=item->child;
|
||||
while (child && !fail)
|
||||
{
|
||||
ret=print_value(child,depth+1,fmt);
|
||||
entries[i++]=ret;
|
||||
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
/* If we didn't fail, try to malloc the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
/* If that fails, we fail. */
|
||||
if (!out) fail=1;
|
||||
|
||||
/* Handle failure. */
|
||||
if (fail)
|
||||
{
|
||||
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
|
||||
cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compose the output array. */
|
||||
*out='[';
|
||||
ptr=out+1;*ptr=0;
|
||||
for (i=0;i<numentries;i++)
|
||||
{
|
||||
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
||||
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
|
||||
cJSON_free(entries[i]);
|
||||
}
|
||||
cJSON_free(entries);
|
||||
*ptr++=']';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Build an object from the text. */
|
||||
static const char *parse_object(cJSON *item,const char *value)
|
||||
{
|
||||
cJSON *child;
|
||||
if (*value!='{') {ep=value;return 0;} /* not an object! */
|
||||
|
||||
item->type=cJSON_Object;
|
||||
value=skip(value+1);
|
||||
if (*value=='}') return value+1; /* empty array. */
|
||||
|
||||
item->child=child=cJSON_New_Item();
|
||||
if (!item->child) return 0;
|
||||
value=skip(parse_string(child,skip(value)));
|
||||
if (!value) return 0;
|
||||
child->string=child->valuestring;child->valuestring=0;
|
||||
if (*value!=':') {ep=value;return 0;} /* fail! */
|
||||
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
|
||||
while (*value==',')
|
||||
{
|
||||
cJSON *new_item;
|
||||
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
|
||||
child->next=new_item;new_item->prev=child;child=new_item;
|
||||
value=skip(parse_string(child,skip(value+1)));
|
||||
if (!value) return 0;
|
||||
child->string=child->valuestring;child->valuestring=0;
|
||||
if (*value!=':') {ep=value;return 0;} /* fail! */
|
||||
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
|
||||
if (!value) return 0;
|
||||
}
|
||||
|
||||
if (*value=='}') return value+1; /* end of array */
|
||||
ep=value;return 0; /* malformed. */
|
||||
}
|
||||
|
||||
/* Render an object to text. */
|
||||
static char *print_object(cJSON *item,int depth,int fmt)
|
||||
{
|
||||
char **entries=0,**names=0;
|
||||
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
|
||||
cJSON *child=item->child;
|
||||
int numentries=0,fail=0;
|
||||
/* Count the number of entries. */
|
||||
while (child) numentries++,child=child->next;
|
||||
/* Explicitly handle empty object case */
|
||||
if (!numentries)
|
||||
{
|
||||
out=(char*)cJSON_malloc(fmt?depth+4:3);
|
||||
if (!out) return 0;
|
||||
ptr=out;*ptr++='{';
|
||||
if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
|
||||
*ptr++='}';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
/* Allocate space for the names and the objects */
|
||||
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!entries) return 0;
|
||||
names=(char**)cJSON_malloc(numentries*sizeof(char*));
|
||||
if (!names) {cJSON_free(entries);return 0;}
|
||||
memset(entries,0,sizeof(char*)*numentries);
|
||||
memset(names,0,sizeof(char*)*numentries);
|
||||
|
||||
/* Collect all the results into our arrays: */
|
||||
child=item->child;depth++;if (fmt) len+=depth;
|
||||
while (child)
|
||||
{
|
||||
names[i]=str=print_string_ptr(child->string);
|
||||
entries[i++]=ret=print_value(child,depth,fmt);
|
||||
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
|
||||
child=child->next;
|
||||
}
|
||||
|
||||
/* Try to allocate the output string */
|
||||
if (!fail) out=(char*)cJSON_malloc(len);
|
||||
if (!out) fail=1;
|
||||
|
||||
/* Handle failure */
|
||||
if (fail)
|
||||
{
|
||||
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compose the output: */
|
||||
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
|
||||
for (i=0;i<numentries;i++)
|
||||
{
|
||||
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
|
||||
strcpy(ptr,names[i]);ptr+=strlen(names[i]);
|
||||
*ptr++=':';if (fmt) *ptr++='\t';
|
||||
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
|
||||
if (i!=numentries-1) *ptr++=',';
|
||||
if (fmt) *ptr++='\n';*ptr=0;
|
||||
cJSON_free(names[i]);cJSON_free(entries[i]);
|
||||
}
|
||||
|
||||
cJSON_free(names);cJSON_free(entries);
|
||||
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
|
||||
*ptr++='}';*ptr++=0;
|
||||
return out;
|
||||
}
|
||||
|
||||
/* Get Array size/item / object item. */
|
||||
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
|
||||
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
|
||||
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
|
||||
|
||||
/* Utility for array list handling. */
|
||||
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
|
||||
/* Utility for handling references. */
|
||||
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
|
||||
|
||||
/* Add item to array/object. */
|
||||
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
|
||||
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
|
||||
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
|
||||
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
|
||||
|
||||
cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
|
||||
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
|
||||
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
|
||||
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
|
||||
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
|
||||
|
||||
/* Replace array/object items with new ones. */
|
||||
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
|
||||
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
|
||||
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
|
||||
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){if(newitem->string) cJSON_free(newitem->string);newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
|
||||
|
||||
/* Create basic types: */
|
||||
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
|
||||
cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
|
||||
cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
|
||||
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
|
||||
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
|
||||
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
|
||||
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
|
||||
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
|
||||
|
||||
/* Create Arrays: */
|
||||
cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
|
||||
|
||||
/* Duplication */
|
||||
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
|
||||
{
|
||||
cJSON *newitem,*cptr,*nptr=0,*newchild;
|
||||
/* Bail on bad ptr */
|
||||
if (!item) return 0;
|
||||
/* Create new item */
|
||||
newitem=cJSON_New_Item();
|
||||
if (!newitem) return 0;
|
||||
/* Copy over all vars */
|
||||
newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
|
||||
if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
|
||||
if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
|
||||
/* If non-recursive, then we're done! */
|
||||
if (!recurse) return newitem;
|
||||
/* Walk the ->next chain for the child. */
|
||||
cptr=item->child;
|
||||
while (cptr)
|
||||
{
|
||||
newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
|
||||
if (!newchild) {cJSON_Delete(newitem);return 0;}
|
||||
if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
|
||||
else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
|
||||
cptr=cptr->next;
|
||||
}
|
||||
return newitem;
|
||||
}
|
||||
|
||||
void cJSON_Minify(char *json)
|
||||
{
|
||||
char *into=json;
|
||||
while (*json)
|
||||
{
|
||||
if (*json==' ') json++;
|
||||
else if (*json=='\t') json++; // Whitespace characters.
|
||||
else if (*json=='\r') json++;
|
||||
else if (*json=='\n') json++;
|
||||
else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line.
|
||||
else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments.
|
||||
else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
|
||||
else *into++=*json++; // All other characters.
|
||||
}
|
||||
*into=0; // and null-terminate.
|
||||
}
|
||||
145
lib/amb1_sdk/common/utilities/cJSON.h
Normal file
145
lib/amb1_sdk/common/utilities/cJSON.h
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Copyright (c) 2009 Dave Gamble
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef cJSON__h
|
||||
#define cJSON__h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/* cJSON Types: */
|
||||
#define cJSON_False 0
|
||||
#define cJSON_True 1
|
||||
#define cJSON_NULL 2
|
||||
#define cJSON_Number 3
|
||||
#define cJSON_String 4
|
||||
#define cJSON_Array 5
|
||||
#define cJSON_Object 6
|
||||
|
||||
#define cJSON_IsReference 256
|
||||
|
||||
/* The cJSON structure: */
|
||||
typedef struct cJSON {
|
||||
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
|
||||
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
|
||||
|
||||
int type; /* The type of the item, as above. */
|
||||
|
||||
char *valuestring; /* The item's string, if type==cJSON_String */
|
||||
int valueint; /* The item's number, if type==cJSON_Number */
|
||||
double valuedouble; /* The item's number, if type==cJSON_Number */
|
||||
|
||||
char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
|
||||
} cJSON;
|
||||
|
||||
typedef struct cJSON_Hooks {
|
||||
void *(*malloc_fn)(size_t sz);
|
||||
void (*free_fn)(void *ptr);
|
||||
} cJSON_Hooks;
|
||||
|
||||
/* Supply malloc, realloc and free functions to cJSON */
|
||||
extern void cJSON_InitHooks(cJSON_Hooks* hooks);
|
||||
|
||||
|
||||
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
|
||||
extern cJSON *cJSON_Parse(const char *value);
|
||||
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
|
||||
extern char *cJSON_Print(cJSON *item);
|
||||
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
|
||||
extern char *cJSON_PrintUnformatted(cJSON *item);
|
||||
/* Delete a cJSON entity and all subentities. */
|
||||
extern void cJSON_Delete(cJSON *c);
|
||||
|
||||
/* Returns the number of items in an array (or object). */
|
||||
extern int cJSON_GetArraySize(cJSON *array);
|
||||
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
|
||||
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
|
||||
/* Get item "string" from object. Case insensitive. */
|
||||
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
|
||||
|
||||
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
|
||||
extern const char *cJSON_GetErrorPtr(void);
|
||||
|
||||
/* These calls create a cJSON item of the appropriate type. */
|
||||
extern cJSON *cJSON_CreateNull(void);
|
||||
extern cJSON *cJSON_CreateTrue(void);
|
||||
extern cJSON *cJSON_CreateFalse(void);
|
||||
extern cJSON *cJSON_CreateBool(int b);
|
||||
extern cJSON *cJSON_CreateNumber(double num);
|
||||
extern cJSON *cJSON_CreateString(const char *string);
|
||||
extern cJSON *cJSON_CreateArray(void);
|
||||
extern cJSON *cJSON_CreateObject(void);
|
||||
|
||||
/* These utilities create an Array of count items. */
|
||||
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
|
||||
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
|
||||
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
|
||||
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
|
||||
|
||||
/* Append item to the specified array/object. */
|
||||
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
|
||||
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
|
||||
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
|
||||
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
|
||||
|
||||
/* Remove/Detatch items from Arrays/Objects. */
|
||||
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
|
||||
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
|
||||
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
|
||||
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
|
||||
|
||||
/* Update array items. */
|
||||
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
|
||||
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
|
||||
|
||||
/* Duplicate a cJSON item */
|
||||
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
|
||||
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
|
||||
need to be released. With recurse!=0, it will duplicate any children connected to the item.
|
||||
The item->next and ->prev pointers are always zero on return from Duplicate. */
|
||||
|
||||
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
|
||||
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
|
||||
|
||||
extern void cJSON_Minify(char *json);
|
||||
|
||||
/* Macros for creating things quickly. */
|
||||
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
|
||||
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
|
||||
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
|
||||
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
|
||||
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
|
||||
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
|
||||
|
||||
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
|
||||
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
137
lib/amb1_sdk/common/utilities/http_client.c
Normal file
137
lib/amb1_sdk/common/utilities/http_client.c
Normal file
@@ -0,0 +1,137 @@
|
||||
//#include <stdio.h>
|
||||
//#include <stdlib.h>
|
||||
//#include <string.h>
|
||||
|
||||
#include "platform/platform_stdlib.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
const char * http_strstr(const char *str1, const char *str2) {
|
||||
char *a, *b;
|
||||
|
||||
/* First scan quickly through the two strings looking for a
|
||||
* single-character match. When it's found, then compare the
|
||||
* rest of the substring.
|
||||
*/
|
||||
|
||||
b = (char *)str2;
|
||||
if (*b == 0) {
|
||||
return str1;
|
||||
}
|
||||
for ( ; *str1 != 0; str1 += 1) {
|
||||
if (*str1 != *b) {
|
||||
continue;
|
||||
}
|
||||
a = (char *)str1;
|
||||
while (1) {
|
||||
if (*b == 0) {
|
||||
return str1;
|
||||
}
|
||||
if (*a++ != *b++) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
b = (char *)str2;
|
||||
}
|
||||
return (char *) 0;
|
||||
}
|
||||
|
||||
static void* http_malloc(unsigned int size)
|
||||
{
|
||||
return pvPortMalloc(size);
|
||||
}
|
||||
|
||||
void http_free(void *buf)
|
||||
{
|
||||
vPortFree(buf);
|
||||
}
|
||||
|
||||
static char *http_itoa(int value)
|
||||
{
|
||||
char *val_str;
|
||||
int tmp = value, len = 1;
|
||||
|
||||
while((tmp /= 10) > 0)
|
||||
len ++;
|
||||
|
||||
val_str = (char *) http_malloc(len + 1);
|
||||
sprintf(val_str, "%d", value);
|
||||
|
||||
return val_str;
|
||||
}
|
||||
|
||||
char *http_post_header(char *host, char *resource, char *type, int data_len)
|
||||
{
|
||||
char *len_str = http_itoa(data_len);
|
||||
char *header = (char *) http_malloc(strlen("POST ") + strlen(resource) + strlen(" HTTP/1.1\r\nHost: ") + strlen(host) +
|
||||
strlen("\r\nContent-Type: ") + strlen(type) + strlen("\r\nContent-Length: ") + strlen(len_str) + strlen("\r\n\r\n") + 1);
|
||||
sprintf(header, "POST %s HTTP/1.1\r\nHost: %s\r\nContent-Type: %s\r\nContent-Length: %s\r\n\r\n", resource, host, type, len_str);
|
||||
http_free(len_str);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
char *http_get_header(char *host, char *resource)
|
||||
{
|
||||
char *header = (char *) http_malloc(strlen("GET ") + strlen(resource) + strlen(" HTTP/1.1\r\nHost: ") + strlen(host) + strlen("\r\n\r\n") + 1);
|
||||
sprintf(header, "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n", resource, host);
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
char *http_response_header(char *buf, int response_len)
|
||||
{
|
||||
char *http_response, *http_header = NULL, *header_end;
|
||||
int header_len;
|
||||
|
||||
http_response = (char *) http_malloc(response_len + 1);
|
||||
memcpy(http_response, buf, response_len);
|
||||
http_response[response_len] = '\0';
|
||||
|
||||
if(strncmp(http_response, "HTTP", 4) == 0) {
|
||||
if((header_end = (char *)http_strstr(http_response, "\r\n\r\n")) != NULL) {
|
||||
header_end += 4;
|
||||
header_len = header_end - http_response;
|
||||
http_header = (char *) http_malloc(header_len + 1);
|
||||
memcpy(http_header, http_response, header_len);
|
||||
http_header[header_len] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
http_free(http_response);
|
||||
|
||||
return http_header;
|
||||
}
|
||||
|
||||
char *http_response_body(char *buf, int response_len)
|
||||
{
|
||||
char *http_response, *http_body = NULL, *body_start;
|
||||
int body_len;
|
||||
|
||||
http_response = (char *) http_malloc(response_len + 1);
|
||||
memcpy(http_response, buf, response_len);
|
||||
http_response[response_len] = '\0';
|
||||
|
||||
if(strncmp(http_response, "HTTP", 4) == 0) {
|
||||
if((body_start = (char *)http_strstr(http_response, "\r\n\r\n")) != NULL) {
|
||||
body_start += 4;
|
||||
body_len = http_response + response_len - body_start;
|
||||
|
||||
if(body_len > 0) {
|
||||
http_body = (char *) http_malloc(body_len + 1);
|
||||
memcpy(http_body, body_start, body_len);
|
||||
http_body[body_len] = '\0';
|
||||
}
|
||||
|
||||
http_free(http_response);
|
||||
}
|
||||
else {
|
||||
http_body = http_response;
|
||||
}
|
||||
}
|
||||
else {
|
||||
http_body = http_response;
|
||||
}
|
||||
|
||||
return http_body;
|
||||
}
|
||||
10
lib/amb1_sdk/common/utilities/http_client.h
Normal file
10
lib/amb1_sdk/common/utilities/http_client.h
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef _HTTP_H_
|
||||
#define _HTTP_H_
|
||||
|
||||
char *http_post_header(char *address, char *resource, char *type, int data_len);
|
||||
char *http_get_header(char *address, char *resource);
|
||||
char *http_response_header(char *buf, int response_len);
|
||||
char *http_response_body(char *buf, int response_len);
|
||||
void http_free(void *buf);
|
||||
|
||||
#endif
|
||||
514
lib/amb1_sdk/common/utilities/ssl_client.c
Normal file
514
lib/amb1_sdk/common/utilities/ssl_client.c
Normal file
@@ -0,0 +1,514 @@
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "platform_opts.h"
|
||||
|
||||
#if CONFIG_USE_POLARSSL
|
||||
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/net.h"
|
||||
#include "polarssl/ssl.h"
|
||||
#include "polarssl/error.h"
|
||||
#include "polarssl/memory.h"
|
||||
|
||||
#define SERVER_PORT 443
|
||||
#define SERVER_HOST "192.168.13.15"
|
||||
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
//#define SSL_CLIENT_EXT
|
||||
#ifdef SSL_CLIENT_EXT
|
||||
#define STACKSIZE 2048
|
||||
#else
|
||||
#define STACKSIZE 1150
|
||||
#endif
|
||||
|
||||
static int is_task = 0;
|
||||
static char server_host[16];
|
||||
static size_t min_heap_size = 0;
|
||||
|
||||
static void my_debug(void *ctx, int level, const char *str)
|
||||
{
|
||||
if(level <= DEBUG_LEVEL) {
|
||||
printf("\n\r%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
static int my_random(void *p_rng, unsigned char *output, size_t output_len)
|
||||
{
|
||||
rtw_get_random_bytes(output, output_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void* my_malloc(size_t size)
|
||||
{
|
||||
void *ptr = pvPortMalloc(size);
|
||||
size_t current_heap_size = xPortGetFreeHeapSize();
|
||||
|
||||
if((current_heap_size < min_heap_size) || (min_heap_size == 0))
|
||||
min_heap_size = current_heap_size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#define my_free vPortFree
|
||||
|
||||
static void ssl_client(void *param)
|
||||
{
|
||||
int ret, len, server_fd = -1;
|
||||
unsigned char buf[512];
|
||||
ssl_context ssl;
|
||||
int retry_count = 0;
|
||||
|
||||
memory_set_own(my_malloc, my_free);
|
||||
|
||||
/*
|
||||
* 1. Start the connection
|
||||
*/
|
||||
printf("\n\r . Connecting to tcp/%s/%d...", server_host, SERVER_PORT);
|
||||
|
||||
if((ret = net_connect(&server_fd, server_host, SERVER_PORT)) != 0) {
|
||||
printf(" failed\n\r ! net_connect returned %d\n", ret);
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 2. Setup stuff
|
||||
*/
|
||||
printf("\n\r . Setting up the SSL/TLS structure..." );
|
||||
|
||||
if((ret = ssl_init(&ssl)) != 0) {
|
||||
printf(" failed\n\r ! ssl_init returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
#ifdef SSL_CLIENT_EXT
|
||||
if((ret = ssl_client_ext_init()) != 0) {
|
||||
printf(" failed\n\r ! ssl_client_ext_init returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
|
||||
ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
|
||||
ssl_set_rng(&ssl, my_random, NULL);
|
||||
ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);
|
||||
ssl_set_dbg(&ssl, my_debug, NULL);
|
||||
#ifdef POLARSSL_DEBUG_C
|
||||
debug_set_threshold(DEBUG_LEVEL);
|
||||
#endif
|
||||
#ifdef SSL_CLIENT_EXT
|
||||
if((ret = ssl_client_ext_setup(&ssl)) != 0) {
|
||||
printf(" failed\n\r ! ssl_client_ext_setup returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 3. Handshake
|
||||
*/
|
||||
printf("\n\r . Performing the SSL/TLS handshake...");
|
||||
|
||||
while((ret = ssl_handshake(&ssl)) != 0) {
|
||||
if((ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE
|
||||
&& ret != POLARSSL_ERR_NET_RECV_FAILED) || retry_count >= 5) {
|
||||
printf(" failed\n\r ! ssl_handshake returned -0x%x\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
printf("\n\r . Use ciphersuite %s\n", ssl_get_ciphersuite(&ssl));
|
||||
|
||||
/*
|
||||
* 4. Write the GET request
|
||||
*/
|
||||
printf("\n\r > Write to server:");
|
||||
|
||||
len = sprintf((char *) buf, GET_REQUEST);
|
||||
|
||||
while((ret = ssl_write(&ssl, buf, len)) <= 0) {
|
||||
if(ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE) {
|
||||
printf(" failed\n\r ! ssl_write returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
len = ret;
|
||||
printf(" %d bytes written\n\r\n\r%s\n", len, (char *) buf);
|
||||
|
||||
/*
|
||||
* 5. Read the HTTP response
|
||||
*/
|
||||
printf("\n\r < Read from server:");
|
||||
|
||||
do {
|
||||
len = sizeof(buf) - 1;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ret = ssl_read(&ssl, buf, len);
|
||||
|
||||
if(ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE)
|
||||
continue;
|
||||
|
||||
if(ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY)
|
||||
break;
|
||||
|
||||
if(ret < 0) {
|
||||
printf(" failed\n\r ! ssl_read returned %d\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if(ret == 0) {
|
||||
printf("\n\rEOF\n");
|
||||
break;
|
||||
}
|
||||
|
||||
len = ret;
|
||||
printf(" %d bytes read\n\r\n\r%s\n", len, (char *) buf);
|
||||
}
|
||||
while(1);
|
||||
|
||||
ssl_close_notify(&ssl);
|
||||
|
||||
exit:
|
||||
|
||||
#ifdef POLARSSL_ERROR_C
|
||||
if(ret != 0) {
|
||||
char error_buf[100];
|
||||
polarssl_strerror(ret, error_buf, 100);
|
||||
printf("\n\rLast error was: %d - %s\n", ret, error_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
net_close(server_fd);
|
||||
ssl_free(&ssl);
|
||||
#ifdef SSL_CLIENT_EXT
|
||||
ssl_client_ext_free();
|
||||
#endif
|
||||
exit1:
|
||||
|
||||
if(is_task) {
|
||||
#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1)
|
||||
printf("\n\rMin available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE));
|
||||
#endif
|
||||
|
||||
if(min_heap_size > 0)
|
||||
printf("\n\rMin available heap size = %d bytes during %s\n\r", min_heap_size, __FUNCTION__);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
if(param != NULL)
|
||||
*((int *) param) = ret;
|
||||
}
|
||||
|
||||
void start_ssl_client(void)
|
||||
{
|
||||
is_task = 1;
|
||||
//strcpy(server_host, SERVER_HOST);
|
||||
|
||||
if(xTaskCreate(ssl_client, "ssl_client", STACKSIZE, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
|
||||
printf("\n\r%s xTaskCreate failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
void do_ssl_connect(void)
|
||||
{
|
||||
int ret;
|
||||
static int success = 0;
|
||||
static int fail = 0;
|
||||
|
||||
is_task = 0;
|
||||
strcpy(server_host, SERVER_HOST);
|
||||
ssl_client(&ret);
|
||||
|
||||
if(ret != 0)
|
||||
printf("\n\r%s fail (success %d times, fail %d times)\n\r", __FUNCTION__, success, ++ fail);
|
||||
else
|
||||
printf("\n\r%s success (success %d times, fail %d times)\n\r", __FUNCTION__, ++ success, fail);
|
||||
}
|
||||
|
||||
void cmd_ssl_client(int argc, char **argv)
|
||||
{
|
||||
if(argc == 2) {
|
||||
strcpy(server_host, argv[1]);
|
||||
}
|
||||
else {
|
||||
printf("\n\rUsage: %s SSL_SERVER_HOST", argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
start_ssl_client();
|
||||
}
|
||||
|
||||
#elif CONFIG_USE_MBEDTLS /* CONFIG_USE_POLARSSL */
|
||||
|
||||
#include "mbedtls/config.h"
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/net_sockets.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
#include "mbedtls/error.h"
|
||||
#include "mbedtls/debug.h"
|
||||
|
||||
#define SERVER_PORT "443"
|
||||
#define SERVER_HOST "192.168.13.15"
|
||||
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
|
||||
#define DEBUG_LEVEL 0
|
||||
|
||||
//#define SSL_CLIENT_EXT
|
||||
#define STACKSIZE 2048
|
||||
|
||||
static int is_task = 0;
|
||||
static char server_host[32];
|
||||
static size_t min_heap_size = 0;
|
||||
|
||||
static void my_debug(void *ctx, int level, const char *file, int line, const char *str)
|
||||
{
|
||||
printf("\n\r%s:%d: %s\n\r", file, line, str);
|
||||
}
|
||||
|
||||
static int my_random(void *p_rng, unsigned char *output, size_t output_len)
|
||||
{
|
||||
rtw_get_random_bytes(output, output_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* my_calloc(size_t nelements, size_t elementSize)
|
||||
{
|
||||
size_t current_heap_size, size;
|
||||
void *ptr = NULL;
|
||||
|
||||
size = nelements * elementSize;
|
||||
ptr = pvPortMalloc(size);
|
||||
|
||||
if(ptr)
|
||||
memset(ptr, 0, size);
|
||||
|
||||
current_heap_size = xPortGetFreeHeapSize();
|
||||
|
||||
if((current_heap_size < min_heap_size) || (min_heap_size == 0))
|
||||
min_heap_size = current_heap_size;
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
#define my_free vPortFree
|
||||
|
||||
static void ssl_client(void *param)
|
||||
{
|
||||
int ret, len;
|
||||
int retry_count = 0;
|
||||
unsigned char buf[512];
|
||||
mbedtls_net_context server_fd;
|
||||
mbedtls_ssl_context ssl;
|
||||
mbedtls_ssl_config conf;
|
||||
|
||||
mbedtls_platform_set_calloc_free(my_calloc, my_free);
|
||||
#if defined(MBEDTLS_DEBUG_C)
|
||||
mbedtls_debug_set_threshold(DEBUG_LEVEL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 1. Start the connection
|
||||
*/
|
||||
printf("\n\r . Connecting to tcp/%s/%s...", server_host, SERVER_PORT);
|
||||
|
||||
mbedtls_net_init(&server_fd);
|
||||
|
||||
if((ret = mbedtls_net_connect(&server_fd, server_host, SERVER_PORT, MBEDTLS_NET_PROTO_TCP)) != 0) {
|
||||
printf(" failed\n\r ! mbedtls_net_connect returned %d\n", ret);
|
||||
goto exit1;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 2. Setup stuff
|
||||
*/
|
||||
printf(" . Setting up the SSL/TLS structure...");
|
||||
|
||||
mbedtls_ssl_init(&ssl);
|
||||
mbedtls_ssl_config_init(&conf);
|
||||
|
||||
#ifdef SSL_CLIENT_EXT
|
||||
if((ret = ssl_client_ext_init()) != 0) {
|
||||
printf(" failed\n\r ! ssl_client_ext_init returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
if((ret = mbedtls_ssl_config_defaults(&conf,
|
||||
MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
|
||||
|
||||
printf(" failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_NONE);
|
||||
mbedtls_ssl_conf_rng(&conf, my_random, NULL);
|
||||
mbedtls_ssl_conf_dbg(&conf, my_debug, NULL);
|
||||
|
||||
#ifdef SSL_CLIENT_EXT
|
||||
if((ret = ssl_client_ext_setup(&conf)) != 0) {
|
||||
printf(" failed\n\r ! ssl_client_ext_setup returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
|
||||
printf(" failed\n ! mbedtls_ssl_setup returned %d\n\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
/*
|
||||
* 3. Handshake
|
||||
*/
|
||||
printf("\n\r . Performing the SSL/TLS handshake...");
|
||||
|
||||
while((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
|
||||
if((ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
&& ret != MBEDTLS_ERR_NET_RECV_FAILED) || retry_count >= 5) {
|
||||
|
||||
printf(" failed\n\r ! mbedtls_ssl_handshake returned -0x%x\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
retry_count++;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
printf("\n\r . Use ciphersuite %s\n", mbedtls_ssl_get_ciphersuite(&ssl));
|
||||
|
||||
/*
|
||||
* 4. Write the GET request
|
||||
*/
|
||||
printf("\n\r > Write to server:");
|
||||
|
||||
len = sprintf((char *) buf, GET_REQUEST);
|
||||
|
||||
while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0) {
|
||||
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
printf(" failed\n\r ! mbedtls_ssl_write returned %d\n", ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
len = ret;
|
||||
printf(" %d bytes written\n\n%s", len, (char *) buf);
|
||||
|
||||
/*
|
||||
* 5. Read the HTTP response
|
||||
*/
|
||||
printf(" < Read from server:" );
|
||||
|
||||
do {
|
||||
len = sizeof(buf) - 1;
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ret = mbedtls_ssl_read(&ssl, buf, len);
|
||||
|
||||
if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
|
||||
continue;
|
||||
|
||||
if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY)
|
||||
break;
|
||||
|
||||
if(ret < 0) {
|
||||
printf(" failed\n ! mbedtls_ssl_read returned %d\n", ret);
|
||||
break;
|
||||
}
|
||||
|
||||
if(ret == 0) {
|
||||
printf("\n\nEOF\n\n");
|
||||
break;
|
||||
}
|
||||
|
||||
len = ret;
|
||||
printf(" %d bytes read\n\n%s", len, (char *) buf);
|
||||
}
|
||||
while(1);
|
||||
|
||||
mbedtls_ssl_close_notify(&ssl);
|
||||
|
||||
exit:
|
||||
|
||||
#ifdef MBEDTLS_ERROR_C
|
||||
if(ret != 0) {
|
||||
char error_buf[100];
|
||||
mbedtls_strerror(ret, error_buf, 100);
|
||||
printf("Last error was: %d - %s\n\n", ret, error_buf);
|
||||
}
|
||||
#endif
|
||||
|
||||
mbedtls_net_free(&server_fd);
|
||||
mbedtls_ssl_free(&ssl);
|
||||
mbedtls_ssl_config_free(&conf);
|
||||
|
||||
#ifdef SSL_CLIENT_EXT
|
||||
ssl_client_ext_free();
|
||||
#endif
|
||||
|
||||
exit1:
|
||||
if(is_task) {
|
||||
#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1)
|
||||
printf("\n\rMin available stack size of %s = %d * %d bytes\n\r", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE));
|
||||
#endif
|
||||
|
||||
if(min_heap_size > 0)
|
||||
printf("\n\rMin available heap size = %d bytes during %s\n\r", min_heap_size, __FUNCTION__);
|
||||
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
if(param != NULL)
|
||||
*((int *) param) = ret;
|
||||
}
|
||||
|
||||
void start_ssl_client(void)
|
||||
{
|
||||
is_task = 1;
|
||||
//strcpy(server_host, SERVER_HOST);
|
||||
|
||||
if(xTaskCreate(ssl_client, "ssl_client", STACKSIZE, NULL, tskIDLE_PRIORITY + 1, NULL) != pdPASS)
|
||||
printf("\n\r%s xTaskCreate failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
void do_ssl_connect(void)
|
||||
{
|
||||
int ret;
|
||||
static int success = 0;
|
||||
static int fail = 0;
|
||||
|
||||
is_task = 0;
|
||||
strcpy(server_host, SERVER_HOST);
|
||||
ssl_client(&ret);
|
||||
|
||||
if(ret != 0)
|
||||
printf("\n\r%s fail (success %d times, fail %d times)\n\r", __FUNCTION__, success, ++ fail);
|
||||
else
|
||||
printf("\n\r%s success (success %d times, fail %d times)\n\r", __FUNCTION__, ++ success, fail);
|
||||
}
|
||||
|
||||
void cmd_ssl_client(int argc, char **argv)
|
||||
{
|
||||
if(argc == 2) {
|
||||
strcpy(server_host, argv[1]);
|
||||
}
|
||||
else {
|
||||
printf("\n\rUsage: %s SSL_SERVER_HOST", argv[0]);
|
||||
return;
|
||||
}
|
||||
|
||||
start_ssl_client();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_USE_POLARSSL */
|
||||
371
lib/amb1_sdk/common/utilities/ssl_client_ext.c
Normal file
371
lib/amb1_sdk/common/utilities/ssl_client_ext.c
Normal file
@@ -0,0 +1,371 @@
|
||||
#include "platform_opts.h"
|
||||
|
||||
#if CONFIG_USE_POLARSSL
|
||||
|
||||
#include <polarssl/ssl.h>
|
||||
#include <polarssl/memory.h>
|
||||
|
||||
//#define SSL_VERIFY_CLIENT
|
||||
//#define SSL_VERIFY_SERVER
|
||||
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
static x509_crt* _cli_crt = NULL;
|
||||
static pk_context* _clikey_rsa = NULL;
|
||||
|
||||
static const char *test_client_key = \
|
||||
"-----BEGIN RSA PRIVATE KEY-----\r\n" \
|
||||
"MIICXgIBAAKBgQDKLbkPtV0uhoqkHxHl/sZlq5TrUqu6pScqGkMnEUDKIFR5QMNf\r\n" \
|
||||
"qLgbGPwbreN4AkHQlvqnn/2Swz1uurUH4pxcGp54j7QmANXvd5hJtCMhPpDcPS6k\r\n" \
|
||||
"ldlIJ8y3KoCoqAot6uo9IL/IKKk3aOQqeHKayIyjOOksjMkgeE8/gCpmFQIDAQAB\r\n" \
|
||||
"AoGBAKoSBj+Bh83wXUWr4SmAxLGXwSCnHVBXRveyudRuPfsJcSXCZdbdHWml/cTm\r\n" \
|
||||
"5Jb6BxUJO/avreW8GLxBkLD+XhnXlkw1RJ8FYZPXdzlNJzoYyVK0GZ/qyGacEEFt\r\n" \
|
||||
"ekvGfBJIq+7ksKcJt5c9qARClOvauYLRGwubl64xD6PupSINAkEA+5C395h227nc\r\n" \
|
||||
"5zF8s2rYBP78i5uS7hKqqVjGy8pcIFHiM/0ehzcN3V3gJXLjkAbXfvP0h/tm8eQG\r\n" \
|
||||
"QUpJBY/YLwJBAM2+IOfTmEBxrpASUeN1Lx9yg0+Swyz8oz2a2blfFwbpCWBi18M2\r\n" \
|
||||
"huo+YECeMggqBBYwgQ9J2ixpaj/e9+0pkPsCQQDztTWkFf4/y4WoLBcEseNoo6YB\r\n" \
|
||||
"kcv7+/V9bdXZI8ewP+OGPhdPIxS5efJmFTFEHHy0Lp6dBf6rJB6zLcYkL0BdAkEA\r\n" \
|
||||
"nGBqeknlavX9DBwgiZXD308WZyDRoBvVpzlPSwnvYp01N0FpZULIgLowRmz28iWd\r\n" \
|
||||
"PZBYR9qGLUNiMnGyV1xEiQJAOdlBM4M9Xj2Z9inCdkgFkbIOSe5kvIPC24CjZyyG\r\n" \
|
||||
"g3lK/YezoDmdD//OLoY81y6VdO5dwjm7P0wZB63EDRidHA==\r\n" \
|
||||
"-----END RSA PRIVATE KEY-----\r\n";
|
||||
|
||||
static const char *test_client_cert = \
|
||||
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||
"MIIC4DCCAkmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJDTjEL\r\n" \
|
||||
"MAkGA1UECAwCSlMxCzAJBgNVBAcMAlNaMRAwDgYDVQQKDAdSZWFsc2lsMRAwDgYD\r\n" \
|
||||
"VQQLDAdSZWFsdGVrMRAwDgYDVQQDDAdSZWFsc2lsMRwwGgYJKoZIhvcNAQkBFg1h\r\n" \
|
||||
"QHJlYWxzaWwuY29tMB4XDTE1MTIyMzA2NTI0MFoXDTE2MTIyMjA2NTI0MFowdDEL\r\n" \
|
||||
"MAkGA1UEBhMCQ04xCzAJBgNVBAgMAkpTMRAwDgYDVQQKDAdSZWFsc2lsMRAwDgYD\r\n" \
|
||||
"VQQLDAdSZWFsdGVrMRYwFAYDVQQDDA0xOTIuMTY4LjEuMTQxMRwwGgYJKoZIhvcN\r\n" \
|
||||
"AQkBFg1jQHJlYWxzaWwuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDK\r\n" \
|
||||
"LbkPtV0uhoqkHxHl/sZlq5TrUqu6pScqGkMnEUDKIFR5QMNfqLgbGPwbreN4AkHQ\r\n" \
|
||||
"lvqnn/2Swz1uurUH4pxcGp54j7QmANXvd5hJtCMhPpDcPS6kldlIJ8y3KoCoqAot\r\n" \
|
||||
"6uo9IL/IKKk3aOQqeHKayIyjOOksjMkgeE8/gCpmFQIDAQABo3sweTAJBgNVHRME\r\n" \
|
||||
"AjAAMCwGCWCGSAGG+EIBDQQfFh1PcGVuU1NMIEdlbmVyYXRlZCBDZXJ0aWZpY2F0\r\n" \
|
||||
"ZTAdBgNVHQ4EFgQUJLmwJNyKHCTEspNTPNpbPjXkjnQwHwYDVR0jBBgwFoAUAfLa\r\n" \
|
||||
"cSF933h+3pYNcs36lvm7yEkwDQYJKoZIhvcNAQELBQADgYEAlo495gu94nMHFYx4\r\n" \
|
||||
"+V7PjwGIqanqwLjsem9qvwJa/K1QoM4JxnqRXFUdSfZMhnlrMgPer4fDHpWAutWB\r\n" \
|
||||
"X2Fiww+VVJSn8Go0seK8RQf8n/n3rJ5B3lef1Po2zHchELWhlFT6k5Won7gp64RN\r\n" \
|
||||
"9PcwFFy0Va/bkJsot//kdZNKs/g=\r\n" \
|
||||
"-----END CERTIFICATE-----\r\n";
|
||||
#endif
|
||||
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
static x509_crt* _ca_crt = NULL;
|
||||
|
||||
static const char *test_ca_cert = \
|
||||
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||
"MIICxDCCAi2gAwIBAgIJANdeY8UOfqpBMA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNV\r\n" \
|
||||
"BAYTAkNOMQswCQYDVQQIDAJKUzELMAkGA1UEBwwCU1oxEDAOBgNVBAoMB1JlYWxz\r\n" \
|
||||
"aWwxEDAOBgNVBAsMB1JlYWx0ZWsxEDAOBgNVBAMMB1JlYWxzaWwxHDAaBgkqhkiG\r\n" \
|
||||
"9w0BCQEWDWFAcmVhbHNpbC5jb20wHhcNMTUxMjIzMDYzMDA1WhcNMTYxMjIyMDYz\r\n" \
|
||||
"MDA1WjB7MQswCQYDVQQGEwJDTjELMAkGA1UECAwCSlMxCzAJBgNVBAcMAlNaMRAw\r\n" \
|
||||
"DgYDVQQKDAdSZWFsc2lsMRAwDgYDVQQLDAdSZWFsdGVrMRAwDgYDVQQDDAdSZWFs\r\n" \
|
||||
"c2lsMRwwGgYJKoZIhvcNAQkBFg1hQHJlYWxzaWwuY29tMIGfMA0GCSqGSIb3DQEB\r\n" \
|
||||
"AQUAA4GNADCBiQKBgQCmfNpluJZP0Sla+MIYzRGA1rljK5VncuBKQiKBF4BdO73H\r\n" \
|
||||
"OTUoT0ydR7x7lS2Ns1HQop2oldroJVBj38+pLci1i/3flkONCDfsWOzfcGZ9RItq\r\n" \
|
||||
"Zf9eQI8CEZI5i0Fvi3mgaoqCXvutFBrtTQRNsKQD69SqxEWWPb1y+Fd2nONeawID\r\n" \
|
||||
"AQABo1AwTjAdBgNVHQ4EFgQUAfLacSF933h+3pYNcs36lvm7yEkwHwYDVR0jBBgw\r\n" \
|
||||
"FoAUAfLacSF933h+3pYNcs36lvm7yEkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\r\n" \
|
||||
"AQsFAAOBgQA6McwC1Vk4k/5Bh/sf9cfwSK9A0ecaIH0NizYoWpWRAsv7TDgj0PbO\r\n" \
|
||||
"Qqxi/QhpuYezgRqKqAv7QYNSQa39X7opzSsdSGtTnId374PZZeCDqZpfcAbsNk5o\r\n" \
|
||||
"6HLpJ27esFa/flTL0FtmO+AT2uiPMvRP0a4u4uuLQK2Jgm/CmzJ47w==\r\n" \
|
||||
"-----END CERTIFICATE-----\r\n";
|
||||
|
||||
static int my_verify(void *data, x509_crt *crt, int depth, int *flags)
|
||||
{
|
||||
char buf[1024];
|
||||
((void) data);
|
||||
|
||||
printf("Verify requested for (Depth %d):\n", depth);
|
||||
x509_crt_info(buf, sizeof(buf) - 1, "", crt);
|
||||
printf("%s", buf);
|
||||
|
||||
if(((*flags) & BADCERT_EXPIRED) != 0)
|
||||
printf("server certificate has expired\n");
|
||||
|
||||
if(((*flags) & BADCERT_REVOKED) != 0)
|
||||
printf(" ! server certificate has been revoked\n");
|
||||
|
||||
if(((*flags) & BADCERT_CN_MISMATCH) != 0)
|
||||
printf(" ! CN mismatch\n");
|
||||
|
||||
if(((*flags) & BADCERT_NOT_TRUSTED) != 0)
|
||||
printf(" ! self-signed or not signed by a trusted CA\n");
|
||||
|
||||
if(((*flags) & BADCRL_NOT_TRUSTED) != 0)
|
||||
printf(" ! CRL not trusted\n");
|
||||
|
||||
if(((*flags) & BADCRL_EXPIRED) != 0)
|
||||
printf(" ! CRL expired\n");
|
||||
|
||||
if(((*flags) & BADCERT_OTHER) != 0)
|
||||
printf(" ! other (unknown) flag\n");
|
||||
|
||||
if((*flags) == 0)
|
||||
printf(" Certificate verified without error flags\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ssl_client_ext_init(void)
|
||||
{
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
_cli_crt = polarssl_malloc(sizeof(x509_crt));
|
||||
|
||||
if(_cli_crt)
|
||||
x509_crt_init(_cli_crt);
|
||||
else
|
||||
return -1;
|
||||
|
||||
_clikey_rsa = polarssl_malloc(sizeof(pk_context));
|
||||
|
||||
if(_clikey_rsa)
|
||||
pk_init(_clikey_rsa);
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
_ca_crt = polarssl_malloc(sizeof(x509_crt));
|
||||
|
||||
if(_ca_crt)
|
||||
x509_crt_init(_ca_crt);
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ssl_client_ext_free(void)
|
||||
{
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
if(_cli_crt) {
|
||||
x509_crt_free(_cli_crt);
|
||||
polarssl_free(_cli_crt);
|
||||
_cli_crt = NULL;
|
||||
}
|
||||
|
||||
if(_clikey_rsa) {
|
||||
pk_free(_clikey_rsa);
|
||||
polarssl_free(_clikey_rsa);
|
||||
_clikey_rsa = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
if(_ca_crt) {
|
||||
x509_crt_free(_ca_crt);
|
||||
polarssl_free(_ca_crt);
|
||||
_ca_crt = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int ssl_client_ext_setup(ssl_context *ssl)
|
||||
{
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
if(x509_crt_parse(_cli_crt, test_client_cert, strlen(test_client_cert)) != 0)
|
||||
return -1;
|
||||
|
||||
if(pk_parse_key(_clikey_rsa, test_client_key, strlen(test_client_key), NULL, 0) != 0)
|
||||
return -1;
|
||||
|
||||
ssl_set_own_cert(ssl, _cli_crt, _clikey_rsa);
|
||||
#endif
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
if(x509_crt_parse(_ca_crt, test_ca_cert, strlen(test_ca_cert)) != 0)
|
||||
return -1;
|
||||
|
||||
ssl_set_ca_chain(ssl, _ca_crt, NULL, NULL);
|
||||
ssl_set_authmode(ssl, SSL_VERIFY_REQUIRED);
|
||||
ssl_set_verify(ssl, my_verify, NULL);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#elif CONFIG_USE_MBEDTLS /* CONFIG_USE_POLARSSL */
|
||||
|
||||
#include "mbedtls/config.h"
|
||||
#include "mbedtls/platform.h"
|
||||
#include "mbedtls/ssl.h"
|
||||
|
||||
//#define SSL_VERIFY_CLIENT
|
||||
//#define SSL_VERIFY_SERVER
|
||||
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
static mbedtls_x509_crt* _cli_crt = NULL;
|
||||
static mbedtls_pk_context* _clikey_rsa = NULL;
|
||||
|
||||
static const char *test_client_key = \
|
||||
"-----BEGIN RSA PRIVATE KEY-----\r\n" \
|
||||
"MIICXAIBAAKBgQDxzEGPfEgtHIvwr2Q9uVwfe+HaP80ymn7v8ANHp6kvL870fnij\r\n" \
|
||||
"oJlcMlDbYE5lZmHA3Z6t4wSLh5k1rAFakGNDvl6G/mF45vSCAWgrN+JOqBVBSdQ0\r\n" \
|
||||
"iu+qlRwZMvE9yI68a9OLT8w1ijaFAGkh2p4jn9P1++t9Gf25B50wngZpNwIDAQAB\r\n" \
|
||||
"AoGADjCUcF00xyDzvW4tjcnA9EAK4wn3es7CQEZvitb2AMTnekWpwsB7/4McZ6Nh\r\n" \
|
||||
"NmYpum3HECFQdPfCL/omIjBzAruFHzx8Z0QAMN/cKIiQSd5Tx8MbKkOn8teHJe/u\r\n" \
|
||||
"C/wLu/Qtt4l/E0uqyIcW/cyYcnN1/oOBfZglOGTiJ3Q0QNECQQD/Y1FLhzkQ32Ib\r\n" \
|
||||
"Jc70ExPwvIvIu8jjFVyGXEnHtvRF478LgyPeLepiuvNVTTWpQs5bIqT2lRBrgfjO\r\n" \
|
||||
"B+mptDa9AkEA8mCZ1cFfGAQGvEGJFH7K+6nGwGa9eRyRdDEAmnz9Fx8TNu8bv3S0\r\n" \
|
||||
"rFYl2GdYc4DwGWWz91vxTHLtvzRW59OpAwJACBn/dzTn84gSlafiY83DISzqBkkm\r\n" \
|
||||
"u0VvNPfygzpjj2AFLHlRhvfP6qfhlkAnxqHO6Ac2UngyGCb8XJTVrcOAxQJAAb3t\r\n" \
|
||||
"/RpJq6uDvOCfspUCsnJS6lkSrYcmCHa9sV6KlxrzEWcAhQy6q65m0TpU6WeY0iXn\r\n" \
|
||||
"+DQh9NGyobgnk7zyrwJBAMkjC/a9aeUA9y/ePoY5gVzWjPBNKJJplDzJvDLANG5k\r\n" \
|
||||
"7zonQ5Fu2JEZTjh2p3Ev1X3SmhuEijHYoaiXFTUAjlE=\r\n" \
|
||||
"-----END RSA PRIVATE KEY-----\r\n";
|
||||
|
||||
static const char *test_client_cert = \
|
||||
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||
"MIIC3zCCAkigAwIBAgIBAjANBgkqhkiG9w0BAQsFADB7MQswCQYDVQQGEwJDTjEL\r\n" \
|
||||
"MAkGA1UECAwCSlMxCzAJBgNVBAcMAlNaMRAwDgYDVQQKDAdSZWFsc2lsMRAwDgYD\r\n" \
|
||||
"VQQLDAdSZWFsdGVrMRAwDgYDVQQDDAdSZWFsc2lsMRwwGgYJKoZIhvcNAQkBFg1h\r\n" \
|
||||
"QHJlYWxzaWwuY29tMB4XDTE2MDkxNDA2MDg0N1oXDTE3MDkxNDA2MDg0N1owczEL\r\n" \
|
||||
"MAkGA1UEBhMCQ04xCzAJBgNVBAgMAkpTMRAwDgYDVQQKDAdSZWFsc2lsMRAwDgYD\r\n" \
|
||||
"VQQLDAdSZWFsdGVrMRUwEwYDVQQDDAwxOTIuMTY4LjEuNTIxHDAaBgkqhkiG9w0B\r\n" \
|
||||
"CQEWDWNAcmVhbHNpbC5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPHM\r\n" \
|
||||
"QY98SC0ci/CvZD25XB974do/zTKafu/wA0enqS8vzvR+eKOgmVwyUNtgTmVmYcDd\r\n" \
|
||||
"nq3jBIuHmTWsAVqQY0O+Xob+YXjm9IIBaCs34k6oFUFJ1DSK76qVHBky8T3Ijrxr\r\n" \
|
||||
"04tPzDWKNoUAaSHaniOf0/X7630Z/bkHnTCeBmk3AgMBAAGjezB5MAkGA1UdEwQC\r\n" \
|
||||
"MAAwLAYJYIZIAYb4QgENBB8WHU9wZW5TU0wgR2VuZXJhdGVkIENlcnRpZmljYXRl\r\n" \
|
||||
"MB0GA1UdDgQWBBRrALVkL8aJIm4zSHfSHRlPZtPWUzAfBgNVHSMEGDAWgBSg0idX\r\n" \
|
||||
"+PDX/BDU0kIRPUDia1ntRTANBgkqhkiG9w0BAQsFAAOBgQCdo9WhM1cSV/wiHQAa\r\n" \
|
||||
"b7OTj4tIUbTpXzA7zv0Ib5VfmoTWALtGtyw4HeRRWEZxKuSjmsDrhNrmZb0pQ91z\r\n" \
|
||||
"WKsa8KmFPdFJOGkdUyGmCejJQnKBAGZv+LcW377z9v6zeTX2Hw0+RYpjIzVWNw/2\r\n" \
|
||||
"/OII2cfiuu3BUxx1jM2PwA2iTw==\r\n" \
|
||||
"-----END CERTIFICATE-----\r\n";
|
||||
#endif
|
||||
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
static mbedtls_x509_crt* _ca_crt = NULL;
|
||||
|
||||
static const char *test_ca_cert = \
|
||||
"-----BEGIN CERTIFICATE-----\r\n" \
|
||||
"MIICxDCCAi2gAwIBAgIJAO1U1TMWGa37MA0GCSqGSIb3DQEBCwUAMHsxCzAJBgNV\r\n" \
|
||||
"BAYTAkNOMQswCQYDVQQIDAJKUzELMAkGA1UEBwwCU1oxEDAOBgNVBAoMB1JlYWxz\r\n" \
|
||||
"aWwxEDAOBgNVBAsMB1JlYWx0ZWsxEDAOBgNVBAMMB1JlYWxzaWwxHDAaBgkqhkiG\r\n" \
|
||||
"9w0BCQEWDWFAcmVhbHNpbC5jb20wHhcNMTYwOTE0MDU1OTE5WhcNMTcwOTE0MDU1\r\n" \
|
||||
"OTE5WjB7MQswCQYDVQQGEwJDTjELMAkGA1UECAwCSlMxCzAJBgNVBAcMAlNaMRAw\r\n" \
|
||||
"DgYDVQQKDAdSZWFsc2lsMRAwDgYDVQQLDAdSZWFsdGVrMRAwDgYDVQQDDAdSZWFs\r\n" \
|
||||
"c2lsMRwwGgYJKoZIhvcNAQkBFg1hQHJlYWxzaWwuY29tMIGfMA0GCSqGSIb3DQEB\r\n" \
|
||||
"AQUAA4GNADCBiQKBgQDK1uJDOX1TQylVnzKNCgpTDos2oHekx65LZSrg/fB8Rknb\r\n" \
|
||||
"Zi9DXwi9ELCtROHZu5NUOGLjwNN/hqaW09WJrRAd5KrvKIxJZTRsNfPlCBBQOlh8\r\n" \
|
||||
"6aZj9TE+H88x4fFdJPxzMR3hTqtm2/CD0WSEIvhS+4NK8/3qiXiGFF8WYD8HYwID\r\n" \
|
||||
"AQABo1AwTjAdBgNVHQ4EFgQUoNInV/jw1/wQ1NJCET1A4mtZ7UUwHwYDVR0jBBgw\r\n" \
|
||||
"FoAUoNInV/jw1/wQ1NJCET1A4mtZ7UUwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0B\r\n" \
|
||||
"AQsFAAOBgQBxWiMOKuH6i0BD2Gp8nHGgpup5vSu7TKTf1lBnIvKnwfXGTmTI1TjB\r\n" \
|
||||
"d3pXaPB4ehLg/1FNiFJ4mV8+s2fnQfTYuti3XlsBccL08WhprECwjNY3ZoeAXIi3\r\n" \
|
||||
"VGXR2fkZ4jhrf2GHmLTrtvbiatX1bN6EVvzbemHpxCYoGJdibDyCZg==\r\n" \
|
||||
"-----END CERTIFICATE-----\r\n";
|
||||
|
||||
static int my_verify(void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags)
|
||||
{
|
||||
char buf[1024];
|
||||
((void) data);
|
||||
|
||||
printf("Verify requested for (Depth %d):\n", depth);
|
||||
mbedtls_x509_crt_info(buf, sizeof(buf) - 1, "", crt);
|
||||
printf("%s", buf);
|
||||
|
||||
if(((*flags) & MBEDTLS_X509_BADCERT_EXPIRED) != 0)
|
||||
printf("server certificate has expired\n");
|
||||
|
||||
if(((*flags) & MBEDTLS_X509_BADCERT_REVOKED) != 0)
|
||||
printf(" ! server certificate has been revoked\n");
|
||||
|
||||
if(((*flags) & MBEDTLS_X509_BADCERT_CN_MISMATCH) != 0)
|
||||
printf(" ! CN mismatch\n");
|
||||
|
||||
if(((*flags) & MBEDTLS_X509_BADCERT_NOT_TRUSTED) != 0)
|
||||
printf(" ! self-signed or not signed by a trusted CA\n");
|
||||
|
||||
if(((*flags) & MBEDTLS_X509_BADCRL_NOT_TRUSTED) != 0)
|
||||
printf(" ! CRL not trusted\n");
|
||||
|
||||
if(((*flags) & MBEDTLS_X509_BADCRL_EXPIRED) != 0)
|
||||
printf(" ! CRL expired\n");
|
||||
|
||||
if(((*flags) & MBEDTLS_X509_BADCERT_OTHER) != 0)
|
||||
printf(" ! other (unknown) flag\n");
|
||||
|
||||
if((*flags) == 0)
|
||||
printf(" Certificate verified without error flags\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
int ssl_client_ext_init(void)
|
||||
{
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
_cli_crt = (mbedtls_x509_crt *) mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
|
||||
|
||||
if(_cli_crt)
|
||||
mbedtls_x509_crt_init(_cli_crt);
|
||||
else
|
||||
return -1;
|
||||
|
||||
_clikey_rsa = (mbedtls_pk_context *) mbedtls_calloc(1, sizeof(mbedtls_pk_context));
|
||||
|
||||
if(_clikey_rsa)
|
||||
mbedtls_pk_init(_clikey_rsa);
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
_ca_crt = (mbedtls_x509_crt *) mbedtls_calloc(1, sizeof(mbedtls_x509_crt));
|
||||
|
||||
if(_ca_crt)
|
||||
mbedtls_x509_crt_init(_ca_crt);
|
||||
else
|
||||
return -1;
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ssl_client_ext_free(void)
|
||||
{
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
if(_cli_crt) {
|
||||
mbedtls_x509_crt_free(_cli_crt);
|
||||
mbedtls_free(_cli_crt);
|
||||
_cli_crt = NULL;
|
||||
}
|
||||
|
||||
if(_clikey_rsa) {
|
||||
mbedtls_pk_free(_clikey_rsa);
|
||||
mbedtls_free(_clikey_rsa);
|
||||
_clikey_rsa = NULL;
|
||||
}
|
||||
#endif
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
if(_ca_crt) {
|
||||
mbedtls_x509_crt_free(_ca_crt);
|
||||
mbedtls_free(_ca_crt);
|
||||
_ca_crt = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int ssl_client_ext_setup(mbedtls_ssl_config *conf)
|
||||
{
|
||||
/* Since mbedtls crt and pk API will check string terminator to prevent non-null-terminated string, need to count string terminator to buffer length */
|
||||
#ifdef SSL_VERIFY_CLIENT
|
||||
if(mbedtls_x509_crt_parse(_cli_crt, test_client_cert, strlen(test_client_cert) + 1) != 0)
|
||||
return -1;
|
||||
|
||||
if(mbedtls_pk_parse_key(_clikey_rsa, test_client_key, strlen(test_client_key) + 1, NULL, 0) != 0)
|
||||
return -1;
|
||||
|
||||
mbedtls_ssl_conf_own_cert(conf, _cli_crt, _clikey_rsa);
|
||||
#endif
|
||||
#ifdef SSL_VERIFY_SERVER
|
||||
if(mbedtls_x509_crt_parse(_ca_crt, test_ca_cert, strlen(test_ca_cert) + 1) != 0)
|
||||
return -1;
|
||||
|
||||
mbedtls_ssl_conf_ca_chain(conf, _ca_crt, NULL);
|
||||
mbedtls_ssl_conf_authmode(conf, MBEDTLS_SSL_VERIFY_REQUIRED);
|
||||
mbedtls_ssl_conf_verify(conf, my_verify, NULL);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* CONFIG_USE_POLARSSL */
|
||||
121
lib/amb1_sdk/common/utilities/tcpecho.c
Normal file
121
lib/amb1_sdk/common/utilities/tcpecho.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_NETCONN
|
||||
|
||||
#include "lwip/sys.h"
|
||||
#include "lwip/api.h"
|
||||
|
||||
#define TCPECHO_THREAD_PRIO ( tskIDLE_PRIORITY + 3 )
|
||||
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void tcpecho_thread(void *arg)
|
||||
{
|
||||
struct netconn *conn, *newconn;
|
||||
err_t err;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
/* Create a new connection identifier. */
|
||||
conn = netconn_new(NETCONN_TCP);
|
||||
|
||||
if (conn!=NULL)
|
||||
{
|
||||
/* Bind connection to well known port number 7. */
|
||||
err = netconn_bind(conn, NULL, 7);
|
||||
|
||||
if (err == ERR_OK)
|
||||
{
|
||||
/* Tell connection to go into listening mode. */
|
||||
netconn_listen(conn);
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Grab new connection. */
|
||||
newconn = netconn_accept(conn);
|
||||
|
||||
/* Process the new connection. */
|
||||
if (newconn)
|
||||
{
|
||||
struct netbuf *buf;
|
||||
void *data;
|
||||
u16_t len;
|
||||
|
||||
while ((buf = netconn_recv(newconn)) != NULL)
|
||||
{
|
||||
do
|
||||
{
|
||||
netbuf_data(buf, &data, &len);
|
||||
netconn_write(newconn, data, len, NETCONN_COPY);
|
||||
|
||||
}
|
||||
while (netbuf_next(buf) >= 0);
|
||||
|
||||
netbuf_delete(buf);
|
||||
}
|
||||
|
||||
/* Close connection and discard connection identifier. */
|
||||
netconn_close(newconn);
|
||||
netconn_delete(newconn);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(" can not bind TCP netconn");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("can not create TCP netconn");
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void tcpecho_init(void)
|
||||
{
|
||||
sys_thread_new("tcpecho_thread", tcpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE, TCPECHO_THREAD_PRIO);
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
|
||||
void cmd_tcpecho(int argc, char **argv)
|
||||
{
|
||||
printf("\n\rInit TCP ECHO Server ...");
|
||||
tcpecho_init();
|
||||
printf("\n\r\nPlease use echotool to connect to this echo server. ex. echotool 192.168.0.1 /p tcp /r 7 /n 0");
|
||||
}
|
||||
#endif /* LWIP_NETCONN */
|
||||
1386
lib/amb1_sdk/common/utilities/tcptest.c
Normal file
1386
lib/amb1_sdk/common/utilities/tcptest.c
Normal file
File diff suppressed because it is too large
Load Diff
374
lib/amb1_sdk/common/utilities/uart_socket.c
Normal file
374
lib/amb1_sdk/common/utilities/uart_socket.c
Normal file
@@ -0,0 +1,374 @@
|
||||
#include "lwip/api.h"
|
||||
#include "PinNames.h"
|
||||
#include "sockets.h"
|
||||
#include "uart_socket.h"
|
||||
#include "autoconf.h"
|
||||
#define UART_SOCKET_USE_DMA_TX 1
|
||||
/***********************************************************************
|
||||
* Macros *
|
||||
***********************************************************************/
|
||||
#define uart_printf printf
|
||||
#define uart_print_data(x, d, l) \
|
||||
do{\
|
||||
int i;\
|
||||
uart_printf("\n%s: Len=%d\n", (x), (l));\
|
||||
for(i = 0; i < (l); i++)\
|
||||
uart_printf("%02x ", (d)[i]);\
|
||||
uart_printf("\n");\
|
||||
}while(0);
|
||||
|
||||
#if defined(CONFIG_PLATFORM_8195A)
|
||||
#define UART_TX PA_7 //PA_4
|
||||
#define UART_RX PA_6 //PA_0
|
||||
#elif defined(CONFIG_PLATFORM_8711B)
|
||||
#define UART_TX PA_23
|
||||
#define UART_RX PA_18
|
||||
#endif
|
||||
/************************************************************************
|
||||
* extern funtions *
|
||||
************************************************************************/
|
||||
extern void lwip_selectevindicate(int fd);
|
||||
extern void lwip_setsockrcvevent(int fd, int rcvevent);
|
||||
extern int lwip_allocsocketsd();
|
||||
|
||||
/*************************************************************************
|
||||
* uart releated fuantions *
|
||||
*************************************************************************/
|
||||
static void uart_irq(uint32_t id, SerialIrq event)
|
||||
{
|
||||
uart_socket_t *u = (uart_socket_t *)id;
|
||||
|
||||
if(event == RxIrq) {
|
||||
if( u->rx_start == 0 ){
|
||||
rtw_up_sema_from_isr(&u->action_sema); //up action semaphore
|
||||
u->rx_start = 1; // set this flag in uart_irq to indicate data recved
|
||||
}
|
||||
u->recv_buf[u->prxwrite++] = serial_getc(&u->sobj);
|
||||
if(u->prxwrite > (UART_RECV_BUFFER_LEN -1)){ //restart from head if reach tail
|
||||
u->prxwrite = 0;
|
||||
u->rxoverlap = 1; //set overlap indicated that overlaped
|
||||
}
|
||||
if(u->rxoverlap && (u->prxwrite + 1) > u->prxread ){
|
||||
u->prxread = u->prxwrite; //if pwrite overhead pread ,pread is always flow rwrite
|
||||
}
|
||||
u->last_update = xTaskGetTickCountFromISR(); // update tick everytime recved data
|
||||
}
|
||||
|
||||
if(event == TxIrq){
|
||||
}
|
||||
}
|
||||
|
||||
static void uart_send_stream_done(uint32_t id)
|
||||
{
|
||||
uart_socket_t *u = (uart_socket_t *)id;
|
||||
|
||||
//u->tx_start = 0;
|
||||
memset(u->send_buf,0, UART_SEND_BUFFER_LEN); //zero set uart_send_buf
|
||||
rtw_up_sema_from_isr(&u->tx_sema);
|
||||
rtw_up_sema_from_isr(&u->dma_tx_sema);
|
||||
}
|
||||
|
||||
static int uart_send_stream(uart_socket_t *u, char* pbuf, int len)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(!len || (!pbuf) || !u){
|
||||
uart_printf("input error,size should not be null\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if UART_SOCKET_USE_DMA_TX
|
||||
while(rtw_down_sema(&u->dma_tx_sema) == pdTRUE){
|
||||
ret = serial_send_stream_dma(&u->sobj, pbuf, len);
|
||||
if(ret != HAL_OK){
|
||||
rtw_up_sema(&u->dma_tx_sema);
|
||||
return -1;
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#else
|
||||
while (len){
|
||||
serial_putc(&u->sobj, *pbuf);
|
||||
len--;
|
||||
pbuf++;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32 uart_wait_rx_complete(uart_socket_t *u)
|
||||
{
|
||||
s32 tick_current = xTaskGetTickCount();
|
||||
|
||||
while((tick_current -u->last_update) < UART_MAX_DELAY_TIME ){
|
||||
vTaskDelay(5);
|
||||
tick_current = xTaskGetTickCount();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uart_action_handler(void* param)
|
||||
{
|
||||
uart_socket_t *u = (uart_socket_t*)param;
|
||||
if(!u)
|
||||
goto Exit;
|
||||
|
||||
while(rtw_down_sema(&u->action_sema) == pdTRUE) {
|
||||
if(u->fd == -1)
|
||||
goto Exit;
|
||||
if(u->rx_start){
|
||||
/* Blocked here to wait uart rx data completed */
|
||||
uart_wait_rx_complete(u);
|
||||
|
||||
/* As we did not register netconn callback function.,so call lwip_selectevindicate unblocking select */
|
||||
lwip_setsockrcvevent(u->fd, 1);
|
||||
lwip_selectevindicate(u->fd); //unblocking select()
|
||||
u->rx_start = 0;
|
||||
}
|
||||
if(u->tx_start){
|
||||
#if 1
|
||||
if (u->tx_bytes < 128) {
|
||||
uart_print_data("TX:", u->send_buf, u->tx_bytes);
|
||||
} else {
|
||||
uart_printf("\nTX:: Len=%d\n", u->tx_bytes);
|
||||
}
|
||||
#endif
|
||||
u->tx_start = 0;
|
||||
if(uart_send_stream(u, (char*)u->send_buf, u->tx_bytes) == -1){
|
||||
uart_printf("uart send data error!");
|
||||
} else {
|
||||
#if (UART_SOCKET_USE_DMA_TX == 0)
|
||||
memset(u->send_buf,0, UART_SEND_BUFFER_LEN); //zero set uart_send_buf
|
||||
rtw_up_sema(&u->tx_sema);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
Exit:
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
uart_socket_t* uart_open(uart_set_str *puartpara)
|
||||
{
|
||||
PinName uart_tx = UART_TX;
|
||||
PinName uart_rx = UART_RX;
|
||||
uart_socket_t *u;
|
||||
|
||||
u = (uart_socket_t *)rtw_zmalloc(sizeof(uart_socket_t));
|
||||
if(!u){
|
||||
uart_printf("%s(): Alloc memory for uart_socket failed!\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*initial uart */
|
||||
serial_init(&u->sobj, uart_tx,uart_rx);
|
||||
serial_baud(&u->sobj,puartpara->BaudRate);
|
||||
serial_format(&u->sobj, puartpara->number, (SerialParity)puartpara->parity, puartpara->StopBits);
|
||||
|
||||
/*uart irq handle*/
|
||||
serial_irq_handler(&u->sobj, uart_irq, (int)u);
|
||||
serial_irq_set(&u->sobj, RxIrq, 1);
|
||||
serial_irq_set(&u->sobj, TxIrq, 1);
|
||||
|
||||
#if UART_SOCKET_USE_DMA_TX
|
||||
serial_send_comp_handler(&u->sobj, (void*)uart_send_stream_done, (uint32_t)u);
|
||||
#endif
|
||||
|
||||
/*alloc a socket*/
|
||||
u->fd = lwip_allocsocketsd();
|
||||
if(u->fd == -1){
|
||||
uart_printf("Failed to alloc uart socket!\n");
|
||||
goto Exit2;
|
||||
}
|
||||
/*init uart related semaphore*/
|
||||
rtw_init_sema(&u->action_sema, 0);
|
||||
rtw_init_sema(&u->tx_sema, 1);
|
||||
rtw_init_sema(&u->dma_tx_sema, 1);
|
||||
|
||||
/*create uart_thread to handle send&recv data*/
|
||||
{
|
||||
#define UART_ACTION_STACKSIZE 256 //USE_MIN_STACK_SIZE modify from 512 to 256
|
||||
#define UART_ACTION_PRIORITY 1
|
||||
if(xTaskCreate(uart_action_handler, ((const char*)"uart_action"), UART_ACTION_STACKSIZE, u, UART_ACTION_PRIORITY, NULL) != pdPASS){
|
||||
uart_printf("%s xTaskCreate(uart_action) failed", __FUNCTION__);
|
||||
goto Exit1;
|
||||
}
|
||||
}
|
||||
return u;
|
||||
Exit1:
|
||||
/* Free uart related semaphore */
|
||||
rtw_free_sema(&u->action_sema);
|
||||
rtw_free_sema(&u->tx_sema);
|
||||
rtw_free_sema(&u->dma_tx_sema);
|
||||
Exit2:
|
||||
rtw_mfree((u8*)u, sizeof(uart_socket_t));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uart_close(uart_socket_t *u)
|
||||
{
|
||||
if(!u){
|
||||
uart_printf("uart_close(): u is NULL!\r\n");
|
||||
return -1;
|
||||
}
|
||||
/* Close uart socket */
|
||||
if(lwip_close(u->fd) == -1){
|
||||
uart_printf("%s(): close uart failed!", __func__);
|
||||
}
|
||||
/* Delete uart_action task */
|
||||
u->fd = -1;
|
||||
rtw_up_sema(&u->action_sema);
|
||||
rtw_msleep_os(20);
|
||||
|
||||
/* Free uart related semaphore */
|
||||
rtw_free_sema(&u->action_sema);
|
||||
rtw_free_sema(&u->tx_sema);
|
||||
rtw_free_sema(&u->dma_tx_sema);
|
||||
|
||||
/* Free serial */
|
||||
serial_free(&u->sobj);
|
||||
|
||||
rtw_mfree((u8 *)u, sizeof(uart_socket_t));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uart_read(uart_socket_t *u, void *read_buf, size_t size)
|
||||
{
|
||||
/*the same as socket*/
|
||||
int read_bytes = 0;
|
||||
int pread_local,pwrite_local;
|
||||
char *ptr = (char *)read_buf;
|
||||
|
||||
uart_printf("==>uart_read()\n");
|
||||
if(!size || !read_buf || !u){
|
||||
uart_printf("uart_read(): input error,size should not be null\r\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
pread_local = u->prxread;
|
||||
pwrite_local = u->prxwrite;
|
||||
/*calculate how much data not read */
|
||||
if(!u->rxoverlap){
|
||||
read_bytes = pwrite_local - pread_local;
|
||||
} else {
|
||||
read_bytes = (UART_RECV_BUFFER_LEN - pread_local) + pwrite_local;
|
||||
}
|
||||
/*decide how much data shoule copy to application*/
|
||||
if(size < read_bytes)
|
||||
read_bytes = size;
|
||||
|
||||
if(!u->rxoverlap){
|
||||
memcpy(ptr, (u->recv_buf+ pread_local), read_bytes );
|
||||
} else {
|
||||
uart_printf("uart recv buf is write through!!\n");
|
||||
if((pread_local + read_bytes) > UART_RECV_BUFFER_LEN){
|
||||
memcpy(ptr,(u->recv_buf+ pread_local), (UART_RECV_BUFFER_LEN-pread_local));
|
||||
memcpy(ptr+(UART_RECV_BUFFER_LEN-pread_local), u->recv_buf, read_bytes-(UART_RECV_BUFFER_LEN- pread_local));
|
||||
} else
|
||||
memcpy(ptr,(u->recv_buf+ pread_local), read_bytes);
|
||||
}
|
||||
lwip_setsockrcvevent(u->fd, 0);
|
||||
|
||||
if((pread_local + read_bytes) >= UART_RECV_BUFFER_LEN){ //update pread
|
||||
u->prxread = (pread_local + read_bytes) - UART_RECV_BUFFER_LEN;
|
||||
u->rxoverlap = 0; //clean overlap flags
|
||||
} else
|
||||
u->prxread = pread_local + read_bytes;
|
||||
|
||||
return read_bytes;
|
||||
|
||||
}
|
||||
|
||||
|
||||
int uart_write(uart_socket_t *u, void *pbuf, size_t size)
|
||||
{
|
||||
if(!size || !pbuf || !u){
|
||||
uart_printf("input error,please check!");
|
||||
return -1;
|
||||
}
|
||||
if(rtw_down_sema(&u->tx_sema)){
|
||||
//uart_printf("[%d]:uart_write %d!\n", xTaskGetTickCount(), size);
|
||||
memcpy(u->send_buf, pbuf, size);
|
||||
u->tx_bytes = size;
|
||||
u->tx_start = 1; //set uart tx start
|
||||
rtw_up_sema(&u->action_sema); // let uart_handle_run through
|
||||
} else {
|
||||
uart_printf("uart write buf error!");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void uart_socket_example(void *param)
|
||||
{
|
||||
char tx_data[] = {0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06};
|
||||
uart_set_str uartset;
|
||||
struct timeval tv;
|
||||
fd_set readfds;
|
||||
int read_len = 0, count = 0;
|
||||
int ret = 0;
|
||||
char rxbuf[512];
|
||||
int uart_fd;
|
||||
uart_socket_t *uart_socket = NULL;
|
||||
|
||||
uartset.BaudRate = 9600;
|
||||
uartset.number = 8;
|
||||
uartset.StopBits = 0;
|
||||
uartset.FlowControl = 0;
|
||||
uartset.parity = 0;
|
||||
strcpy(uartset.UartName, "uart0");
|
||||
|
||||
uart_socket = uart_open(&uartset);
|
||||
if(uart_socket == NULL){
|
||||
uart_printf("Init uart socket failed!\n");
|
||||
goto Exit;
|
||||
}
|
||||
uart_fd = uart_socket->fd;
|
||||
uart_printf("\nOpen uart socket: %d\n", uart_fd);
|
||||
while(1)
|
||||
{
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(uart_fd, &readfds);
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 20000;
|
||||
if(count++ == 50){
|
||||
uart_write(uart_socket, tx_data, sizeof(tx_data));
|
||||
//uart_print_data("TX:", tx_data, sizeof(tx_data));
|
||||
count = 0;
|
||||
}
|
||||
ret = select(uart_fd + 1, &readfds, NULL, NULL, &tv);
|
||||
//uart_printf("[%d] select ret = %x count=%d\n", xTaskGetTickCount(), ret, count);
|
||||
if(ret > 0)
|
||||
{
|
||||
if(FD_ISSET(uart_fd, &readfds))
|
||||
{
|
||||
read_len = uart_read(uart_socket, rxbuf, sizeof(rxbuf));
|
||||
if(read_len > 0)
|
||||
{
|
||||
uart_print_data("RX:", rxbuf, read_len);
|
||||
if(rtl_strncmp(rxbuf, "close", 5) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
//else for other sockets
|
||||
}
|
||||
}
|
||||
uart_printf("Exit uart socket example!\n");
|
||||
uart_close(uart_socket);
|
||||
Exit:
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void uart_socket()
|
||||
{
|
||||
#define UART_SOCKET_STACK_SIZE 512
|
||||
#define UART_SOCKET_PRIORITY 1
|
||||
if(xTaskCreate(uart_socket_example, "uart_socket", UART_SOCKET_STACK_SIZE, NULL, UART_SOCKET_PRIORITY, NULL) != pdPASS)
|
||||
uart_printf("%s xTaskCreate failed", __FUNCTION__);
|
||||
}
|
||||
|
||||
55
lib/amb1_sdk/common/utilities/uart_socket.h
Normal file
55
lib/amb1_sdk/common/utilities/uart_socket.h
Normal file
@@ -0,0 +1,55 @@
|
||||
#ifndef __UART_SOCKET_H_
|
||||
#define __UART_SOCKET_H_
|
||||
|
||||
//#include "osdep_api.h"
|
||||
#include "osdep_service.h"
|
||||
|
||||
#include "serial_api.h"
|
||||
#include "serial_ex_api.h"
|
||||
|
||||
#define UART_SEND_BUFFER_LEN 512
|
||||
#define UART_RECV_BUFFER_LEN 1024
|
||||
#define UART_MAX_DELAY_TIME 20
|
||||
|
||||
typedef struct _uart_set_str
|
||||
{
|
||||
char UartName[8]; // the name of uart
|
||||
int BaudRate; //The baud rate
|
||||
char number; //The number of data bits
|
||||
char parity; //The parity(default NONE)
|
||||
char StopBits; //The number of stop bits
|
||||
char FlowControl; //support flow control is 1
|
||||
}uart_set_str;
|
||||
|
||||
typedef struct _uart_socket_t
|
||||
{
|
||||
serial_t sobj;
|
||||
int fd;
|
||||
|
||||
/* Used for UART RX */
|
||||
u32 rx_start;
|
||||
//u32 rx_bytes;
|
||||
u32 prxread;
|
||||
u32 prxwrite;
|
||||
u32 rxoverlap;
|
||||
u32 last_update; //tick count when rx byte
|
||||
u8 recv_buf[UART_RECV_BUFFER_LEN];
|
||||
|
||||
u32 tx_start;
|
||||
u32 tx_bytes;
|
||||
u8 send_buf[UART_SEND_BUFFER_LEN];
|
||||
//_Sema tx_sema;
|
||||
//_Sema dma_tx_sema;
|
||||
_sema tx_sema;
|
||||
_sema dma_tx_sema;
|
||||
|
||||
//_Sema action_sema;
|
||||
_sema action_sema;
|
||||
}uart_socket_t;
|
||||
|
||||
uart_socket_t* uart_open(uart_set_str *puartpara);
|
||||
int uart_close(uart_socket_t *u);
|
||||
int uart_read(uart_socket_t *u, void *read_buf, size_t size);
|
||||
int uart_write(uart_socket_t *u, void *pbuf, size_t size);
|
||||
|
||||
#endif //__UART_SOCKET_H_
|
||||
845
lib/amb1_sdk/common/utilities/uart_ymodem.c
Normal file
845
lib/amb1_sdk/common/utilities/uart_ymodem.c
Normal file
@@ -0,0 +1,845 @@
|
||||
/****************************************uart _ymodem.c**************************************************/
|
||||
|
||||
#include "uart_ymodem.h"
|
||||
#include "osdep_service.h"
|
||||
#include "PinNames.h"
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "semphr.h"
|
||||
|
||||
#if defined(CONFIG_PLATFORM_8711B)
|
||||
extern const update_file_img_id OtaImgId[2];
|
||||
u8 uart_signature[9] = {0};
|
||||
update_ota_target_hdr OtaTargetHdr;
|
||||
static u32 flash_write_len = 0;
|
||||
static u32 flash_offset = 0x0;
|
||||
static u32 file_offset = 0;
|
||||
static u32 IMAGE_OFFSET = 0;
|
||||
static u32 IMAGE_LEN = 0;
|
||||
static int hd_flags = 0;
|
||||
static int sig_flags = 0;
|
||||
static int sig_cnt = 0;
|
||||
#endif
|
||||
/*****************************************************************************************
|
||||
* uart basic functions *
|
||||
******************************************************************************************/
|
||||
void uarty_irq(uint32_t id, SerialIrq event)
|
||||
{
|
||||
uart_ymodem_t *ptr = (uart_ymodem_t *)id;
|
||||
//u8 ch = 0;
|
||||
if(event == RxIrq) {
|
||||
if(ptr->uart_recv_index == 0){
|
||||
//RtlUpSemaFromISR(&ptr->uart_rx_sema);//up uart rx semaphore
|
||||
rtw_up_sema_from_isr(&ptr->uart_rx_sema);//up uart rx semaphore
|
||||
}
|
||||
if(ptr->uart_recv_index == RCV_BUF_SIZE)
|
||||
ptr->uart_recv_index = 0;
|
||||
//ch = serial_getc(&ptr->sobj);
|
||||
// printf("[%d] 0x%x\r\n", ptr->uart_recv_index, ch);
|
||||
ptr->uart_irq_buf[ptr->uart_recv_index++] = serial_getc(&ptr->sobj);
|
||||
ptr->tick_last_update = xTaskGetTickCountFromISR(); // update tick everytime recved data
|
||||
}
|
||||
|
||||
if(event == TxIrq){
|
||||
// uart_send_string(sobj, "\r\n8195a$");
|
||||
// rcv_ch = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void uart_init(uart_ymodem_t *ptr)
|
||||
{
|
||||
// serial_t sobj;
|
||||
|
||||
//uart init
|
||||
serial_init(&ptr->sobj,UART_TX,UART_RX);
|
||||
serial_baud(&ptr->sobj,UART_BAUDRATE); //set baudrate 38400
|
||||
serial_format(&ptr->sobj, 8, ParityNone, 0);
|
||||
|
||||
serial_irq_handler(&ptr->sobj, uarty_irq, (int)ptr);
|
||||
serial_irq_set(&ptr->sobj, RxIrq, 1);
|
||||
serial_irq_set(&ptr->sobj, TxIrq, 1);
|
||||
|
||||
//RtlInitSema(&ptr->uart_rx_sema, 0);
|
||||
rtw_init_sema(&ptr->uart_rx_sema, 0);
|
||||
}
|
||||
void uart_sendbyte(uart_ymodem_t *ptr,u8 sendc )
|
||||
{
|
||||
|
||||
serial_putc(&ptr->sobj, sendc);
|
||||
// printf(" uart send 0x%x\r\n",sendc);
|
||||
}
|
||||
|
||||
int uart_recvbytetimeout(uart_ymodem_t *uart_ymodem,u8 *ptr)
|
||||
{
|
||||
int ret = 0;
|
||||
// static int uart_recv_buf_index = 0;
|
||||
|
||||
// printf(" [%d] = %x\r\n",uart_ymodem->uart_recv_buf_index,uart_ymodem->uart_irq_buf[uart_ymodem->uart_recv_buf_index]);
|
||||
*ptr = uart_ymodem->uart_irq_buf[uart_ymodem->uart_recv_buf_index];
|
||||
uart_ymodem->uart_recv_buf_index++;
|
||||
if(uart_ymodem->uart_recv_buf_index == RCV_BUF_SIZE)
|
||||
uart_ymodem->uart_recv_buf_index = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void uart_rxempty(uart_ymodem_t *ptr)
|
||||
{
|
||||
/*clean uart recv buf*/
|
||||
// printf("Uart_RxEmpty\r\n");
|
||||
memset(ptr->uart_irq_buf, 0, RCV_BUF_SIZE);
|
||||
memset(ptr->uart_rcv_buf, 0, RCV_BUF_SIZE);
|
||||
ptr->uart_recv_buf_index = 0;
|
||||
ptr->uart_recv_index = 0;
|
||||
}
|
||||
/*****************************************************************************************
|
||||
* flash function *
|
||||
******************************************************************************************/
|
||||
int ymodem_flashwrite(int flashadd, u8 *pbuf, int len)
|
||||
{
|
||||
|
||||
int ret = 0;
|
||||
flash_t flash;
|
||||
|
||||
// if(!FLASH_ADDRESS_CHECK_WRITE_ERASE(flashadd)){
|
||||
// ret = -1;
|
||||
// return ret;
|
||||
// }
|
||||
if( len == 0){
|
||||
printf("input error,data length should not be null!\r\n");
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
else //as 8711am only canbe r/w in words.so make len is 4-bytes aligmented.
|
||||
len += 4 - ((len%4)==0 ? 4 : (len%4));
|
||||
|
||||
while(len){
|
||||
if(flash_write_word(&flash, flashadd, *(unsigned int *)pbuf) !=1 ){
|
||||
printf("write flash error!\r\n");
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
len -= 4;
|
||||
pbuf += 4;
|
||||
flashadd += 4;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
/****************************uart_ymodem_init**********************************/
|
||||
void uart_ymodem_init(uart_ymodem_t *uart_ymodem_ptr)
|
||||
{
|
||||
// u32 ret = 0;
|
||||
#if CONFIG_CALC_FILE_SIZE
|
||||
u8 filename[33] = {0}; //file name: max 32 bytes+ '\0'=33
|
||||
#endif
|
||||
//init uart struct
|
||||
uart_ymodem_ptr->cur_num = 0;
|
||||
uart_ymodem_ptr->filelen = 0 ;
|
||||
#if CONFIG_CALC_FILE_SIZE
|
||||
uart_ymodem_ptr->filename = &filename[0];
|
||||
#endif
|
||||
uart_ymodem_ptr->len = 0;
|
||||
uart_ymodem_ptr->nxt_num = 0;
|
||||
uart_ymodem_ptr->modemtype = 2; //ymodem protocol
|
||||
uart_ymodem_ptr->rec_err = 0;
|
||||
uart_ymodem_ptr->crc_mode = 1; //crc check
|
||||
uart_ymodem_ptr->uart_recv_buf_index = 0;
|
||||
uart_ymodem_ptr->uart_recv_index = 0;
|
||||
uart_ymodem_ptr->image_address = IMAGE_TWO;
|
||||
|
||||
#if defined(CONFIG_PLATFORM_8711B)
|
||||
rtw_memset(uart_signature, 0, sizeof(uart_signature));
|
||||
rtw_memset(&OtaTargetHdr, 0, sizeof(OtaTargetHdr));
|
||||
flash_write_len = 0;
|
||||
flash_offset = 0x0;
|
||||
file_offset = 0;
|
||||
IMAGE_OFFSET = 0;
|
||||
IMAGE_LEN = 0;
|
||||
hd_flags = 0;
|
||||
sig_flags = 0;
|
||||
sig_cnt = 0;
|
||||
#endif
|
||||
// return uart_ymodem_ptr;
|
||||
}
|
||||
|
||||
void uart_ymodem_deinit(uart_ymodem_t *ptr)
|
||||
{
|
||||
|
||||
/* Free uart_rx-sema */
|
||||
//RtlFreeSema(&ptr->uart_rx_sema);
|
||||
rtw_free_sema(&ptr->uart_rx_sema);
|
||||
|
||||
/* Free serial */
|
||||
serial_free(&ptr->sobj);
|
||||
|
||||
/* Free uart_ymodem_t */
|
||||
//RtlMfree((u8 *)ptr,sizeof(uart_ymodem_t));
|
||||
rtw_mfree((u8 *)ptr,sizeof(uart_ymodem_t));
|
||||
}
|
||||
|
||||
#if CONFIG_CALC_FILE_SIZE
|
||||
unsigned int buf_filelen(u8 *ptr)
|
||||
{
|
||||
int datatype=10, result=0;
|
||||
|
||||
if (ptr[0]=='0' && (ptr[1]=='x' && ptr[1]=='X'))
|
||||
{
|
||||
datatype = 16;
|
||||
ptr += 2;
|
||||
}
|
||||
|
||||
for ( ; *ptr!='\0'; ptr++)
|
||||
{
|
||||
if (*ptr>= '0' && *ptr<='9')
|
||||
{
|
||||
result =result*datatype+*ptr-'0';
|
||||
}
|
||||
else
|
||||
{
|
||||
if (datatype == 10)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (*ptr>='A' && *ptr<='F')
|
||||
{
|
||||
result = result*16 + *ptr-55; //55 = 'A'-10
|
||||
}
|
||||
else if (*ptr>='a' && *ptr<='f')
|
||||
{
|
||||
result = result*16 + *ptr-87; //87 = 'a'-10
|
||||
}
|
||||
else
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
void modem_cancle(uart_ymodem_t *ptr)
|
||||
{
|
||||
uart_sendbyte(ptr,0x18);
|
||||
uart_sendbyte(ptr,0x18);
|
||||
uart_sendbyte(ptr,0x18);
|
||||
uart_sendbyte(ptr,0x18);
|
||||
uart_sendbyte(ptr,0x18);
|
||||
}
|
||||
|
||||
int start_next_round(uart_ymodem_t *ptr)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
// printf(" uart ymodedm transfer %d block\r\n",ptr->nxt_num);
|
||||
//clean recv buf
|
||||
if(!ptr->rec_err){
|
||||
uart_rxempty(ptr);
|
||||
}
|
||||
else{
|
||||
ret = -1;
|
||||
printf("\r\n recv data error!");
|
||||
}
|
||||
|
||||
if (ptr->nxt_num == 0)
|
||||
{
|
||||
if (ptr->crc_mode)
|
||||
{
|
||||
uart_sendbyte(ptr,MODEM_C); //first receiver send c
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_sendbyte(ptr,MODEM_NAK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ptr->rec_err)
|
||||
{
|
||||
uart_sendbyte(ptr,MODEM_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ptr->nxt_num == 1)
|
||||
{
|
||||
if (ptr->crc_mode)
|
||||
{
|
||||
uart_sendbyte(ptr,MODEM_ACK);
|
||||
uart_sendbyte(ptr,MODEM_C);
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_sendbyte(ptr,MODEM_NAK);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_sendbyte(ptr,MODEM_ACK);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
int block_num_check(uart_ymodem_t *ptr)
|
||||
{
|
||||
|
||||
u8 blk,cblk;
|
||||
int stat, ret = 0;
|
||||
/**************** check blk and blk complement *********************/
|
||||
stat = uart_recvbytetimeout(ptr,&blk); //blk num,bytes 2
|
||||
if (stat != 0)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
printf(" blk num = %x\r\n", blk);
|
||||
|
||||
stat = uart_recvbytetimeout(ptr,&cblk); //block num complement,bytes 3
|
||||
if (stat != 0)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
// printf(" block num cmpl = %x\r\n",cblk);
|
||||
|
||||
if (blk+cblk != 0xff)
|
||||
{
|
||||
ret = -1;
|
||||
}
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
int calc_file_name_size(uart_ymodem_t *ptr,u8* bufptr)
|
||||
{
|
||||
int ret = 0;
|
||||
u8* nameptr = ptr->filename;
|
||||
|
||||
while (*bufptr != '\0'){
|
||||
*nameptr++ = *bufptr++;
|
||||
}
|
||||
*nameptr = '\0';
|
||||
bufptr++;
|
||||
while (*bufptr == ' ')
|
||||
{
|
||||
bufptr++;
|
||||
}
|
||||
//file length
|
||||
ptr->filelen = buf_filelen(bufptr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int crc_check(uart_ymodem_t *ptr)
|
||||
{
|
||||
u8 crch, crcl;
|
||||
u8 *in_ptr;
|
||||
int stat,i,ret = 0;
|
||||
u32 cksum = 0;
|
||||
|
||||
stat = uart_recvbytetimeout(ptr,&crch); //CRC byte 1
|
||||
if (stat != 0){
|
||||
ret = 1;
|
||||
}
|
||||
// printf(" char recved CRC byte 1 = %x\r\n", crch);
|
||||
if (ptr->crc_mode){
|
||||
stat = uart_recvbytetimeout(ptr,&crcl); //CRC byte 2
|
||||
if (stat != 0){
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
// printf(" char recved CRC byte 2 = %x\r\n", crcl);
|
||||
#if CRC_CHECK
|
||||
for (i=0; i<ptr->len; i++) //sum check for last block
|
||||
{
|
||||
cksum += ptr->uart_rcv_buf[i];
|
||||
}
|
||||
if(cksum == 0)
|
||||
{
|
||||
ret = 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (ptr->crc_mode)
|
||||
{
|
||||
in_ptr = ptr->uart_rcv_buf;
|
||||
cksum = 0;
|
||||
|
||||
for (stat=ptr->len ; stat>0; stat--)
|
||||
{
|
||||
cksum = cksum^(int)(*in_ptr++) << 8;
|
||||
for (i=8; i !=0; i--)
|
||||
{
|
||||
if (cksum & 0x8000)
|
||||
cksum = cksum << 1 ^ 0x1021;
|
||||
else
|
||||
cksum = cksum << 1;
|
||||
}
|
||||
|
||||
}
|
||||
cksum &= 0xffff;
|
||||
|
||||
if (cksum != (crch<<8 | crcl))
|
||||
{
|
||||
ptr->rec_err = 1;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i=0; i<ptr->len; i++) //sum check
|
||||
{
|
||||
cksum += ptr->uart_rcv_buf[i];
|
||||
}
|
||||
if ((cksum&0xff)!=crch)
|
||||
{
|
||||
ptr->rec_err = 1;
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
|
||||
}
|
||||
#if DUMP_DATA
|
||||
void flash_dump_data(uart_ymodem_t *ptr)
|
||||
{
|
||||
int i,offset = 0;
|
||||
u32 data;
|
||||
printf("flash dump data");
|
||||
for(i = 0;i< ptr->filelen;i+=4){
|
||||
flash_read_word(&ptr->flash, ptr->image_address + 0x10 + offset, &data);
|
||||
offset += 4;
|
||||
printf("%x ",data);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_PLATFORM_8711B)
|
||||
int data_write_to_flash(uart_ymodem_t *ptr)
|
||||
{
|
||||
int ret = 0;
|
||||
u8 *pImgId = NULL;
|
||||
u32 buf_offset = 0;
|
||||
u32 write_len = 0;
|
||||
uint32_t uart_ota_target_index = OTA_INDEX_2;
|
||||
|
||||
if(!hd_flags){
|
||||
/* check OTA index we should update */
|
||||
if (ota_get_cur_index() == OTA_INDEX_1) {
|
||||
uart_ota_target_index = OTA_INDEX_2;
|
||||
printf("OTA2 address space will be upgraded\n");
|
||||
} else {
|
||||
uart_ota_target_index = OTA_INDEX_1;
|
||||
printf("OTA1 address space will be upgraded\n");
|
||||
}
|
||||
pImgId = (u8 *)&OtaImgId[uart_ota_target_index];
|
||||
|
||||
/* -----step3: parse firmware file header and get the target OTA image header-----*/
|
||||
/* parse firmware file header and get the target OTA image header-----*/
|
||||
if(!get_ota_tartget_header(ptr->uart_rcv_buf, ptr->len, &OtaTargetHdr, pImgId)){
|
||||
printf("\n\rget OTA header failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*get new image addr and check new address validity*/
|
||||
if(!get_ota_address(uart_ota_target_index, &ptr->image_address, &OtaTargetHdr)){
|
||||
printf("\n\rget OTA address failed\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*get new image length from the firmware header*/
|
||||
IMAGE_LEN = OtaTargetHdr.FileImgHdr.ImgLen;
|
||||
|
||||
/*-------------------step4: erase flash space for new firmware--------------*/
|
||||
/*erase flash space new OTA image */
|
||||
erase_ota_target_flash(ptr->image_address, IMAGE_LEN);
|
||||
/*erase flash space for new RDP image*/
|
||||
if(OtaTargetHdr.RdpStatus == ENABLE) {
|
||||
device_mutex_lock(RT_DEV_LOCK_FLASH);
|
||||
flash_erase_sector(&ptr->flash, RDP_FLASH_ADDR - SPI_FLASH_BASE);
|
||||
device_mutex_unlock(RT_DEV_LOCK_FLASH);
|
||||
}
|
||||
|
||||
IMAGE_OFFSET = OtaTargetHdr.FileImgHdr.Offset;
|
||||
hd_flags = 1;
|
||||
}
|
||||
//printf("\n\r file_offset = %d ptr->len = %d", file_offset, ptr->len);
|
||||
|
||||
/*---------step5: download new firmware from server and write it to flash--------*/
|
||||
if(IMAGE_OFFSET >= file_offset && IMAGE_OFFSET < file_offset + ptr->len){
|
||||
buf_offset = IMAGE_OFFSET - file_offset;
|
||||
write_len = ptr->len - buf_offset;
|
||||
file_offset += ptr->len;
|
||||
if(!sig_flags){
|
||||
if(write_len < 8){
|
||||
sig_cnt = write_len;
|
||||
}else{
|
||||
sig_cnt = 8;
|
||||
sig_flags = 1;
|
||||
}
|
||||
_memcpy(uart_signature, ptr->uart_rcv_buf + buf_offset, sig_cnt);
|
||||
buf_offset += sig_cnt;
|
||||
flash_offset += sig_cnt;
|
||||
write_len -= sig_cnt;
|
||||
if(!write_len)
|
||||
return ret;
|
||||
}
|
||||
}else if(IMAGE_OFFSET < file_offset && IMAGE_OFFSET + IMAGE_LEN >= file_offset + ptr->len){
|
||||
buf_offset = 0;
|
||||
write_len = ptr->len;
|
||||
file_offset += ptr->len;
|
||||
if(!sig_flags){
|
||||
_memcpy(uart_signature + sig_cnt, ptr->uart_rcv_buf + buf_offset, 8 - sig_cnt);
|
||||
sig_cnt = 8 - sig_cnt;
|
||||
buf_offset += sig_cnt;
|
||||
flash_offset += sig_cnt;
|
||||
write_len -= sig_cnt;
|
||||
sig_flags = 1;
|
||||
}
|
||||
}else if(IMAGE_OFFSET + IMAGE_LEN > file_offset && IMAGE_OFFSET + IMAGE_LEN < file_offset + ptr->len){
|
||||
buf_offset = 0;
|
||||
write_len = IMAGE_OFFSET + IMAGE_LEN - file_offset;
|
||||
file_offset += ptr->len;
|
||||
}else{
|
||||
file_offset += ptr->len;
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_mutex_lock(RT_DEV_LOCK_FLASH);
|
||||
if(flash_stream_write(&ptr->flash, ptr->image_address + flash_offset - SPI_FLASH_BASE, write_len, ptr->uart_rcv_buf + buf_offset) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
device_mutex_unlock(RT_DEV_LOCK_FLASH);
|
||||
return 1;
|
||||
}
|
||||
device_mutex_unlock(RT_DEV_LOCK_FLASH);
|
||||
flash_offset += write_len;
|
||||
flash_write_len += write_len;
|
||||
return ret;
|
||||
}
|
||||
int set_signature(uart_ymodem_t *ptr)
|
||||
{
|
||||
int ret = 1 ;
|
||||
uint32_t uart_ota_target_index = OTA_INDEX_2;
|
||||
|
||||
if(ptr->image_address == OTA1_ADDR)
|
||||
uart_ota_target_index = OTA_INDEX_1;
|
||||
else
|
||||
uart_ota_target_index = OTA_INDEX_2;
|
||||
|
||||
if((flash_write_len <= 0) || (flash_write_len != (OtaTargetHdr.FileImgHdr.ImgLen - 8))) {
|
||||
printf("\n\rdownload new firmware failed\n");
|
||||
return 1;
|
||||
}
|
||||
printf("\n\r[%s] %s\n", __FUNCTION__, uart_signature);
|
||||
/*-------------step6: verify checksum and update signature-----------------*/
|
||||
if(verify_ota_checksum(ptr->image_address, flash_write_len, uart_signature, &OtaTargetHdr)){
|
||||
if(!change_ota_signature(ptr->image_address, uart_signature, uart_ota_target_index)) {
|
||||
printf("\n%s: change signature failed\n", __FUNCTION__);
|
||||
return 1;
|
||||
}
|
||||
ret = 0;
|
||||
} else {
|
||||
/*if checksum error, clear the signature zone which has been
|
||||
written in flash in case of boot from the wrong firmware*/
|
||||
#if 1
|
||||
device_mutex_lock(RT_DEV_LOCK_FLASH);
|
||||
flash_erase_sector(&ptr->flash, ptr->image_address - SPI_FLASH_BASE);
|
||||
device_mutex_unlock(RT_DEV_LOCK_FLASH);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
int data_write_to_flash(uart_ymodem_t *ptr)
|
||||
{
|
||||
int ret = 0;
|
||||
// uint32_t update_image_address = IMAGE_TWO;
|
||||
static int offset = 0x0;
|
||||
u32 data;
|
||||
static int flags = 1; //write update image header only once
|
||||
// int file_blk_size = 0
|
||||
|
||||
flash_read_word(&ptr->flash, OFFSET_DATA, &data);
|
||||
// file_blk_size = ((ptr->filelen - 1)/4096) + 1;
|
||||
if(data == ~0x0){
|
||||
flash_write_word(&ptr->flash, OFFSET_DATA, ptr->image_address);
|
||||
}
|
||||
// printf("image_address get from flash = 0x%x\n\r",ptr->image_address);
|
||||
//erase flash where to be written,since ymodem blk size can be 128 or 1024,so, erase once when gather 4096
|
||||
if(offset ==0 || (offset % 4096)==0){
|
||||
flash_erase_sector(&ptr->flash, ptr->image_address + offset);
|
||||
}
|
||||
//write to flash
|
||||
//write back image size and address
|
||||
if(!flags){
|
||||
flash_write_word(&ptr->flash, ptr->image_address, ptr->filelen);
|
||||
flash_write_word(&ptr->flash, ptr->image_address+4,0x10004000);
|
||||
flags = 1;
|
||||
}
|
||||
// ymodem_flashwrite(update_image_address + offset, ptr->uart_rcv_buf, ptr->len);
|
||||
device_mutex_lock(RT_DEV_LOCK_FLASH);
|
||||
flash_stream_write(&ptr->flash, ptr->image_address+offset, ptr->len, ptr->uart_rcv_buf);
|
||||
device_mutex_unlock(RT_DEV_LOCK_FLASH);
|
||||
offset += ptr->len;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int set_signature(uart_ymodem_t *ptr)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t sig_readback0,sig_readback1;
|
||||
uint32_t oldimg2addr;
|
||||
|
||||
//old image address
|
||||
flash_read_word(&ptr->flash, 0x18, &oldimg2addr);
|
||||
oldimg2addr = (oldimg2addr&0xFFFF)*1024;
|
||||
printf(" lod image address 0x%x\n\r",oldimg2addr);
|
||||
//Set signature in New Image 2 addr + 8 and + 12
|
||||
// flash_write_word(&ptr->flash,ptr->image_address + 8, 0x35393138);//0x35393138
|
||||
// flash_write_word(&ptr->flash,ptr->image_address + 12, 0x31313738);
|
||||
// flash_read_word(&ptr->flash, ptr->image_address + 8, &sig_readback0);
|
||||
// flash_read_word(&ptr->flash, ptr->image_address + 12, &sig_readback1);
|
||||
// printf(" new signature %x,%x,\n\r",sig_readback0, sig_readback1);
|
||||
#if 1
|
||||
flash_write_word(&ptr->flash,oldimg2addr + 8, 0x35393130);
|
||||
flash_write_word(&ptr->flash,oldimg2addr + 12, 0x31313738);
|
||||
flash_read_word(&ptr->flash, oldimg2addr + 8, &sig_readback0);
|
||||
flash_read_word(&ptr->flash, oldimg2addr + 12, &sig_readback1);
|
||||
printf(" old signature %x,%x\n\r",sig_readback0, sig_readback1);
|
||||
#endif
|
||||
printf(" set signature success!\n\r");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if AUTO_REBOOT
|
||||
void auto_reboot(void)
|
||||
{
|
||||
#if defined(CONFIG_PLATFORM_8711B)
|
||||
//wifi_off();
|
||||
|
||||
/* Set processor clock to default before system reset */
|
||||
//HAL_WRITE32(SYSTEM_CTRL_BASE, REG_SYS_CLK_CTRL1, 0x00000021);
|
||||
CPU_ClkSet(CLK_31_25M);
|
||||
osDelay(100);
|
||||
|
||||
/* CPU reset: Cortex-M3 SCB->AIRCR*/
|
||||
NVIC_SystemReset();
|
||||
#else
|
||||
// Set processor clock to default before system reset
|
||||
HAL_WRITE32(SYSTEM_CTRL_BASE, 0x14, 0x00000021);
|
||||
osDelay(100);
|
||||
|
||||
// Cortex-M3 SCB->AIRCR
|
||||
HAL_WRITE32(0xE000ED00, 0x0C, (0x5FA << 16) | // VECTKEY
|
||||
(HAL_READ32(0xE000ED00, 0x0C) & (7 << 8)) | // PRIGROUP
|
||||
(1 << 2)); // SYSRESETREQ
|
||||
while(1) osDelay(1000);
|
||||
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static void uart_ymodem_thread(void* param)
|
||||
{
|
||||
u8 ch;
|
||||
u32 stat, error_bit = 0, transfer_over = 0;
|
||||
u32 can_counter = 0, eot_counter = 0;
|
||||
u32 i, send_count = 0 , ret = 0;
|
||||
static int first_time = 1;
|
||||
uart_ymodem_t *ymodem_ptr = (uart_ymodem_t *)param;
|
||||
printf(" ==>uart ymodem_task\r\n");
|
||||
while(1)
|
||||
{
|
||||
//wait 2min,2*60*1000/100
|
||||
if(send_count >= (2*60*10)){
|
||||
error_bit = 6;
|
||||
printf("no response after 2min\r\n");
|
||||
goto exit;
|
||||
}
|
||||
else{
|
||||
if (ymodem_ptr->crc_mode){
|
||||
uart_sendbyte(ymodem_ptr,MODEM_C); //first receiver send c
|
||||
}
|
||||
else{
|
||||
uart_sendbyte(ymodem_ptr,MODEM_NAK);
|
||||
}
|
||||
send_count++;
|
||||
}
|
||||
if(xSemaphoreTake(ymodem_ptr->uart_rx_sema, 0) == pdTRUE){
|
||||
//RtlUpSema(&ymodem_ptr->uart_rx_sema);
|
||||
rtw_up_sema(&ymodem_ptr->uart_rx_sema);
|
||||
break;
|
||||
}
|
||||
else
|
||||
// send every 100ms
|
||||
vTaskDelay(100);
|
||||
}
|
||||
start:
|
||||
while(xSemaphoreTake(ymodem_ptr->uart_rx_sema, portMAX_DELAY) == pdTRUE){
|
||||
// ymodem_ptr->tick_current = ymodem_ptr->tick_last_update = xTaskGetTickCount();
|
||||
ymodem_ptr->tick_current = xTaskGetTickCount();
|
||||
while((int)(ymodem_ptr->tick_current - ymodem_ptr->tick_last_update) < 50 ){
|
||||
ymodem_ptr->tick_current = xTaskGetTickCount();
|
||||
vTaskDelay(5);
|
||||
}
|
||||
printf("uart_recv_index = %d current=%d last=%d\r\n",ymodem_ptr->uart_recv_index, ymodem_ptr->tick_current, ymodem_ptr->tick_last_update);
|
||||
/*uart data recv done and process what we have recvied*/
|
||||
stat = uart_recvbytetimeout(ymodem_ptr,&ch);
|
||||
if (stat == 0)
|
||||
{
|
||||
switch (ch)
|
||||
{
|
||||
case MODEM_SOH :
|
||||
ymodem_ptr->len = 128;
|
||||
// printf(" char recved was MODEM_SOH!\r\n");
|
||||
break;
|
||||
case MODEM_STX :
|
||||
ymodem_ptr->len = 1024;
|
||||
// printf(" char recved was MODEM_STX!\r\n");
|
||||
break;
|
||||
case MODEM_CAN :
|
||||
if ((++can_counter) >= MODEM_CAN_COUNT)
|
||||
{
|
||||
error_bit = 1;
|
||||
goto exit;
|
||||
}
|
||||
// printf(" char recved was MODEM_CAN!\r\n");
|
||||
break;
|
||||
case MODEM_EOT :
|
||||
// printf(" char recved was MODEM_EOT!\r\n");
|
||||
if ((++eot_counter) >= MODEM_EOT_COUNT)
|
||||
{
|
||||
uart_sendbyte(ymodem_ptr,MODEM_ACK);
|
||||
if (ymodem_ptr->modemtype == 2) //Ymodem protocol
|
||||
{
|
||||
uart_sendbyte(ymodem_ptr,MODEM_C); //first send a C
|
||||
uart_sendbyte(ymodem_ptr,MODEM_ACK); //then send ack
|
||||
uart_sendbyte(ymodem_ptr,MODEM_C); // and then send c
|
||||
modem_cancle(ymodem_ptr); //cancel the transits
|
||||
}
|
||||
transfer_over = 1;
|
||||
goto exit;
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_sendbyte(ymodem_ptr,MODEM_ACK);
|
||||
uart_sendbyte(ymodem_ptr,MODEM_C);
|
||||
goto start;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
error_bit = 1;
|
||||
goto exit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//block num check
|
||||
if(block_num_check(ymodem_ptr)){
|
||||
error_bit = 2;
|
||||
goto exit;
|
||||
}
|
||||
#if CONFIG_CALC_FILE_SIZE
|
||||
// calculate file name and file size
|
||||
if(ymodem_ptr->nxt_num == 0 && first_time){
|
||||
error_bit = calc_file_name_size(ymodem_ptr,&ymodem_ptr->uart_irq_buf[3]);
|
||||
// first_time = 0;
|
||||
}
|
||||
#endif
|
||||
//copy data from uart irq buf to uart recv buf without header
|
||||
for (i=0; i<ymodem_ptr->len; i++)
|
||||
{
|
||||
stat = uart_recvbytetimeout(ymodem_ptr,&ymodem_ptr->uart_rcv_buf[i]);
|
||||
// printf(" data recv[%d] =%x\r\n",i,ymodem_ptr->uart_rcv_buf[i]);
|
||||
}
|
||||
//write data to flash,but do not write first block data
|
||||
if(ymodem_ptr->nxt_num != 0 || !first_time){
|
||||
if(data_write_to_flash(ymodem_ptr)){
|
||||
error_bit = 3;
|
||||
goto exit;
|
||||
}
|
||||
first_time = 0;
|
||||
}
|
||||
//crc check
|
||||
ret = crc_check(ymodem_ptr);
|
||||
if(ret == 1){
|
||||
error_bit = 4;
|
||||
goto exit;
|
||||
}
|
||||
else if(ret == 2 && ymodem_ptr->nxt_num == 0xff){
|
||||
printf(" next num = %x\r\n",ymodem_ptr->nxt_num);
|
||||
transfer_over = 1;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
#if 0 //avoid skip block
|
||||
uart_ymodem->cur_num = blk;
|
||||
if (blk != uart_ymodem->nxt_num)
|
||||
{
|
||||
error_bit = -1;
|
||||
}
|
||||
#endif
|
||||
ymodem_ptr->nxt_num++;
|
||||
ymodem_ptr->rec_err=0;
|
||||
//start another round
|
||||
if(start_next_round(ymodem_ptr)){
|
||||
error_bit = 5;
|
||||
printf(" start next round failed!\r\n");
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
exit:
|
||||
//if anything goes wrong or transfer over,we kill ourself.
|
||||
if(error_bit || transfer_over){
|
||||
if(error_bit)
|
||||
printf("error!!! error bit = %d\r\n",error_bit);
|
||||
else{
|
||||
printf(" [%s, %d Bytes] transfer_over!\r\n",ymodem_ptr->filename,ymodem_ptr->filelen);
|
||||
ret = set_signature(ymodem_ptr);
|
||||
#if DUMP_DATA
|
||||
flash_dump_data(ymodem_ptr);
|
||||
#endif
|
||||
#if AUTO_REBOOT
|
||||
if(!ret){
|
||||
printf("\n\r[%s] Ready to reboot\r\n", __FUNCTION__);
|
||||
auto_reboot();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
first_time = 1;
|
||||
uart_ymodem_deinit(ymodem_ptr);
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
int uart_ymodem(void)
|
||||
{
|
||||
int ret = 0;
|
||||
uart_ymodem_t *uart_ymodem_ptr;
|
||||
|
||||
printf("uart ymodem update start\r\n");
|
||||
//uart_ymodem_ptr = (uart_ymodem_t *)RtlMalloc(sizeof(uart_ymodem_t));
|
||||
uart_ymodem_ptr = (uart_ymodem_t *)rtw_malloc(sizeof(uart_ymodem_t));
|
||||
if(!uart_ymodem_ptr){
|
||||
printf("uart ymodem malloc fail!\r\n");
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
uart_ymodem_init(uart_ymodem_ptr);
|
||||
if(ret == -1){
|
||||
ret = -1;
|
||||
return ret;
|
||||
}
|
||||
//uart initial
|
||||
uart_init(uart_ymodem_ptr);
|
||||
if(xTaskCreate(uart_ymodem_thread, ((const char*)"uart_ymodem_thread"), UART_YMODEM_TASK_DEPTH, uart_ymodem_ptr, UART_YMODEM_TASK_PRIORITY, NULL) != pdPASS)
|
||||
printf("%s xTaskCreate(uart_thread) failed\r\n", __FUNCTION__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
94
lib/amb1_sdk/common/utilities/uart_ymodem.h
Normal file
94
lib/amb1_sdk/common/utilities/uart_ymodem.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/****************************************uart_ymodem.h**************************************************/
|
||||
|
||||
#ifndef __YMODEM_H_
|
||||
#define __YMODEM_H_
|
||||
|
||||
//#include "osdep_api.h"
|
||||
#include "osdep_service.h"
|
||||
#include "serial_api.h"
|
||||
#include "flash_api.h"
|
||||
#include "device_lock.h"
|
||||
/***********************************************************************
|
||||
* Macros *
|
||||
***********************************************************************/
|
||||
#if defined(CONFIG_PLATFORM_8711B)
|
||||
// 8710B
|
||||
#define UART_TX PA_23
|
||||
#define UART_RX PA_18
|
||||
#else
|
||||
// 8711AM
|
||||
#define UART_TX PA_7
|
||||
#define UART_RX PA_6
|
||||
//8711AF
|
||||
//#define UART_TX PA_4
|
||||
//#define UART_RX PA_0
|
||||
#endif
|
||||
|
||||
#define UART_BAUDRATE 115200
|
||||
#define UART_YMODEM_TASK_PRIORITY 5
|
||||
#define UART_YMODEM_TASK_DEPTH 512
|
||||
|
||||
#define CONFIG_CALC_FILE_SIZE 1
|
||||
#define CRC_CHECK 1
|
||||
#define AUTO_REBOOT 0
|
||||
#define DUMP_DATA 0
|
||||
|
||||
#define OFFSET_DATA FLASH_SYSTEM_DATA_ADDR
|
||||
#define IMAGE_TWO (0x80000)
|
||||
//Y-modem related
|
||||
#define MODEM_MAX_RETRIES 1
|
||||
#define MODEM_CRC_RETRIES 51
|
||||
#define MODEM_CAN_COUNT 3
|
||||
#define MODEM_EOT_COUNT 1
|
||||
|
||||
// ymodem protocol definition
|
||||
#define MODEM_SOH 0x01
|
||||
#define MODEM_STX 0x02
|
||||
#define MODEM_EOT 0x04
|
||||
#define MODEM_ACK 0x06
|
||||
#define MODEM_NAK 0x15
|
||||
#define MODEM_CAN 0x18
|
||||
#define MODEM_C 0x43
|
||||
// 1 block size byte + 2 block number bytes + 1024 data body + 2 crc bytes
|
||||
#define RCV_BUF_SIZE ((1)+(2)+(1024)+(2))
|
||||
/******************************** data struct **********************************/
|
||||
typedef struct _uart_ymodem_t
|
||||
{
|
||||
serial_t sobj;
|
||||
flash_t flash;
|
||||
|
||||
/* Used for UART RX */
|
||||
u8 uart_rcv_buf[RCV_BUF_SIZE];
|
||||
u8 uart_irq_buf[RCV_BUF_SIZE];
|
||||
//_Sema uart_rx_sema;
|
||||
_sema uart_rx_sema;
|
||||
u32 image_address;
|
||||
|
||||
u32 tick_last_update;
|
||||
u32 tick_current;
|
||||
u32 uart_recv_index;
|
||||
u32 uart_recv_buf_index;
|
||||
/* uart ymodem related*/
|
||||
u32 modemtype;
|
||||
u32 crc_mode;
|
||||
u32 nxt_num; //next block num
|
||||
u32 cur_num; //current block num
|
||||
u32 len;
|
||||
u32 rec_err; //blcok data recv status
|
||||
u32 filelen; //Ymodem file length
|
||||
u8 *buf; //data buf
|
||||
u8 *filename; //file name
|
||||
}uart_ymodem_t;
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"{
|
||||
#endif
|
||||
|
||||
extern int uart_ymodem(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
92
lib/amb1_sdk/common/utilities/udpecho.c
Normal file
92
lib/amb1_sdk/common/utilities/udpecho.c
Normal file
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Adam Dunkels <adam@sics.se>
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "lwip/opt.h"
|
||||
|
||||
#if LWIP_NETCONN
|
||||
|
||||
#include "lwip/api.h"
|
||||
#include "lwip/sys.h"
|
||||
|
||||
|
||||
#define UDPECHO_THREAD_PRIO ( tskIDLE_PRIORITY + 3 )
|
||||
|
||||
static struct netconn *conn;
|
||||
static struct netbuf *buf;
|
||||
static struct ip_addr *addr;
|
||||
static unsigned short port;
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
static void udpecho_thread(void *arg)
|
||||
{
|
||||
err_t err;
|
||||
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
|
||||
conn = netconn_new(NETCONN_UDP);
|
||||
if (conn!= NULL)
|
||||
{
|
||||
err = netconn_bind(conn, IP_ADDR_ANY, 7);
|
||||
if (err == ERR_OK)
|
||||
{
|
||||
while (1)
|
||||
{
|
||||
buf = netconn_recv(conn);
|
||||
|
||||
if (buf!= NULL)
|
||||
{
|
||||
addr = netbuf_fromaddr(buf);
|
||||
port = netbuf_fromport(buf);
|
||||
netconn_connect(conn, addr, port);
|
||||
buf->addr = NULL;
|
||||
netconn_send(conn,buf);
|
||||
netbuf_delete(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("can not bind netconn");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("can create new UDP netconn");
|
||||
}
|
||||
}
|
||||
/*-----------------------------------------------------------------------------------*/
|
||||
void udpecho_init(void)
|
||||
{
|
||||
sys_thread_new("udpecho_thread", udpecho_thread, NULL, DEFAULT_THREAD_STACKSIZE,UDPECHO_THREAD_PRIO );
|
||||
}
|
||||
|
||||
#endif /* LWIP_NETCONN */
|
||||
7
lib/amb1_sdk/common/utilities/update.c
Normal file
7
lib/amb1_sdk/common/utilities/update.c
Normal file
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
|
||||
The code in this file has been moved to the following file:
|
||||
"soc\realtek\8195a\misc\platform\ota_8195a.c".
|
||||
Please use new file "ota_8195a.c" to replace the previous "update.c" file.
|
||||
|
||||
*/
|
||||
11
lib/amb1_sdk/common/utilities/update.h
Normal file
11
lib/amb1_sdk/common/utilities/update.h
Normal file
@@ -0,0 +1,11 @@
|
||||
#ifndef UPDATE_H
|
||||
#define UPDATE_H
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
int update_ota_local(char *ip, int port);
|
||||
int update_ota_cloud(char *repository, char *file_path);
|
||||
void cmd_update(int argc, char **argv);
|
||||
void cmd_ota_image(bool cmd);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#endif
|
||||
1376
lib/amb1_sdk/common/utilities/xml.c
Normal file
1376
lib/amb1_sdk/common/utilities/xml.c
Normal file
File diff suppressed because it is too large
Load Diff
43
lib/amb1_sdk/common/utilities/xml.h
Normal file
43
lib/amb1_sdk/common/utilities/xml.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef _XML_H_
|
||||
#define _XML_H_
|
||||
|
||||
struct xml_node {
|
||||
char *name;
|
||||
char *text;
|
||||
char *prefix;
|
||||
char *uri;
|
||||
char *attr;
|
||||
struct xml_node *parent;
|
||||
struct xml_node *child;
|
||||
struct xml_node *prev;
|
||||
struct xml_node *next;
|
||||
};
|
||||
|
||||
struct xml_node_set {
|
||||
int count;
|
||||
struct xml_node **node;
|
||||
};
|
||||
|
||||
void xml_free(void *buf);
|
||||
int xml_doc_name(char *doc_buf, int doc_len, char **doc_prefix, char **doc_name, char **doc_uri);
|
||||
struct xml_node *xml_parse_doc(char *doc_buf, int doc_len, char *prefix, char *doc_name, char *uri);
|
||||
struct xml_node *xml_parse(char *doc_buf, int doc_len);
|
||||
struct xml_node *xml_new_element(char *prefix, char *name, char *uri);
|
||||
struct xml_node *xml_new_text(char *text);
|
||||
int xml_is_element(struct xml_node *node);
|
||||
int xml_is_text(struct xml_node *node);
|
||||
struct xml_node* xml_copy_tree(struct xml_node *root);
|
||||
void xml_delete_tree(struct xml_node *root);
|
||||
void xml_add_child(struct xml_node *node, struct xml_node *child);
|
||||
void xml_clear_child(struct xml_node *node);
|
||||
struct xml_node* xml_text_child(struct xml_node *node);
|
||||
void xml_set_text(struct xml_node *node, char *text);
|
||||
struct xml_node_set* xml_find_element(struct xml_node *root, char *name);
|
||||
struct xml_node_set* xml_find_path(struct xml_node *root, char *path);
|
||||
void xml_delete_set(struct xml_node_set *node_set);
|
||||
char *xml_dump_tree(struct xml_node *root);
|
||||
char *xml_dump_tree_ex(struct xml_node *root, char *prolog, int new_line, int space);
|
||||
void xml_set_attribute(struct xml_node *node, char *attr, char *value);
|
||||
char *xml_get_attribute(struct xml_node *node, char *attr);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user