mirror of
https://github.com/ghsecuritylab/ameba_ws2812b.git
synced 2026-04-05 21:15:21 +00:00
first commit
This commit is contained in:
parent
48de61fed7
commit
28cd8da44d
1181 changed files with 784669 additions and 0 deletions
596
component/common/utilities/cJSON.c
Normal file
596
component/common/utilities/cJSON.c
Normal file
|
|
@ -0,0 +1,596 @@
|
|||
/*
|
||||
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;}
|
||||
|
||||
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. */
|
||||
static 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
component/common/utilities/cJSON.h
Normal file
145
component/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
|
||||
283
component/common/utilities/ssl_client.c
Normal file
283
component/common/utilities/ssl_client.c
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "polarssl/config.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.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_USE_SRP 0
|
||||
#define STACKSIZE 1150
|
||||
|
||||
static int is_task = 0;
|
||||
char server_host[16];
|
||||
#if SSL_USE_SRP
|
||||
char srp_username[16];
|
||||
char srp_password[16];
|
||||
#endif
|
||||
|
||||
static void my_debug(void *ctx, int level, const char *str)
|
||||
{
|
||||
if(level <= DEBUG_LEVEL) {
|
||||
printf("\n\r%s", str);
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned int arc4random(void)
|
||||
{
|
||||
unsigned int res = xTaskGetTickCount();
|
||||
static unsigned int seed = 0xDEADB00B;
|
||||
|
||||
seed = ((seed & 0x007F00FF) << 7) ^
|
||||
((seed & 0x0F80FF00) >> 8) ^ // be sure to stir those low bits
|
||||
(res << 13) ^ (res >> 9); // using the clock too!
|
||||
|
||||
return seed;
|
||||
}
|
||||
|
||||
static void get_random_bytes(void *buf, size_t len)
|
||||
{
|
||||
unsigned int ranbuf;
|
||||
unsigned int *lp;
|
||||
int i, count;
|
||||
count = len / sizeof(unsigned int);
|
||||
lp = (unsigned int *) buf;
|
||||
|
||||
for(i = 0; i < count; i ++) {
|
||||
lp[i] = arc4random();
|
||||
len -= sizeof(unsigned int);
|
||||
}
|
||||
|
||||
if(len > 0) {
|
||||
ranbuf = arc4random();
|
||||
memcpy(&lp[i], &ranbuf, len);
|
||||
}
|
||||
}
|
||||
|
||||
static int my_random(void *p_rng, unsigned char *output, size_t output_len)
|
||||
{
|
||||
get_random_bytes(output, output_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef POLARSSL_MEMORY_C
|
||||
static size_t min_heap_size = 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
|
||||
|
||||
#endif
|
||||
|
||||
static void ssl_client(void *param)
|
||||
{
|
||||
int ret, len, server_fd = -1;
|
||||
unsigned char buf[512];
|
||||
ssl_context ssl;
|
||||
|
||||
#ifdef POLARSSL_MEMORY_C
|
||||
memory_set_own(my_malloc, my_free);
|
||||
#endif
|
||||
/*
|
||||
* 0. Initialize the session data
|
||||
*/
|
||||
memset(&ssl, 0, sizeof(ssl_context));
|
||||
|
||||
/*
|
||||
* 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 exit;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
printf(" ok\n");
|
||||
|
||||
ssl_set_endpoint(&ssl, SSL_IS_CLIENT);
|
||||
ssl_set_authmode(&ssl, SSL_VERIFY_NONE);
|
||||
ssl_set_rng(&ssl, my_random, NULL);
|
||||
#ifdef POLARSSL_DEBUG_C
|
||||
debug_set_threshold(DEBUG_LEVEL);
|
||||
#endif
|
||||
ssl_set_dbg(&ssl, my_debug, NULL);
|
||||
ssl_set_bio(&ssl, net_recv, &server_fd, net_send, &server_fd);
|
||||
#if SSL_USE_SRP
|
||||
if(strlen(srp_username))
|
||||
ssl_set_srp(&ssl, srp_username, strlen(srp_username), srp_password, strlen(srp_password));
|
||||
#endif
|
||||
/*
|
||||
* 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) {
|
||||
printf(" failed\n\r ! ssl_handshake returned -0x%x\n", -ret);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
#ifdef POLARSSL_MEMORY_C
|
||||
if(min_heap_size > 0)
|
||||
printf("\n\rMin available heap size = %d bytes during %s\n\r", min_heap_size, __FUNCTION__);
|
||||
#endif
|
||||
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]);
|
||||
#if SSL_USE_SRP
|
||||
strcpy(srp_username, "");
|
||||
strcpy(srp_password, "");
|
||||
#endif
|
||||
}
|
||||
#if SSL_USE_SRP
|
||||
else if(argc == 4) {
|
||||
strcpy(server_host, argv[1]);
|
||||
strcpy(srp_username, argv[2]);
|
||||
strcpy(srp_password, argv[3]);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
#if SSL_USE_SRP
|
||||
printf("\n\rUsage: %s SSL_SERVER_HOST [SRP_USER_NAME SRP_PASSWORD]", argv[0]);
|
||||
#else
|
||||
printf("\n\rUsage: %s SSL_SERVER_HOST", argv[0]);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
start_ssl_client();
|
||||
}
|
||||
121
component/common/utilities/tcpecho.c
Normal file
121
component/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 */
|
||||
534
component/common/utilities/tcptest.c
Normal file
534
component/common/utilities/tcptest.c
Normal file
|
|
@ -0,0 +1,534 @@
|
|||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <lwip/sockets.h>
|
||||
#include <lwip/raw.h>
|
||||
#include <lwip/icmp.h>
|
||||
#include <lwip/inet_chksum.h>
|
||||
#include <platform/platform_stdlib.h>
|
||||
|
||||
#define TCP_PACKET_COUNT 10000
|
||||
#define BSD_STACK_SIZE 256
|
||||
|
||||
#define HOST_IP "192.168.1.101"
|
||||
#define REMOTE_IP ((u32_t)0xc0a80165UL) /*192.168.1.101*/
|
||||
#define LOCAL_IP ((u32_t)0xc0a80164UL) /*192.168.1.100*/
|
||||
|
||||
unsigned int g_srv_buf_size = 1500;
|
||||
unsigned int g_cli_buf_size = 1500;
|
||||
xTaskHandle g_server_task = NULL;
|
||||
xTaskHandle g_client_task = NULL;
|
||||
|
||||
xTaskHandle udpcllient_task = NULL;
|
||||
xTaskHandle udpserver_task = NULL;
|
||||
|
||||
unsigned char g_start_server = 0;
|
||||
unsigned char g_start_client = 0;
|
||||
unsigned char g_terminate = 0;
|
||||
|
||||
unsigned char udp_start_server = 0;
|
||||
unsigned char udp_start_client= 0;
|
||||
char g_server_ip[16];
|
||||
unsigned long g_ulPacketCount = TCP_PACKET_COUNT;
|
||||
|
||||
int BsdTcpClient(const char *host_ip, unsigned short usPort)
|
||||
{
|
||||
int iCounter;
|
||||
short sTestBufLen;
|
||||
struct sockaddr_in sAddr;
|
||||
int iAddrSize;
|
||||
int iSockFD;
|
||||
int iStatus;
|
||||
long lLoopCount = 0;
|
||||
char *cBsdBuf = NULL;
|
||||
|
||||
if(g_cli_buf_size > 4300)
|
||||
g_cli_buf_size = 4300;
|
||||
else if (g_cli_buf_size == 0)
|
||||
g_cli_buf_size = 1500;
|
||||
|
||||
cBsdBuf = pvPortMalloc(g_cli_buf_size);
|
||||
if(NULL == cBsdBuf){
|
||||
printf("\n\rTCP: Allocate client buffer failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// filling the buffer
|
||||
for (iCounter = 0; iCounter < g_cli_buf_size; iCounter++) {
|
||||
cBsdBuf[iCounter] = (char)(iCounter % 10);
|
||||
}
|
||||
sTestBufLen = g_cli_buf_size;
|
||||
|
||||
//filling the TCP server socket address
|
||||
FD_ZERO(&sAddr);
|
||||
sAddr.sin_family = AF_INET;
|
||||
sAddr.sin_port = htons(usPort);
|
||||
sAddr.sin_addr.s_addr = inet_addr(host_ip);
|
||||
|
||||
iAddrSize = sizeof(struct sockaddr_in);
|
||||
|
||||
// creating a TCP socket
|
||||
iSockFD = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( iSockFD < 0 ) {
|
||||
printf("\n\rTCP ERROR: create tcp client socket fd error!");
|
||||
goto Exit1;
|
||||
}
|
||||
|
||||
printf("\n\rTCP: ServerIP=%s port=%d.", host_ip, usPort);
|
||||
printf("\n\rTCP: Create socket %d.", iSockFD);
|
||||
// connecting to TCP server
|
||||
iStatus = connect(iSockFD, (struct sockaddr *)&sAddr, iAddrSize);
|
||||
if (iStatus < 0) {
|
||||
printf("\n\rTCP ERROR: tcp client connect server error! ");
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
printf("\n\rTCP: Connect server successfully.");
|
||||
// sending multiple packets to the TCP server
|
||||
while (lLoopCount < g_ulPacketCount && !g_terminate) {
|
||||
// sending packet
|
||||
iStatus = send(iSockFD, cBsdBuf, sTestBufLen, 0 );
|
||||
if( iStatus <= 0 ) {
|
||||
printf("\r\nTCP ERROR: tcp client send data error! iStatus:%d", iStatus);
|
||||
goto Exit;
|
||||
}
|
||||
lLoopCount++;
|
||||
//printf("BsdTcpClient:: send data count:%ld iStatus:%d \n\r", lLoopCount, iStatus);
|
||||
}
|
||||
|
||||
printf("\n\rTCP: Sent %u packets successfully.",g_ulPacketCount);
|
||||
|
||||
Exit:
|
||||
//closing the socket after sending 1000 packets
|
||||
close(iSockFD);
|
||||
|
||||
Exit1:
|
||||
//free buffer
|
||||
vPortFree(cBsdBuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BsdTcpServer(unsigned short usPort)
|
||||
{
|
||||
struct sockaddr_in sAddr;
|
||||
struct sockaddr_in sLocalAddr;
|
||||
int iCounter;
|
||||
int iAddrSize;
|
||||
int iSockFD;
|
||||
int iStatus;
|
||||
int iNewSockFD;
|
||||
long lLoopCount = 0;
|
||||
//long lNonBlocking = 1;
|
||||
int iTestBufLen;
|
||||
int n;
|
||||
char *cBsdBuf = NULL;
|
||||
|
||||
if(g_srv_buf_size > 5000)
|
||||
g_srv_buf_size = 5000;
|
||||
else if (g_srv_buf_size == 0)
|
||||
g_srv_buf_size = 1500;
|
||||
|
||||
cBsdBuf = pvPortMalloc(g_srv_buf_size);
|
||||
if(NULL == cBsdBuf){
|
||||
printf("\n\rTCP: Allocate server buffer failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// filling the buffer
|
||||
for (iCounter = 0; iCounter < g_srv_buf_size; iCounter++) {
|
||||
cBsdBuf[iCounter] = (char)(iCounter % 10);
|
||||
}
|
||||
iTestBufLen = g_srv_buf_size;
|
||||
|
||||
// creating a TCP socket
|
||||
iSockFD = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if( iSockFD < 0 ) {
|
||||
goto Exit2;
|
||||
}
|
||||
|
||||
printf("\n\rTCP: Create server socket %d\n\r", iSockFD);
|
||||
n = 1;
|
||||
setsockopt( iSockFD, SOL_SOCKET, SO_REUSEADDR,
|
||||
(const char *) &n, sizeof( n ) );
|
||||
|
||||
//filling the TCP server socket address
|
||||
memset((char *)&sLocalAddr, 0, sizeof(sLocalAddr));
|
||||
sLocalAddr.sin_family = AF_INET;
|
||||
sLocalAddr.sin_len = sizeof(sLocalAddr);
|
||||
sLocalAddr.sin_port = htons(usPort);
|
||||
sLocalAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
iAddrSize = sizeof(sLocalAddr);
|
||||
|
||||
// binding the TCP socket to the TCP server address
|
||||
iStatus = bind(iSockFD, (struct sockaddr *)&sLocalAddr, iAddrSize);
|
||||
if( iStatus < 0 ) {
|
||||
printf("\n\rTCP ERROR: bind tcp server socket fd error! ");
|
||||
goto Exit1;
|
||||
}
|
||||
printf("\n\rTCP: Bind successfully.");
|
||||
|
||||
// putting the socket for listening to the incoming TCP connection
|
||||
iStatus = listen(iSockFD, 20);
|
||||
if( iStatus != 0 ) {
|
||||
printf("\n\rTCP ERROR: listen tcp server socket fd error! ");
|
||||
goto Exit1;
|
||||
}
|
||||
printf("\n\rTCP: Listen port %d", usPort);
|
||||
|
||||
// setting socket option to make the socket as non blocking
|
||||
//iStatus = setsockopt(iSockFD, SOL_SOCKET, SO_NONBLOCKING,
|
||||
// &lNonBlocking, sizeof(lNonBlocking));
|
||||
//if( iStatus < 0 ) {
|
||||
// return -1;
|
||||
//}
|
||||
Restart:
|
||||
iNewSockFD = -1;
|
||||
lLoopCount = 0;
|
||||
|
||||
// waiting for an incoming TCP connection
|
||||
while( iNewSockFD < 0 ) {
|
||||
// accepts a connection form a TCP client, if there is any
|
||||
// otherwise returns SL_EAGAIN
|
||||
int addrlen=sizeof(sAddr);
|
||||
iNewSockFD = accept(iSockFD, ( struct sockaddr *)&sAddr,
|
||||
(socklen_t*)&addrlen);
|
||||
if( iNewSockFD < 0 ) {
|
||||
printf("\n\rTCP ERROR: Accept tcp client socket fd error! ");
|
||||
goto Exit1;
|
||||
}
|
||||
printf("\n\rTCP: Accept socket %d successfully.", iNewSockFD);
|
||||
}
|
||||
|
||||
// waits packets from the connected TCP client
|
||||
while (!g_terminate) {
|
||||
iStatus = recv(iNewSockFD, cBsdBuf, iTestBufLen, 0); //MSG_DONTWAIT MSG_WAITALL
|
||||
if( iStatus < 0 ) {
|
||||
printf("\n\rTCP ERROR: server recv data error iStatus:%d ", iStatus);
|
||||
goto Exit;
|
||||
} else if (iStatus == 0) {
|
||||
printf("\n\rTCP: Recieved %u packets successfully.", lLoopCount);
|
||||
close(iNewSockFD);
|
||||
goto Restart;
|
||||
}
|
||||
lLoopCount++;
|
||||
}
|
||||
|
||||
Exit:
|
||||
// close the connected socket after receiving from connected TCP client
|
||||
close(iNewSockFD);
|
||||
|
||||
Exit1:
|
||||
// close the listening socket
|
||||
close(iSockFD);
|
||||
|
||||
Exit2:
|
||||
//free buffer
|
||||
vPortFree(cBsdBuf);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void TcpServerHandler(void *param)
|
||||
{
|
||||
unsigned short port = 5001;
|
||||
|
||||
printf("\n\rTCP: Start tcp Server!");
|
||||
if(g_start_server)
|
||||
BsdTcpServer(port);
|
||||
|
||||
#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
|
||||
printf("\n\rTCP: Tcp server stopped!");
|
||||
g_server_task = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
static void TcpClientHandler(void *param)
|
||||
{
|
||||
unsigned short port = 5001;
|
||||
|
||||
printf("\n\rTCP: Start tcp client!");
|
||||
if(g_start_client)
|
||||
BsdTcpClient(g_server_ip, port);
|
||||
|
||||
#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
|
||||
printf("\n\rTCP: Tcp client stopped!");
|
||||
g_client_task = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
|
||||
/***************************udp related*********************************/
|
||||
int udpclient()
|
||||
{
|
||||
int cli_sockfd;
|
||||
socklen_t addrlen;
|
||||
struct sockaddr_in cli_addr;
|
||||
int loop= 0;
|
||||
char *buffer ;
|
||||
// int delay = 2;
|
||||
|
||||
|
||||
if(!g_ulPacketCount)
|
||||
g_ulPacketCount = 100;
|
||||
|
||||
if(!g_cli_buf_size)
|
||||
g_cli_buf_size = 1500;
|
||||
|
||||
buffer = (char*)pvPortMalloc(g_cli_buf_size);
|
||||
|
||||
if(NULL == buffer){
|
||||
printf("\n\rudpclient: Allocate buffer failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*create socket*/
|
||||
memset(buffer, 0, g_cli_buf_size);
|
||||
cli_sockfd=socket(AF_INET,SOCK_DGRAM,0);
|
||||
if (cli_sockfd<0) {
|
||||
printf("create socket failed\r\n\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* fill sockaddr_in*/
|
||||
addrlen=sizeof(struct sockaddr_in);
|
||||
memset(&cli_addr, 0, addrlen);
|
||||
|
||||
cli_addr.sin_family=AF_INET;
|
||||
cli_addr.sin_addr.s_addr=inet_addr(g_server_ip);
|
||||
cli_addr.sin_port=htons(5001);
|
||||
|
||||
/* send data to server*/
|
||||
while(loop < g_ulPacketCount && !g_terminate) {
|
||||
if(sendto(cli_sockfd, buffer, g_cli_buf_size, 0,(struct sockaddr*)&cli_addr, addrlen) < 0) {
|
||||
// Dynamic delay to prevent send fail due to limited skb, this will degrade throughtput
|
||||
// if(delay < 100)
|
||||
// delay += 2;
|
||||
}
|
||||
|
||||
// vTaskDelay(delay);
|
||||
loop++;
|
||||
}
|
||||
close(cli_sockfd);
|
||||
//free buffer
|
||||
vPortFree(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int udpserver()
|
||||
{
|
||||
int ser_sockfd;
|
||||
socklen_t addrlen;
|
||||
struct sockaddr_in ser_addr, peer_addr;
|
||||
uint32_t start_time, end_time;
|
||||
unsigned char *buffer;
|
||||
int total_size = 0, report_interval = 1;
|
||||
|
||||
if (g_srv_buf_size == 0)
|
||||
g_srv_buf_size = 1500;
|
||||
|
||||
buffer = pvPortMalloc(g_srv_buf_size);
|
||||
|
||||
if(NULL == buffer){
|
||||
printf("\n\rudpclient: Allocate buffer failed.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*create socket*/
|
||||
ser_sockfd=socket(AF_INET,SOCK_DGRAM,0);
|
||||
if (ser_sockfd<0) {
|
||||
printf("\n\rudp server success");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*fill the socket in*/
|
||||
addrlen=sizeof(ser_addr);
|
||||
memset(&ser_addr, 0,addrlen);
|
||||
ser_addr.sin_family=AF_INET;
|
||||
ser_addr.sin_addr.s_addr=htonl(INADDR_ANY);
|
||||
ser_addr.sin_port=htons(5001);
|
||||
|
||||
/*bind*/
|
||||
if (bind(ser_sockfd,(struct sockaddr *)&ser_addr,addrlen)<0) {
|
||||
printf("bind failed\r\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
start_time = xTaskGetTickCount();
|
||||
total_size = 0;
|
||||
|
||||
while(1) {
|
||||
int read_size = 0;
|
||||
addrlen = sizeof(peer_addr);
|
||||
read_size=recvfrom(ser_sockfd,buffer,g_srv_buf_size,0,(struct sockaddr *) &peer_addr,&addrlen);
|
||||
if(read_size < 0){
|
||||
printf("%s recv error\r\n", __FUNCTION__);
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
end_time = xTaskGetTickCount();
|
||||
total_size += read_size;
|
||||
if((end_time - start_time) >= (configTICK_RATE_HZ * report_interval)) {
|
||||
printf("\nUDP recv %d bytes in %d ticks, %d Kbits/sec\n",
|
||||
total_size, end_time - start_time, total_size * 8 / 1024 / ((end_time - start_time) / configTICK_RATE_HZ));
|
||||
start_time = end_time;
|
||||
total_size = 0;
|
||||
}
|
||||
|
||||
/*ack data to client*/
|
||||
// Not send ack to prevent send fail due to limited skb, but it will have warning at iperf client
|
||||
// sendto(ser_sockfd,buffer,read_size,0,(struct sockaddr*)&peer_addr,sizeof(peer_addr));
|
||||
}
|
||||
|
||||
Exit:
|
||||
close(ser_sockfd);
|
||||
//free buffer
|
||||
vPortFree(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Udpclienthandler(void *param)
|
||||
{
|
||||
/*here gives the udp demo code*/
|
||||
printf("\n\rUdp client test");
|
||||
|
||||
udpclient();
|
||||
#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1)
|
||||
printf("\n\rMin available stack size of %s = %d * %d bytes", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE));
|
||||
#endif
|
||||
printf("\n\rUDP: udp client stopped!");
|
||||
udpcllient_task = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
void Udpserverhandler(void *param)
|
||||
{
|
||||
/*here gives the udp demo code*/
|
||||
printf("\n\rUdp server test");
|
||||
|
||||
udpserver();
|
||||
#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && (INCLUDE_uxTaskGetStackHighWaterMark == 1)
|
||||
printf("\n\rMin available stack size of %s = %d * %d bytes", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL), sizeof(portBASE_TYPE));
|
||||
#endif
|
||||
printf("\n\rUDP: udp client stopped!");
|
||||
udpserver_task = NULL;
|
||||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
/***************************end of udp*********************************/
|
||||
void cmd_tcp(int argc, char **argv)
|
||||
{
|
||||
g_terminate = g_start_server = g_start_client = 0;
|
||||
g_ulPacketCount = 10000;
|
||||
memset(g_server_ip, 0, 16);
|
||||
|
||||
if(argc < 2)
|
||||
goto Exit;
|
||||
|
||||
if(strcmp(argv[1], "-s") == 0 ||strcmp(argv[1], "s") == 0) {
|
||||
if(g_server_task){
|
||||
printf("\n\rTCP: Tcp Server is already running.");
|
||||
return;
|
||||
}else{
|
||||
g_start_server = 1;
|
||||
if(argc == 3)
|
||||
g_srv_buf_size = atoi(argv[2]);
|
||||
}
|
||||
}else if(strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "c") == 0) {
|
||||
if(g_client_task){
|
||||
printf("\n\rTCP: Tcp client is already running. Please enter \"tcp stop\" to stop it.");
|
||||
return;
|
||||
}else{
|
||||
if(argc < 4)
|
||||
goto Exit;
|
||||
g_start_client = 1;
|
||||
strncpy(g_server_ip, argv[2], (strlen(argv[2])>16)?16:strlen(argv[2]));
|
||||
g_cli_buf_size = atoi(argv[3]);
|
||||
if(argc == 5)
|
||||
g_ulPacketCount = atoi(argv[4]);
|
||||
}
|
||||
|
||||
}else if(strcmp(argv[1], "stop") == 0){
|
||||
g_terminate = 1;
|
||||
}else
|
||||
goto Exit;
|
||||
|
||||
if(g_start_server && (NULL == g_server_task)){
|
||||
if(xTaskCreate(TcpServerHandler, "tcp_server", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, &g_server_task) != pdPASS)
|
||||
printf("\n\rTCP ERROR: Create tcp server task failed.");
|
||||
}
|
||||
if(g_start_client && (NULL == g_client_task)){
|
||||
if(xTaskCreate(TcpClientHandler, "tcp_client", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1 + PRIORITIE_OFFSET, &g_client_task) != pdPASS)
|
||||
printf("\n\rTCP ERROR: Create tcp client task failed.");
|
||||
}
|
||||
|
||||
return;
|
||||
Exit:
|
||||
printf("\n\rTCP: Tcp test command format error!");
|
||||
printf("\n\rPlease Enter: \"tcp -s\" to start tcp server or \"tcp <-c *.*.*.*> <buf len> [count]]\" to start tcp client\n\r");
|
||||
return;
|
||||
}
|
||||
|
||||
void cmd_udp(int argc, char **argv)
|
||||
{
|
||||
g_terminate = udp_start_server = udp_start_client = 0;
|
||||
g_ulPacketCount = 10000;
|
||||
if(argc == 2){
|
||||
if(strcmp(argv[1], "-s") == 0 ||strcmp(argv[1], "s") == 0){
|
||||
if(udpserver_task){
|
||||
printf("\r\nUDP: UDP Server is already running.");
|
||||
return;
|
||||
}else{
|
||||
udp_start_server = 1;
|
||||
}
|
||||
}else if(strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "c") == 0){
|
||||
if(udpcllient_task){
|
||||
printf("\r\nUDP: UDP Server is already running.");
|
||||
return;
|
||||
}else{
|
||||
udp_start_client= 1;
|
||||
}
|
||||
}else if(strcmp(argv[1], "stop") == 0){
|
||||
g_terminate = 1;
|
||||
}else
|
||||
goto Exit;
|
||||
}else if(strcmp(argv[1], "-c") == 0 || strcmp(argv[1], "c") == 0) {
|
||||
if(udpcllient_task){
|
||||
printf("\n\nUDP: UDP client is already running. Please enter \"udp stop\" to stop it.");
|
||||
return;
|
||||
}else{
|
||||
if(argc < 4)
|
||||
goto Exit;
|
||||
udp_start_client = 1;
|
||||
strncpy(g_server_ip, argv[2], (strlen(argv[2])>16)?16:strlen(argv[2]));
|
||||
g_cli_buf_size = atoi(argv[3]);
|
||||
if(argc == 5)
|
||||
g_ulPacketCount = atoi(argv[4]);
|
||||
}
|
||||
|
||||
}else
|
||||
goto Exit;
|
||||
|
||||
if(udp_start_server && (NULL == udpserver_task)){
|
||||
if(xTaskCreate(Udpserverhandler, "udp_server", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &udpserver_task) != pdPASS)
|
||||
printf("\r\nUDP ERROR: Create udp server task failed.");
|
||||
}
|
||||
|
||||
if(udp_start_client && (NULL == udpcllient_task)){
|
||||
if(xTaskCreate(Udpclienthandler, "udp_client", BSD_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &udpcllient_task) != pdPASS)
|
||||
printf("\r\nUDP ERROR: Create udp client task failed.");
|
||||
}
|
||||
|
||||
return;
|
||||
Exit:
|
||||
printf("\r\nUDP: udp test command format error!");
|
||||
printf("\r\nPlease Enter: \"udp -s\" to start udp server or \"udp -c to start udp client\r\n");
|
||||
return;
|
||||
}
|
||||
|
||||
92
component/common/utilities/udpecho.c
Normal file
92
component/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 */
|
||||
971
component/common/utilities/update.c
Normal file
971
component/common/utilities/update.c
Normal file
|
|
@ -0,0 +1,971 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <lwip/sockets.h>
|
||||
#include <sys.h>
|
||||
|
||||
#if !defined(CONFIG_PLATFORM_8195A) && !defined(CONFIG_PLATFORM_8711B)
|
||||
#include <flash/stm32_flash.h>
|
||||
#if defined(STM32F2XX)
|
||||
#include <stm32f2xx_flash.h>
|
||||
#elif defined(STM32F4XX)
|
||||
#include <stm32f4xx_flash.h>
|
||||
#elif defined(STM32f1xx)
|
||||
#include <stm32f10x_flash.h>
|
||||
#endif
|
||||
#include "cloud_updater.h"
|
||||
#else
|
||||
#include "flash_api.h"
|
||||
#endif
|
||||
#include "update.h"
|
||||
#if defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B)
|
||||
#define OFFSET_DATA FLASH_SYSTEM_DATA_ADDR
|
||||
#define IMAGE_2 0x0000B000
|
||||
#define WRITE_OTA_ADDR 0
|
||||
#define CONFIG_CUSTOM_SIGNATURE 1
|
||||
#define SWAP_UPDATE 0
|
||||
|
||||
#if WRITE_OTA_ADDR
|
||||
#define BACKUP_SECTOR (FLASH_SYSTEM_DATA_ADDR - 0x1000)
|
||||
#endif
|
||||
|
||||
#if CONFIG_CUSTOM_SIGNATURE
|
||||
/* ---------------------------------------------------
|
||||
* Customized Signature
|
||||
* ---------------------------------------------------*/
|
||||
// This signature can be used to verify the correctness of the image
|
||||
// It will be located in fixed location in application image
|
||||
#pragma location=".custom.validate.rodata"
|
||||
const unsigned char cus_sig[32] = "Customer Signature-modelxxx";
|
||||
#endif
|
||||
|
||||
#else
|
||||
#define CONFIG_SECTOR FLASH_Sector_1
|
||||
#define APPLICATION_SECTOR FLASH_Sector_2
|
||||
#define UPDATE_SECTOR FLASH_Sector_8
|
||||
#endif
|
||||
#define STACK_SIZE 1024
|
||||
#define TASK_PRIORITY tskIDLE_PRIORITY + 1
|
||||
#define BUF_SIZE 512
|
||||
#define ETH_ALEN 6
|
||||
|
||||
#define SERVER_LOCAL 1
|
||||
#define SERVER_CLOUD 2
|
||||
#define SERVER_TYPE SERVER_LOCAL
|
||||
#define UPDATE_DBG 1
|
||||
|
||||
#if (SERVER_TYPE == SERVER_LOCAL)
|
||||
typedef struct
|
||||
{
|
||||
uint32_t ip_addr;
|
||||
uint16_t port;
|
||||
}update_cfg_local_t;
|
||||
#endif
|
||||
|
||||
#if (SERVER_TYPE == SERVER_CLOUD)
|
||||
#define REPOSITORY_LEN 16
|
||||
#define FILE_PATH_LEN 64
|
||||
typedef struct
|
||||
{
|
||||
uint8_t repository[REPOSITORY_LEN];
|
||||
uint8_t file_path[FILE_PATH_LEN];
|
||||
}update_cfg_cloud_t;
|
||||
#endif
|
||||
|
||||
sys_thread_t TaskOTA = NULL;
|
||||
//---------------------------------------------------------------------
|
||||
static void* update_malloc(unsigned int size)
|
||||
{
|
||||
return pvPortMalloc(size);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
static void update_free(void *buf)
|
||||
{
|
||||
vPortFree(buf);
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
#if (SERVER_TYPE == SERVER_LOCAL)
|
||||
#if defined(STM32F2XX) ||(STM32F4XX)
|
||||
static void update_ota_local_task(void *param)
|
||||
{
|
||||
int server_socket = 0;
|
||||
struct sockaddr_in server_addr;
|
||||
char *buf;
|
||||
int read_bytes, size = 0, i;
|
||||
update_cfg_local_t *cfg = (update_cfg_local_t*)param;
|
||||
uint32_t address, checksum = 0;
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
char mac[ETH_ALEN];
|
||||
#endif
|
||||
printf("\n\r[%s] Update task start", __FUNCTION__);
|
||||
buf = update_malloc(BUF_SIZE);
|
||||
if(!buf){
|
||||
printf("\n\r[%s] Alloc buffer failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
// Connect socket
|
||||
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(server_socket < 0){
|
||||
printf("\n\r[%s] Create socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr.s_addr = cfg->ip_addr;
|
||||
server_addr.sin_port = cfg->port;
|
||||
|
||||
if(connect(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){
|
||||
printf("\n\r[%s] socket connect failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
// Erase config sectors
|
||||
if(flash_EraseSector(CONFIG_SECTOR) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
// Read MAC address
|
||||
if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Read MAC error", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#endif
|
||||
// Erase update sectors
|
||||
for(i = UPDATE_SECTOR; i <= FLASH_Sector_11; i += 8){
|
||||
if(flash_EraseSector(i) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
// Write update sectors
|
||||
address = flash_SectorAddress(UPDATE_SECTOR);
|
||||
printf("\n\r");
|
||||
while(1){
|
||||
read_bytes = read(server_socket, buf, BUF_SIZE);
|
||||
if(read_bytes == 0) break; // Read end
|
||||
if(read_bytes < 0){
|
||||
printf("\n\r[%s] Read socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
if(flash_Wrtie(address + size, buf, read_bytes) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes;
|
||||
for(i = 0; i < read_bytes; i ++)
|
||||
checksum += buf[i];
|
||||
printf("\rUpdate file size = %d ", size);
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
//Write MAC address
|
||||
if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){
|
||||
if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Write MAC failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Write config sectors
|
||||
address = flash_SectorAddress(CONFIG_SECTOR);
|
||||
if( (flash_Wrtie(address, (char*)&size, 4) < 0) ||
|
||||
(flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
printf("\n\r[%s] Update OTA success!", __FUNCTION__);
|
||||
update_ota_exit:
|
||||
if(buf)
|
||||
update_free(buf);
|
||||
if(server_socket >= 0)
|
||||
close(server_socket);
|
||||
if(param)
|
||||
update_free(param);
|
||||
TaskOTA = NULL;
|
||||
printf("\n\r[%s] Update task exit", __FUNCTION__);
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
#elif defined(STM32f1xx)
|
||||
static void update_ota_local_task(void *param)
|
||||
{
|
||||
int server_socket;
|
||||
struct sockaddr_in server_addr;
|
||||
char *buf, flag_a = 0;
|
||||
int read_bytes, size = 0, i;
|
||||
update_cfg_local_t *cfg = (update_cfg_local_t*)param;
|
||||
uint32_t address, checksum = 0;
|
||||
uint16_t a = 0;
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
char mac[ETH_ALEN];
|
||||
#endif
|
||||
|
||||
printf("\n\r[%s] Update task start", __FUNCTION__);
|
||||
buf = update_malloc(BUF_SIZE);
|
||||
if(!buf){
|
||||
printf("\n\r[%s] Alloc buffer failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
// Connect socket
|
||||
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(server_socket < 0){
|
||||
printf("\n\r[%s] Create socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr.s_addr = cfg->ip_addr;
|
||||
server_addr.sin_port = cfg->port;
|
||||
|
||||
if(connect(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){
|
||||
printf("\n\r[%s] socket connect failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
// Erase config sectors
|
||||
for(i = CONFIG_SECTOR; i < APPLICATION_SECTOR; i += FLASH_PAGE_SIZE){
|
||||
if(flash_EraseSector(i) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
// Read MAC address
|
||||
if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Read MAC error", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Erase update sectors
|
||||
for(i = UPDATE_SECTOR; i < FLASH_Sector_0 + FLASH_SIZE; i += FLASH_PAGE_SIZE){
|
||||
if(flash_EraseSector(i) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
// Write update sectors
|
||||
address = UPDATE_SECTOR;
|
||||
printf("\n\r");
|
||||
while(1){
|
||||
read_bytes = read(server_socket, buf, BUF_SIZE);
|
||||
if(read_bytes == 0) break; // Read end
|
||||
if(read_bytes < 0){
|
||||
printf("\n\r[%s] Read socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
if(flag_a == 0){
|
||||
if(read_bytes % 2 != 0){
|
||||
a = buf[read_bytes - 1];
|
||||
flag_a = 1;
|
||||
if(flash_Wrtie(address + size, buf, read_bytes - 1) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes - 1;
|
||||
}
|
||||
else{
|
||||
if(flash_Wrtie(address + size, buf, read_bytes) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes;
|
||||
}
|
||||
}
|
||||
else{
|
||||
a = buf[0] << 8 | a;
|
||||
if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += 2;
|
||||
a = 0;
|
||||
flag_a = 0;
|
||||
if((read_bytes - 1) % 2 != 0){
|
||||
a = buf[read_bytes - 1];
|
||||
flag_a = 1;
|
||||
if(flash_Wrtie(address + size, buf + 1, read_bytes - 2) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes - 2;
|
||||
}
|
||||
else{
|
||||
if(flash_Wrtie(address + size, buf + 1, read_bytes - 1) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes - 1;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < read_bytes; i ++)
|
||||
checksum += buf[i];
|
||||
printf("\rUpdate file size = %d ", size);
|
||||
}
|
||||
if(flag_a){
|
||||
if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += 1;
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
//Write MAC address
|
||||
if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){
|
||||
if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Write MAC failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write config sectors
|
||||
address = CONFIG_SECTOR;
|
||||
if( (flash_Wrtie(address, (char*)&size, 4) < 0) ||
|
||||
(flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
printf("\n\r[%s] Update OTA success!", __FUNCTION__);
|
||||
update_ota_exit:
|
||||
if(buf)
|
||||
update_free(buf);
|
||||
if(server_socket >= 0)
|
||||
close(server_socket);
|
||||
if(param)
|
||||
update_free(param);
|
||||
TaskOTA = NULL;
|
||||
printf("\n\r[%s] Update task exit", __FUNCTION__);
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
#elif defined(CONFIG_PLATFORM_8195A) || defined(CONFIG_PLATFORM_8711B)
|
||||
|
||||
void ota_platform_reset(void)
|
||||
{
|
||||
//wifi_off();
|
||||
|
||||
// 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);
|
||||
}
|
||||
#if WRITE_OTA_ADDR
|
||||
int write_ota_addr_to_system_data(flash_t *flash, uint32_t ota_addr)
|
||||
{
|
||||
uint32_t data, i = 0;
|
||||
//Get upgraded image 2 addr from offset
|
||||
flash_read_word(flash, OFFSET_DATA, &data);
|
||||
printf("\n\r[%s] data 0x%x ota_addr 0x%x", __FUNCTION__, data, ota_addr);
|
||||
if(data == ~0x0){
|
||||
flash_write_word(flash, OFFSET_DATA, ota_addr);
|
||||
}else{
|
||||
//erase backup sector
|
||||
flash_erase_sector(flash, BACKUP_SECTOR);
|
||||
//backup system data to backup sector
|
||||
for(i = 0; i < 0x1000; i+= 4){
|
||||
flash_read_word(flash, OFFSET_DATA + i, &data);
|
||||
if(i == 0)
|
||||
data = ota_addr;
|
||||
flash_write_word(flash, BACKUP_SECTOR + i,data);
|
||||
}
|
||||
//erase system data
|
||||
flash_erase_sector(flash, OFFSET_DATA);
|
||||
//write data back to system data
|
||||
for(i = 0; i < 0x1000; i+= 4){
|
||||
flash_read_word(flash, BACKUP_SECTOR + i, &data);
|
||||
flash_write_word(flash, OFFSET_DATA + i,data);
|
||||
}
|
||||
//erase backup sector
|
||||
flash_erase_sector(flash, BACKUP_SECTOR);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
static void update_ota_local_task(void *param)
|
||||
{
|
||||
int server_socket;
|
||||
struct sockaddr_in server_addr;
|
||||
unsigned char *buf;
|
||||
int read_bytes = 0, size = 0, i = 0;
|
||||
update_cfg_local_t *cfg = (update_cfg_local_t *)param;
|
||||
uint32_t address, checksum = 0;
|
||||
flash_t flash;
|
||||
uint32_t NewImg2BlkSize = 0, NewImg2Len = 0, NewImg2Addr = 0, file_checksum[3];
|
||||
uint32_t Img2Len = 0;
|
||||
int ret = -1 ;
|
||||
//uint8_t signature[8] = {0x38,0x31,0x39,0x35,0x38,0x37,0x31,0x31};
|
||||
uint32_t IMAGE_x = 0, ImgxLen = 0, ImgxAddr = 0;
|
||||
#if WRITE_OTA_ADDR
|
||||
uint32_t ota_addr = 0x80000;
|
||||
#endif
|
||||
#if CONFIG_CUSTOM_SIGNATURE
|
||||
char custom_sig[32] = "Customer Signature-modelxxx";
|
||||
uint32_t read_custom_sig[8];
|
||||
#endif
|
||||
printf("\n\r[%s] Update task start", __FUNCTION__);
|
||||
buf = update_malloc(BUF_SIZE);
|
||||
if(!buf){
|
||||
printf("\n\r[%s] Alloc buffer failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
// Connect socket
|
||||
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(server_socket < 0){
|
||||
printf("\n\r[%s] Create socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_addr.s_addr = cfg->ip_addr;
|
||||
server_addr.sin_port = cfg->port;
|
||||
|
||||
if(connect(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1){
|
||||
printf("\n\r[%s] socket connect failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
DBG_INFO_MSG_OFF(_DBG_SPI_FLASH_);
|
||||
|
||||
#if 1
|
||||
// The upgraded image2 pointer must 4K aligned and should not overlap with Default Image2
|
||||
flash_read_word(&flash, IMAGE_2, &Img2Len);
|
||||
IMAGE_x = IMAGE_2 + Img2Len + 0x10;
|
||||
flash_read_word(&flash, IMAGE_x, &ImgxLen);
|
||||
flash_read_word(&flash, IMAGE_x+4, &ImgxAddr);
|
||||
if(ImgxAddr==0x30000000){
|
||||
printf("\n\r[%s] IMAGE_3 0x%x Img3Len 0x%x", __FUNCTION__, IMAGE_x, ImgxLen);
|
||||
}else{
|
||||
printf("\n\r[%s] no IMAGE_3", __FUNCTION__);
|
||||
// no image3
|
||||
IMAGE_x = IMAGE_2;
|
||||
ImgxLen = Img2Len;
|
||||
}
|
||||
#if WRITE_OTA_ADDR
|
||||
if((ota_addr > IMAGE_x) && ((ota_addr < (IMAGE_x+ImgxLen))) ||
|
||||
(ota_addr < IMAGE_x) ||
|
||||
((ota_addr & 0xfff) != 0)||
|
||||
(ota_addr == ~0x0)){
|
||||
printf("\n\r[%s] illegal ota addr 0x%x", __FUNCTION__, ota_addr);
|
||||
goto update_ota_exit;
|
||||
}else
|
||||
write_ota_addr_to_system_data( &flash, ota_addr);
|
||||
#endif
|
||||
//Get upgraded image 2 addr from offset
|
||||
flash_read_word(&flash, OFFSET_DATA, &NewImg2Addr);
|
||||
if((NewImg2Addr > IMAGE_x) && ((NewImg2Addr < (IMAGE_x+ImgxLen))) ||
|
||||
(NewImg2Addr < IMAGE_x) ||
|
||||
((NewImg2Addr & 0xfff) != 0)||
|
||||
(NewImg2Addr == ~0x0)){
|
||||
printf("\n\r[%s] after read, NewImg2Addr 0x%x, Img2Len 0x%x", __FUNCTION__, NewImg2Addr, Img2Len);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#else
|
||||
//For test, hard code addr
|
||||
NewImg2Addr = 0x80000;
|
||||
#endif
|
||||
|
||||
//Clear file_checksum
|
||||
memset(file_checksum, 0, sizeof(file_checksum));
|
||||
|
||||
if(file_checksum[0] == 0){
|
||||
printf("\n\r[%s] Read chechsum first", __FUNCTION__);
|
||||
read_bytes = read(server_socket, file_checksum, sizeof(file_checksum));
|
||||
// !X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X
|
||||
// !W checksum !W padding 0 !W file size !W
|
||||
// !X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X!X
|
||||
printf("\n\r[%s] chechsum read_bytes %d", __FUNCTION__, read_bytes);
|
||||
printf("\n\r[%s] chechsum 0x%x, file size 0x%x", __FUNCTION__, file_checksum[0],file_checksum[2]);
|
||||
if(file_checksum[2] == 0){
|
||||
printf("\n\r[%s] No checksum and file size", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
|
||||
#if SWAP_UPDATE
|
||||
uint32_t SigImage0,SigImage1;
|
||||
uint32_t Part1Addr=0xFFFFFFFF, Part2Addr=0xFFFFFFFF;
|
||||
uint32_t OldImg2Addr;
|
||||
flash_read_word(&flash, 0x18, &Part1Addr);
|
||||
Part1Addr = (Part1Addr&0xFFFF)*1024; // first partition
|
||||
Part2Addr = NewImg2Addr;
|
||||
|
||||
// read Part1/Part2 signature
|
||||
flash_read_word(&flash, Part1Addr+8, &SigImage0);
|
||||
flash_read_word(&flash, Part1Addr+12, &SigImage1);
|
||||
printf("\n\r[%s] Part1 Sig %x", __FUNCTION__, SigImage0);
|
||||
if(SigImage0==0x35393138 && SigImage1==0x31313738)
|
||||
OldImg2Addr = Part1Addr; // newer version, change to older version
|
||||
else
|
||||
NewImg2Addr = Part1Addr; // update to older version
|
||||
flash_read_word(&flash, Part2Addr+8, &SigImage0);
|
||||
flash_read_word(&flash, Part2Addr+12, &SigImage1);
|
||||
printf("\n\r[%s] Part2 Sig %x", __FUNCTION__, SigImage0);
|
||||
if(SigImage0==0x35393138 && SigImage1==0x31313738)
|
||||
OldImg2Addr = Part2Addr;
|
||||
else
|
||||
NewImg2Addr = Part2Addr;
|
||||
|
||||
printf("\n\r[%s] New %x, Old %x", __FUNCTION__, NewImg2Addr, OldImg2Addr);
|
||||
|
||||
if( NewImg2Addr==Part1Addr ){
|
||||
if( file_checksum[2] > (Part2Addr-Part1Addr) ){ // firmware size too large
|
||||
printf("\n\r[%s] Part1 size < OTA size", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
// or update to partition2
|
||||
// NewImg2Addr = Part2Addr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//Erase upgraded image 2 region
|
||||
if(NewImg2Len == 0){
|
||||
NewImg2Len = file_checksum[2];
|
||||
printf("\n\r[%s] NewImg2Len %d ", __FUNCTION__, NewImg2Len);
|
||||
if((int)NewImg2Len > 0){
|
||||
NewImg2BlkSize = ((NewImg2Len - 1)/4096) + 1;
|
||||
printf("\n\r[%s] NewImg2BlkSize %d 0x%8x", __FUNCTION__, NewImg2BlkSize, NewImg2BlkSize);
|
||||
for( i = 0; i < NewImg2BlkSize; i++)
|
||||
flash_erase_sector(&flash, NewImg2Addr + i * 4096);
|
||||
}else{
|
||||
printf("\n\r[%s] Size INVALID", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
|
||||
printf("\n\r[%s] NewImg2Addr 0x%x", __FUNCTION__, NewImg2Addr);
|
||||
// Write New Image 2 sector
|
||||
if(NewImg2Addr != ~0x0){
|
||||
address = NewImg2Addr;
|
||||
printf("\n\r");
|
||||
while(1){
|
||||
memset(buf, 0, BUF_SIZE);
|
||||
read_bytes = read(server_socket, buf, BUF_SIZE);
|
||||
if(read_bytes == 0) break; // Read end
|
||||
if(read_bytes < 0){
|
||||
printf("\n\r[%s] Read socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
//printf("\n\r[%s] read_bytes %d", __FUNCTION__, read_bytes);
|
||||
|
||||
#if 1
|
||||
if(flash_stream_write(&flash, address + size, read_bytes, buf) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes;
|
||||
for(i = 0; i < read_bytes; i ++)
|
||||
checksum += buf[i];
|
||||
#else
|
||||
size += read_bytes;
|
||||
for(i = 0; i < read_bytes; i ++){
|
||||
checksum += buf[i];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
printf("\n\r");
|
||||
printf("\n\rUpdate file size = %d checksum 0x%x ", size, checksum);
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
//Write MAC address
|
||||
if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){
|
||||
if(flash_write_word(&flash, FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Write MAC failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
printf("\n\r checksum 0x%x file_checksum 0x%x ", checksum, *(file_checksum));
|
||||
#if CONFIG_CUSTOM_SIGNATURE
|
||||
for(i = 0; i < 8; i ++){
|
||||
flash_read_word(&flash, NewImg2Addr + 0x28 + i *4, read_custom_sig + i);
|
||||
}
|
||||
printf("\n\r[%s] read_custom_sig %s", __FUNCTION__ , (char*)read_custom_sig);
|
||||
#endif
|
||||
// compare checksum with received checksum
|
||||
if(!memcmp(&checksum,file_checksum,sizeof(checksum))
|
||||
#if CONFIG_CUSTOM_SIGNATURE
|
||||
&& !strcmp((char*)read_custom_sig,custom_sig)
|
||||
#endif
|
||||
){
|
||||
|
||||
//Set signature in New Image 2 addr + 8 and + 12
|
||||
uint32_t sig_readback0,sig_readback1;
|
||||
flash_write_word(&flash,NewImg2Addr + 8, 0x35393138);
|
||||
flash_write_word(&flash,NewImg2Addr + 12, 0x31313738);
|
||||
flash_read_word(&flash, NewImg2Addr + 8, &sig_readback0);
|
||||
flash_read_word(&flash, NewImg2Addr + 12, &sig_readback1);
|
||||
printf("\n\r[%s] signature %x,%x, checksum 0x%x", __FUNCTION__ , sig_readback0, sig_readback1, checksum);
|
||||
#if SWAP_UPDATE
|
||||
flash_write_word(&flash,OldImg2Addr + 8, 0x35393130);
|
||||
flash_write_word(&flash,OldImg2Addr + 12, 0x31313738);
|
||||
flash_read_word(&flash, OldImg2Addr + 8, &sig_readback0);
|
||||
flash_read_word(&flash, OldImg2Addr + 12, &sig_readback1);
|
||||
printf("\n\r[%s] old signature %x,%x", __FUNCTION__ , sig_readback0, sig_readback1);
|
||||
#endif
|
||||
printf("\n\r[%s] Update OTA success!", __FUNCTION__);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
update_ota_exit:
|
||||
if(buf)
|
||||
update_free(buf);
|
||||
if(server_socket >= 0)
|
||||
close(server_socket);
|
||||
if(param)
|
||||
update_free(param);
|
||||
TaskOTA = NULL;
|
||||
printf("\n\r[%s] Update task exit", __FUNCTION__);
|
||||
if(!ret){
|
||||
printf("\n\r[%s] Ready to reboot", __FUNCTION__);
|
||||
ota_platform_reset();
|
||||
}
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int update_ota_local(char *ip, int port)
|
||||
{
|
||||
update_cfg_local_t *pUpdateCfg;
|
||||
|
||||
if(TaskOTA){
|
||||
printf("\n\r[%s] Update task has created.", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
pUpdateCfg = update_malloc(sizeof(update_cfg_local_t));
|
||||
if(pUpdateCfg == NULL){
|
||||
printf("\n\r[%s] Alloc update cfg failed", __FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
pUpdateCfg->ip_addr = inet_addr(ip);
|
||||
pUpdateCfg->port = ntohs(port);
|
||||
|
||||
TaskOTA = sys_thread_new("OTA_server", update_ota_local_task, pUpdateCfg, STACK_SIZE, TASK_PRIORITY);
|
||||
if(TaskOTA == NULL){
|
||||
update_free(pUpdateCfg);
|
||||
printf("\n\r[%s] Create update task failed", __FUNCTION__);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif // #if (SERVER_TYPE == SERVER_LOCAL)
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
#if (SERVER_TYPE == SERVER_CLOUD)
|
||||
#if defined(STM32F2XX) ||(STM32F4XX)
|
||||
static void update_ota_cloud_task(void *param)
|
||||
{
|
||||
struct updater_ctx ctx;
|
||||
char *buf;
|
||||
int read_bytes, size = 0, i;
|
||||
uint32_t address, checksum = 0;
|
||||
update_cfg_cloud_t *cfg = (update_cfg_cloud_t*)param;
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
char mac[ETH_ALEN];
|
||||
#endif
|
||||
printf("\n\r[%s] Update task start", __FUNCTION__);
|
||||
buf = update_malloc(BUF_SIZE);
|
||||
if(!buf){
|
||||
printf("\n\r[%s] Alloc buffer failed", __FUNCTION__);
|
||||
goto update_ota_exit_1;
|
||||
}
|
||||
// Init ctx
|
||||
if(updater_init_ctx(&ctx, (char*)cfg->repository, (char*)cfg->file_path) != 0) {
|
||||
printf("\n\r[%s] Cloud ctx init failed", __FUNCTION__);
|
||||
goto update_ota_exit_1;
|
||||
}
|
||||
printf("\n\r[%s] Firmware link: %s, size = %d bytes, checksum = 0x%08x, version = %s\n", __FUNCTION__,
|
||||
ctx.link, ctx.size, ctx.checksum, ctx.version);
|
||||
|
||||
// Erase config sectors
|
||||
if(flash_EraseSector(CONFIG_SECTOR) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
// Read MAC address
|
||||
if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Read MAC error", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#endif
|
||||
// Erase update sectors
|
||||
for(i = UPDATE_SECTOR; i <= FLASH_Sector_11; i += 8){
|
||||
if(flash_EraseSector(i) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
// Write update sectors
|
||||
address = flash_SectorAddress(UPDATE_SECTOR);
|
||||
printf("\n\r");
|
||||
while(ctx.bytes < ctx.size){
|
||||
read_bytes = updater_read_bytes(&ctx, (unsigned char*)buf, BUF_SIZE);
|
||||
if(read_bytes == 0) break; // Read end
|
||||
if(read_bytes < 0){
|
||||
printf("\n\r[%s] Read socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
if(flash_Wrtie(address + size, buf, read_bytes) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes;
|
||||
for(i = 0; i < read_bytes; i ++)
|
||||
checksum += buf[i];
|
||||
printf("\rUpdate file size = %d/%d bytes ", ctx.bytes, ctx.size);
|
||||
}
|
||||
printf("\n\r[%s] ctx checksum = %08x, computed checksum = %08x\n", __FUNCTION__, ctx.checksum, checksum);
|
||||
if(checksum != ctx.checksum){
|
||||
printf("\n\r[%s] Checksum error", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
//Write MAC address
|
||||
if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){
|
||||
if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Write MAC failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
// Write config sectors
|
||||
address = flash_SectorAddress(CONFIG_SECTOR);
|
||||
if( (flash_Wrtie(address, (char*)&size, 4) < 0) ||
|
||||
(flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
printf("\n\r[%s] Update OTA success!", __FUNCTION__);
|
||||
|
||||
update_ota_exit:
|
||||
updater_free_ctx(&ctx);
|
||||
update_ota_exit_1:
|
||||
if(buf)
|
||||
update_free(buf);
|
||||
if(param)
|
||||
update_free(param);
|
||||
TaskOTA = NULL;
|
||||
printf("\n\r[%s] Update task exit", __FUNCTION__);
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
#elif defined(STM32f1xx)
|
||||
static void update_ota_cloud_task(void *param)
|
||||
{
|
||||
struct updater_ctx ctx;
|
||||
char *buf, flag_a = 0;
|
||||
int read_bytes, size = 0, i;
|
||||
uint32_t address, checksum = 0;
|
||||
update_cfg_cloud_t *cfg = (update_cfg_cloud_t*)param;
|
||||
uint16_t a = 0;
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
char mac[ETH_ALEN];
|
||||
#endif
|
||||
printf("\n\r[%s] Update task start", __FUNCTION__);
|
||||
buf = update_malloc(BUF_SIZE);
|
||||
if(!buf){
|
||||
printf("\n\r[%s] Alloc buffer failed", __FUNCTION__);
|
||||
goto update_ota_exit_1;
|
||||
}
|
||||
// Init ctx
|
||||
if(updater_init_ctx(&ctx, (char*)cfg->repository, (char*)cfg->file_path) != 0) {
|
||||
printf("\n\r[%s] Cloud ctx init failed", __FUNCTION__);
|
||||
goto update_ota_exit_1;
|
||||
}
|
||||
printf("\n\r[%s] Firmware link: %s, size = %d bytes, checksum = 0x%08x, version = %s\n", __FUNCTION__,
|
||||
ctx.link, ctx.size, ctx.checksum, ctx.version);
|
||||
|
||||
// Erase config sectors
|
||||
for(i = CONFIG_SECTOR; i < APPLICATION_SECTOR; i += FLASH_PAGE_SIZE){
|
||||
if(flash_EraseSector(i) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
// Read MAC address
|
||||
if(flash_Read(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Read MAC error", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Erase update sectors
|
||||
for(i = UPDATE_SECTOR; i < FLASH_Sector_0 + FLASH_SIZE; i += FLASH_PAGE_SIZE){
|
||||
if(flash_EraseSector(i) < 0){
|
||||
printf("\n\r[%s] Erase sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
// Write update sectors
|
||||
address = UPDATE_SECTOR;
|
||||
printf("\n\r");
|
||||
while(ctx.bytes < ctx.size){
|
||||
read_bytes = updater_read_bytes(&ctx, (unsigned char*)buf, BUF_SIZE);
|
||||
if(read_bytes == 0) break; // Read end
|
||||
if(read_bytes < 0){
|
||||
printf("\n\r[%s] Read socket failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
if(flag_a == 0){
|
||||
if(read_bytes % 2 != 0){
|
||||
a = buf[read_bytes - 1];
|
||||
flag_a = 1;
|
||||
if(flash_Wrtie(address + size, buf, read_bytes - 1) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes - 1;
|
||||
}
|
||||
else{
|
||||
if(flash_Wrtie(address + size, buf, read_bytes) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes;
|
||||
}
|
||||
}
|
||||
else{
|
||||
a = buf[0]<< 8 |a;
|
||||
if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += 2;
|
||||
a = 0;
|
||||
flag_a = 0;
|
||||
if((read_bytes - 1) % 2 != 0){
|
||||
a = buf[read_bytes - 1];
|
||||
flag_a = 1;
|
||||
if(flash_Wrtie(address + size, buf + 1, read_bytes - 2) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes - 2;
|
||||
}
|
||||
else{
|
||||
if(flash_Wrtie(address + size, buf + 1, read_bytes - 1) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += read_bytes - 1;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < read_bytes; i ++)
|
||||
checksum += buf[i];
|
||||
printf("\rUpdate file size = %d/%d bytes ", ctx.bytes, ctx.size);
|
||||
}
|
||||
if(flag_a){
|
||||
if(flash_Wrtie(address + size, (char*)(&a), 2) < 0){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
size += 1;
|
||||
}
|
||||
printf("\n\r[%s] ctx checksum = %08x, computed checksum = %08x\n", __FUNCTION__, ctx.checksum, checksum);
|
||||
if(checksum != ctx.checksum){
|
||||
printf("\n\r[%s] Checksum error", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
#if CONFIG_WRITE_MAC_TO_FLASH
|
||||
//Write MAC address
|
||||
if(!(mac[0]==0xff&&mac[1]==0xff&&mac[2]==0xff&&mac[3]==0xff&&mac[4]==0xff&&mac[5]==0xff)){
|
||||
if(flash_Wrtie(FLASH_ADD_STORE_MAC, mac, ETH_ALEN) < 0){
|
||||
printf("\n\r[%s] Write MAC failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Write config sectors
|
||||
address = CONFIG_SECTOR;
|
||||
if( (flash_Wrtie(address, (char*)&size, 4) < 0) ||
|
||||
(flash_Wrtie(address+4, (char*)&checksum, 4) < 0) ){
|
||||
printf("\n\r[%s] Write sector failed", __FUNCTION__);
|
||||
goto update_ota_exit;
|
||||
}
|
||||
printf("\n\r[%s] Update OTA success!", __FUNCTION__);
|
||||
|
||||
update_ota_exit:
|
||||
updater_free_ctx(&ctx);
|
||||
update_ota_exit_1:
|
||||
if(buf)
|
||||
update_free(buf);
|
||||
if(param)
|
||||
update_free(param);
|
||||
TaskOTA = NULL;
|
||||
printf("\n\r[%s] Update task exit", __FUNCTION__);
|
||||
vTaskDelete(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
int update_ota_cloud(char *repository, char *file_path)
|
||||
{
|
||||
update_cfg_cloud_t *pUpdateCfg;
|
||||
|
||||
if(TaskOTA){
|
||||
printf("\n\r[%s] Update task has created.", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
pUpdateCfg = update_malloc(sizeof(update_cfg_cloud_t));
|
||||
if(pUpdateCfg == NULL){
|
||||
printf("\n\r[%s] Alloc update cfg failed.", __FUNCTION__);
|
||||
goto exit;
|
||||
}
|
||||
if(strlen(repository) > (REPOSITORY_LEN-1)){
|
||||
printf("\n\r[%s] Repository length is too long.", __FUNCTION__);
|
||||
goto exit;
|
||||
}
|
||||
if(strlen(file_path) > (FILE_PATH_LEN-1)){
|
||||
printf("\n\r[%s] File path length is too long.", __FUNCTION__);
|
||||
goto exit;
|
||||
}
|
||||
strcpy((char*)pUpdateCfg->repository, repository);
|
||||
strcpy((char*)pUpdateCfg->file_path, file_path);
|
||||
|
||||
TaskOTA = sys_thread_new("OTA_server", update_ota_cloud_task, pUpdateCfg, STACK_SIZE, TASK_PRIORITY);
|
||||
if(TaskOTA == NULL){
|
||||
printf("\n\r[%s] Create update task failed", __FUNCTION__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
exit:
|
||||
update_free(pUpdateCfg);
|
||||
return 0;
|
||||
}
|
||||
#endif // #if (SERVER_TYPE == SERVER_CLOUD)
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
void cmd_update(int argc, char **argv)
|
||||
{
|
||||
// printf("\n\r[%s] Firmware A", __FUNCTION__);
|
||||
#if (SERVER_TYPE == SERVER_LOCAL)
|
||||
int port;
|
||||
if(argc != 3){
|
||||
printf("\n\r[%s] Usage: update IP PORT", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
port = atoi(argv[2]);
|
||||
update_ota_local(argv[1], port);
|
||||
#endif
|
||||
#if (SERVER_TYPE == SERVER_CLOUD)
|
||||
if(argc != 3){
|
||||
printf("\n\r[%s] Usage: update REPOSITORY FILE_PATH", __FUNCTION__);
|
||||
return;
|
||||
}
|
||||
update_ota_cloud(argv[1], argv[2]);
|
||||
#endif
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
|
||||
10
component/common/utilities/update.h
Normal file
10
component/common/utilities/update.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#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);
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
#endif
|
||||
1197
component/common/utilities/webserver.c
Normal file
1197
component/common/utilities/webserver.c
Normal file
File diff suppressed because it is too large
Load diff
71
component/common/utilities/webserver.h
Normal file
71
component/common/utilities/webserver.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
FreeRTOS V6.0.4 - Copyright (C) 2010 Real Time Engineers Ltd.
|
||||
|
||||
***************************************************************************
|
||||
* *
|
||||
* If you are: *
|
||||
* *
|
||||
* + New to FreeRTOS, *
|
||||
* + Wanting to learn FreeRTOS or multitasking in general quickly *
|
||||
* + Looking for basic training, *
|
||||
* + Wanting to improve your FreeRTOS skills and productivity *
|
||||
* *
|
||||
* then take a look at the FreeRTOS eBook *
|
||||
* *
|
||||
* "Using the FreeRTOS Real Time Kernel - a Practical Guide" *
|
||||
* http://www.FreeRTOS.org/Documentation *
|
||||
* *
|
||||
* A pdf reference manual is also available. Both are usually delivered *
|
||||
* to your inbox within 20 minutes to two hours when purchased between 8am *
|
||||
* and 8pm GMT (although please allow up to 24 hours in case of *
|
||||
* exceptional circumstances). Thank you for your support! *
|
||||
* *
|
||||
***************************************************************************
|
||||
|
||||
This file is part of the FreeRTOS distribution.
|
||||
|
||||
FreeRTOS is free software; you can redistribute it and/or modify it under
|
||||
the terms of the GNU General Public License (version 2) as published by the
|
||||
Free Software Foundation AND MODIFIED BY the FreeRTOS exception.
|
||||
***NOTE*** The exception to the GPL is included to allow you to distribute
|
||||
a combined work that includes FreeRTOS without being obliged to provide the
|
||||
source code for proprietary components outside of the FreeRTOS kernel.
|
||||
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
more details. You should have received a copy of the GNU General Public
|
||||
License and the FreeRTOS license exception along with FreeRTOS; if not it
|
||||
can be viewed here: http://www.freertos.org/a00114.html and also obtained
|
||||
by writing to Richard Barry, contact details for whom are available on the
|
||||
FreeRTOS WEB site.
|
||||
|
||||
1 tab == 4 spaces!
|
||||
|
||||
http://www.FreeRTOS.org - Documentation, latest information, license and
|
||||
contact details.
|
||||
|
||||
http://www.SafeRTOS.com - A version that is certified for use in safety
|
||||
critical systems.
|
||||
|
||||
http://www.OpenRTOS.com - Commercial support, development, porting,
|
||||
licensing and training services.
|
||||
*/
|
||||
|
||||
#ifndef BASIC_WEB_SERVER_H
|
||||
#define BASIC_WEB_SERVER_H
|
||||
#include <wifi/wifi_conf.h>
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/* MACROS */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
#define basicwebWEBSERVER_PRIORITY ( tskIDLE_PRIORITY + 2 )
|
||||
|
||||
#define lwipBASIC_SERVER_STACK_SIZE 256
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
/* The function that implements the WEB server task. */
|
||||
extern void start_web_server(void);
|
||||
|
||||
#endif /*
|
||||
*/
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue