Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
K
k-sdk
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
陈伟灿
k-sdk
Commits
e5cd9e56
Commit
e5cd9e56
authored
Sep 30, 2020
by
尹佳钦
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
2020 0930
parent
e5950adc
Changes
29
Hide whitespace changes
Inline
Side-by-side
Showing
29 changed files
with
2279 additions
and
2234 deletions
+2279
-2234
platform/zigbee/app/builder/Z3GatewayHost/ZB/kk_device_manager.c
...m/zigbee/app/builder/Z3GatewayHost/ZB/kk_device_manager.c
+3
-0
platform/zigbee/app/builder/Z3GatewayHost/rpc_api/src/rpc_interface_parse.c
...p/builder/Z3GatewayHost/rpc_api/src/rpc_interface_parse.c
+1
-1
platform/zigbee/platform/base/hal/micro/unix/host/micro.c
platform/zigbee/platform/base/hal/micro/unix/host/micro.c
+3
-3
platform/zigbee/protocol/zigbee/app/ezsp-host/ash/ash-host-ui.c
...rm/zigbee/protocol/zigbee/app/ezsp-host/ash/ash-host-ui.c
+173
-172
platform/zigbee/protocol/zigbee/app/ezsp-host/ash/ash-host-ui.h
...rm/zigbee/protocol/zigbee/app/ezsp-host/ash/ash-host-ui.h
+25
-25
platform/zigbee/protocol/zigbee/app/ezsp-host/ezsp-host-io.c
platform/zigbee/protocol/zigbee/app/ezsp-host/ezsp-host-io.c
+1
-0
platform/zigbee/protocol/zigbee/app/ezsp-host/ezsp-host-ui.c
platform/zigbee/protocol/zigbee/app/ezsp-host/ezsp-host-ui.c
+14
-14
platform/zigbee/protocol/zigbee/app/framework/include/af-types.h
...m/zigbee/protocol/zigbee/app/framework/include/af-types.h
+61
-61
platform/zigbee/protocol/zigbee/app/framework/plugin-host/gateway/backchannel-support.c
...e/app/framework/plugin-host/gateway/backchannel-support.c
+122
-122
platform/zigbee/protocol/zigbee/app/framework/plugin-host/gateway/gateway-support.c
...igbee/app/framework/plugin-host/gateway/gateway-support.c
+30
-30
platform/zigbee/protocol/zigbee/app/framework/plugin-host/gateway/gateway-support.h
...igbee/app/framework/plugin-host/gateway/gateway-support.h
+4
-4
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-common/ota-cli.h
...protocol/zigbee/app/framework/plugin/ota-common/ota-cli.h
+1
-1
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-common/ota-common.c
...tocol/zigbee/app/framework/plugin/ota-common/ota-common.c
+9
-9
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server-policy/ota-server-policy.c
...pp/framework/plugin/ota-server-policy/ota-server-policy.c
+202
-197
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server-cli.c
...l/zigbee/app/framework/plugin/ota-server/ota-server-cli.c
+2
-2
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server-dynamic-block-period.c
...ework/plugin/ota-server/ota-server-dynamic-block-period.c
+7
-7
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server-page-request.c
...app/framework/plugin/ota-server/ota-server-page-request.c
+4
-4
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server.c
...tocol/zigbee/app/framework/plugin/ota-server/ota-server.c
+399
-352
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage-common-cli.c
...mework/plugin/ota-storage-common/ota-storage-common-cli.c
+2
-2
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage-common.c
.../framework/plugin/ota-storage-common/ota-storage-common.c
+15
-15
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage.h
...bee/app/framework/plugin/ota-storage-common/ota-storage.h
+9
-9
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-posix-filesystem/ota-storage-linux.c
...k/plugin/ota-storage-posix-filesystem/ota-storage-linux.c
+1033
-1041
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-posix-filesystem/ota-storage-linux.h
...k/plugin/ota-storage-posix-filesystem/ota-storage-linux.h
+6
-6
platform/zigbee/protocol/zigbee/app/framework/security/af-security-common.c
...otocol/zigbee/app/framework/security/af-security-common.c
+1
-1
platform/zigbee/protocol/zigbee/app/framework/util/af-main-host.c
.../zigbee/protocol/zigbee/app/framework/util/af-main-host.c
+5
-9
platform/zigbee/protocol/zigbee/app/framework/util/client-api.c
...rm/zigbee/protocol/zigbee/app/framework/util/client-api.c
+2
-2
platform/zigbee/protocol/zigbee/app/framework/util/process-cluster-message.c
...tocol/zigbee/app/framework/util/process-cluster-message.c
+5
-5
platform/zigbee/protocol/zigbee/app/framework/util/util.c
platform/zigbee/protocol/zigbee/app/framework/util/util.c
+1
-1
platform/zigbee/protocol/zigbee/app/util/serial/linux-serial.c
...orm/zigbee/protocol/zigbee/app/util/serial/linux-serial.c
+139
-139
No files found.
platform/zigbee/app/builder/Z3GatewayHost/ZB/kk_device_manager.c
View file @
e5cd9e56
...
@@ -156,6 +156,9 @@ void emberAfPluginDeviceTableDeviceLeftCallback(EmberEUI64 nodeEui64)
...
@@ -156,6 +156,9 @@ void emberAfPluginDeviceTableDeviceLeftCallback(EmberEUI64 nodeEui64)
rpc_printfJSON
(
"left"
,
nodeJson
);
rpc_printfJSON
(
"left"
,
nodeJson
);
kk_msg_report_dev_leave
(
deviceTable
[
deviceTableIndex
].
eui64
);
kk_msg_report_dev_leave
(
deviceTable
[
deviceTableIndex
].
eui64
);
kk_device_table_delete
(
deviceTable
[
deviceTableIndex
].
eui64
);
kk_device_db_delete
(
deviceTable
[
deviceTableIndex
].
eui64
);
}
}
...
...
platform/zigbee/app/builder/Z3GatewayHost/rpc_api/src/rpc_interface_parse.c
View file @
e5cd9e56
...
@@ -266,7 +266,7 @@ int _init_param(struct jrpc_server *server) {
...
@@ -266,7 +266,7 @@ int _init_param(struct jrpc_server *server) {
//kk_zlog_init("paltform");
//kk_zlog_init("paltform");
printf
(
"getenv
\r\n
"
);
printf
(
"getenv
\r\n
"
);
char
*
debug_level_env
=
getenv
(
"
HOME
"
);
char
*
debug_level_env
=
getenv
(
"
JRPC_DEBUG
"
);
printf
(
"getenv(JRPC_DEBUG):%s
\n
"
,
server
->
debug_level
);
printf
(
"getenv(JRPC_DEBUG):%s
\n
"
,
server
->
debug_level
);
if
(
debug_level_env
==
NULL
)
if
(
debug_level_env
==
NULL
)
server
->
debug_level
=
0
;
server
->
debug_level
=
0
;
...
...
platform/zigbee/platform/base/hal/micro/unix/host/micro.c
View file @
e5cd9e56
...
@@ -47,13 +47,13 @@ void halReboot(void)
...
@@ -47,13 +47,13 @@ void halReboot(void)
uint8_t
halGetResetInfo
(
void
)
uint8_t
halGetResetInfo
(
void
)
{
{
return
RESET_SOFTWARE
;
return
RESET_SOFTWARE
;
}
}
PGM_P
halGetResetString
(
void
)
PGM_P
halGetResetString
(
void
)
{
{
static
PGM_P
resetString
=
"SOFTWARE"
;
static
PGM_P
resetString
=
"SOFTWARE"
;
return
(
resetString
);
return
(
resetString
);
}
}
// Ideally this should not be necessary, but the serial code references
// Ideally this should not be necessary, but the serial code references
...
...
platform/zigbee/protocol/zigbee/app/ezsp-host/ash/ash-host-ui.c
View file @
e5cd9e56
...
@@ -36,9 +36,10 @@
...
@@ -36,9 +36,10 @@
static
const
char
options
[]
=
"b:f:hv::i:n:o:p:r:s:t:x:"
;
static
const
char
options
[]
=
"b:f:hv::i:n:o:p:r:s:t:x:"
;
bool
checkSerialPort
(
const
char
*
portString
);
bool
checkSerialPort
(
const
char
*
portString
);
bool
ezspInternalProcessCommandOptions
(
int
argc
,
char
*
argv
[],
char
*
errStr
)
bool
ezspInternalProcessCommandOptions
(
int
argc
,
char
*
argv
[],
char
*
errStr
)
{
{
int
c
;
int
c
;
char
port
[
ASH_PORT_LEN
];
char
port
[
ASH_PORT_LEN
];
char
devport
[
ASH_PORT_LEN
];
char
devport
[
ASH_PORT_LEN
];
uint32_t
baud
;
uint32_t
baud
;
...
@@ -48,181 +49,181 @@ bool ezspInternalProcessCommandOptions(int argc, char *argv[], char *errStr)
...
@@ -48,181 +49,181 @@ bool ezspInternalProcessCommandOptions(int argc, char *argv[], char *errStr)
uint8_t
portnum
;
uint8_t
portnum
;
uint8_t
cfg
;
uint8_t
cfg
;
int
blksize
;
int
blksize
;
int
optionCount
=
0
;
int
optionCount
=
0
;
if
(
!
argv
||
!
errStr
)
{
if
(
!
argv
||
!
errStr
)
{
snprintf
(
errStr
,
ERR_LEN
,
"Error: argv[] is %s and errStr is %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Error: argv[] is %s and errStr is %s.
\n
"
,
argv
?
"valid"
:
"NULL"
,
argv
?
"valid"
:
"NULL"
,
errStr
?
"valid"
:
"NULL"
);
errStr
?
"valid"
:
"NULL"
);
return
false
;
return
false
;
}
}
while
(
true
)
{
while
(
true
)
{
c
=
getopt
(
argc
,
argv
,
options
);
c
=
getopt
(
argc
,
argv
,
options
);
if
(
c
==
-
1
)
{
if
(
c
==
-
1
)
{
if
(
optind
!=
argc
)
{
if
(
optind
!=
argc
)
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid option %s.
\n
"
,
argv
[
optind
]);
snprintf
(
errStr
,
ERR_LEN
,
"Invalid option %s.
\n
"
,
argv
[
optind
]);
}
}
break
;
break
;
}
}
optionCount
++
;
optionCount
++
;
switch
(
c
)
{
switch
(
c
)
{
case
'b'
:
case
'b'
:
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%u"
,
&
baud
)
!=
1
))
{
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%u"
,
&
baud
)
!=
1
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid baud rate %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid baud rate %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
{
}
else
{
ashWriteConfig
(
baudRate
,
baud
);
ashWriteConfig
(
baudRate
,
baud
);
}
}
break
;
break
;
case
'f'
:
case
'f'
:
if
(
!
optarg
)
{
if
(
!
optarg
)
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid flow control choice NULL.
\n
"
);
snprintf
(
errStr
,
ERR_LEN
,
"Invalid flow control choice NULL.
\n
"
);
break
;
break
;
}
}
switch
(
*
optarg
)
{
switch
(
*
optarg
)
{
case
'r'
:
case
'r'
:
ashWriteConfig
(
rtsCts
,
true
);
ashWriteConfig
(
rtsCts
,
true
);
break
;
break
;
case
'x'
:
case
'x'
:
ashWriteConfig
(
rtsCts
,
false
);
ashWriteConfig
(
rtsCts
,
false
);
break
;
break
;
default:
default:
snprintf
(
errStr
,
ERR_LEN
,
"Invalid flow control choice %s.
\n
"
,
optarg
);
snprintf
(
errStr
,
ERR_LEN
,
"Invalid flow control choice %s.
\n
"
,
optarg
);
}
}
break
;
break
;
case
'h'
:
case
'h'
:
case
'?'
:
case
'?'
:
snprintf
(
errStr
,
ERR_LEN
,
"
\n
"
);
snprintf
(
errStr
,
ERR_LEN
,
"
\n
"
);
break
;
break
;
case
'i'
:
case
'i'
:
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
enable
)
!=
1
)
||
(
enable
>
1
))
{
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
enable
)
!=
1
)
||
(
enable
>
1
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid input buffer choice %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid input buffer choice %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
{
}
else
{
blksize
=
enable
?
256
:
1
;
blksize
=
enable
?
256
:
1
;
ashWriteConfig
(
inBlockLen
,
blksize
);
ashWriteConfig
(
inBlockLen
,
blksize
);
}
}
break
;
break
;
case
'n'
:
case
'n'
:
if
(
optionCount
!=
1
)
{
if
(
optionCount
!=
1
)
{
snprintf
(
errStr
,
ERR_LEN
,
"NCP option, if present, must be first.
\n
"
);
snprintf
(
errStr
,
ERR_LEN
,
"NCP option, if present, must be first.
\n
"
);
}
else
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
cfg
)
!=
1
)
||
(
cfg
>
1
))
{
}
else
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
cfg
)
!=
1
)
||
(
cfg
>
1
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid NCP config choice %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid NCP config choice %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
{
}
else
{
ashSelectHostConfig
(
cfg
);
ashSelectHostConfig
(
cfg
);
}
}
break
;
break
;
case
'o'
:
case
'o'
:
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
enable
)
!=
1
)
||
(
enable
>
1
))
{
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
enable
)
!=
1
)
||
(
enable
>
1
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid output buffer choice %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid output buffer choice %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
{
}
else
{
blksize
=
enable
?
256
:
1
;
blksize
=
enable
?
256
:
1
;
ashWriteConfig
(
outBlockLen
,
blksize
);
ashWriteConfig
(
outBlockLen
,
blksize
);
}
}
break
;
break
;
case
'p'
:
case
'p'
:
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%39s"
,
port
)
<=
0
))
{
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%39s"
,
port
)
<=
0
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid serial port name %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid serial port name %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
if
(
strlen
(
port
)
>=
ASH_PORT_LEN
-
1
)
{
}
else
if
(
strlen
(
port
)
>=
ASH_PORT_LEN
-
1
)
{
snprintf
(
errStr
,
ERR_LEN
,
"Serial port name %s too long.
\n
"
,
port
);
snprintf
(
errStr
,
ERR_LEN
,
"Serial port name %s too long.
\n
"
,
port
);
}
else
{
}
else
{
// Handle some common variations specifying a serial port
// Handle some common variations specifying a serial port
strncpy
(
devport
,
"/dev/"
,
5
);
strncpy
(
devport
,
"/dev/"
,
5
);
devport
[
5
]
=
'\0'
;
devport
[
5
]
=
'\0'
;
if
(
strncmp
(
devport
,
port
,
5
)
==
0
)
{
if
(
strncmp
(
devport
,
port
,
5
)
==
0
)
{
strncat
(
devport
,
port
+
5
,
ASH_PORT_LEN
-
5
-
1
);
strncat
(
devport
,
port
+
5
,
ASH_PORT_LEN
-
5
-
1
);
#ifdef __CYGWIN__
#ifdef __CYGWIN__
}
else
if
(
((
strncmp
(
"COM"
,
port
,
3
)
==
0
)
}
else
if
(
((
strncmp
(
"COM"
,
port
,
3
)
==
0
)
||
(
strncmp
(
"com"
,
port
,
3
)
==
0
)
)
||
(
strncmp
(
"com"
,
port
,
3
)
==
0
)
)
&&
(
sscanf
(
port
+
3
,
"%hhu"
,
&
portnum
)
==
1
)
&&
(
sscanf
(
port
+
3
,
"%hhu"
,
&
portnum
)
==
1
)
&&
(
portnum
>
0
)
)
{
&&
(
portnum
>
0
)
)
{
snprintf
(
devport
,
ASH_PORT_LEN
,
"/dev/ttyS%hhu"
,
portnum
-
1
);
snprintf
(
devport
,
ASH_PORT_LEN
,
"/dev/ttyS%hhu"
,
portnum
-
1
);
}
else
if
(
(
sscanf
(
port
,
"%hhu"
,
&
portnum
)
==
1
)
&&
portnum
)
{
}
else
if
(
(
sscanf
(
port
,
"%hhu"
,
&
portnum
)
==
1
)
&&
portnum
)
{
snprintf
(
devport
,
ASH_PORT_LEN
,
"/dev/ttyS%hhu"
,
portnum
-
1
);
snprintf
(
devport
,
ASH_PORT_LEN
,
"/dev/ttyS%hhu"
,
portnum
-
1
);
#else
#else
}
else
if
(
sscanf
(
port
,
"%hhu"
,
&
portnum
)
==
1
)
{
}
else
if
(
sscanf
(
port
,
"%hhu"
,
&
portnum
)
==
1
)
{
snprintf
(
devport
,
ASH_PORT_LEN
,
"/dev/ttyS%hhu"
,
portnum
);
snprintf
(
devport
,
ASH_PORT_LEN
,
"/dev/ttyS%hhu"
,
portnum
);
#endif
#endif
}
else
{
}
else
{
strncat
(
devport
,
port
,
ASH_PORT_LEN
-
1
);
strncat
(
devport
,
port
,
ASH_PORT_LEN
-
1
);
}
}
strncpy
(
ashHostConfig
.
serialPort
,
devport
,
ASH_PORT_LEN
-
1
);
strncpy
(
ashHostConfig
.
serialPort
,
devport
,
ASH_PORT_LEN
-
1
);
ashHostConfig
.
serialPort
[
ASH_PORT_LEN
-
1
]
=
'\0'
;
ashHostConfig
.
serialPort
[
ASH_PORT_LEN
-
1
]
=
'\0'
;
if
(
!
checkSerialPort
(
ashHostConfig
.
serialPort
))
{
if
(
!
checkSerialPort
(
ashHostConfig
.
serialPort
))
{
return
false
;
return
false
;
}
}
}
}
break
;
break
;
case
'r'
:
case
'r'
:
if
(
!
optarg
)
{
if
(
!
optarg
)
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid reset method NULL.
\n
"
);
snprintf
(
errStr
,
ERR_LEN
,
"Invalid reset method NULL.
\n
"
);
break
;
break
;
}
}
switch
(
*
optarg
)
{
switch
(
*
optarg
)
{
case
'r'
:
case
'r'
:
ashWriteConfig
(
resetMethod
,
ASH_RESET_METHOD_RST
);
ashWriteConfig
(
resetMethod
,
ASH_RESET_METHOD_RST
);
break
;
break
;
case
'd'
:
case
'd'
:
ashWriteConfig
(
resetMethod
,
ASH_RESET_METHOD_DTR
);
ashWriteConfig
(
resetMethod
,
ASH_RESET_METHOD_DTR
);
break
;
break
;
case
'c'
:
case
'c'
:
ashWriteConfig
(
resetMethod
,
ASH_RESET_METHOD_CUSTOM
);
ashWriteConfig
(
resetMethod
,
ASH_RESET_METHOD_CUSTOM
);
break
;
break
;
default:
default:
snprintf
(
errStr
,
ERR_LEN
,
"Invalid reset method %s.
\n
"
,
optarg
);
snprintf
(
errStr
,
ERR_LEN
,
"Invalid reset method %s.
\n
"
,
optarg
);
}
}
break
;
break
;
case
's'
:
case
's'
:
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
stops
)
!=
1
)
||
(
stops
<
1
)
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
stops
)
!=
1
)
||
(
stops
<
1
)
||
(
stops
>
2
))
{
||
(
stops
>
2
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid number of stop bits %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid number of stop bits %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
{
}
else
{
ashWriteConfig
(
stopBits
,
stops
);
ashWriteConfig
(
stopBits
,
stops
);
}
}
break
;
break
;
case
't'
:
case
't'
:
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
trace
)
!=
1
))
{
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
trace
)
!=
1
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid trace flag value %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid trace flag value %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
{
}
else
{
ashWriteConfig
(
traceFlags
,
trace
);
ashWriteConfig
(
traceFlags
,
trace
);
}
}
break
;
break
;
case
'v'
:
case
'v'
:
if
(
!
backchannelSupported
)
{
if
(
!
backchannelSupported
)
{
fprintf
(
stderr
,
"Error: Backchannel support not compiled into this application.
\n
"
);
fprintf
(
stderr
,
"Error: Backchannel support not compiled into this application.
\n
"
);
exit
(
1
);
exit
(
1
);
}
}
backchannelEnable
=
true
;
backchannelEnable
=
true
;
if
(
optarg
)
{
if
(
optarg
)
{
int
port
=
atoi
(
optarg
);
int
port
=
atoi
(
optarg
);
if
(
port
==
0
||
port
>
65535
)
{
if
(
port
==
0
||
port
>
65535
)
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid virtual ISA port number '%d'.
\n
"
,
port
);
snprintf
(
errStr
,
ERR_LEN
,
"Invalid virtual ISA port number '%d'.
\n
"
,
port
);
}
}
backchannelSerialPortOffset
=
port
;
backchannelSerialPortOffset
=
port
;
}
}
break
;
break
;
case
'x'
:
case
'x'
:
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
enable
)
!=
1
)
||
(
enable
>
1
))
{
if
(
!
optarg
||
(
sscanf
(
optarg
,
"%hhu"
,
&
enable
)
!=
1
)
||
(
enable
>
1
))
{
snprintf
(
errStr
,
ERR_LEN
,
"Invalid randomization choice %s.
\n
"
,
snprintf
(
errStr
,
ERR_LEN
,
"Invalid randomization choice %s.
\n
"
,
optarg
?
optarg
:
"NULL"
);
optarg
?
optarg
:
"NULL"
);
}
else
{
}
else
{
ashWriteConfig
(
randomize
,
enable
);
ashWriteConfig
(
randomize
,
enable
);
}
}
break
;
break
;
default:
default:
assert
(
1
);
assert
(
1
);
break
;
break
;
}
// end of switch (c)
}
// end of switch (c)
}
//end while
}
//end while
return
true
;
return
true
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
...
platform/zigbee/protocol/zigbee/app/ezsp-host/ash/ash-host-ui.h
View file @
e5cd9e56
...
@@ -31,31 +31,31 @@ void ashPrintCounters(AshCount *counters, bool clear);
...
@@ -31,31 +31,31 @@ void ashPrintCounters(AshCount *counters, bool clear);
void
ashClearCounters
(
AshCount
*
counters
);
void
ashClearCounters
(
AshCount
*
counters
);
static
const
char
usage
[]
=
static
const
char
usage
[]
=
" {ncp type} {options}
\n
"
" {ncp type} {options}
\n
"
" ncp type:
\n
"
" ncp type:
\n
"
" -n 0,1 0=EM2xx/EM3xx @ 115200 bps, RTS/CTS
\n
"
" -n 0,1 0=EM2xx/EM3xx @ 115200 bps, RTS/CTS
\n
"
" 1=EM2xx/EM3xx @ 57600 bps, XON/XOFF
\n
"
" 1=EM2xx/EM3xx @ 57600 bps, XON/XOFF
\n
"
" (if present must be the first option)
\n
"
" (if present must be the first option)
\n
"
" options:
\n
"
" options:
\n
"
" -b <baud rate> 9600, 19200, 38400, 57600, 115200, etc.
\n
"
" -b <baud rate> 9600, 19200, 38400, 57600, 115200, etc.
\n
"
" -f r,x flow control: r=RST/CTS, x=XON/XOFF
\n
"
" -f r,x flow control: r=RST/CTS, x=XON/XOFF
\n
"
" -h display usage information
\n
"
" -h display usage information
\n
"
" -i 0,1 enable/disable input buffering
\n
"
" -i 0,1 enable/disable input buffering
\n
"
" -o 0,1 enable/disable output buffering
\n
"
" -o 0,1 enable/disable output buffering
\n
"
" -p <port> serial port name or number (eg, COM1, ttyS0, or 1)
\n
"
" -p <port> serial port name or number (eg, COM1, ttyS0, or 1)
\n
"
" -r d,r,c ncp reset method: d=DTR, r=RST frame, c=custom
\n
"
" -r d,r,c ncp reset method: d=DTR, r=RST frame, c=custom
\n
"
" -s 1,2 stop bits
\n
"
" -s 1,2 stop bits
\n
"
" -t <trace flags> trace B0=frames, B1=verbose frames, B2=events, B3=EZSP
\n
"
" -t <trace flags> trace B0=frames, B1=verbose frames, B2=events, B3=EZSP
\n
"
" -v[base-port] enables virtual ISA support. The [base-port] argument
\n
"
" -v[base-port] enables virtual ISA support. The [base-port] argument
\n
"
" is optional. Both serial ports are available via telnet
\n
"
" is optional. Both serial ports are available via telnet
\n
"
" instead of local console. RAW serial port is available
\n
"
" instead of local console. RAW serial port is available
\n
"
" on the first port (offset 0 from base port), and CLI is
\n
"
" on the first port (offset 0 from base port), and CLI is
\n
"
" available on the second port (offset 1 from base port).
\n
"
" available on the second port (offset 1 from base port).
\n
"
" By default, 4900 is the base-port, therefore RAW access
\n
"
" By default, 4900 is the base-port, therefore RAW access
\n
"
" is available from port 4900, and CLI access is available
\n
"
" is available from port 4900, and CLI access is available
\n
"
" on port 4901.
\n
"
" on port 4901.
\n
"
" NOTE: No space is allowed between '-v' and [base-port].
\n
"
" NOTE: No space is allowed between '-v' and [base-port].
\n
"
" -x 0,1 enable/disable data randomization
\n
"
;
" -x 0,1 enable/disable data randomization
\n
"
;
static
const
AshCount
zeroAshCount
=
{
0
};
static
const
AshCount
zeroAshCount
=
{
0
};
...
...
platform/zigbee/protocol/zigbee/app/ezsp-host/ezsp-host-io.c
View file @
e5cd9e56
...
@@ -559,6 +559,7 @@ bool ezspSerialPortRegisterCallback(EzspSerialPortCallbackFunction callback)
...
@@ -559,6 +559,7 @@ bool ezspSerialPortRegisterCallback(EzspSerialPortCallbackFunction callback)
void
ezspSerialWriteByte
(
uint8_t
byte
)
void
ezspSerialWriteByte
(
uint8_t
byte
)
{
{
BUMP_HOST_COUNTER
(
txBytes
);
BUMP_HOST_COUNTER
(
txBytes
);
#ifdef IO_LOG
#ifdef IO_LOG
{
{
...
...
platform/zigbee/protocol/zigbee/app/ezsp-host/ezsp-host-ui.c
View file @
e5cd9e56
...
@@ -66,10 +66,10 @@
...
@@ -66,10 +66,10 @@
void
ezspPrintUsage
(
char
*
name
)
void
ezspPrintUsage
(
char
*
name
)
{
{
char
*
shortName
=
strrchr
(
name
,
'/'
);
char
*
shortName
=
strrchr
(
name
,
'/'
);
shortName
=
shortName
?
shortName
+
1
:
name
;
shortName
=
shortName
?
shortName
+
1
:
name
;
fprintf
(
stderr
,
"Usage: %s"
,
shortName
);
fprintf
(
stderr
,
"Usage: %s"
,
shortName
);
fprintf
(
stderr
,
usage
);
fprintf
(
stderr
,
usage
);
}
}
#ifdef __CYGWIN__
#ifdef __CYGWIN__
...
@@ -103,16 +103,16 @@ bool checkSerialPort(const char* portString, bool silent)
...
@@ -103,16 +103,16 @@ bool checkSerialPort(const char* portString, bool silent)
bool
ezspProcessCommandOptions
(
int
argc
,
char
*
argv
[])
bool
ezspProcessCommandOptions
(
int
argc
,
char
*
argv
[])
{
{
char
errStr
[
ERR_LEN
]
=
""
;
char
errStr
[
ERR_LEN
]
=
""
;
if
(
!
ezspInternalProcessCommandOptions
(
argc
,
argv
,
errStr
))
{
if
(
!
ezspInternalProcessCommandOptions
(
argc
,
argv
,
errStr
))
{
return
false
;
return
false
;
}
}
if
(
*
errStr
!=
'\0'
)
{
if
(
*
errStr
!=
'\0'
)
{
fprintf
(
stderr
,
"%s"
,
errStr
);
fprintf
(
stderr
,
"%s"
,
errStr
);
ezspPrintUsage
(
argv
[
0
]);
ezspPrintUsage
(
argv
[
0
]);
}
}
return
(
*
errStr
==
'\0'
);
return
(
*
errStr
==
'\0'
);
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
...
platform/zigbee/protocol/zigbee/app/framework/include/af-types.h
View file @
e5cd9e56
...
@@ -1122,26 +1122,26 @@ typedef struct {
...
@@ -1122,26 +1122,26 @@ typedef struct {
* an upgrade file.
* an upgrade file.
*/
*/
typedef
struct
{
typedef
struct
{
uint16_t
manufacturerId
;
uint16_t
manufacturerId
;
uint16_t
imageTypeId
;
uint16_t
imageTypeId
;
uint32_t
firmwareVersion
;
uint32_t
firmwareVersion
;
/**
/**
* This is only used for device specific files.
* This is only used for device specific files.
* It will be set to all 0's when the image does not
* It will be set to all 0's when the image does not
* have an upgrade destination field in it.
* have an upgrade destination field in it.
* Little endian format.
* Little endian format.
*/
*/
uint8_t
deviceSpecificFileEui64
[
EUI64_SIZE
];
uint8_t
deviceSpecificFileEui64
[
EUI64_SIZE
];
}
EmberAfOtaImageId
;
}
EmberAfOtaImageId
;
/**
/**
* @brief The list of options possible for the image block request/response.
* @brief The list of options possible for the image block request/response.
*/
*/
enum
{
enum
{
EMBER_AF_IMAGE_BLOCK_REQUEST_OPTIONS_NONE
=
0
,
EMBER_AF_IMAGE_BLOCK_REQUEST_OPTIONS_NONE
=
0
,
EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_CLIENT
=
1
,
EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_CLIENT
=
1
,
EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_SERVER
=
2
,
EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_SERVER
=
2
,
};
};
typedef
uint8_t
EmberAfImageBlockRequestOptions
;
typedef
uint8_t
EmberAfImageBlockRequestOptions
;
...
@@ -1150,18 +1150,18 @@ typedef uint8_t EmberAfImageBlockRequestOptions;
...
@@ -1150,18 +1150,18 @@ typedef uint8_t EmberAfImageBlockRequestOptions;
* emberAfImageBlockRequestCallback() to let the application decide what to do.
* emberAfImageBlockRequestCallback() to let the application decide what to do.
*/
*/
typedef
struct
{
typedef
struct
{
const
EmberAfOtaImageId
*
id
;
const
EmberAfOtaImageId
*
id
;
uint32_t
offset
;
uint32_t
offset
;
uint32_t
waitTimeSecondsResponse
;
uint32_t
waitTimeSecondsResponse
;
EmberNodeId
source
;
EmberNodeId
source
;
EmberEUI64
sourceEui
;
// optionally present in messages
EmberEUI64
sourceEui
;
// optionally present in messages
// The minBlockRequestPeriod can be treated as milliseconds or seconds on the
// The minBlockRequestPeriod can be treated as milliseconds or seconds on the
// client. The OTA server plugin has optional support to probe clients and
// client. The OTA server plugin has optional support to probe clients and
// treat this field with appropriate units (ms or sec)
// treat this field with appropriate units (ms or sec)
uint16_t
minBlockRequestPeriod
;
// optionally present in messages
uint16_t
minBlockRequestPeriod
;
// optionally present in messages
uint8_t
maxDataSize
;
uint8_t
maxDataSize
;
uint8_t
clientEndpoint
;
uint8_t
clientEndpoint
;
EmberAfImageBlockRequestOptions
bitmask
;
EmberAfImageBlockRequestOptions
bitmask
;
}
EmberAfImageBlockRequestCallbackStruct
;
}
EmberAfImageBlockRequestCallbackStruct
;
/**
/**
...
@@ -1169,11 +1169,11 @@ typedef struct {
...
@@ -1169,11 +1169,11 @@ typedef struct {
* device operation.
* device operation.
*/
*/
typedef
enum
{
typedef
enum
{
EMBER_AF_OTA_STORAGE_SUCCESS
=
0
,
EMBER_AF_OTA_STORAGE_SUCCESS
=
0
,
EMBER_AF_OTA_STORAGE_ERROR
=
1
,
EMBER_AF_OTA_STORAGE_ERROR
=
1
,
EMBER_AF_OTA_STORAGE_RETURN_DATA_TOO_LONG
=
2
,
EMBER_AF_OTA_STORAGE_RETURN_DATA_TOO_LONG
=
2
,
EMBER_AF_OTA_STORAGE_PARTIAL_FILE_FOUND
=
3
,
EMBER_AF_OTA_STORAGE_PARTIAL_FILE_FOUND
=
3
,
EMBER_AF_OTA_STORAGE_OPERATION_IN_PROGRESS
=
4
,
EMBER_AF_OTA_STORAGE_OPERATION_IN_PROGRESS
=
4
,
}
EmberAfOtaStorageStatus
;
}
EmberAfOtaStorageStatus
;
/**
/**
...
@@ -1203,41 +1203,41 @@ typedef uint8_t EmberAfOtaDownloadResult;
...
@@ -1203,41 +1203,41 @@ typedef uint8_t EmberAfOtaDownloadResult;
* It is not a byte-for-byte copy.
* It is not a byte-for-byte copy.
*/
*/
typedef
struct
{
typedef
struct
{
// Magic Number omitted since it is always the same.
// Magic Number omitted since it is always the same.
uint16_t
headerVersion
;
uint16_t
headerVersion
;
uint16_t
headerLength
;
uint16_t
headerLength
;
uint16_t
fieldControl
;
uint16_t
fieldControl
;
uint16_t
manufacturerId
;
uint16_t
manufacturerId
;
uint16_t
imageTypeId
;
// a.k.a. Device ID
uint16_t
imageTypeId
;
// a.k.a. Device ID
uint32_t
firmwareVersion
;
uint32_t
firmwareVersion
;
uint16_t
zigbeeStackVersion
;
uint16_t
zigbeeStackVersion
;
/**
/**
* @brief The spec. does NOT require that the string be NULL terminated in the
* @brief The spec. does NOT require that the string be NULL terminated in the
* header stored on disk. Therefore we make sure we can support a
* header stored on disk. Therefore we make sure we can support a
* 32-character string without a NULL terminator by adding +1 in the data
* 32-character string without a NULL terminator by adding +1 in the data
* structure.
* structure.
*/
*/
uint8_t
headerString
[
EMBER_AF_OTA_MAX_HEADER_STRING_LENGTH
+
1
];
uint8_t
headerString
[
EMBER_AF_OTA_MAX_HEADER_STRING_LENGTH
+
1
];
/**
/**
* @brief When reading the header this will be the complete length of
* @brief When reading the header this will be the complete length of
* the file. When writing the header, this must be set to
* the file. When writing the header, this must be set to
* the length of the MFG image data portion including all tags.
* the length of the MFG image data portion including all tags.
*/
*/
uint32_t
imageSize
;
uint32_t
imageSize
;
/**
/**
* @brief The remaining four fields are optional. The field control should be checked
* @brief The remaining four fields are optional. The field control should be checked
* to determine if their values are valid.
* to determine if their values are valid.
*/
*/
uint8_t
securityCredentials
;
uint8_t
securityCredentials
;
union
{
union
{
uint8_t
EUI64
[
EUI64_SIZE
];
uint8_t
EUI64
[
EUI64_SIZE
];
uint8_t
UID
[
UID_SIZE
];
uint8_t
UID
[
UID_SIZE
];
}
upgradeFileDestination
;
}
upgradeFileDestination
;
uint16_t
minimumHardwareVersion
;
uint16_t
minimumHardwareVersion
;
uint16_t
maximumHardwareVersion
;
uint16_t
maximumHardwareVersion
;
}
EmberAfOtaHeader
;
}
EmberAfOtaHeader
;
/**
/**
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin-host/gateway/backchannel-support.c
View file @
e5cd9e56
...
@@ -89,94 +89,94 @@ static int myVprintf(int fd, const char* formatString, va_list ap);
...
@@ -89,94 +89,94 @@ static int myVprintf(int fd, const char* formatString, va_list ap);
EmberStatus
backchannelStartServer
(
uint8_t
port
)
EmberStatus
backchannelStartServer
(
uint8_t
port
)
{
{
struct
sockaddr_in
serverAddress
;
struct
sockaddr_in
serverAddress
;
int
flags
;
int
flags
;
if
(
!
backchannelEnable
)
{
if
(
!
backchannelEnable
)
{
return
EMBER_INVALID_CALL
;
return
EMBER_INVALID_CALL
;
}
}
if
(
port
>
1
)
{
if
(
port
>
1
)
{
return
EMBER_SERIAL_INVALID_PORT
;
return
EMBER_SERIAL_INVALID_PORT
;
}
}
if
(
socketFd
[
port
]
!=
-
1
)
{
if
(
socketFd
[
port
]
!=
-
1
)
{
return
EMBER_INVALID_CALL
;
return
EMBER_INVALID_CALL
;
}
}
socketFd
[
port
]
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
socketFd
[
port
]
=
socket
(
AF_INET
,
SOCK_STREAM
,
0
);
if
(
socketFd
[
port
]
<
0
)
{
if
(
socketFd
[
port
]
<
0
)
{
unixError
(
"Error: Could not open socket"
);
unixError
(
"Error: Could not open socket"
);
return
EMBER_ERR_FATAL
;
return
EMBER_ERR_FATAL
;
}
}
flags
=
1
;
// Enable SO_REUSEADDR to reduce bind() complaints
flags
=
1
;
// Enable SO_REUSEADDR to reduce bind() complaints
(
void
)
setsockopt
(
socketFd
[
port
],
SOL_SOCKET
,
SO_REUSEADDR
,
&
flags
,
(
void
)
setsockopt
(
socketFd
[
port
],
SOL_SOCKET
,
SO_REUSEADDR
,
&
flags
,
sizeof
(
flags
));
sizeof
(
flags
));
bzero
(
&
(
clientConnections
[
port
]),
sizeof
(
struct
sockaddr_in
));
bzero
(
&
(
clientConnections
[
port
]),
sizeof
(
struct
sockaddr_in
));
bzero
((
char
*
)
&
serverAddress
,
sizeof
(
serverAddress
));
bzero
((
char
*
)
&
serverAddress
,
sizeof
(
serverAddress
));
serverAddress
.
sin_family
=
AF_INET
;
serverAddress
.
sin_family
=
AF_INET
;
serverAddress
.
sin_addr
.
s_addr
=
INADDR_ANY
;
serverAddress
.
sin_addr
.
s_addr
=
INADDR_ANY
;
serverAddress
.
sin_port
=
htons
(
SERVER_PORT_OFFSET
+
port
);
serverAddress
.
sin_port
=
htons
(
SERVER_PORT_OFFSET
+
port
);
if
(
bind
(
socketFd
[
port
],
if
(
bind
(
socketFd
[
port
],
(
struct
sockaddr
*
)
&
serverAddress
,
(
struct
sockaddr
*
)
&
serverAddress
,
sizeof
(
serverAddress
))
<
0
)
{
sizeof
(
serverAddress
))
<
0
)
{
unixError
(
"Error: Could not bind socket to %u"
,
SERVER_PORT_OFFSET
+
port
);
unixError
(
"Error: Could not bind socket to %u"
,
SERVER_PORT_OFFSET
+
port
);
return
EMBER_ERR_FATAL
;
return
EMBER_ERR_FATAL
;
}
}
if
(
0
>
listen
(
socketFd
[
port
],
0
))
{
if
(
0
>
listen
(
socketFd
[
port
],
0
))
{
unixError
(
"Error: Could not mark socket as listening"
);
unixError
(
"Error: Could not mark socket as listening"
);
return
EMBER_ERR_FATAL
;
return
EMBER_ERR_FATAL
;
}
}
infoPrint
(
"Listening for connections on port %u"
,
SERVER_PORT_OFFSET
+
port
);
infoPrint
(
"Listening for connections on port %u"
,
SERVER_PORT_OFFSET
+
port
);
return
EMBER_SUCCESS
;
return
EMBER_SUCCESS
;
}
}
EmberStatus
backchannelClientConnectionCleanup
(
uint8_t
port
)
EmberStatus
backchannelClientConnectionCleanup
(
uint8_t
port
)
{
{
if
(
!
backchannelEnable
)
{
if
(
!
backchannelEnable
)
{
return
EMBER_INVALID_CALL
;
return
EMBER_INVALID_CALL
;
}
}
if
(
port
>
1
)
{
if
(
port
>
1
)
{
return
EMBER_SERIAL_INVALID_PORT
;
return
EMBER_SERIAL_INVALID_PORT
;
}
}
if
(
clientFd
[
port
]
!=
INVALID_FD
)
{
if
(
clientFd
[
port
]
!=
INVALID_FD
)
{
myPrintf
(
REMOTE_STDOUT
,
myPrintf
(
REMOTE_STDOUT
,
"Server closing client connection from %s:%u on port %u
\n
"
,
"Server closing client connection from %s:%u on port %u
\n
"
,
inet_ntoa
(
clientConnections
[
port
].
sin_addr
),
inet_ntoa
(
clientConnections
[
port
].
sin_addr
),
ntohs
(
clientConnections
[
port
].
sin_port
),
ntohs
(
clientConnections
[
port
].
sin_port
),
SERVER_PORT_OFFSET
+
port
);
SERVER_PORT_OFFSET
+
port
);
infoPrint
(
"Server closing client connection from %s:%u on port %u
\n
"
,
infoPrint
(
"Server closing client connection from %s:%u on port %u
\n
"
,
inet_ntoa
(
clientConnections
[
port
].
sin_addr
),
inet_ntoa
(
clientConnections
[
port
].
sin_addr
),
ntohs
(
clientConnections
[
port
].
sin_port
),
ntohs
(
clientConnections
[
port
].
sin_port
),
SERVER_PORT_OFFSET
+
port
);
SERVER_PORT_OFFSET
+
port
);
close
(
clientFd
[
port
]);
close
(
clientFd
[
port
]);
clientFd
[
port
]
=
INVALID_FD
;
clientFd
[
port
]
=
INVALID_FD
;
bzero
(
&
(
clientConnections
[
port
]),
sizeof
(
struct
sockaddr_in
));
bzero
(
&
(
clientConnections
[
port
]),
sizeof
(
struct
sockaddr_in
));
}
}
return
EMBER_SUCCESS
;
return
EMBER_SUCCESS
;
}
}
EmberStatus
backchannelStopServer
(
uint8_t
port
)
EmberStatus
backchannelStopServer
(
uint8_t
port
)
{
{
if
(
!
backchannelEnable
)
{
if
(
!
backchannelEnable
)
{
return
EMBER_INVALID_CALL
;
return
EMBER_INVALID_CALL
;
}
}
if
(
port
>
1
)
{
if
(
port
>
1
)
{
return
EMBER_SERIAL_INVALID_PORT
;
return
EMBER_SERIAL_INVALID_PORT
;
}
}
backchannelClientConnectionCleanup
(
port
);
backchannelClientConnectionCleanup
(
port
);
if
(
socketFd
[
port
]
!=
INVALID_FD
)
{
if
(
socketFd
[
port
]
!=
INVALID_FD
)
{
myPrintf
(
LOCAL_STDOUT
,
"Server closing socket connection %u
\n
"
,
myPrintf
(
LOCAL_STDOUT
,
"Server closing socket connection %u
\n
"
,
SERVER_PORT_OFFSET
+
port
);
SERVER_PORT_OFFSET
+
port
);
close
(
socketFd
[
port
]);
close
(
socketFd
[
port
]);
socketFd
[
port
]
=
INVALID_FD
;
socketFd
[
port
]
=
INVALID_FD
;
}
}
return
EMBER_SUCCESS
;
return
EMBER_SUCCESS
;
}
}
// Retrieves a single byte from the client connection. Returns the number
// Retrieves a single byte from the client connection. Returns the number
...
@@ -226,23 +226,23 @@ EmberStatus backchannelSend(uint8_t port, uint8_t * data, uint8_t length)
...
@@ -226,23 +226,23 @@ EmberStatus backchannelSend(uint8_t port, uint8_t * data, uint8_t length)
// If one doesn't exist, it can wait for a new connection and return
// If one doesn't exist, it can wait for a new connection and return
// the result.
// the result.
BackchannelState
backchannelCheckConnection
(
uint8_t
port
,
BackchannelState
backchannelCheckConnection
(
uint8_t
port
,
bool
waitForConnection
)
bool
waitForConnection
)
{
{
if
(
!
backchannelEnable
)
{
if
(
!
backchannelEnable
)
{
return
CONNECTION_ERROR
;
return
CONNECTION_ERROR
;
}
else
if
(
clientFd
[
port
]
>=
0
)
{
}
else
if
(
clientFd
[
port
]
>=
0
)
{
return
CONNECTION_EXISTS
;
return
CONNECTION_EXISTS
;
}
}
bool
getConnection
=
false
;
bool
getConnection
=
false
;
if
(
waitForConnection
)
{
if
(
waitForConnection
)
{
infoPrint
(
"Waiting for client connection on port %u"
,
infoPrint
(
"Waiting for client connection on port %u"
,
port
+
SERVER_PORT_OFFSET
);
port
+
SERVER_PORT_OFFSET
);
getConnection
=
true
;
getConnection
=
true
;
}
else
if
(
!
willServerConnectionBlock
(
port
))
{
}
else
if
(
!
willServerConnectionBlock
(
port
))
{
getConnection
=
true
;
getConnection
=
true
;
}
}
if
(
getConnection
)
{
if
(
getConnection
)
{
return
(
getNewConnection
(
port
)
return
(
getNewConnection
(
port
)
...
@@ -450,32 +450,32 @@ static bool getNewConnection(uint8_t port)
...
@@ -450,32 +450,32 @@ static bool getNewConnection(uint8_t port)
// Print an error message plus the associated 'errno' string
// Print an error message plus the associated 'errno' string
static
void
unixError
(
const
char
*
format
,
...)
static
void
unixError
(
const
char
*
format
,
...)
{
{
va_list
ap
=
{
0
};
va_list
ap
=
{
0
};
va_start
(
ap
,
format
);
va_start
(
ap
,
format
);
myVprintf
(
LOCAL_STDERR
,
format
,
ap
);
myVprintf
(
LOCAL_STDERR
,
format
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
myPrintf
(
LOCAL_STDERR
,
": %s
\n
"
,
strerror
(
errno
));
myPrintf
(
LOCAL_STDERR
,
": %s
\n
"
,
strerror
(
errno
));
}
}
static
void
debugPrint
(
const
char
*
formatString
,
...)
static
void
debugPrint
(
const
char
*
formatString
,
...)
{
{
if
(
debugOn
)
{
if
(
debugOn
)
{
va_list
ap
=
{
0
};
va_list
ap
=
{
0
};
myPrintf
(
LOCAL_STDERR
,
"[%s] "
,
debugString
);
myPrintf
(
LOCAL_STDERR
,
"[%s] "
,
debugString
);
va_start
(
ap
,
formatString
);
va_start
(
ap
,
formatString
);
myVprintf
(
LOCAL_STDERR
,
formatString
,
ap
);
myVprintf
(
LOCAL_STDERR
,
formatString
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
myPrintf
(
LOCAL_STDERR
,
"
\n
"
);
myPrintf
(
LOCAL_STDERR
,
"
\n
"
);
}
}
}
}
static
void
infoPrint
(
const
char
*
formatString
,
...)
static
void
infoPrint
(
const
char
*
formatString
,
...)
{
{
va_list
ap
=
{
0
};
va_list
ap
=
{
0
};
va_start
(
ap
,
formatString
);
va_start
(
ap
,
formatString
);
myVprintf
(
LOCAL_STDOUT
,
formatString
,
ap
);
myVprintf
(
LOCAL_STDOUT
,
formatString
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
myPrintf
(
LOCAL_STDOUT
,
"
\n
"
);
myPrintf
(
LOCAL_STDOUT
,
"
\n
"
);
}
}
// Because we mess around with FDs, we need our own printing routine
// Because we mess around with FDs, we need our own printing routine
...
@@ -483,20 +483,20 @@ static void infoPrint(const char* formatString, ...)
...
@@ -483,20 +483,20 @@ static void infoPrint(const char* formatString, ...)
static
int
myPrintf
(
int
fd
,
const
char
*
formatString
,
...)
static
int
myPrintf
(
int
fd
,
const
char
*
formatString
,
...)
{
{
va_list
ap
=
{
0
};
va_list
ap
=
{
0
};
int
returnCode
;
int
returnCode
;
va_start
(
ap
,
formatString
);
va_start
(
ap
,
formatString
);
returnCode
=
myVprintf
(
fd
,
formatString
,
ap
);
returnCode
=
myVprintf
(
fd
,
formatString
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
return
returnCode
;
return
returnCode
;
}
}
// Returns 0 on success, 1 on error
// Returns 0 on success, 1 on error
static
int
myVprintf
(
int
fd
,
const
char
*
formatString
,
va_list
ap
)
static
int
myVprintf
(
int
fd
,
const
char
*
formatString
,
va_list
ap
)
{
{
int
length
;
int
length
;
char
string
[
MAX_STRING_LENGTH
];
char
string
[
MAX_STRING_LENGTH
];
length
=
vsnprintf
(
string
,
MAX_STRING_LENGTH
-
1
,
formatString
,
ap
);
length
=
vsnprintf
(
string
,
MAX_STRING_LENGTH
-
1
,
formatString
,
ap
);
string
[
length
]
=
'\0'
;
string
[
length
]
=
'\0'
;
return
(
length
!=
write
(
fd
,
string
,
length
));
return
(
length
!=
write
(
fd
,
string
,
length
));
}
}
platform/zigbee/protocol/zigbee/app/framework/plugin-host/gateway/gateway-support.c
View file @
e5cd9e56
...
@@ -65,28 +65,28 @@ static void ezspSerialPortCallback(EzspSerialPortEvent event, int fileDescriptor
...
@@ -65,28 +65,28 @@ static void ezspSerialPortCallback(EzspSerialPortEvent event, int fileDescriptor
static
EmberStatus
gatewayBackchannelStart
(
void
)
static
EmberStatus
gatewayBackchannelStart
(
void
)
{
{
if
(
backchannelEnable
)
{
if
(
backchannelEnable
)
{
if
(
EMBER_SUCCESS
!=
backchannelStartServer
(
SERIAL_PORT_CLI
))
{
if
(
EMBER_SUCCESS
!=
backchannelStartServer
(
SERIAL_PORT_CLI
))
{
fprintf
(
stderr
,
fprintf
(
stderr
,
"Fatal: Failed to start backchannel services for CLI.
\n
"
);
"Fatal: Failed to start backchannel services for CLI.
\n
"
);
return
EMBER_ERR_FATAL
;
return
EMBER_ERR_FATAL
;
}
}
if
(
EMBER_SUCCESS
!=
backchannelStartServer
(
SERIAL_PORT_RAW
))
{
if
(
EMBER_SUCCESS
!=
backchannelStartServer
(
SERIAL_PORT_RAW
))
{
fprintf
(
stderr
,
fprintf
(
stderr
,
"Fatal: Failed to start backchannel services for RAW data.
\n
"
);
"Fatal: Failed to start backchannel services for RAW data.
\n
"
);
return
EMBER_ERR_FATAL
;
return
EMBER_ERR_FATAL
;
}
}
}
}
return
EMBER_SUCCESS
;
return
EMBER_SUCCESS
;
}
}
void
gatewayBackchannelStop
(
void
)
void
gatewayBackchannelStop
(
void
)
{
{
if
(
backchannelEnable
)
{
if
(
backchannelEnable
)
{
backchannelStopServer
(
SERIAL_PORT_CLI
);
backchannelStopServer
(
SERIAL_PORT_CLI
);
backchannelStopServer
(
SERIAL_PORT_RAW
);
backchannelStopServer
(
SERIAL_PORT_RAW
);
}
}
}
}
bool
emberAfMainStartCallback
(
int
*
returnCode
,
bool
emberAfMainStartCallback
(
int
*
returnCode
,
...
@@ -95,21 +95,21 @@ bool emberAfMainStartCallback(int* returnCode,
...
@@ -95,21 +95,21 @@ bool emberAfMainStartCallback(int* returnCode,
{
{
debugPrint
(
"gatewaitInit()"
);
debugPrint
(
"gatewaitInit()"
);
// This will process EZSP command-line options as well as determine
// This will process EZSP command-line options as well as determine
// whether the backchannel should be turned on.
// whether the backchannel should be turned on.
if
(
!
ezspProcessCommandOptions
(
argc
,
argv
))
{
if
(
!
ezspProcessCommandOptions
(
argc
,
argv
))
{
*
returnCode
=
EMBER_ERR_FATAL
;
*
returnCode
=
EMBER_ERR_FATAL
;
return
true
;
return
true
;
}
}
*
returnCode
=
gatewayBackchannelStart
();
*
returnCode
=
gatewayBackchannelStart
();
if
(
*
returnCode
!=
EMBER_SUCCESS
)
{
if
(
*
returnCode
!=
EMBER_SUCCESS
)
{
return
true
;
return
true
;
}
}
emberSerialSetPrompt
(
cliPrompt
);
emberSerialSetPrompt
(
cliPrompt
);
emberSerialCommandCompletionInit
(
emberCommandTable
);
emberSerialCommandCompletionInit
(
emberCommandTable
);
return
false
;
return
false
;
}
}
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin-host/gateway/gateway-support.h
View file @
e5cd9e56
...
@@ -3,10 +3,10 @@ void gatewayBackchannelStop(void);
...
@@ -3,10 +3,10 @@ void gatewayBackchannelStop(void);
typedef
uint8_t
BackchannelState
;
typedef
uint8_t
BackchannelState
;
enum
{
enum
{
NO_CONNECTION
=
0
,
NO_CONNECTION
=
0
,
CONNECTION_EXISTS
=
1
,
CONNECTION_EXISTS
=
1
,
NEW_CONNECTION
=
2
,
NEW_CONNECTION
=
2
,
CONNECTION_ERROR
=
3
,
CONNECTION_ERROR
=
3
,
};
};
extern
const
bool
backchannelSupported
;
extern
const
bool
backchannelSupported
;
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-common/ota-cli.h
View file @
e5cd9e56
...
@@ -38,7 +38,7 @@ void emAfOtaImageDelete(void);
...
@@ -38,7 +38,7 @@ void emAfOtaImageDelete(void);
// Server CLI interface
// Server CLI interface
#if !defined (EMBER_AF_PLUGIN_OTA_SERVER)
#if !defined (EMBER_AF_PLUGIN_OTA_SERVER)
#define OTA_SERVER_COMMANDS
#define OTA_SERVER_COMMANDS
#endif
#endif
void
otaImageNotifyCommand
(
void
);
void
otaImageNotifyCommand
(
void
);
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-common/ota-common.c
View file @
e5cd9e56
...
@@ -21,9 +21,9 @@
...
@@ -21,9 +21,9 @@
// This relates all OTA command IDs in app/framework/gen/command-id.h
// This relates all OTA command IDs in app/framework/gen/command-id.h
// to minimum message lengths (does not include EMBER_AF_ZCL_OVERHEAD)
// to minimum message lengths (does not include EMBER_AF_ZCL_OVERHEAD)
PGM
uint8_t
emAfOtaMinMessageLengths
[]
=
{
PGM
uint8_t
emAfOtaMinMessageLengths
[]
=
{
2
,
// Image Notify
2
,
// Image Notify
8
,
// Query Next Image Request
8
,
// Query Next Image Request
1
,
// Query Next Image Response
1
,
// Query Next Image Response
13
,
// Image Block Request
13
,
// Image Block Request
13
,
// Image Page Request
13
,
// Image Page Request
1
,
// Image Block Response (abort is shortest)
1
,
// Image Block Response (abort is shortest)
...
@@ -48,14 +48,14 @@ EmberAfOtaImageId emAfOtaCreateEmberAfOtaImageIdStruct(uint16_t manufacturerId,
...
@@ -48,14 +48,14 @@ EmberAfOtaImageId emAfOtaCreateEmberAfOtaImageIdStruct(uint16_t manufacturerId,
// This assumes the message has already been validated for its length
// This assumes the message has already been validated for its length
uint8_t
emAfOtaParseImageIdFromMessage
(
EmberAfOtaImageId
*
returnId
,
uint8_t
emAfOtaParseImageIdFromMessage
(
EmberAfOtaImageId
*
returnId
,
const
uint8_t
*
buffer
,
const
uint8_t
*
buffer
,
uint8_t
length
)
uint8_t
length
)
{
{
returnId
->
manufacturerId
=
emberAfGetInt16u
(
buffer
,
0
,
length
);
returnId
->
manufacturerId
=
emberAfGetInt16u
(
buffer
,
0
,
length
);
returnId
->
imageTypeId
=
emberAfGetInt16u
(
buffer
,
2
,
length
);
returnId
->
imageTypeId
=
emberAfGetInt16u
(
buffer
,
2
,
length
);
returnId
->
firmwareVersion
=
emberAfGetInt32u
(
buffer
,
4
,
length
);
returnId
->
firmwareVersion
=
emberAfGetInt32u
(
buffer
,
4
,
length
);
MEMSET
(
returnId
->
deviceSpecificFileEui64
,
0
,
EUI64_SIZE
);
MEMSET
(
returnId
->
deviceSpecificFileEui64
,
0
,
EUI64_SIZE
);
return
8
;
return
8
;
}
}
#if defined(EMBER_AF_PRINT_CORE)
#if defined(EMBER_AF_PRINT_CORE)
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server-policy/ota-server-policy.c
View file @
e5cd9e56
...
@@ -22,19 +22,19 @@
...
@@ -22,19 +22,19 @@
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
typedef
enum
{
typedef
enum
{
UPGRADE_IF_SERVER_HAS_NEWER
=
0
,
UPGRADE_IF_SERVER_HAS_NEWER
=
0
,
DOWNGRADE_IF_SERVER_HAS_OLDER
=
1
,
DOWNGRADE_IF_SERVER_HAS_OLDER
=
1
,
REINSTALL_IF_SERVER_HAS_SAME
=
2
,
REINSTALL_IF_SERVER_HAS_SAME
=
2
,
NO_NEXT_VERSION
=
3
,
NO_NEXT_VERSION
=
3
,
}
NextVersionPolicy
;
}
NextVersionPolicy
;
#define QUERY_POLICY_MAX NO_NEXT_VERSION
#define QUERY_POLICY_MAX NO_NEXT_VERSION
#ifdef EMBER_COMMAND_INTEPRETER_HAS_DESCRIPTION_FIELD
#ifdef EMBER_COMMAND_INTEPRETER_HAS_DESCRIPTION_FIELD
static
PGM_P
nextVersionPolicyStrings
[]
=
{
static
PGM_P
nextVersionPolicyStrings
[]
=
{
"Upgrade if server has newer"
,
"Upgrade if server has newer"
,
"Downgrade if server has older"
,
"Downgrade if server has older"
,
"Reinstall if server has same"
,
"Reinstall if server has same"
,
"No next version"
,
"No next version"
,
};
};
#endif // EMBER_COMMAND_INTEPRETER_HAS_DESCRIPTION_FIELD
#endif // EMBER_COMMAND_INTEPRETER_HAS_DESCRIPTION_FIELD
...
@@ -70,10 +70,10 @@ PGM_P imageBlockRequestPolicyStrings[] = {
...
@@ -70,10 +70,10 @@ PGM_P imageBlockRequestPolicyStrings[] = {
#endif
#endif
typedef
enum
{
typedef
enum
{
UPGRADE_NOW
=
0
,
UPGRADE_NOW
=
0
,
UPGRADE_SOON
=
1
,
UPGRADE_SOON
=
1
,
UPGRADE_ASK_ME_LATER
=
2
,
UPGRADE_ASK_ME_LATER
=
2
,
UPGRADE_ABORT
=
3
,
UPGRADE_ABORT
=
3
,
}
UpgradePolicy
;
}
UpgradePolicy
;
#define UPGRADE_POLICY_MAX UPGRADE_ABORT
#define UPGRADE_POLICY_MAX UPGRADE_ABORT
...
@@ -81,18 +81,18 @@ UpgradePolicy upgradePolicy = UPGRADE_NOW;
...
@@ -81,18 +81,18 @@ UpgradePolicy upgradePolicy = UPGRADE_NOW;
#define UPGRADE_SOON_TIME_SECONDS (2 * 60)
#define UPGRADE_SOON_TIME_SECONDS (2 * 60)
PGM_P
upgradePolicyStrings
[]
=
{
PGM_P
upgradePolicyStrings
[]
=
{
"Upgrade Now"
,
"Upgrade Now"
,
"Upgrade In a few minutes"
,
"Upgrade In a few minutes"
,
"Ask me later to upgrade"
,
"Ask me later to upgrade"
,
"Abort upgrade"
,
"Abort upgrade"
,
};
};
// This corresponds to the enumerated UpgradePolicy list.
// This corresponds to the enumerated UpgradePolicy list.
PGM
uint32_t
upgradeTimes
[]
=
{
PGM
uint32_t
upgradeTimes
[]
=
{
0
,
// Now
0
,
// Now
UPGRADE_SOON_TIME_SECONDS
,
// in a little while
UPGRADE_SOON_TIME_SECONDS
,
// in a little while
0xFFFFFFFFL
,
// go ask your father (wait forever)
0xFFFFFFFFL
,
// go ask your father (wait forever)
0
,
// unused
0
,
// unused
};
};
#if defined EM_AF_TEST_HARNESS_CODE
#if defined EM_AF_TEST_HARNESS_CODE
...
@@ -112,8 +112,8 @@ static uint8_t pageRequestStatus = PAGE_REQUEST_STATUS_CODE;
...
@@ -112,8 +112,8 @@ static uint8_t pageRequestStatus = PAGE_REQUEST_STATUS_CODE;
static
uint16_t
otaMinimumBlockPeriodMs
=
0
;
static
uint16_t
otaMinimumBlockPeriodMs
=
0
;
#define SERVER_AND_CLIENT_SUPPORT_MIN_BLOCK_REQUEST \
#define SERVER_AND_CLIENT_SUPPORT_MIN_BLOCK_REQUEST \
(EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_CLIENT \
(EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_CLIENT \
| EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_SERVER)
| EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_SERVER)
#ifdef EMBER_TEST
#ifdef EMBER_TEST
uint8_t
testClientDelayUnit
=
OTA_SERVER_DO_NOT_OVERRIDE_CLIENT_DELAY_UNITS
;
uint8_t
testClientDelayUnit
=
OTA_SERVER_DO_NOT_OVERRIDE_CLIENT_DELAY_UNITS
;
...
@@ -164,135 +164,140 @@ void emAfOtaServerPolicyPrint(void)
...
@@ -164,135 +164,140 @@ void emAfOtaServerPolicyPrint(void)
}
}
static
bool
determineNextSoftwareVersion
(
uint32_t
versionServerHas
,
static
bool
determineNextSoftwareVersion
(
uint32_t
versionServerHas
,
uint32_t
versionClientHas
)
uint32_t
versionClientHas
)
{
{
// Our system here controls whether we tell the client to
// Our system here controls whether we tell the client to
// (A) upgrade, because we have a newer version
// (A) upgrade, because we have a newer version
// (B) downgrade, because we have an older version we want to install
// (B) downgrade, because we have an older version we want to install
// (C) reinstall, because we have the same version you have currently
// (C) reinstall, because we have the same version you have currently
// (D) do nothing (no 'next' image is avaiable)
// (D) do nothing (no 'next' image is avaiable)
switch
(
nextVersionPolicy
)
{
switch
(
nextVersionPolicy
)
{
case
UPGRADE_IF_SERVER_HAS_NEWER
:
case
UPGRADE_IF_SERVER_HAS_NEWER
:
if
(
versionServerHas
>
versionClientHas
)
{
if
(
versionServerHas
>
versionClientHas
)
{
return
true
;
return
true
;
}
}
break
;
break
;
case
DOWNGRADE_IF_SERVER_HAS_OLDER
:
case
DOWNGRADE_IF_SERVER_HAS_OLDER
:
if
(
versionServerHas
<
versionClientHas
)
{
if
(
versionServerHas
<
versionClientHas
)
{
return
true
;
return
true
;
}
}
break
;
break
;
case
REINSTALL_IF_SERVER_HAS_SAME
:
case
REINSTALL_IF_SERVER_HAS_SAME
:
if
(
versionServerHas
==
versionClientHas
)
{
if
(
versionServerHas
==
versionClientHas
)
{
return
true
;
return
true
;
}
}
break
;
break
;
case
NO_NEXT_VERSION
:
case
NO_NEXT_VERSION
:
default:
default:
break
;
break
;
}
}
return
false
;
return
false
;
}
}
uint8_t
emberAfOtaServerQueryCallback
(
const
EmberAfOtaImageId
*
currentImageId
,
uint8_t
emberAfOtaServerQueryCallback
(
const
EmberAfOtaImageId
*
currentImageId
,
uint16_t
*
hardwareVersion
,
uint16_t
*
hardwareVersion
,
EmberAfOtaImageId
*
nextUpgradeImageId
)
EmberAfOtaImageId
*
nextUpgradeImageId
)
{
{
// This function is called by the OTA cluster server to determine what
// This function is called by the OTA cluster server to determine what
// the 'next' version of software is for a particular device requesting
// the 'next' version of software is for a particular device requesting
// a new download image. The server returns a status code indicating
// a new download image. The server returns a status code indicating
// EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE, or EMBER_ZCL_STATUS_SUCCESS
// EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE, or EMBER_ZCL_STATUS_SUCCESS
// (new image is available). It then also fills in the 'nextUpgradeImageId'
// (new image is available). It then also fills in the 'nextUpgradeImageId'
// structure with the appropriate version.
// structure with the appropriate version.
// The server can use whatever criteria it wants to dictate what
// The server can use whatever criteria it wants to dictate what
// the 'next' version is and if it is currently available.
// the 'next' version is and if it is currently available.
// This sample does this based on a global policy value.
// This sample does this based on a global policy value.
uint8_t
status
=
EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE
;
uint8_t
status
=
EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE
;
bool
hardwareVersionMismatch
=
false
;
bool
hardwareVersionMismatch
=
false
;
otaPrintln
(
"QueryNextImageRequest mfgId:0x%2x imageTypeId:0x%2x, fw:0x%4x"
,
otaPrintln
(
"QueryNextImageRequest mfgId:0x%2x imageTypeId:0x%2x, fw:0x%4x"
,
currentImageId
->
manufacturerId
,
currentImageId
->
manufacturerId
,
currentImageId
->
imageTypeId
,
currentImageId
->
imageTypeId
,
currentImageId
->
firmwareVersion
);
currentImageId
->
firmwareVersion
);
*
nextUpgradeImageId
*
nextUpgradeImageId
=
emberAfOtaStorageSearchCallback
(
currentImageId
->
manufacturerId
,
=
emberAfOtaStorageSearchCallback
(
currentImageId
->
manufacturerId
,
currentImageId
->
imageTypeId
,
currentImageId
->
imageTypeId
,
hardwareVersion
);
hardwareVersion
);
if
(
emberAfIsOtaImageIdValid
(
nextUpgradeImageId
))
{
if
(
emberAfIsOtaImageIdValid
(
nextUpgradeImageId
))
{
// We only perform a check if both the query and the
// We only perform a check if both the query and the
// file have hardware version(s). If one or the other doesn't
// file have hardware version(s). If one or the other doesn't
// have them, we assume a match is still possible.
// have them, we assume a match is still possible.
if
(
hardwareVersion
)
{
otaPrintln
(
"[OTA]2222,hardwareVersion=%d"
,
hardwareVersion
);
EmberAfOtaHeader
header
;
if
(
hardwareVersion
)
{
emberAfOtaStorageGetFullHeaderCallback
(
nextUpgradeImageId
,
EmberAfOtaHeader
header
;
&
header
);
emberAfOtaStorageGetFullHeaderCallback
(
nextUpgradeImageId
,
if
(
header
.
fieldControl
&
HARDWARE_VERSIONS_PRESENT_MASK
)
{
&
header
);
if
(
*
hardwareVersion
<
header
.
minimumHardwareVersion
if
(
header
.
fieldControl
&
HARDWARE_VERSIONS_PRESENT_MASK
)
{
||
header
.
maximumHardwareVersion
<
*
hardwareVersion
)
{
otaPrintln
(
"[OTA]3333"
);
otaPrintln
(
"Hardware version 0x%02X does not fall within the min (0x%02X) and max (0x%02X) hardware versions in the file."
,
if
(
*
hardwareVersion
<
header
.
minimumHardwareVersion
*
hardwareVersion
,
||
header
.
maximumHardwareVersion
<
*
hardwareVersion
)
{
header
.
minimumHardwareVersion
,
otaPrintln
(
"Hardware version 0x%02X does not fall within the min (0x%02X) and max (0x%02X) hardware versions in the file."
,
header
.
maximumHardwareVersion
);
*
hardwareVersion
,
hardwareVersionMismatch
=
true
;
header
.
minimumHardwareVersion
,
}
header
.
maximumHardwareVersion
);
}
hardwareVersionMismatch
=
true
;
}
}
// "!hardwareVersionMismatch" does not mean the hardware
}
// versions match. It just means we don't *disqualify* the image
}
// as a potential upgrade candidate because the hardware is out
// "!hardwareVersionMismatch" does not mean the hardware
// of range.
// versions match. It just means we don't *disqualify* the image
if
(
!
hardwareVersionMismatch
)
{
// as a potential upgrade candidate because the hardware is out
status
=
(
determineNextSoftwareVersion
(
nextUpgradeImageId
->
firmwareVersion
,
// of range.
currentImageId
->
firmwareVersion
)
if
(
!
hardwareVersionMismatch
)
{
?
EMBER_ZCL_STATUS_SUCCESS
otaPrintln
(
"[OTA]4444,%x,%x"
,
nextUpgradeImageId
->
firmwareVersion
,
currentImageId
->
firmwareVersion
);
:
EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE
);
status
=
(
determineNextSoftwareVersion
(
nextUpgradeImageId
->
firmwareVersion
,
if
(
status
==
EMBER_ZCL_STATUS_SUCCESS
)
{
currentImageId
->
firmwareVersion
)
otaPrintln
(
"Next fw version is: 0x%4X"
,
?
EMBER_ZCL_STATUS_SUCCESS
nextUpgradeImageId
->
firmwareVersion
);
:
EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE
);
}
otaPrintln
(
"[OTA]555,status=%x"
,
status
);
}
if
(
status
==
EMBER_ZCL_STATUS_SUCCESS
)
{
}
otaPrintln
(
"Next fw version is: 0x%4X"
,
return
status
;
nextUpgradeImageId
->
firmwareVersion
);
}
}
}
otaPrintln
(
"[OTA]11111"
);
return
status
;
}
}
uint8_t
emberAfOtaServerBlockSizeCallback
(
EmberNodeId
clientNodeId
)
uint8_t
emberAfOtaServerBlockSizeCallback
(
EmberNodeId
clientNodeId
)
{
{
// This function provides a way for the server to potentially
// This function provides a way for the server to potentially
// adjust the block size based on the client who is requesting.
// adjust the block size based on the client who is requesting.
// In other words if we are using source routing we will limit
// In other words if we are using source routing we will limit
// data returned by enough to put a source route into the message.
// data returned by enough to put a source route into the message.
EmberApsFrame
apsFrame
;
EmberApsFrame
apsFrame
;
uint8_t
maxSize
;
uint8_t
maxSize
;
apsFrame
.
options
=
EMBER_APS_OPTION_NONE
;
apsFrame
.
options
=
EMBER_APS_OPTION_NONE
;
if
(
emberAfIsCurrentSecurityProfileSmartEnergy
())
{
if
(
emberAfIsCurrentSecurityProfileSmartEnergy
())
{
apsFrame
.
options
|=
EMBER_APS_OPTION_ENCRYPTION
;
apsFrame
.
options
|=
EMBER_APS_OPTION_ENCRYPTION
;
}
}
maxSize
=
emberAfMaximumApsPayloadLength
(
EMBER_OUTGOING_DIRECT
,
maxSize
=
emberAfMaximumApsPayloadLength
(
EMBER_OUTGOING_DIRECT
,
clientNodeId
,
clientNodeId
,
&
apsFrame
);
&
apsFrame
);
maxSize
-=
IMAGE_BLOCK_RESPONSE_OVERHEAD
;
maxSize
-=
IMAGE_BLOCK_RESPONSE_OVERHEAD
;
return
maxSize
;
return
maxSize
;
}
}
uint8_t
emberAfOtaServerImageBlockRequestCallback
(
EmberAfImageBlockRequestCallbackStruct
*
data
)
uint8_t
emberAfOtaServerImageBlockRequestCallback
(
EmberAfImageBlockRequestCallbackStruct
*
data
)
{
{
uint8_t
status
;
uint8_t
status
;
uint16_t
serverBlockPeriodValue
=
otaMinimumBlockPeriodMs
;
uint16_t
serverBlockPeriodValue
=
otaMinimumBlockPeriodMs
;
uint8_t
clientDelayUnit
;
uint8_t
clientDelayUnit
;
bool
useSecondsDelay
=
false
;
bool
useSecondsDelay
=
false
;
if
(
SERVER_AND_CLIENT_SUPPORT_MIN_BLOCK_REQUEST
if
(
SERVER_AND_CLIENT_SUPPORT_MIN_BLOCK_REQUEST
==
(
data
->
bitmask
&
SERVER_AND_CLIENT_SUPPORT_MIN_BLOCK_REQUEST
))
{
==
(
data
->
bitmask
&
SERVER_AND_CLIENT_SUPPORT_MIN_BLOCK_REQUEST
))
{
clientDelayUnit
=
emberAfPluginOtaServerPolicyGetClientDelayUnits
(
clientDelayUnit
=
emberAfPluginOtaServerPolicyGetClientDelayUnits
(
data
->
source
,
data
->
source
,
data
->
sourceEui
);
data
->
sourceEui
);
#ifdef EMBER_TEST
#ifdef EMBER_TEST
if
(
OTA_SERVER_DO_NOT_OVERRIDE_CLIENT_DELAY_UNITS
!=
testClientDelayUnit
)
{
if
(
OTA_SERVER_DO_NOT_OVERRIDE_CLIENT_DELAY_UNITS
!=
testClientDelayUnit
)
{
...
@@ -300,46 +305,46 @@ uint8_t emberAfOtaServerImageBlockRequestCallback(EmberAfImageBlockRequestCallba
...
@@ -300,46 +305,46 @@ uint8_t emberAfOtaServerImageBlockRequestCallback(EmberAfImageBlockRequestCallba
}
}
#endif // EMBER_TEST
#endif // EMBER_TEST
switch
(
clientDelayUnit
)
{
switch
(
clientDelayUnit
)
{
case
OTA_SERVER_NO_RATE_LIMITING_FOR_CLIENT
:
case
OTA_SERVER_NO_RATE_LIMITING_FOR_CLIENT
:
return
EMBER_ZCL_STATUS_SUCCESS
;
return
EMBER_ZCL_STATUS_SUCCESS
;
break
;
break
;
case
OTA_SERVER_CLIENT_USES_MILLISECONDS
:
case
OTA_SERVER_CLIENT_USES_MILLISECONDS
:
break
;
break
;
case
OTA_SERVER_CLIENT_USES_SECONDS
:
case
OTA_SERVER_CLIENT_USES_SECONDS
:
useSecondsDelay
=
true
;
useSecondsDelay
=
true
;
break
;
break
;
case
OTA_SERVER_DISCOVER_CLIENT_DELAY_UNITS
:
case
OTA_SERVER_DISCOVER_CLIENT_DELAY_UNITS
:
{
{
// If we support dynamic block request, check to see if we know how the
// If we support dynamic block request, check to see if we know how the
// client treats the field. If we haven't tested the client yet or don't
// client treats the field. If we haven't tested the client yet or don't
// have a spot for it as an active OTA session, we tell it to
// have a spot for it as an active OTA session, we tell it to
// WAIT_FOR_DATA
// WAIT_FOR_DATA
status
=
emAfOtaServerCheckDynamicBlockPeriodDownload
(
data
);
status
=
emAfOtaServerCheckDynamicBlockPeriodDownload
(
data
);
if
(
EMBER_ZCL_STATUS_WAIT_FOR_DATA
==
status
)
{
if
(
EMBER_ZCL_STATUS_WAIT_FOR_DATA
==
status
)
{
return
EMBER_ZCL_STATUS_WAIT_FOR_DATA
;
return
EMBER_ZCL_STATUS_WAIT_FOR_DATA
;
}
}
useSecondsDelay
=
emAfOtaServerDynamicBlockPeriodClientUsesSeconds
(
data
->
source
);
useSecondsDelay
=
emAfOtaServerDynamicBlockPeriodClientUsesSeconds
(
data
->
source
);
}
}
break
;
break
;
default:
default:
break
;
break
;
}
}
if
(
useSecondsDelay
)
{
if
(
useSecondsDelay
)
{
serverBlockPeriodValue
/=
1000
;
serverBlockPeriodValue
/=
1000
;
}
}
if
(
data
->
minBlockRequestPeriod
!=
serverBlockPeriodValue
)
{
if
(
data
->
minBlockRequestPeriod
!=
serverBlockPeriodValue
)
{
data
->
minBlockRequestPeriod
=
serverBlockPeriodValue
;
data
->
minBlockRequestPeriod
=
serverBlockPeriodValue
;
return
EMBER_ZCL_STATUS_WAIT_FOR_DATA
;
return
EMBER_ZCL_STATUS_WAIT_FOR_DATA
;
}
}
}
}
#if defined EM_AF_TEST_HARNESS_CODE
#if defined EM_AF_TEST_HARNESS_CODE
// TEST Harness code
// TEST Harness code
...
@@ -357,41 +362,41 @@ uint8_t emberAfOtaServerImageBlockRequestCallback(EmberAfImageBlockRequestCallba
...
@@ -357,41 +362,41 @@ uint8_t emberAfOtaServerImageBlockRequestCallback(EmberAfImageBlockRequestCallba
}
}
#endif
#endif
return
EMBER_ZCL_STATUS_SUCCESS
;
return
EMBER_ZCL_STATUS_SUCCESS
;
}
}
bool
emberAfOtaServerUpgradeEndRequestCallback
(
EmberNodeId
source
,
bool
emberAfOtaServerUpgradeEndRequestCallback
(
EmberNodeId
source
,
uint8_t
status
,
uint8_t
status
,
uint32_t
*
returnValue
,
uint32_t
*
returnValue
,
const
EmberAfOtaImageId
*
imageId
)
const
EmberAfOtaImageId
*
imageId
)
{
{
otaPrintln
(
"Client 0x%2X indicated upgrade status: 0x%X"
,
otaPrintln
(
"Client 0x%2X indicated upgrade status: 0x%X"
,
source
,
source
,
status
);
status
);
emAfOtaServerCompleteDynamicBlockPeriodDownload
(
source
);
emAfOtaServerCompleteDynamicBlockPeriodDownload
(
source
);
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
// If status != EMBER_ZCL_STATUS_SUCCESS then this callback is
// If status != EMBER_ZCL_STATUS_SUCCESS then this callback is
// only informative. Return code will be ignored.
// only informative. Return code will be ignored.
return
false
;
return
false
;
}
}
otaPrintln
(
"Upgrade End Response: %p"
,
upgradePolicyStrings
[
upgradePolicy
]);
otaPrintln
(
"Upgrade End Response: %p"
,
upgradePolicyStrings
[
upgradePolicy
]);
if
(
upgradePolicy
==
UPGRADE_ABORT
)
{
if
(
upgradePolicy
==
UPGRADE_ABORT
)
{
return
false
;
return
false
;
}
}
*
returnValue
=
upgradeTimes
[
upgradePolicy
];
*
returnValue
=
upgradeTimes
[
upgradePolicy
];
return
true
;
return
true
;
}
}
void
emAfOtaServerSetQueryPolicy
(
uint8_t
value
)
void
emAfOtaServerSetQueryPolicy
(
uint8_t
value
)
{
{
if
(
value
<=
QUERY_POLICY_MAX
)
{
if
(
value
<=
QUERY_POLICY_MAX
)
{
nextVersionPolicy
=
(
NextVersionPolicy
)
value
;
nextVersionPolicy
=
(
NextVersionPolicy
)
value
;
}
}
}
}
void
emAfOtaServerSetBlockRequestPolicy
(
uint8_t
value
)
void
emAfOtaServerSetBlockRequestPolicy
(
uint8_t
value
)
...
@@ -401,7 +406,7 @@ void emAfOtaServerSetBlockRequestPolicy(uint8_t value)
...
@@ -401,7 +406,7 @@ void emAfOtaServerSetBlockRequestPolicy(uint8_t value)
imageBlockRequestPolicy
=
(
ImageBlockRequestPolicy
)
value
;
imageBlockRequestPolicy
=
(
ImageBlockRequestPolicy
)
value
;
}
}
#else
#else
otaPrintln
(
"Unsupported."
);
otaPrintln
(
"Unsupported."
);
#endif
#endif
}
}
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server-cli.c
View file @
e5cd9e56
...
@@ -149,9 +149,9 @@ static PGM_P notifyArguments[] = {
...
@@ -149,9 +149,9 @@ static PGM_P notifyArguments[] = {
emberCommandEntryTerminator(),
emberCommandEntryTerminator(),
EmberCommandEntry
emberAfPluginOtaServerCommands
[]
=
{
EmberCommandEntry
emberAfPluginOtaServerCommands
[]
=
{
OTA_SERVER_COMMANDS
OTA_SERVER_COMMANDS
emberCommandEntryTerminator
(),
emberCommandEntryTerminator
(),
};
};
#endif // EMBER_AF_GENERATE_CLI
#endif // EMBER_AF_GENERATE_CLI
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server-dynamic-block-period.c
View file @
e5cd9e56
...
@@ -79,13 +79,13 @@ uint8_t getIndexForDownloadingNodeId(EmberNodeId nodeId)
...
@@ -79,13 +79,13 @@ uint8_t getIndexForDownloadingNodeId(EmberNodeId nodeId)
void
emAfOtaServerDynamicBlockPeriodInit
()
void
emAfOtaServerDynamicBlockPeriodInit
()
{
{
// Initialize array to have no current OTA downloads
// Initialize array to have no current OTA downloads
uint8_t
nodeIndex
;
uint8_t
nodeIndex
;
for
(
nodeIndex
=
0
;
nodeIndex
<
MAX_DOWNLOADS
;
nodeIndex
++
)
{
for
(
nodeIndex
=
0
;
nodeIndex
<
MAX_DOWNLOADS
;
nodeIndex
++
)
{
downloadingNodes
[
nodeIndex
].
nodeId
=
EMBER_NULL_NODE_ID
;
downloadingNodes
[
nodeIndex
].
nodeId
=
EMBER_NULL_NODE_ID
;
downloadingNodes
[
nodeIndex
].
unitDiscoveryState
=
STATE_NONE
;
downloadingNodes
[
nodeIndex
].
unitDiscoveryState
=
STATE_NONE
;
downloadingNodes
[
nodeIndex
].
msTickWhenLastSeen
=
0
;
downloadingNodes
[
nodeIndex
].
msTickWhenLastSeen
=
0
;
}
}
}
}
void
emAfOtaServerDynamicBlockPeriodTick
()
void
emAfOtaServerDynamicBlockPeriodTick
()
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server-page-request.c
View file @
e5cd9e56
...
@@ -111,11 +111,11 @@ uint8_t emAfOtaPageRequestHandler(uint8_t clientEndpoint,
...
@@ -111,11 +111,11 @@ uint8_t emAfOtaPageRequestHandler(uint8_t clientEndpoint,
void
emAfOtaPageRequestTick
(
uint8_t
endpoint
)
void
emAfOtaPageRequestTick
(
uint8_t
endpoint
)
{
{
if
(
requesterNodeId
==
EMBER_NULL_NODE_ID
)
{
if
(
requesterNodeId
==
EMBER_NULL_NODE_ID
)
{
return
;
return
;
}
}
sendBlockRequest
();
sendBlockRequest
();
emberAfScheduleServerTickExtended
(
endpoint
,
emberAfScheduleServerTickExtended
(
endpoint
,
ZCL_OTA_BOOTLOAD_CLUSTER_ID
,
ZCL_OTA_BOOTLOAD_CLUSTER_ID
,
requesterResponseSpacing
,
requesterResponseSpacing
,
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-server/ota-server.c
View file @
e5cd9e56
...
@@ -46,9 +46,9 @@ uint8_t otaServerEndpoint = 0; // invalid endpoint
...
@@ -46,9 +46,9 @@ uint8_t otaServerEndpoint = 0; // invalid endpoint
#define MAX_POSSIBLE_SERVER_BLOCK_SIZE 63
#define MAX_POSSIBLE_SERVER_BLOCK_SIZE 63
#if defined(EMBER_AF_PLUGIN_OTA_SERVER_MIN_BLOCK_REQUEST_SUPPORT)
#if defined(EMBER_AF_PLUGIN_OTA_SERVER_MIN_BLOCK_REQUEST_SUPPORT)
#define MIN_BLOCK_REQUEST_SERVER_SUPPORT EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_SERVER
#define MIN_BLOCK_REQUEST_SERVER_SUPPORT EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_SERVER
#else
#else
#define MIN_BLOCK_REQUEST_SERVER_SUPPORT 0
#define MIN_BLOCK_REQUEST_SERVER_SUPPORT 0
#endif
#endif
// -----------------------------------------------------------------------------
// -----------------------------------------------------------------------------
...
@@ -58,7 +58,7 @@ uint8_t otaServerEndpoint = 0; // invalid endpoint
...
@@ -58,7 +58,7 @@ uint8_t otaServerEndpoint = 0; // invalid endpoint
static
bool
commandParse
(
EmberAfClusterCommand
*
command
);
static
bool
commandParse
(
EmberAfClusterCommand
*
command
);
#define prepareClusterResponse(commandId, status) \
#define prepareClusterResponse(commandId, status) \
emAfOtaServerPrepareResponse(false, \
emAfOtaServerPrepareResponse(false, \
(commandId), \
(commandId), \
(status), \
(status), \
0) // defaultResponsePayloadCommandId
0) // defaultResponsePayloadCommandId
...
@@ -77,14 +77,14 @@ static void addEmberAfOtaImageIdIntoResponse(const EmberAfOtaImageId* id);
...
@@ -77,14 +77,14 @@ static void addEmberAfOtaImageIdIntoResponse(const EmberAfOtaImageId* id);
void
emberAfOtaBootloadClusterServerInitCallback
(
uint8_t
endpoint
)
void
emberAfOtaBootloadClusterServerInitCallback
(
uint8_t
endpoint
)
{
{
emberAfOtaStorageInitCallback
();
emberAfOtaStorageInitCallback
();
otaServerEndpoint
=
endpoint
;
otaServerEndpoint
=
endpoint
;
emAfOtaServerDynamicBlockPeriodInit
();
emAfOtaServerDynamicBlockPeriodInit
();
}
}
void
emberAfOtaBootloadClusterServerTickCallback
(
uint8_t
endpoint
)
void
emberAfOtaBootloadClusterServerTickCallback
(
uint8_t
endpoint
)
{
{
emAfOtaPageRequestTick
(
endpoint
);
emAfOtaPageRequestTick
(
endpoint
);
}
}
// This tick is endpointless and declared differently in plugin.properties
// This tick is endpointless and declared differently in plugin.properties
...
@@ -98,11 +98,11 @@ void emberAfOtaServerTick(void)
...
@@ -98,11 +98,11 @@ void emberAfOtaServerTick(void)
// -------------------------------------------------------
// -------------------------------------------------------
bool
emberAfOtaServerIncomingMessageRawCallback
(
EmberAfClusterCommand
*
command
)
bool
emberAfOtaServerIncomingMessageRawCallback
(
EmberAfClusterCommand
*
command
)
{
{
EmberStatus
status
;
EmberStatus
status
;
if
(
!
commandParse
(
command
))
{
if
(
!
commandParse
(
command
))
{
emberAfOtaBootloadClusterPrintln
(
"ClusterError: failed parsing cmd 0x%x"
,
emberAfOtaBootloadClusterPrintln
(
"ClusterError: failed parsing cmd 0x%x"
,
command
->
commandId
);
command
->
commandId
);
emberAfOtaBootloadClusterFlush
();
emberAfOtaBootloadClusterFlush
();
status
=
emberAfSendDefaultResponse
(
command
,
EMBER_ZCL_STATUS_INVALID_FIELD
);
status
=
emberAfSendDefaultResponse
(
command
,
EMBER_ZCL_STATUS_INVALID_FIELD
);
}
else
{
}
else
{
status
=
emberAfSendResponse
();
status
=
emberAfSendResponse
();
...
@@ -115,29 +115,29 @@ bool emberAfOtaServerIncomingMessageRawCallback(EmberAfClusterCommand* command)
...
@@ -115,29 +115,29 @@ bool emberAfOtaServerIncomingMessageRawCallback(EmberAfClusterCommand* command)
status
);
status
);
}
}
// Always return true to indicate we processed the message.
// Always return true to indicate we processed the message.
return
true
;
return
true
;
}
}
static
uint8_t
queryNextImageRequestHandler
(
const
EmberAfOtaImageId
*
currentImageId
,
static
uint8_t
queryNextImageRequestHandler
(
const
EmberAfOtaImageId
*
currentImageId
,
uint16_t
*
hardwareVersion
)
uint16_t
*
hardwareVersion
)
{
{
uint8_t
status
;
uint8_t
status
;
EmberAfOtaImageId
upgradeImageId
;
EmberAfOtaImageId
upgradeImageId
;
status
=
emberAfOtaServerQueryCallback
(
currentImageId
,
status
=
emberAfOtaServerQueryCallback
(
currentImageId
,
hardwareVersion
,
hardwareVersion
,
&
upgradeImageId
);
&
upgradeImageId
);
prepareClusterResponse
(
ZCL_QUERY_NEXT_IMAGE_RESPONSE_COMMAND_ID
,
prepareClusterResponse
(
ZCL_QUERY_NEXT_IMAGE_RESPONSE_COMMAND_ID
,
status
);
status
);
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
return
status
;
return
status
;
}
}
addEmberAfOtaImageIdIntoResponse
(
&
upgradeImageId
);
addEmberAfOtaImageIdIntoResponse
(
&
upgradeImageId
);
emberAfPutInt32uInResp
(
emberAfOtaStorageGetTotalImageSizeCallback
(
&
upgradeImageId
));
emberAfPutInt32uInResp
(
emberAfOtaStorageGetTotalImageSizeCallback
(
&
upgradeImageId
));
return
status
;
return
status
;
}
}
bool
emberAfOtaServerSendImageNotifyCallback
(
EmberNodeId
dest
,
bool
emberAfOtaServerSendImageNotifyCallback
(
EmberNodeId
dest
,
...
@@ -185,28 +185,28 @@ bool emberAfOtaServerSendImageNotifyCallback(EmberNodeId dest,
...
@@ -185,28 +185,28 @@ bool emberAfOtaServerSendImageNotifyCallback(EmberNodeId dest,
}
}
static
void
printBlockRequestInfo
(
const
EmberAfOtaImageId
*
id
,
static
void
printBlockRequestInfo
(
const
EmberAfOtaImageId
*
id
,
uint8_t
maxDataSize
,
uint8_t
maxDataSize
,
uint32_t
offset
)
uint32_t
offset
)
{
{
// To reduce the redundant data printed by the server, it will only print
// To reduce the redundant data printed by the server, it will only print
// a request for a different image than the last one. To change this
// a request for a different image than the last one. To change this
// behavior update the bool below.
// behavior update the bool below.
const
bool
printAllRequests
=
false
;
const
bool
printAllRequests
=
false
;
static
EmberAfOtaImageId
lastImageId
=
INVALID_OTA_IMAGE_ID
;
static
EmberAfOtaImageId
lastImageId
=
INVALID_OTA_IMAGE_ID
;
if
(
!
printAllRequests
if
(
!
printAllRequests
&&
(
0
==
MEMCOMPARE
(
id
,
&
lastImageId
,
sizeof
(
EmberAfOtaImageId
))))
{
&&
(
0
==
MEMCOMPARE
(
id
,
&
lastImageId
,
sizeof
(
EmberAfOtaImageId
))))
{
return
;
return
;
}
}
MEMMOVE
(
&
lastImageId
,
id
,
sizeof
(
EmberAfOtaImageId
));
MEMMOVE
(
&
lastImageId
,
id
,
sizeof
(
EmberAfOtaImageId
));
emberAfOtaBootloadClusterPrintln
(
"NEW ImageBlockReq mfgId:%2x imageTypeId:%2x, file:%4x, maxDataSize:%d, offset:0x%4x"
,
emberAfOtaBootloadClusterPrintln
(
"NEW ImageBlockReq mfgId:%2x imageTypeId:%2x, file:%4x, maxDataSize:%d, offset:0x%4x"
,
id
->
manufacturerId
,
id
->
manufacturerId
,
id
->
imageTypeId
,
id
->
imageTypeId
,
id
->
firmwareVersion
,
id
->
firmwareVersion
,
maxDataSize
,
maxDataSize
,
offset
);
offset
);
//emberAfPluginOtaServerUpdateStartedCallback(id->manufacturerId,
//emberAfPluginOtaServerUpdateStartedCallback(id->manufacturerId,
//id->imageTypeId,
//id->imageTypeId,
// id->firmwareVersion,
// id->firmwareVersion,
...
@@ -218,28 +218,28 @@ static void printBlockRequestInfo(const EmberAfOtaImageId* id,
...
@@ -218,28 +218,28 @@ static void printBlockRequestInfo(const EmberAfOtaImageId* id,
// It returns 0 on error, or the number of bytes sent on success.
// It returns 0 on error, or the number of bytes sent on success.
uint8_t
emAfOtaImageBlockRequestHandler
(
EmberAfImageBlockRequestCallbackStruct
*
callbackData
)
uint8_t
emAfOtaImageBlockRequestHandler
(
EmberAfImageBlockRequestCallbackStruct
*
callbackData
)
{
{
uint8_t
data
[
MAX_POSSIBLE_SERVER_BLOCK_SIZE
];
uint8_t
data
[
MAX_POSSIBLE_SERVER_BLOCK_SIZE
];
uint32_t
actualLength
;
uint32_t
actualLength
;
uint8_t
status
=
EMBER_ZCL_STATUS_SUCCESS
;
uint8_t
status
=
EMBER_ZCL_STATUS_SUCCESS
;
uint8_t
serverBlockSize
=
emberAfOtaServerBlockSizeCallback
(
callbackData
->
source
);
uint8_t
serverBlockSize
=
emberAfOtaServerBlockSizeCallback
(
callbackData
->
source
);
#ifdef EMBER_AF_PLUGIN_SUB_GHZ_SERVER
#ifdef EMBER_AF_PLUGIN_SUB_GHZ_SERVER
EmberDutyCycleState
dcState
;
EmberDutyCycleState
dcState
;
#endif
#endif
if
(
serverBlockSize
>
MAX_POSSIBLE_SERVER_BLOCK_SIZE
)
{
if
(
serverBlockSize
>
MAX_POSSIBLE_SERVER_BLOCK_SIZE
)
{
serverBlockSize
=
MAX_POSSIBLE_SERVER_BLOCK_SIZE
;
serverBlockSize
=
MAX_POSSIBLE_SERVER_BLOCK_SIZE
;
}
}
// Delay checks
// Delay checks
// We delay the OTA client if the following conditions happen, listed by order
// We delay the OTA client if the following conditions happen, listed by order
// 1. The duty cycle state has moved to Critical state (for SE1.4 subghz)
// 1. The duty cycle state has moved to Critical state (for SE1.4 subghz)
// 2. We support a dynamically-treated Minimum Block Period, which means we
// 2. We support a dynamically-treated Minimum Block Period, which means we
// can only support so many clients downloading at once. When we're at that
// can only support so many clients downloading at once. When we're at that
// max, we tell new clients to delay and come back later
// max, we tell new clients to delay and come back later
// 3. The OTA client indicates that it supports the Minimum Block Period, and
// 3. The OTA client indicates that it supports the Minimum Block Period, and
// its value differs from the value the server holds. We tell it to wait
// its value differs from the value the server holds. We tell it to wait
// for data with the updated block period value
// for data with the updated block period value
// 4. Test code desires a delay
// 4. Test code desires a delay
#ifdef EMBER_AF_PLUGIN_SUB_GHZ_SERVER
#ifdef EMBER_AF_PLUGIN_SUB_GHZ_SERVER
// SE1.4 says that when in Critical Duty Cycle state... "If active, the OTA server
// SE1.4 says that when in Critical Duty Cycle state... "If active, the OTA server
...
@@ -251,67 +251,67 @@ uint8_t emAfOtaImageBlockRequestHandler(EmberAfImageBlockRequestCallbackStruct*
...
@@ -251,67 +251,67 @@ uint8_t emAfOtaImageBlockRequestHandler(EmberAfImageBlockRequestCallbackStruct*
status
=
EMBER_ZCL_STATUS_WAIT_FOR_DATA
;
status
=
EMBER_ZCL_STATUS_WAIT_FOR_DATA
;
}
else
}
else
#endif
#endif
status
=
emberAfOtaServerImageBlockRequestCallback
(
callbackData
);
status
=
emberAfOtaServerImageBlockRequestCallback
(
callbackData
);
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
prepareClusterResponse
(
ZCL_IMAGE_BLOCK_RESPONSE_COMMAND_ID
,
prepareClusterResponse
(
ZCL_IMAGE_BLOCK_RESPONSE_COMMAND_ID
,
status
);
status
);
if
(
status
==
EMBER_ZCL_STATUS_WAIT_FOR_DATA
)
{
if
(
status
==
EMBER_ZCL_STATUS_WAIT_FOR_DATA
)
{
// Current time (0 = use relative time, not UTC)
// Current time (0 = use relative time, not UTC)
emberAfPutInt32uInResp
(
0
);
emberAfPutInt32uInResp
(
0
);
emberAfPutInt32uInResp
(
callbackData
->
waitTimeSecondsResponse
);
emberAfPutInt32uInResp
(
callbackData
->
waitTimeSecondsResponse
);
#if defined(EMBER_AF_PLUGIN_OTA_SERVER_MIN_BLOCK_REQUEST_SUPPORT)
#if defined(EMBER_AF_PLUGIN_OTA_SERVER_MIN_BLOCK_REQUEST_SUPPORT)
// The min block request period is in milliseconds as defined in af-types.h
// The min block request period is in milliseconds as defined in af-types.h
// This attribute, BockRequestDelay, used to be in milliseconds
// This attribute, BockRequestDelay, used to be in milliseconds
// (09-5264-23, section 6.7.10)
// (09-5264-23, section 6.7.10)
// It now (15-0324-02) is called MinimumBlockPeriod and is defined to be
// It now (15-0324-02) is called MinimumBlockPeriod and is defined to be
// in seconds (section 11.10.10)
// in seconds (section 11.10.10)
emberAfPutInt16uInResp
(
callbackData
->
minBlockRequestPeriod
);
emberAfPutInt16uInResp
(
callbackData
->
minBlockRequestPeriod
);
#endif
#endif
}
}
return
0
;
return
0
;
}
}
MEMSET
(
data
,
0
,
MAX_POSSIBLE_SERVER_BLOCK_SIZE
);
MEMSET
(
data
,
0
,
MAX_POSSIBLE_SERVER_BLOCK_SIZE
);
printBlockRequestInfo
(
callbackData
->
id
,
printBlockRequestInfo
(
callbackData
->
id
,
callbackData
->
maxDataSize
,
callbackData
->
maxDataSize
,
callbackData
->
offset
);
callbackData
->
offset
);
callbackData
->
maxDataSize
=
(
callbackData
->
maxDataSize
<
serverBlockSize
callbackData
->
maxDataSize
=
(
callbackData
->
maxDataSize
<
serverBlockSize
?
callbackData
->
maxDataSize
?
callbackData
->
maxDataSize
:
serverBlockSize
);
:
serverBlockSize
);
if
(
EMBER_AF_OTA_STORAGE_SUCCESS
if
(
EMBER_AF_OTA_STORAGE_SUCCESS
!=
emberAfOtaStorageReadImageDataCallback
(
callbackData
->
id
,
!=
emberAfOtaStorageReadImageDataCallback
(
callbackData
->
id
,
callbackData
->
offset
,
callbackData
->
offset
,
callbackData
->
maxDataSize
,
callbackData
->
maxDataSize
,
data
,
data
,
&
actualLength
)
&
actualLength
)
||
actualLength
==
0
)
{
||
actualLength
==
0
)
{
status
=
EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE
;
status
=
EMBER_ZCL_STATUS_NO_IMAGE_AVAILABLE
;
// emberAfPluginOtaServerUpdateCompleteCallback(callbackData->id->manufacturerId,
// emberAfPluginOtaServerUpdateCompleteCallback(callbackData->id->manufacturerId,
// callbackData->id->imageTypeId,
// callbackData->id->imageTypeId,
// callbackData->id->firmwareVersion,
// callbackData->id->firmwareVersion,
// callbackData->source,
// callbackData->source,
// status);
// status);
}
}
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
!
emAfOtaPageRequestErrorHandler
())
{
if
(
!
emAfOtaPageRequestErrorHandler
())
{
// If the page request code didn't handle the error (because this code
// If the page request code didn't handle the error (because this code
// wasn't called due to a page request) then we send a normal
// wasn't called due to a page request) then we send a normal
// response. We don't generate an error message because in that case
// response. We don't generate an error message because in that case
// we were sending an unsolicited image block response.
// we were sending an unsolicited image block response.
prepareDefaultResponse
(
status
,
ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
);
prepareDefaultResponse
(
status
,
ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
);
}
}
return
0
;
return
0
;
}
}
prepareClusterResponse
(
ZCL_IMAGE_BLOCK_RESPONSE_COMMAND_ID
,
status
);
prepareClusterResponse
(
ZCL_IMAGE_BLOCK_RESPONSE_COMMAND_ID
,
status
);
addEmberAfOtaImageIdIntoResponse
(
callbackData
->
id
);
addEmberAfOtaImageIdIntoResponse
(
callbackData
->
id
);
emberAfPutInt32uInResp
(
callbackData
->
offset
);
emberAfPutInt32uInResp
(
callbackData
->
offset
);
emberAfPutInt8uInResp
((
uint8_t
)
actualLength
);
emberAfPutInt8uInResp
((
uint8_t
)
actualLength
);
emberAfPutBlockInResp
(
data
,
actualLength
);
emberAfPutBlockInResp
(
data
,
actualLength
);
emberAfSetCommandEndpoints
(
otaServerEndpoint
,
callbackData
->
clientEndpoint
);
emberAfSetCommandEndpoints
(
otaServerEndpoint
,
callbackData
->
clientEndpoint
);
//emberAfPluginOtaServerBlockSentCallback((uint8_t)actualLength,
//emberAfPluginOtaServerBlockSentCallback((uint8_t)actualLength,
// callbackData->id->manufacturerId,
// callbackData->id->manufacturerId,
...
@@ -319,85 +319,85 @@ uint8_t emAfOtaImageBlockRequestHandler(EmberAfImageBlockRequestCallbackStruct*
...
@@ -319,85 +319,85 @@ uint8_t emAfOtaImageBlockRequestHandler(EmberAfImageBlockRequestCallbackStruct*
// callbackData->id->firmwareVersion);
// callbackData->id->firmwareVersion);
// We can't send more than 128 bytes in a packet so we can safely cast this
// We can't send more than 128 bytes in a packet so we can safely cast this
// to a 1-byte number.
// to a 1-byte number.
return
(
uint8_t
)
actualLength
;
return
(
uint8_t
)
actualLength
;
}
}
static
void
constructUpgradeEndResponse
(
const
EmberAfOtaImageId
*
imageId
,
static
void
constructUpgradeEndResponse
(
const
EmberAfOtaImageId
*
imageId
,
uint32_t
upgradeTime
)
uint32_t
upgradeTime
)
{
{
prepareClusterResponse
(
ZCL_UPGRADE_END_RESPONSE_COMMAND_ID
,
prepareClusterResponse
(
ZCL_UPGRADE_END_RESPONSE_COMMAND_ID
,
0
);
// status code (will ignore)
0
);
// status code (will ignore)
appResponseLength
--
;
// The above function wrote an extra byte which we
appResponseLength
--
;
// The above function wrote an extra byte which we
// don't want because there is no status code for this
// don't want because there is no status code for this
// message
// message
addEmberAfOtaImageIdIntoResponse
(
imageId
);
addEmberAfOtaImageIdIntoResponse
(
imageId
);
// We always use relative time. There is no benefit in using
// We always use relative time. There is no benefit in using
// UTC time since the client has to support both.
// UTC time since the client has to support both.
emberAfPutInt32uInResp
(
0
);
// current time
emberAfPutInt32uInResp
(
0
);
// current time
emberAfPutInt32uInResp
(
upgradeTime
);
emberAfPutInt32uInResp
(
upgradeTime
);
}
}
static
void
upgradeEndRequestHandler
(
EmberNodeId
source
,
static
void
upgradeEndRequestHandler
(
EmberNodeId
source
,
uint8_t
status
,
uint8_t
status
,
const
EmberAfOtaImageId
*
imageId
)
const
EmberAfOtaImageId
*
imageId
)
{
{
uint32_t
upgradeTime
;
uint32_t
upgradeTime
;
bool
goAhead
;
bool
goAhead
;
EmberAfStatus
defaultRespStatus
=
EMBER_ZCL_STATUS_SUCCESS
;
EmberAfStatus
defaultRespStatus
=
EMBER_ZCL_STATUS_SUCCESS
;
emberAfOtaBootloadClusterPrintln
(
"RX UpgradeEndReq status:%x"
,
emberAfOtaBootloadClusterPrintln
(
"RX UpgradeEndReq status:%x"
,
status
);
status
);
// This callback is considered only informative when the status
// This callback is considered only informative when the status
// is a failure.
// is a failure.
goAhead
=
emberAfOtaServerUpgradeEndRequestCallback
(
source
,
goAhead
=
emberAfOtaServerUpgradeEndRequestCallback
(
source
,
status
,
status
,
&
upgradeTime
,
&
upgradeTime
,
imageId
);
imageId
);
if
(
status
==
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
status
==
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
goAhead
)
{
if
(
goAhead
)
{
constructUpgradeEndResponse
(
imageId
,
upgradeTime
);
constructUpgradeEndResponse
(
imageId
,
upgradeTime
);
//emberAfPluginOtaServerUpdateCompleteCallback(imageId->manufacturerId,
//emberAfPluginOtaServerUpdateCompleteCallback(imageId->manufacturerId,
// imageId->imageTypeId,
// imageId->imageTypeId,
// imageId->firmwareVersion,
// imageId->firmwareVersion,
// source,
// source,
// status);
// status);
return
;
return
;
}
else
{
}
else
{
defaultRespStatus
=
EMBER_ZCL_STATUS_ABORT
;
defaultRespStatus
=
EMBER_ZCL_STATUS_ABORT
;
}
}
}
}
prepareDefaultResponse
(
defaultRespStatus
,
prepareDefaultResponse
(
defaultRespStatus
,
ZCL_UPGRADE_END_REQUEST_COMMAND_ID
);
ZCL_UPGRADE_END_REQUEST_COMMAND_ID
);
}
}
static
void
querySpecificFileRequestHandler
(
uint8_t
*
requestNodeAddress
,
static
void
querySpecificFileRequestHandler
(
uint8_t
*
requestNodeAddress
,
const
EmberAfOtaImageId
*
imageId
,
const
EmberAfOtaImageId
*
imageId
,
uint16_t
currentStackVersion
)
uint16_t
currentStackVersion
)
{
{
// Not supported yet.
// Not supported yet.
prepareDefaultResponse
(
EMBER_ZCL_STATUS_UNSUP_CLUSTER_COMMAND
,
prepareDefaultResponse
(
EMBER_ZCL_STATUS_UNSUP_CLUSTER_COMMAND
,
ZCL_QUERY_SPECIFIC_FILE_REQUEST_COMMAND_ID
);
ZCL_QUERY_SPECIFIC_FILE_REQUEST_COMMAND_ID
);
}
}
void
emAfOtaServerPrepareResponse
(
bool
useDefaultResponse
,
void
emAfOtaServerPrepareResponse
(
bool
useDefaultResponse
,
uint8_t
commandId
,
uint8_t
commandId
,
uint8_t
status
,
uint8_t
status
,
uint8_t
defaultResponsePayloadCommandId
)
uint8_t
defaultResponsePayloadCommandId
)
{
{
emberAfResponseApsFrame
.
sourceEndpoint
=
otaServerEndpoint
;
emberAfResponseApsFrame
.
sourceEndpoint
=
otaServerEndpoint
;
appResponseLength
=
0
;
appResponseLength
=
0
;
emberAfResponseApsFrame
.
clusterId
=
ZCL_OTA_BOOTLOAD_CLUSTER_ID
;
emberAfResponseApsFrame
.
clusterId
=
ZCL_OTA_BOOTLOAD_CLUSTER_ID
;
emberAfResponseApsFrame
.
options
=
emberAfResponseApsFrame
.
options
=
((
emAfOtaServerHandlingPageRequest
()
((
emAfOtaServerHandlingPageRequest
()
&&
commandId
==
ZCL_IMAGE_BLOCK_RESPONSE_COMMAND_ID
)
&&
commandId
==
ZCL_IMAGE_BLOCK_RESPONSE_COMMAND_ID
)
?
EMBER_APS_OPTION_NONE
?
EMBER_APS_OPTION_NONE
:
EMBER_APS_OPTION_RETRY
);
:
EMBER_APS_OPTION_RETRY
);
// Assume emberAfResponseApsFrame.destinationEndpoint has already
// Assume emberAfResponseApsFrame.destinationEndpoint has already
// been set based on the framework. In most cases it is as simple
// been set based on the framework. In most cases it is as simple
...
@@ -423,189 +423,236 @@ void emAfOtaServerPrepareResponse(bool useDefaultResponse,
...
@@ -423,189 +423,236 @@ void emAfOtaServerPrepareResponse(bool useDefaultResponse,
static
void
addEmberAfOtaImageIdIntoResponse
(
const
EmberAfOtaImageId
*
id
)
static
void
addEmberAfOtaImageIdIntoResponse
(
const
EmberAfOtaImageId
*
id
)
{
{
emberAfPutInt16uInResp
(
id
->
manufacturerId
);
emberAfPutInt16uInResp
(
id
->
manufacturerId
);
emberAfPutInt16uInResp
(
id
->
imageTypeId
);
emberAfPutInt16uInResp
(
id
->
imageTypeId
);
emberAfPutInt32uInResp
(
id
->
firmwareVersion
);
emberAfPutInt32uInResp
(
id
->
firmwareVersion
);
}
}
static
bool
commandParse
(
EmberAfClusterCommand
*
command
)
static
bool
commandParse
(
EmberAfClusterCommand
*
command
)
{
{
uint8_t
commandId
=
command
->
commandId
;
uint8_t
commandId
=
command
->
commandId
;
uint8_t
*
buffer
=
command
->
buffer
;
uint8_t
*
buffer
=
command
->
buffer
;
uint8_t
length
=
command
->
bufLen
;
uint8_t
length
=
command
->
bufLen
;
uint8_t
index
=
EMBER_AF_ZCL_OVERHEAD
;
uint8_t
index
=
EMBER_AF_ZCL_OVERHEAD
;
EmberAfOtaImageId
imageId
=
INVALID_OTA_IMAGE_ID
;
EmberAfOtaImageId
imageId
=
INVALID_OTA_IMAGE_ID
;
if
(
commandId
>
LAST_MESSAGE_ID
if
(
commandId
>
LAST_MESSAGE_ID
||
(
length
||
(
length
<
(
EMBER_AF_ZCL_OVERHEAD
+
emAfOtaMinMessageLengths
[
commandId
])))
{
<
(
EMBER_AF_ZCL_OVERHEAD
+
emAfOtaMinMessageLengths
[
commandId
])))
{
return
false
;
return
false
;
}
}
switch
(
commandId
)
{
switch
(
commandId
)
{
case
ZCL_QUERY_NEXT_IMAGE_REQUEST_COMMAND_ID
:
case
ZCL_QUERY_NEXT_IMAGE_REQUEST_COMMAND_ID
:
case
ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
:
case
ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
:
case
ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
:
{
case
ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
:
{
uint8_t
fieldControl
;
uint8_t
fieldControl
;
uint32_t
offset
;
uint32_t
offset
;
uint8_t
maxDataSize
;
uint8_t
maxDataSize
;
uint16_t
hardwareVersion
;
uint16_t
hardwareVersion
;
bool
hardwareVersionPresent
=
false
;
bool
hardwareVersionPresent
=
false
;
fieldControl
=
emberAfGetInt8u
(
buffer
,
index
,
length
);
fieldControl
=
emberAfGetInt8u
(
buffer
,
index
,
length
);
index
++
;
index
++
;
index
+=
emAfOtaParseImageIdFromMessage
(
&
imageId
,
index
+=
emAfOtaParseImageIdFromMessage
(
&
imageId
,
&
(
buffer
[
index
]),
&
(
buffer
[
index
]),
length
);
length
);
if
(
commandId
==
ZCL_QUERY_NEXT_IMAGE_REQUEST_COMMAND_ID
)
{
if
(
commandId
==
ZCL_QUERY_NEXT_IMAGE_REQUEST_COMMAND_ID
)
{
if
(
fieldControl
&
QUERY_NEXT_IMAGE_HW_VER_PRESENT_MASK
)
{
if
(
fieldControl
&
QUERY_NEXT_IMAGE_HW_VER_PRESENT_MASK
)
{
hardwareVersionPresent
=
true
;
hardwareVersionPresent
=
true
;
hardwareVersion
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
hardwareVersion
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
index
+=
2
;
index
+=
2
;
}
}
queryNextImageRequestHandler
(
&
imageId
,
queryNextImageRequestHandler
(
&
imageId
,
(
hardwareVersionPresent
(
hardwareVersionPresent
?
&
hardwareVersion
?
&
hardwareVersion
:
NULL
));
:
NULL
));
return
true
;
return
true
;
}
// else // ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
}
// else // ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
// or ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
// or ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
offset
=
emberAfGetInt32u
(
buffer
,
index
,
length
);
offset
=
emberAfGetInt32u
(
buffer
,
index
,
length
);
index
+=
4
;
index
+=
4
;
maxDataSize
=
emberAfGetInt8u
(
buffer
,
index
,
length
);
maxDataSize
=
emberAfGetInt8u
(
buffer
,
index
,
length
);
index
++
;
index
++
;
if
(
commandId
==
ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
)
{
if
(
commandId
==
ZCL_IMAGE_BLOCK_REQUEST_COMMAND_ID
)
{
EmberAfImageBlockRequestCallbackStruct
callbackStruct
;
EmberAfImageBlockRequestCallbackStruct
callbackStruct
;
MEMSET
(
&
callbackStruct
,
0
,
sizeof
(
EmberAfImageBlockRequestCallbackStruct
));
MEMSET
(
&
callbackStruct
,
0
,
sizeof
(
EmberAfImageBlockRequestCallbackStruct
));
if
(
fieldControl
&
OTA_FIELD_CONTROL_NODE_EUI64_PRESENT_BIT
)
{
if
(
fieldControl
&
OTA_FIELD_CONTROL_NODE_EUI64_PRESENT_BIT
)
{
MEMCOPY
(
callbackStruct
.
sourceEui
,
&
(
buffer
[
index
]),
EUI64_SIZE
);
MEMCOPY
(
callbackStruct
.
sourceEui
,
&
(
buffer
[
index
]),
EUI64_SIZE
);
index
+=
EUI64_SIZE
;
index
+=
EUI64_SIZE
;
}
}
if
(
fieldControl
&
OTA_FIELD_CONTROL_MIN_BLOCK_REQUEST_PRESENT_BIT
)
{
if
(
fieldControl
&
OTA_FIELD_CONTROL_MIN_BLOCK_REQUEST_PRESENT_BIT
)
{
callbackStruct
.
minBlockRequestPeriod
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
callbackStruct
.
minBlockRequestPeriod
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
callbackStruct
.
bitmask
|=
EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_CLIENT
;
callbackStruct
.
bitmask
|=
EMBER_AF_IMAGE_BLOCK_REQUEST_MIN_BLOCK_REQUEST_SUPPORTED_BY_CLIENT
;
index
+=
2
;
index
+=
2
;
}
}
callbackStruct
.
clientEndpoint
=
command
->
apsFrame
->
sourceEndpoint
;
callbackStruct
.
clientEndpoint
=
command
->
apsFrame
->
sourceEndpoint
;
callbackStruct
.
source
=
command
->
source
;
callbackStruct
.
source
=
command
->
source
;
callbackStruct
.
id
=
&
imageId
;
callbackStruct
.
id
=
&
imageId
;
callbackStruct
.
offset
=
offset
;
callbackStruct
.
offset
=
offset
;
callbackStruct
.
maxDataSize
=
maxDataSize
;
callbackStruct
.
maxDataSize
=
maxDataSize
;
callbackStruct
.
bitmask
|=
MIN_BLOCK_REQUEST_SERVER_SUPPORT
;
callbackStruct
.
bitmask
|=
MIN_BLOCK_REQUEST_SERVER_SUPPORT
;
emAfOtaImageBlockRequestHandler
(
&
callbackStruct
);
emAfOtaImageBlockRequestHandler
(
&
callbackStruct
);
}
else
{
// ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
}
else
{
// ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
uint16_t
pageSize
;
uint16_t
pageSize
;
uint16_t
responseSpacing
;
uint16_t
responseSpacing
;
uint8_t
status
;
uint8_t
status
;
pageSize
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
pageSize
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
index
+=
2
;
index
+=
2
;
responseSpacing
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
responseSpacing
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
index
+=
2
;
index
+=
2
;
status
=
emAfOtaPageRequestHandler
(
command
->
apsFrame
->
sourceEndpoint
,
status
=
emAfOtaPageRequestHandler
(
command
->
apsFrame
->
sourceEndpoint
,
otaServerEndpoint
,
otaServerEndpoint
,
&
imageId
,
&
imageId
,
offset
,
offset
,
maxDataSize
,
maxDataSize
,
pageSize
,
pageSize
,
responseSpacing
);
responseSpacing
);
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
status
!=
EMBER_ZCL_STATUS_SUCCESS
)
{
prepareDefaultResponse
(
status
,
prepareDefaultResponse
(
status
,
ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
);
ZCL_IMAGE_PAGE_REQUEST_COMMAND_ID
);
}
}
}
}
return
true
;
return
true
;
}
}
case
ZCL_UPGRADE_END_REQUEST_COMMAND_ID
:
{
case
ZCL_UPGRADE_END_REQUEST_COMMAND_ID
:
{
uint8_t
status
=
emberAfGetInt8u
(
buffer
,
index
,
length
);
uint8_t
status
=
emberAfGetInt8u
(
buffer
,
index
,
length
);
index
++
;
index
++
;
if
(
status
==
EMBER_ZCL_STATUS_SUCCESS
)
{
if
(
status
==
EMBER_ZCL_STATUS_SUCCESS
)
{
index
+=
emAfOtaParseImageIdFromMessage
(
&
imageId
,
index
+=
emAfOtaParseImageIdFromMessage
(
&
imageId
,
&
(
buffer
[
index
]),
&
(
buffer
[
index
]),
length
);
length
);
}
}
upgradeEndRequestHandler
(
command
->
source
,
status
,
&
imageId
);
upgradeEndRequestHandler
(
command
->
source
,
status
,
&
imageId
);
return
true
;
return
true
;
}
}
case
ZCL_QUERY_SPECIFIC_FILE_REQUEST_COMMAND_ID
:
{
case
ZCL_QUERY_SPECIFIC_FILE_REQUEST_COMMAND_ID
:
{
uint8_t
*
requestNodeAddress
=
&
(
buffer
[
index
]);
uint8_t
*
requestNodeAddress
=
&
(
buffer
[
index
]);
uint16_t
currentStackVersion
;
uint16_t
currentStackVersion
;
index
+=
8
;
// add 8 to jump over the requestNodeAddress
index
+=
8
;
// add 8 to jump over the requestNodeAddress
index
+=
emAfOtaParseImageIdFromMessage
(
&
imageId
,
index
+=
emAfOtaParseImageIdFromMessage
(
&
imageId
,
&
(
buffer
[
index
]),
&
(
buffer
[
index
]),
length
);
length
);
currentStackVersion
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
currentStackVersion
=
emberAfGetInt16u
(
buffer
,
index
,
length
);
index
+=
2
;
index
+=
2
;
querySpecificFileRequestHandler
(
requestNodeAddress
,
querySpecificFileRequestHandler
(
requestNodeAddress
,
&
imageId
,
&
imageId
,
currentStackVersion
);
currentStackVersion
);
return
true
;
return
true
;
}
}
}
}
return
false
;
return
false
;
}
}
void
emberAfOtaServerSendUpgradeCommandCallback
(
EmberNodeId
dest
,
void
emberAfOtaServerSendUpgradeCommandCallback
(
EmberNodeId
dest
,
uint8_t
endpoint
,
uint8_t
endpoint
,
const
EmberAfOtaImageId
*
id
)
const
EmberAfOtaImageId
*
id
)
{
{
EmberStatus
status
;
EmberStatus
status
;
emberAfResponseDestination
=
dest
;
emberAfResponseDestination
=
dest
;
emberAfResponseApsFrame
.
destinationEndpoint
=
endpoint
;
emberAfResponseApsFrame
.
destinationEndpoint
=
endpoint
;
constructUpgradeEndResponse
(
id
,
constructUpgradeEndResponse
(
id
,
0
);
// upgrade time (0 = now)
0
);
// upgrade time (0 = now)
status
=
emberAfSendResponse
();
status
=
emberAfSendResponse
();
if
(
EMBER_SUCCESS
!=
status
)
{
if
(
EMBER_SUCCESS
!=
status
)
{
emberAfOtaBootloadClusterPrintln
(
"OTA: failed sending upgrade response: "
emberAfOtaBootloadClusterPrintln
(
"OTA: failed sending upgrade response: "
"error 0x%x"
,
status
);
"error 0x%x"
,
status
);
}
}
}
void
kk_ota_test123123123
()
{
EmberAfOtaImageId
id
;
id
.
manufacturerId
=
0x1268
;
id
.
imageTypeId
=
0x2904
;
id
.
firmwareVersion
=
15
;
emberAfOtaServerSendImageNotifyCallback
(
0xffff
,
1
,
0x03
,
0
,
&
id
);
}
}
void
kk_ota_test111
()
{
/*zclBufferSetup(ZCL_CLUSTER_SPECIFIC_COMMAND | ZCL_FRAME_CONTROL_SERVER_TO_CLIENT|ZCL_DISABLE_DEFAULT_RESPONSE_MASK, \
(ZCL_OTA_BOOTLOAD_CLUSTER_ID), \
(ZCL_IMAGE_NOTIFY_COMMAND_ID));
zclBufferAddByte(0x03);
zclBufferAddByte(0x00);
zclBufferAddWord(0x1234);
zclBufferAddWord(0x5678);
zclBufferAddInt32(0x11223344);
rpcSendCommand(0xffff,1,1,false);
emberAfCorePrintln("[kk_ota_test111] \r\n");*/
emberAfCorePrintln
(
"[kk_ota_test111]
\r\n
"
);
static
int
cnt
;
EmberAfOtaImageId
id
=
emberAfOtaStorageIteratorFirstCallback
();
cnt
=
0
;
do
{
emberAfCorePrintln
(
"**********%d********
\r\n
"
,
++
cnt
);
emberAfCorePrintln
(
"manufacturerId=0x%4X
\r\n
"
,
id
.
manufacturerId
);
emberAfCorePrintln
(
"imageTypeId=0x%4X
\r\n
"
,
id
.
imageTypeId
);
emberAfCorePrintln
(
"firmwareVersion=0x%8X
\r\n
"
,
id
.
firmwareVersion
);
id
=
emberAfOtaStorageIteratorNextCallback
();
}
while
(
emberAfIsOtaImageIdValid
(
&
id
));
}
static
int
s_ota_server_init
=
0
;
static
int
s_ota_server_init
=
0
;
EmberAfOtaImageId
kk_get_imageId
(
char
*
filename
){
EmberAfOtaImageId
kk_get_imageId
(
char
*
filename
){
char
*
oatfile
=
NULL
;
char
*
oatfile
=
NULL
;
EmberAfOtaImageId
id
=
emberAfOtaStorageIteratorFirstCallback
();
EmberAfOtaImageId
id
=
emberAfOtaStorageIteratorFirstCallback
();
do
{
do
{
oatfile
=
emAfOtaStorageGetFilepath
(
&
id
);
oatfile
=
emAfOtaStorageGetFilepath
(
&
id
);
if
(
oatfile
!=
NULL
&&
strcmp
(
oatfile
,
filename
)
==
0
){
if
(
oatfile
!=
NULL
&&
strcmp
(
oatfile
,
filename
)
==
0
){
return
id
;
return
id
;
}
}
id
=
emberAfOtaStorageIteratorNextCallback
();
id
=
emberAfOtaStorageIteratorNextCallback
();
}
while
(
emberAfIsOtaImageIdValid
(
&
id
));
}
while
(
emberAfIsOtaImageIdValid
(
&
id
));
return
emberAfInvalidImageId
;
return
emberAfInvalidImageId
;
}
}
void
kk_ota_notify
(
char
*
filepath
){
void
kk_ota_notify
(
char
*
filepath
){
if
(
s_ota_server_init
==
0
){
if
(
s_ota_server_init
==
0
){
s_ota_server_init
=
1
;
s_ota_server_init
=
1
;
emberAfOtaBootloadClusterServerInitCallback
(
0x00
);
emberAfOtaBootloadClusterServerInitCallback
(
0x00
);
}
}
//add file
//add file
emAfOtaReloadStorageDevice
();
emAfOtaReloadStorageDevice
();
//TODO:开启通知, 通过mac地址获取dest,endpoint
//TODO:开启通知, 通过mac地址获取dest,endpoint
EmberNodeId
dest
;
EmberNodeId
dest
;
uint8_t
endpoint
;
uint8_t
endpoint
;
EmberAfOtaImageId
id
;
EmberAfOtaImageId
id
;
id
=
kk_get_imageId
(
filepath
);
id
=
kk_get_imageId
(
filepath
);
emberAfOtaServerSendUpgradeCommandCallback
(
dest
,
endpoint
,
&
id
);
emberAfOtaServerSendUpgradeCommandCallback
(
dest
,
endpoint
,
&
id
);
}
}
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage-common-cli.c
View file @
e5cd9e56
...
@@ -142,10 +142,10 @@ void emAfOtaImageDelete(void)
...
@@ -142,10 +142,10 @@ void emAfOtaImageDelete(void)
void
emAfOtaReloadStorageDevice
(
void
)
void
emAfOtaReloadStorageDevice
(
void
)
{
{
#if defined (EMBER_AF_PLUGIN_OTA_STORAGE_POSIX_FILESYSTEM)
#if defined (EMBER_AF_PLUGIN_OTA_STORAGE_POSIX_FILESYSTEM)
emAfOtaStorageClose
();
emAfOtaStorageClose
();
#endif
#endif
emberAfOtaStorageInitCallback
();
emberAfOtaStorageInitCallback
();
}
}
#define PRINT_BLOCK_LENGTH 64
#define PRINT_BLOCK_LENGTH 64
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage-common.c
View file @
e5cd9e56
...
@@ -39,18 +39,18 @@
...
@@ -39,18 +39,18 @@
EmberAfOtaImageId
emAfOtaStorageGetImageIdFromHeader
(
const
EmberAfOtaHeader
*
header
)
EmberAfOtaImageId
emAfOtaStorageGetImageIdFromHeader
(
const
EmberAfOtaHeader
*
header
)
{
{
EmberAfOtaImageId
id
=
INVALID_OTA_IMAGE_ID
;
EmberAfOtaImageId
id
=
INVALID_OTA_IMAGE_ID
;
id
.
manufacturerId
=
header
->
manufacturerId
;
id
.
manufacturerId
=
header
->
manufacturerId
;
id
.
imageTypeId
=
header
->
imageTypeId
;
id
.
imageTypeId
=
header
->
imageTypeId
;
id
.
firmwareVersion
=
header
->
firmwareVersion
;
id
.
firmwareVersion
=
header
->
firmwareVersion
;
if
(
headerHasUpgradeFileDest
(
header
))
{
if
(
headerHasUpgradeFileDest
(
header
))
{
MEMCOPY
(
id
.
deviceSpecificFileEui64
,
MEMCOPY
(
id
.
deviceSpecificFileEui64
,
&
header
->
upgradeFileDestination
,
&
header
->
upgradeFileDestination
,
EUI64_SIZE
);
EUI64_SIZE
);
}
}
return
id
;
return
id
;
}
}
uint16_t
emGetUpgradeFileDestinationLength
(
uint16_t
headerVersion
)
uint16_t
emGetUpgradeFileDestinationLength
(
uint16_t
headerVersion
)
...
@@ -249,7 +249,7 @@ EmberAfOtaStorageStatus emAfOtaStorageReadAllTagInfo(const EmberAfOtaImageId* id
...
@@ -249,7 +249,7 @@ EmberAfOtaStorageStatus emAfOtaStorageReadAllTagInfo(const EmberAfOtaImageId* id
bool
emberAfIsOtaImageIdValid
(
const
EmberAfOtaImageId
*
idToCompare
)
bool
emberAfIsOtaImageIdValid
(
const
EmberAfOtaImageId
*
idToCompare
)
{
{
return
(
0
!=
MEMPGMCOMPARE
(
idToCompare
,
return
(
0
!=
MEMPGMCOMPARE
(
idToCompare
,
&
emberAfInvalidImageId
,
&
emberAfInvalidImageId
,
sizeof
(
EmberAfOtaImageId
)));
sizeof
(
EmberAfOtaImageId
)));
}
}
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-common/ota-storage.h
View file @
e5cd9e56
...
@@ -40,18 +40,18 @@
...
@@ -40,18 +40,18 @@
#define TAG_OVERHEAD (2 + 4) // 2 bytes for the tag ID, 4 bytes for the length
#define TAG_OVERHEAD (2 + 4) // 2 bytes for the tag ID, 4 bytes for the length
#define isValidHeaderVersion(headerVersion) \
#define isValidHeaderVersion(headerVersion) \
((headerVersion == OTA_HEADER_VERSION_ZIGBEE) || (headerVersion == OTA_HEADER_VERSION_THREAD))
((headerVersion == OTA_HEADER_VERSION_ZIGBEE) || (headerVersion == OTA_HEADER_VERSION_THREAD))
#define SECURITY_CREDENTIAL_VERSION_FIELD_PRESENT_MASK 0x0001
#define SECURITY_CREDENTIAL_VERSION_FIELD_PRESENT_MASK 0x0001
#define DEVICE_SPECIFIC_FILE_PRESENT_MASK 0x0002
#define DEVICE_SPECIFIC_FILE_PRESENT_MASK 0x0002
#define HARDWARE_VERSIONS_PRESENT_MASK 0x0004
#define HARDWARE_VERSIONS_PRESENT_MASK 0x0004
#define headerHasSecurityCredentials(header) \
#define headerHasSecurityCredentials(header) \
((header)->fieldControl & SECURITY_CREDENTIAL_VERSION_FIELD_PRESENT_MASK)
((header)->fieldControl & SECURITY_CREDENTIAL_VERSION_FIELD_PRESENT_MASK)
#define headerHasUpgradeFileDest(header) \
#define headerHasUpgradeFileDest(header) \
((header)->fieldControl & DEVICE_SPECIFIC_FILE_PRESENT_MASK)
((header)->fieldControl & DEVICE_SPECIFIC_FILE_PRESENT_MASK)
#define headerHasHardwareVersions(header) \
#define headerHasHardwareVersions(header) \
((header)->fieldControl & HARDWARE_VERSIONS_PRESENT_MASK)
((header)->fieldControl & HARDWARE_VERSIONS_PRESENT_MASK)
// This size does NOT include the tag overhead.
// This size does NOT include the tag overhead.
#define SIGNATURE_TAG_DATA_SIZE (EUI64_SIZE + EMBER_SIGNATURE_SIZE)
#define SIGNATURE_TAG_DATA_SIZE (EUI64_SIZE + EMBER_SIGNATURE_SIZE)
...
@@ -63,11 +63,11 @@
...
@@ -63,11 +63,11 @@
#define INVALID_EUI64 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define INVALID_EUI64 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define INVALID_OTA_IMAGE_ID \
#define INVALID_OTA_IMAGE_ID \
{ INVALID_MANUFACTURER_ID, \
{ INVALID_MANUFACTURER_ID, \
INVALID_DEVICE_ID, \
INVALID_DEVICE_ID, \
INVALID_FIRMWARE_VERSION, \
INVALID_FIRMWARE_VERSION, \
INVALID_EUI64, \
INVALID_EUI64, \
}
}
#define INVALID_SLOT (uint32_t)-1
#define INVALID_SLOT (uint32_t)-1
...
...
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-posix-filesystem/ota-storage-linux.c
View file @
e5cd9e56
...
@@ -64,12 +64,12 @@ static char* tempStorageFilepath = NULL;
...
@@ -64,12 +64,12 @@ static char* tempStorageFilepath = NULL;
static
const
char
*
tempStorageFile
=
"temporary-storage.ota"
;
static
const
char
*
tempStorageFile
=
"temporary-storage.ota"
;
typedef
struct
{
typedef
struct
{
EmberAfOtaHeader
*
header
;
EmberAfOtaHeader
*
header
;
char
*
filepath
;
char
*
filepath
;
const
char
*
filenameStart
;
// ptr to data in 'filepath'
const
char
*
filenameStart
;
// ptr to data in 'filepath'
struct
OtaImage
*
next
;
struct
OtaImage
*
next
;
struct
OtaImage
*
prev
;
struct
OtaImage
*
prev
;
off_t
fileSize
;
off_t
fileSize
;
}
OtaImage
;
}
OtaImage
;
static
OtaImage
*
imageListFirst
=
NULL
;
static
OtaImage
*
imageListFirst
=
NULL
;
...
@@ -79,26 +79,26 @@ static uint8_t imageCount = 0;
...
@@ -79,26 +79,26 @@ static uint8_t imageCount = 0;
#define OTA_MAX_FILENAME_LENGTH 1000
#define OTA_MAX_FILENAME_LENGTH 1000
static
const
uint8_t
otaFileMagicNumberBytes
[]
=
{
static
const
uint8_t
otaFileMagicNumberBytes
[]
=
{
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
),
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
),
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
>>
8
),
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
>>
8
),
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
>>
16
),
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
>>
16
),
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
>>
24
),
(
uint8_t
)(
OTA_FILE_MAGIC_NUMBER
>>
24
),
};
};
#define ALWAYS_PRESENT_MASK 0xFFFF
#define ALWAYS_PRESENT_MASK 0xFFFF
enum
FieldType
{
enum
FieldType
{
INVALID_FIELD
=
0
,
INVALID_FIELD
=
0
,
INTEGER_FIELD
=
1
,
INTEGER_FIELD
=
1
,
BYTE_ARRAY_FIELD
=
2
,
BYTE_ARRAY_FIELD
=
2
,
STRING_FIELD
=
3
,
STRING_FIELD
=
3
,
};
};
typedef
struct
{
typedef
struct
{
const
char
*
name
;
const
char
*
name
;
const
enum
FieldType
type
;
const
enum
FieldType
type
;
const
uint16_t
length
;
const
uint16_t
length
;
const
uint16_t
maskForOptionalField
;
const
uint16_t
maskForOptionalField
;
}
EmberAfOtaHeaderFieldDefinition
;
}
EmberAfOtaHeaderFieldDefinition
;
// This global is used to define what is in the OTA header and help map that
// This global is used to define what is in the OTA header and help map that
...
@@ -106,54 +106,54 @@ typedef struct {
...
@@ -106,54 +106,54 @@ typedef struct {
// emGetOtaHeaderFieldDefinition() to get the field definitions. Do not use this
// emGetOtaHeaderFieldDefinition() to get the field definitions. Do not use this
// array directly.
// array directly.
const
static
EmberAfOtaHeaderFieldDefinition
otaHeaderFieldDefinitions
[]
=
{
const
static
EmberAfOtaHeaderFieldDefinition
otaHeaderFieldDefinitions
[]
=
{
{
"Magic Number"
,
INTEGER_FIELD
,
4
,
ALWAYS_PRESENT_MASK
},
{
"Magic Number"
,
INTEGER_FIELD
,
4
,
ALWAYS_PRESENT_MASK
},
{
"Header Version"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Header Version"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
// The fields returned above SHALL not depend on otaHeaderVersion, because
// The fields returned above SHALL not depend on otaHeaderVersion, because
// when reading in the header, we must be able to determine the location of
// when reading in the header, we must be able to determine the location of
// the header version
// the header version
{
"Header Length"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Header Length"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Field Control"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Field Control"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Manufacturer ID"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Manufacturer ID"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Image Type"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Image Type"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Firmware Version"
,
INTEGER_FIELD
,
4
,
ALWAYS_PRESENT_MASK
},
{
"Firmware Version"
,
INTEGER_FIELD
,
4
,
ALWAYS_PRESENT_MASK
},
{
"Zigbee Stack Version"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Zigbee Stack Version"
,
INTEGER_FIELD
,
2
,
ALWAYS_PRESENT_MASK
},
{
"Header String"
,
STRING_FIELD
,
32
,
ALWAYS_PRESENT_MASK
},
{
"Header String"
,
STRING_FIELD
,
32
,
ALWAYS_PRESENT_MASK
},
{
"Total Image Size"
,
INTEGER_FIELD
,
4
,
ALWAYS_PRESENT_MASK
},
{
"Total Image Size"
,
INTEGER_FIELD
,
4
,
ALWAYS_PRESENT_MASK
},
{
"Security Credentials"
,
INTEGER_FIELD
,
1
,
SECURITY_CREDENTIAL_VERSION_FIELD_PRESENT_MASK
},
{
"Security Credentials"
,
INTEGER_FIELD
,
1
,
SECURITY_CREDENTIAL_VERSION_FIELD_PRESENT_MASK
},
{
"Upgrade File Destination"
,
BYTE_ARRAY_FIELD
,
EUI64_SIZE
,
DEVICE_SPECIFIC_FILE_PRESENT_MASK
},
{
"Upgrade File Destination"
,
BYTE_ARRAY_FIELD
,
EUI64_SIZE
,
DEVICE_SPECIFIC_FILE_PRESENT_MASK
},
{
"Minimum Hardware Version"
,
INTEGER_FIELD
,
2
,
HARDWARE_VERSIONS_PRESENT_MASK
},
{
"Minimum Hardware Version"
,
INTEGER_FIELD
,
2
,
HARDWARE_VERSIONS_PRESENT_MASK
},
{
"Maximum Hardware Version"
,
INTEGER_FIELD
,
2
,
HARDWARE_VERSIONS_PRESENT_MASK
},
{
"Maximum Hardware Version"
,
INTEGER_FIELD
,
2
,
HARDWARE_VERSIONS_PRESENT_MASK
},
// Tag Data information omitted
// Tag Data information omitted
{
NULL
,
INVALID_FIELD
,
0
,
0
},
{
NULL
,
INVALID_FIELD
,
0
,
0
},
};
};
typedef
enum
{
typedef
enum
{
// Don't define all index numbers so the compiler
// Don't define all index numbers so the compiler
// automatically numbers them. We just define the first.
// automatically numbers them. We just define the first.
MAGIC_NUMBER_INDEX
=
0
,
MAGIC_NUMBER_INDEX
=
0
,
HEADER_VERSION_INDEX
,
HEADER_VERSION_INDEX
,
HEADER_LENGTH_INDEX
,
HEADER_LENGTH_INDEX
,
FIELD_CONTROL_INDEX
,
FIELD_CONTROL_INDEX
,
MANUFACTURER_ID_INDEX
,
MANUFACTURER_ID_INDEX
,
IMAGE_TYPE_INDEX
,
IMAGE_TYPE_INDEX
,
FIRMWARE_VERSION_INDEX
,
FIRMWARE_VERSION_INDEX
,
ZIGBEE_STACK_VERSION_INDEX
,
ZIGBEE_STACK_VERSION_INDEX
,
HEADER_STRING_INDEX
,
HEADER_STRING_INDEX
,
TOTAL_IMAGE_SIZE_INDEX
,
TOTAL_IMAGE_SIZE_INDEX
,
SECURITY_CREDENTIALS_INDEX
,
SECURITY_CREDENTIALS_INDEX
,
UPGRADE_FILE_DESTINATION_INDEX
,
UPGRADE_FILE_DESTINATION_INDEX
,
MINIMUM_HARDWARE_VERSION_INDEX
,
MINIMUM_HARDWARE_VERSION_INDEX
,
MAXIMUM_HARDWARE_VERSION_INDEX
,
MAXIMUM_HARDWARE_VERSION_INDEX
,
// This defines the maximum number of entries and refers to the invalid entry
// This defines the maximum number of entries and refers to the invalid entry
INVALID_FIELD_INDEX
,
INVALID_FIELD_INDEX
,
}
EmberAfOtaBootloadFileHeaderFieldIndex_t
;
}
EmberAfOtaBootloadFileHeaderFieldIndex_t
;
#define FIELD_INDEX_MAX INVALID_FIELD_INDEX
#define FIELD_INDEX_MAX INVALID_FIELD_INDEX
typedef
struct
{
typedef
struct
{
void
*
location
;
void
*
location
;
bool
found
;
bool
found
;
}
EmberAfOtaHeaderFieldLocation
;
}
EmberAfOtaHeaderFieldLocation
;
static
EmberAfOtaHeaderFieldLocation
otaHeaderFieldLocations
[
FIELD_INDEX_MAX
];
static
EmberAfOtaHeaderFieldLocation
otaHeaderFieldLocations
[
FIELD_INDEX_MAX
];
...
@@ -170,9 +170,9 @@ static OtaImage* iterator = NULL;
...
@@ -170,9 +170,9 @@ static OtaImage* iterator = NULL;
#endif
#endif
static
EmAfOtaStorageLinuxConfig
config
=
{
static
EmAfOtaStorageLinuxConfig
config
=
{
fals
e
,
// memoryDebug
tru
e
,
// memoryDebug
fals
e
,
// fileDebug
tru
e
,
// fileDebug
fals
e
,
// fieldDebug
tru
e
,
// fieldDebug
true
,
// ignoreFilesWithUnderscorePrefix
true
,
// ignoreFilesWithUnderscorePrefix
true
,
// printFileDiscoveryOrRemoval
true
,
// printFileDiscoveryOrRemoval
NULL
,
// fileAddedHandler
NULL
,
// fileAddedHandler
...
@@ -235,493 +235,493 @@ static bool createStorageDirectory = true;
...
@@ -235,493 +235,493 @@ static bool createStorageDirectory = true;
// loads a single file into its header cache.
// loads a single file into its header cache.
EmberAfOtaStorageStatus
emAfOtaSetStorageDevice
(
const
void
*
device
)
EmberAfOtaStorageStatus
emAfOtaSetStorageDevice
(
const
void
*
device
)
{
{
if
(
initDone
)
{
if
(
initDone
)
{
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
if
(
device
==
NULL
)
{
if
(
device
==
NULL
)
{
// We interpet this to mean, don't use a storage directory.
// We interpet this to mean, don't use a storage directory.
// This option is useful when creating files via the PC
// This option is useful when creating files via the PC
// tool.
// tool.
createStorageDirectory
=
false
;
createStorageDirectory
=
false
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
const
char
*
directoryOrFile
=
(
const
char
*
)
device
;
const
char
*
directoryOrFile
=
(
const
char
*
)
device
;
int
length
=
strnlen
(
directoryOrFile
,
MAX_FILEPATH_LENGTH
+
1
);
int
length
=
strnlen
(
directoryOrFile
,
MAX_FILEPATH_LENGTH
+
1
);
if
(
MAX_FILEPATH_LENGTH
<
length
)
{
if
(
MAX_FILEPATH_LENGTH
<
length
)
{
error
(
"Storage directory path too long (max = %d)!
\n
"
,
error
(
"Storage directory path too long (max = %d)!
\n
"
,
MAX_FILEPATH_LENGTH
);
MAX_FILEPATH_LENGTH
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
// Add 1 for '\0' and 1 for '/'. This may or may not be necessary
// Add 1 for '\0' and 1 for '/'. This may or may not be necessary
// because the path already has it or it is only a file.
// because the path already has it or it is only a file.
storageDevice
=
myMalloc
(
length
+
2
,
storageDevice
=
myMalloc
(
length
+
2
,
"emAfSetStorageDevice(): storageDevice"
);
"emAfSetStorageDevice(): storageDevice"
);
if
(
storageDevice
==
NULL
)
{
if
(
storageDevice
==
NULL
)
{
error
(
"Could not allocate %d bytes!
\n
"
,
length
);
error
(
"Could not allocate %d bytes!
\n
"
,
length
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
if
(
directoryOrFile
[
length
-
1
]
==
'/'
)
{
if
(
directoryOrFile
[
length
-
1
]
==
'/'
)
{
// We don't want to copy the '/' yet, since stat() will
// We don't want to copy the '/' yet, since stat() will
// complain if we pass it in.
// complain if we pass it in.
length
--
;
length
--
;
}
}
MEMSET
(
storageDevice
,
0
,
length
+
2
);
MEMSET
(
storageDevice
,
0
,
length
+
2
);
strncpy
(
storageDevice
,
directoryOrFile
,
length
);
strncpy
(
storageDevice
,
directoryOrFile
,
length
);
struct
stat
statInfo
;
struct
stat
statInfo
;
int
returnValue
=
stat
(
storageDevice
,
&
statInfo
);
int
returnValue
=
stat
(
storageDevice
,
&
statInfo
);
debug
(
config
.
fileDebug
,
debug
(
config
.
fileDebug
,
"Checking for existence of '%s'
\n
"
,
"Checking for existence of '%s'
\n
"
,
storageDevice
);
storageDevice
);
if
(
returnValue
!=
0
)
{
if
(
returnValue
!=
0
)
{
error
(
"Could not read storage device '%s'. %s
\n
"
,
error
(
"Could not read storage device '%s'. %s
\n
"
,
directoryOrFile
,
directoryOrFile
,
strerror
(
errno
));
strerror
(
errno
));
myFree
(
storageDevice
);
myFree
(
storageDevice
);
storageDevice
=
NULL
;
storageDevice
=
NULL
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
if
(
S_ISDIR
(
statInfo
.
st_mode
))
{
if
(
S_ISDIR
(
statInfo
.
st_mode
))
{
storageDeviceIsDirectory
=
true
;
storageDeviceIsDirectory
=
true
;
storageDevice
[
length
]
=
'/'
;
storageDevice
[
length
]
=
'/'
;
}
}
debug
(
config
.
fileDebug
,
"Storage device set to '%s'.
\n
"
,
storageDevice
);
debug
(
config
.
fileDebug
,
"Storage device set to '%s'.
\n
"
,
storageDevice
);
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
void
emAfOtaStorageGetConfig
(
EmAfOtaStorageLinuxConfig
*
currentConfig
)
void
emAfOtaStorageGetConfig
(
EmAfOtaStorageLinuxConfig
*
currentConfig
)
{
{
memcpy
(
currentConfig
,
&
config
,
sizeof
(
EmAfOtaStorageLinuxConfig
));
memcpy
(
currentConfig
,
&
config
,
sizeof
(
EmAfOtaStorageLinuxConfig
));
}
}
void
emAfOtaStorageSetConfig
(
const
EmAfOtaStorageLinuxConfig
*
newConfig
)
void
emAfOtaStorageSetConfig
(
const
EmAfOtaStorageLinuxConfig
*
newConfig
)
{
{
memcpy
(
&
config
,
newConfig
,
sizeof
(
EmAfOtaStorageLinuxConfig
));
memcpy
(
&
config
,
newConfig
,
sizeof
(
EmAfOtaStorageLinuxConfig
));
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageInitCallback
(
void
)
EmberAfOtaStorageStatus
emberAfOtaStorageInitCallback
(
void
)
{
{
if
(
initDone
)
{
if
(
initDone
)
{
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
if
(
config
.
fileDebug
)
{
if
(
config
.
fileDebug
)
{
char
cwd
[
MAX_FILEPATH_LENGTH
];
char
cwd
[
MAX_FILEPATH_LENGTH
];
debug
(
config
.
fileDebug
,
"Current Working Directory: %s
\n
"
,
debug
(
config
.
fileDebug
,
"Current Working Directory: %s
\n
"
,
(
NULL
==
getcwd
(
cwd
,
MAX_FILEPATH_LENGTH
)
(
NULL
==
getcwd
(
cwd
,
MAX_FILEPATH_LENGTH
)
?
"UNKNOWN!"
?
"UNKNOWN!"
:
cwd
));
:
cwd
));
}
}
EmberAfOtaStorageStatus
status
;
EmberAfOtaStorageStatus
status
;
if
(
storageDevice
==
NULL
)
{
if
(
storageDevice
==
NULL
)
{
if
(
createStorageDirectory
)
{
if
(
createStorageDirectory
)
{
status
=
createDefaultStorageDirectory
();
status
=
createDefaultStorageDirectory
();
if
(
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
if
(
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
return
status
;
return
status
;
}
}
}
else
{
}
else
{
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
}
}
if
(
storageDeviceIsDirectory
)
{
if
(
storageDeviceIsDirectory
)
{
status
=
initImageDirectory
();
status
=
initImageDirectory
();
}
else
{
}
else
{
OtaImage
*
newImage
=
addImageFileToList
(
storageDevice
,
true
);
OtaImage
*
newImage
=
addImageFileToList
(
storageDevice
,
true
);
if
(
config
.
fileAddedHandler
!=
NULL
if
(
config
.
fileAddedHandler
!=
NULL
&&
newImage
!=
NULL
)
{
&&
newImage
!=
NULL
)
{
(
config
.
fileAddedHandler
)(
newImage
->
header
);
(
config
.
fileAddedHandler
)(
newImage
->
header
);
}
}
status
=
(
NULL
==
newImage
status
=
(
NULL
==
newImage
?
EMBER_AF_OTA_STORAGE_ERROR
?
EMBER_AF_OTA_STORAGE_ERROR
:
EMBER_AF_OTA_STORAGE_SUCCESS
);
:
EMBER_AF_OTA_STORAGE_SUCCESS
);
}
}
iterator
=
NULL
;
// Must be initialized via
iterator
=
NULL
;
// Must be initialized via
// otaStorageIteratorReset()
// otaStorageIteratorReset()
if
(
status
==
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
if
(
status
==
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
initDone
=
true
;
initDone
=
true
;
}
}
return
status
;
return
status
;
}
}
void
emAfOtaStorageClose
(
void
)
void
emAfOtaStorageClose
(
void
)
{
{
OtaImage
*
ptr
=
imageListLast
;
OtaImage
*
ptr
=
imageListLast
;
while
(
ptr
!=
NULL
)
{
while
(
ptr
!=
NULL
)
{
OtaImage
*
current
=
ptr
;
OtaImage
*
current
=
ptr
;
ptr
=
(
OtaImage
*
)
ptr
->
prev
;
ptr
=
(
OtaImage
*
)
ptr
->
prev
;
freeOtaImage
(
current
);
freeOtaImage
(
current
);
}
}
imageListLast
=
NULL
;
imageListLast
=
NULL
;
imageListFirst
=
NULL
;
imageListFirst
=
NULL
;
if
(
storageDevice
!=
NULL
)
{
if
(
storageDevice
!=
NULL
)
{
myFree
(
storageDevice
);
myFree
(
storageDevice
);
storageDevice
=
NULL
;
storageDevice
=
NULL
;
}
}
if
(
tempStorageFilepath
!=
NULL
)
{
if
(
tempStorageFilepath
!=
NULL
)
{
myFree
(
tempStorageFilepath
);
myFree
(
tempStorageFilepath
);
tempStorageFilepath
=
NULL
;
tempStorageFilepath
=
NULL
;
}
}
initDone
=
false
;
initDone
=
false
;
imageCount
=
0
;
imageCount
=
0
;
}
}
uint8_t
emberAfOtaStorageGetCountCallback
(
void
)
uint8_t
emberAfOtaStorageGetCountCallback
(
void
)
{
{
return
imageCount
;
return
imageCount
;
}
}
EmberAfOtaImageId
emberAfOtaStorageSearchCallback
(
uint16_t
manufacturerId
,
EmberAfOtaImageId
emberAfOtaStorageSearchCallback
(
uint16_t
manufacturerId
,
uint16_t
manufacturerDeviceId
,
uint16_t
manufacturerDeviceId
,
const
uint16_t
*
hardwareVersion
)
const
uint16_t
*
hardwareVersion
)
{
{
EmberAfOtaImageId
id
=
{
EmberAfOtaImageId
id
=
{
manufacturerId
,
manufacturerId
,
manufacturerDeviceId
,
manufacturerDeviceId
,
INVALID_FIRMWARE_VERSION
,
INVALID_FIRMWARE_VERSION
,
INVALID_EUI64
,
INVALID_EUI64
,
};
};
OtaImage
*
image
=
imageSearchInternal
(
&
id
);
OtaImage
*
image
=
imageSearchInternal
(
&
id
);
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
return
emberAfInvalidImageId
;
return
emberAfInvalidImageId
;
}
}
// We assume that if there is no hardware version information in the header
// We assume that if there is no hardware version information in the header
// then it can be used on ANY hardware version. The behavior of the server
// then it can be used on ANY hardware version. The behavior of the server
// in this case is not spelled out by the specification.
// in this case is not spelled out by the specification.
if
(
hardwareVersion
!=
NULL
if
(
hardwareVersion
!=
NULL
&&
headerHasHardwareVersions
(
image
->
header
)
&&
headerHasHardwareVersions
(
image
->
header
)
&&
!
(
*
hardwareVersion
>=
image
->
header
->
minimumHardwareVersion
&&
!
(
*
hardwareVersion
>=
image
->
header
->
minimumHardwareVersion
&&
*
hardwareVersion
<=
image
->
header
->
maximumHardwareVersion
))
{
&&
*
hardwareVersion
<=
image
->
header
->
maximumHardwareVersion
))
{
return
emberAfInvalidImageId
;
return
emberAfInvalidImageId
;
}
}
id
.
firmwareVersion
=
image
->
header
->
firmwareVersion
;
id
.
firmwareVersion
=
image
->
header
->
firmwareVersion
;
return
id
;
return
id
;
}
}
const
char
*
emAfOtaStorageGetFilepath
(
const
EmberAfOtaImageId
*
id
)
const
char
*
emAfOtaStorageGetFilepath
(
const
EmberAfOtaImageId
*
id
)
{
{
OtaImage
*
image
=
findImageById
(
id
);
OtaImage
*
image
=
findImageById
(
id
);
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
return
NULL
;
return
NULL
;
}
}
return
image
->
filepath
;
return
image
->
filepath
;
}
}
EmberAfOtaImageId
emberAfOtaStorageIteratorFirstCallback
(
void
)
EmberAfOtaImageId
emberAfOtaStorageIteratorFirstCallback
(
void
)
{
{
iterator
=
imageListFirst
;
iterator
=
imageListFirst
;
return
getIteratorImageId
();
return
getIteratorImageId
();
}
}
EmberAfOtaImageId
emberAfOtaStorageIteratorNextCallback
(
void
)
EmberAfOtaImageId
emberAfOtaStorageIteratorNextCallback
(
void
)
{
{
if
(
iterator
!=
NULL
)
{
if
(
iterator
!=
NULL
)
{
iterator
=
(
OtaImage
*
)
iterator
->
next
;
iterator
=
(
OtaImage
*
)
iterator
->
next
;
}
}
return
getIteratorImageId
();
return
getIteratorImageId
();
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageReadImageDataCallback
(
const
EmberAfOtaImageId
*
id
,
EmberAfOtaStorageStatus
emberAfOtaStorageReadImageDataCallback
(
const
EmberAfOtaImageId
*
id
,
uint32_t
offset
,
uint32_t
offset
,
uint32_t
length
,
uint32_t
length
,
uint8_t
*
returnData
,
uint8_t
*
returnData
,
uint32_t
*
returnedLength
)
uint32_t
*
returnedLength
)
{
{
OtaImage
*
image
=
imageSearchInternal
(
id
);
OtaImage
*
image
=
imageSearchInternal
(
id
);
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
error
(
"No such Image (Mfg ID: 0x%04X, Image ID: 0x%04X, Version: 0x%08X
\n
"
,
error
(
"No such Image (Mfg ID: 0x%04X, Image ID: 0x%04X, Version: 0x%08X
\n
"
,
id
->
manufacturerId
,
id
->
manufacturerId
,
id
->
imageTypeId
,
id
->
imageTypeId
,
id
->
firmwareVersion
);
id
->
firmwareVersion
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
// Windows requires the 'b' (binary) as part of the mode so that line endings
// Windows requires the 'b' (binary) as part of the mode so that line endings
// are not truncated. POSIX ignores this.
// are not truncated. POSIX ignores this.
FILE
*
fileHandle
=
fopen
(
image
->
filepath
,
"rb"
);
FILE
*
fileHandle
=
fopen
(
image
->
filepath
,
"rb"
);
if
(
fileHandle
==
NULL
)
{
if
(
fileHandle
==
NULL
)
{
error
(
"Failed to open file '%s' for reading: %s
\n
"
,
error
(
"Failed to open file '%s' for reading: %s
\n
"
,
image
->
filenameStart
,
image
->
filenameStart
,
strerror
(
errno
));
strerror
(
errno
));
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
if
(
0
!=
fseek
(
fileHandle
,
offset
,
SEEK_SET
))
{
if
(
0
!=
fseek
(
fileHandle
,
offset
,
SEEK_SET
))
{
error
(
"Failed to seek in file '%s' to offset %d
\n
"
,
error
(
"Failed to seek in file '%s' to offset %d
\n
"
,
image
->
filenameStart
,
image
->
filenameStart
,
offset
);
offset
);
fclose
(
fileHandle
);
fclose
(
fileHandle
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
*
returnedLength
=
fread
(
returnData
,
1
,
length
,
fileHandle
);
*
returnedLength
=
fread
(
returnData
,
1
,
length
,
fileHandle
);
fclose
(
fileHandle
);
fclose
(
fileHandle
);
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
EmberAfOtaStorageStatus
emAfOtaStorageCreateImage
(
EmberAfOtaHeader
*
header
,
EmberAfOtaStorageStatus
emAfOtaStorageCreateImage
(
EmberAfOtaHeader
*
header
,
const
char
*
filename
)
const
char
*
filename
)
{
{
// Windows requires the 'b' (binary) as part of the mode so that line endings
// Windows requires the 'b' (binary) as part of the mode so that line endings
// are not truncated. POSIX ignores this.
// are not truncated. POSIX ignores this.
FILE
*
fileHandle
=
fopen
(
filename
,
"wb"
);
FILE
*
fileHandle
=
fopen
(
filename
,
"wb"
);
if
(
fileHandle
==
NULL
)
{
if
(
fileHandle
==
NULL
)
{
error
(
"Could not open file '%s' for writing: %s
\n
"
,
error
(
"Could not open file '%s' for writing: %s
\n
"
,
filename
,
filename
,
strerror
(
errno
));
strerror
(
errno
));
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
uint8_t
buffer
[
OTA_MAXIMUM_HEADER_LENGTH
];
uint8_t
buffer
[
OTA_MAXIMUM_HEADER_LENGTH
];
uint8_t
*
bufferPtr
=
buffer
;
uint8_t
*
bufferPtr
=
buffer
;
memcpy
(
bufferPtr
,
otaFileMagicNumberBytes
,
4
);
memcpy
(
bufferPtr
,
otaFileMagicNumberBytes
,
4
);
bufferPtr
+=
4
;
bufferPtr
+=
4
;
bufferPtr
[
0
]
=
(
uint8_t
)(
header
->
headerVersion
);
bufferPtr
[
0
]
=
(
uint8_t
)(
header
->
headerVersion
);
bufferPtr
[
1
]
=
(
uint8_t
)(
header
->
headerVersion
>>
8
);
bufferPtr
[
1
]
=
(
uint8_t
)(
header
->
headerVersion
>>
8
);
bufferPtr
+=
2
;
bufferPtr
+=
2
;
mapHeaderFieldDefinitionToDataStruct
(
header
);
mapHeaderFieldDefinitionToDataStruct
(
header
);
header
->
headerLength
=
calculateOtaFileHeaderLength
(
header
);
header
->
headerLength
=
calculateOtaFileHeaderLength
(
header
);
header
->
imageSize
+=
header
->
headerLength
;
header
->
imageSize
+=
header
->
headerLength
;
EmberAfOtaBootloadFileHeaderFieldIndex_t
fieldIndex
=
HEADER_LENGTH_INDEX
;
EmberAfOtaBootloadFileHeaderFieldIndex_t
fieldIndex
=
HEADER_LENGTH_INDEX
;
while
(
fieldIndex
<
FIELD_INDEX_MAX
)
{
while
(
fieldIndex
<
FIELD_INDEX_MAX
)
{
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
header
->
headerVersion
,
fieldIndex
);
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
header
->
headerVersion
,
fieldIndex
);
debug
(
config
.
memoryDebug
,
debug
(
config
.
memoryDebug
,
"Writing Header Field: %s, bufferPtr: 0x%08X
\n
"
,
"Writing Header Field: %s, bufferPtr: 0x%08X
\n
"
,
definition
->
name
,
definition
->
name
,
(
unsigned
int
)
bufferPtr
);
(
unsigned
int
)
bufferPtr
);
bufferPtr
=
writeHeaderDataToBuffer
(
fieldIndex
,
bufferPtr
=
writeHeaderDataToBuffer
(
fieldIndex
,
header
->
headerVersion
,
header
->
headerVersion
,
bufferPtr
);
bufferPtr
);
// I have run into stack corruption bugs in the past so this
// I have run into stack corruption bugs in the past so this
// is to try and catch any new issues.
// is to try and catch any new issues.
assert
(
bufferPtr
-
buffer
<=
OTA_MAXIMUM_HEADER_LENGTH
);
assert
(
bufferPtr
-
buffer
<=
OTA_MAXIMUM_HEADER_LENGTH
);
fieldIndex
++
;
fieldIndex
++
;
}
}
unmapHeaderFieldDefinitions
();
unmapHeaderFieldDefinitions
();
size_t
written
=
fwrite
(
buffer
,
1
,
header
->
headerLength
,
fileHandle
);
size_t
written
=
fwrite
(
buffer
,
1
,
header
->
headerLength
,
fileHandle
);
if
(
written
!=
header
->
headerLength
)
{
if
(
written
!=
header
->
headerLength
)
{
error
(
"Wrote only %d bytes but expected to write %d.
\n
"
,
error
(
"Wrote only %d bytes but expected to write %d.
\n
"
,
written
,
written
,
header
->
headerLength
);
header
->
headerLength
);
fclose
(
fileHandle
);
fclose
(
fileHandle
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
fflush
(
fileHandle
);
fflush
(
fileHandle
);
fclose
(
fileHandle
);
fclose
(
fileHandle
);
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
EmberAfOtaStorageStatus
emAfOtaStorageAddImageFile
(
const
char
*
filename
)
EmberAfOtaStorageStatus
emAfOtaStorageAddImageFile
(
const
char
*
filename
)
{
{
return
(
NULL
==
addImageFileToList
(
filename
,
return
(
NULL
==
addImageFileToList
(
filename
,
false
)
// print image info?
false
)
// print image info?
?
EMBER_AF_OTA_STORAGE_ERROR
?
EMBER_AF_OTA_STORAGE_ERROR
:
EMBER_AF_OTA_STORAGE_SUCCESS
);
:
EMBER_AF_OTA_STORAGE_SUCCESS
);
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageDeleteImageCallback
(
const
EmberAfOtaImageId
*
id
)
EmberAfOtaStorageStatus
emberAfOtaStorageDeleteImageCallback
(
const
EmberAfOtaImageId
*
id
)
{
{
OtaImage
*
image
=
imageSearchInternal
(
id
);
OtaImage
*
image
=
imageSearchInternal
(
id
);
// EMAPPFWKV2-1169: if we find the image, we delete it and return success.
// EMAPPFWKV2-1169: if we find the image, we delete it and return success.
// If we don't have the image, then we are ready to receive another one,
// If we don't have the image, then we are ready to receive another one,
// so we should return success.
// so we should return success.
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
if
(
config
.
printFileDiscoveryOrRemoval
)
{
if
(
config
.
printFileDiscoveryOrRemoval
)
{
note
(
"No such Image (Mfg ID: 0x%04X, Image ID: 0x%04X, Version: 0x%08X
\n
"
,
note
(
"No such Image (Mfg ID: 0x%04X, Image ID: 0x%04X, Version: 0x%08X
\n
"
,
id
->
manufacturerId
,
id
->
manufacturerId
,
id
->
imageTypeId
,
id
->
imageTypeId
,
id
->
firmwareVersion
);
id
->
firmwareVersion
);
}
}
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
if
(
config
.
printFileDiscoveryOrRemoval
)
{
if
(
config
.
printFileDiscoveryOrRemoval
)
{
note
(
"Image '%s' removed from storage list. NOT deleted from disk.
\n
"
,
note
(
"Image '%s' removed from storage list. NOT deleted from disk.
\n
"
,
image
->
filenameStart
);
image
->
filenameStart
);
}
}
removeImage
(
image
);
removeImage
(
image
);
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
// Although the call is to "clear" temp data we actually end up allocating
// Although the call is to "clear" temp data we actually end up allocating
// space for the filename and creating an empty file.
// space for the filename and creating an empty file.
EmberAfOtaStorageStatus
emberAfOtaStorageClearTempDataCallback
(
void
)
EmberAfOtaStorageStatus
emberAfOtaStorageClearTempDataCallback
(
void
)
{
{
EmberAfOtaStorageStatus
status
=
EMBER_AF_OTA_STORAGE_ERROR
;
EmberAfOtaStorageStatus
status
=
EMBER_AF_OTA_STORAGE_ERROR
;
FILE
*
fileHandle
=
NULL
;
FILE
*
fileHandle
=
NULL
;
if
(
!
storageDeviceIsDirectory
)
{
if
(
!
storageDeviceIsDirectory
)
{
error
(
"Cannot create temp. OTA data because storage device is a file, not a directory.
\n
"
);
error
(
"Cannot create temp. OTA data because storage device is a file, not a directory.
\n
"
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
if
(
storageDevice
==
NULL
)
{
if
(
storageDevice
==
NULL
)
{
error
(
"No storage device defined!"
);
error
(
"No storage device defined!"
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
if
(
tempStorageFilepath
==
NULL
)
{
if
(
tempStorageFilepath
==
NULL
)
{
// Add 1 to make sure we have room for a NULL terminating character
// Add 1 to make sure we have room for a NULL terminating character
int
tempFilepathLength
=
(
strlen
(
storageDevice
)
int
tempFilepathLength
=
(
strlen
(
storageDevice
)
+
strlen
(
tempStorageFile
)
+
1
);
+
strlen
(
tempStorageFile
)
+
1
);
if
(
tempFilepathLength
>
MAX_FILEPATH_LENGTH
)
{
if
(
tempFilepathLength
>
MAX_FILEPATH_LENGTH
)
{
goto
clearTempDataCallbackDone
;
goto
clearTempDataCallbackDone
;
}
}
tempStorageFilepath
=
myMalloc
(
tempFilepathLength
,
tempStorageFilepath
=
myMalloc
(
tempFilepathLength
,
"otaStorageCreateTempData(): tempFilepath"
);
"otaStorageCreateTempData(): tempFilepath"
);
if
(
tempStorageFilepath
==
NULL
)
{
if
(
tempStorageFilepath
==
NULL
)
{
goto
clearTempDataCallbackDone
;
goto
clearTempDataCallbackDone
;
}
}
snprintf
(
tempStorageFilepath
,
snprintf
(
tempStorageFilepath
,
tempFilepathLength
,
tempFilepathLength
,
"%s%s"
,
"%s%s"
,
storageDevice
,
storageDevice
,
tempStorageFile
);
tempStorageFile
);
}
}
OtaImage
*
image
=
findImageByFilename
(
tempStorageFilepath
);
OtaImage
*
image
=
findImageByFilename
(
tempStorageFilepath
);
if
(
image
)
{
if
(
image
)
{
removeImage
(
image
);
removeImage
(
image
);
}
}
// Windows requires the 'b' (binary) as part of the mode so that line endings
// Windows requires the 'b' (binary) as part of the mode so that line endings
// are not truncated. POSIX ignores this.
// are not truncated. POSIX ignores this.
fileHandle
=
fopen
(
tempStorageFilepath
,
fileHandle
=
fopen
(
tempStorageFilepath
,
"wb"
);
// truncate the file to zero length
"wb"
);
// truncate the file to zero length
if
(
fileHandle
==
NULL
)
{
if
(
fileHandle
==
NULL
)
{
error
(
"Could not open temporary file '%s' for writing: %s
\n
"
,
error
(
"Could not open temporary file '%s' for writing: %s
\n
"
,
tempStorageFilepath
,
tempStorageFilepath
,
strerror
(
errno
));
strerror
(
errno
));
}
else
{
}
else
{
status
=
EMBER_AF_OTA_STORAGE_SUCCESS
;
status
=
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
clearTempDataCallbackDone:
clearTempDataCallbackDone:
// tempStorageFilepath is used throughout the life of the storage
// tempStorageFilepath is used throughout the life of the storage
// device, so we only need to free it if there was an error,
// device, so we only need to free it if there was an error,
// or when the storage device changed. We expect we can
// or when the storage device changed. We expect we can
// only change the storage device if we first call emAfOtaStorageClose()
// only change the storage device if we first call emAfOtaStorageClose()
// which frees the tempStorageFilepath data as well.
// which frees the tempStorageFilepath data as well.
if
((
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
if
((
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
&&
tempStorageFilepath
)
{
&&
tempStorageFilepath
)
{
myFree
(
tempStorageFilepath
);
myFree
(
tempStorageFilepath
);
tempStorageFilepath
=
NULL
;
tempStorageFilepath
=
NULL
;
}
}
if
(
fileHandle
)
{
if
(
fileHandle
)
{
fclose
(
fileHandle
);
fclose
(
fileHandle
);
}
}
return
status
;
return
status
;
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageWriteTempDataCallback
(
uint32_t
offset
,
EmberAfOtaStorageStatus
emberAfOtaStorageWriteTempDataCallback
(
uint32_t
offset
,
uint32_t
length
,
uint32_t
length
,
const
uint8_t
*
data
)
const
uint8_t
*
data
)
{
{
if
(
tempStorageFilepath
==
NULL
)
{
if
(
tempStorageFilepath
==
NULL
)
{
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
return
writeRawData
(
offset
,
tempStorageFilepath
,
length
,
data
);
return
writeRawData
(
offset
,
tempStorageFilepath
,
length
,
data
);
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageCheckTempDataCallback
(
uint32_t
*
returnOffset
,
EmberAfOtaStorageStatus
emberAfOtaStorageCheckTempDataCallback
(
uint32_t
*
returnOffset
,
uint32_t
*
returnTotalSize
,
uint32_t
*
returnTotalSize
,
EmberAfOtaImageId
*
returnOtaImageId
)
EmberAfOtaImageId
*
returnOtaImageId
)
{
{
OtaImage
*
image
;
OtaImage
*
image
;
if
(
tempStorageFilepath
==
NULL
)
{
if
(
tempStorageFilepath
==
NULL
)
{
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
image
=
addImageFileToList
(
tempStorageFilepath
,
true
);
image
=
addImageFileToList
(
tempStorageFilepath
,
true
);
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
*
returnTotalSize
=
image
->
header
->
imageSize
;
*
returnTotalSize
=
image
->
header
->
imageSize
;
*
returnOffset
=
image
->
fileSize
;
*
returnOffset
=
image
->
fileSize
;
MEMSET
(
returnOtaImageId
,
0
,
sizeof
(
EmberAfOtaImageId
));
MEMSET
(
returnOtaImageId
,
0
,
sizeof
(
EmberAfOtaImageId
));
*
returnOtaImageId
=
emAfOtaStorageGetImageIdFromHeader
(
image
->
header
);
*
returnOtaImageId
=
emAfOtaStorageGetImageIdFromHeader
(
image
->
header
);
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
EmberAfOtaStorageStatus
emAfOtaStorageAppendImageData
(
const
char
*
filename
,
EmberAfOtaStorageStatus
emAfOtaStorageAppendImageData
(
const
char
*
filename
,
uint32_t
length
,
uint32_t
length
,
const
uint8_t
*
data
)
const
uint8_t
*
data
)
{
{
OtaImage
*
image
=
findImageByFilename
(
filename
);
OtaImage
*
image
=
findImageByFilename
(
filename
);
if
(
image
!=
NULL
)
{
if
(
image
!=
NULL
)
{
// The file is already in use by the storage device, so it cannot
// The file is already in use by the storage device, so it cannot
// be modified.
// be modified.
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
return
writeRawData
(
APPEND_OFFSET
,
filename
,
length
,
data
);
return
writeRawData
(
APPEND_OFFSET
,
filename
,
length
,
data
);
}
}
int
remainingAllocations
(
void
)
int
remainingAllocations
(
void
)
{
{
return
allocations
;
return
allocations
;
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageGetFullHeaderCallback
(
const
EmberAfOtaImageId
*
id
,
EmberAfOtaStorageStatus
emberAfOtaStorageGetFullHeaderCallback
(
const
EmberAfOtaImageId
*
id
,
EmberAfOtaHeader
*
returnData
)
EmberAfOtaHeader
*
returnData
)
{
{
OtaImage
*
image
=
imageSearchInternal
(
id
);
OtaImage
*
image
=
imageSearchInternal
(
id
);
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
return
false
;
return
false
;
}
}
MEMCOPY
(
returnData
,
image
->
header
,
sizeof
(
EmberAfOtaHeader
));
MEMCOPY
(
returnData
,
image
->
header
,
sizeof
(
EmberAfOtaHeader
));
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
uint32_t
emberAfOtaStorageGetTotalImageSizeCallback
(
const
EmberAfOtaImageId
*
id
)
uint32_t
emberAfOtaStorageGetTotalImageSizeCallback
(
const
EmberAfOtaImageId
*
id
)
{
{
OtaImage
*
image
=
imageSearchInternal
(
id
);
OtaImage
*
image
=
imageSearchInternal
(
id
);
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
return
0
;
return
0
;
}
}
return
image
->
fileSize
;
return
image
->
fileSize
;
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageFinishDownloadCallback
(
uint32_t
offset
)
EmberAfOtaStorageStatus
emberAfOtaStorageFinishDownloadCallback
(
uint32_t
offset
)
{
{
// Not used. The OS filesystem keeps track of the latest download offset.
// Not used. The OS filesystem keeps track of the latest download offset.
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
void
emAfOtaStorageInfoPrint
(
void
)
void
emAfOtaStorageInfoPrint
(
void
)
{
{
note
(
"Storage Module: OTA POSIX Filesystem Storage Module
\n
"
);
note
(
"Storage Module: OTA POSIX Filesystem Storage Module
\n
"
);
note
(
"Storage Directory: %s
\n
"
,
defaultStorageDirectory
);
note
(
"Storage Directory: %s
\n
"
,
defaultStorageDirectory
);
}
}
uint32_t
emberAfOtaStorageDriverMaxDownloadSizeCallback
(
void
)
uint32_t
emberAfOtaStorageDriverMaxDownloadSizeCallback
(
void
)
{
{
// In theory we are limited by the local disk space, but for now
// In theory we are limited by the local disk space, but for now
// assume there is no limit.
// assume there is no limit.
return
0xFFFFFFFFUL
;
return
0xFFFFFFFFUL
;
}
}
EmberAfOtaStorageStatus
emberAfOtaStorageDriverPrepareToResumeDownloadCallback
(
void
)
EmberAfOtaStorageStatus
emberAfOtaStorageDriverPrepareToResumeDownloadCallback
(
void
)
{
{
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
//==============================================================================
//==============================================================================
...
@@ -730,193 +730,185 @@ EmberAfOtaStorageStatus emberAfOtaStorageDriverPrepareToResumeDownloadCallback(v
...
@@ -730,193 +730,185 @@ EmberAfOtaStorageStatus emberAfOtaStorageDriverPrepareToResumeDownloadCallback(v
static
EmberAfOtaStorageStatus
createDefaultStorageDirectory
(
void
)
static
EmberAfOtaStorageStatus
createDefaultStorageDirectory
(
void
)
{
{
struct
stat
statInfo
;
struct
stat
statInfo
;
int
returnValue
=
stat
(
defaultStorageDirectory
,
&
statInfo
);
int
returnValue
=
stat
(
defaultStorageDirectory
,
&
statInfo
);
if
(
returnValue
==
0
)
{
if
(
returnValue
==
0
)
{
if
(
!
S_ISDIR
(
statInfo
.
st_mode
))
{
if
(
!
S_ISDIR
(
statInfo
.
st_mode
))
{
error
(
"Default storage directory '%s' is not a directory!
\n
"
,
error
(
"Default storage directory '%s' is not a directory!
\n
"
,
defaultStorageDirectory
);
defaultStorageDirectory
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
debug
(
config
.
fileDebug
,
debug
(
config
.
fileDebug
,
"Default storage directory already exists '%s'
\n
"
,
"Default storage directory already exists '%s'
\n
"
,
defaultStorageDirectory
);
defaultStorageDirectory
);
}
else
{
}
else
{
// Does not exist, therefore we must create it.
// Does not exist, therefore we must create it.
debug
(
config
.
fileDebug
,
debug
(
config
.
fileDebug
,
"Creating default storage directory '%s'
\n
"
,
"Creating default storage directory '%s'
\n
"
,
defaultStorageDirectory
);
defaultStorageDirectory
);
int
status
=
portableMkdir
(
defaultStorageDirectory
);
int
status
=
portableMkdir
(
defaultStorageDirectory
);
if
(
status
!=
0
)
{
if
(
status
!=
0
)
{
error
(
"Could not create default directory '%s': %s
\n
"
,
error
(
"Could not create default directory '%s': %s
\n
"
,
defaultStorageDirectory
,
defaultStorageDirectory
,
strerror
(
errno
));
strerror
(
errno
));
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
}
}
return
emAfOtaSetStorageDevice
(
defaultStorageDirectory
);
return
emAfOtaSetStorageDevice
(
defaultStorageDirectory
);
}
}
static
bool
doEui64sMatch
(
const
uint8_t
*
firstEui64
,
static
bool
doEui64sMatch
(
const
uint8_t
*
firstEui64
,
const
uint8_t
*
secondEui64
)
const
uint8_t
*
secondEui64
)
{
{
return
(
0
==
MEMCOMPARE
(
firstEui64
,
secondEui64
,
EUI64_SIZE
));
return
(
0
==
MEMCOMPARE
(
firstEui64
,
secondEui64
,
EUI64_SIZE
));
}
}
static
OtaImage
*
findImageByFilename
(
const
char
*
tempFilepath
)
static
OtaImage
*
findImageByFilename
(
const
char
*
tempFilepath
)
{
{
OtaImage
*
ptr
=
imageListFirst
;
OtaImage
*
ptr
=
imageListFirst
;
while
(
ptr
!=
NULL
)
{
while
(
ptr
!=
NULL
)
{
if
(
0
==
strcmp
(
ptr
->
filepath
,
tempFilepath
))
{
if
(
0
==
strcmp
(
ptr
->
filepath
,
tempFilepath
))
{
return
ptr
;
return
ptr
;
}
}
ptr
=
(
OtaImage
*
)
ptr
->
next
;
ptr
=
(
OtaImage
*
)
ptr
->
next
;
}
}
return
NULL
;
return
NULL
;
}
}
static
EmberAfOtaStorageStatus
writeRawData
(
uint32_t
offset
,
static
EmberAfOtaStorageStatus
writeRawData
(
uint32_t
offset
,
const
char
*
filepath
,
const
char
*
filepath
,
uint32_t
length
,
uint32_t
length
,
const
uint8_t
*
data
)
const
uint8_t
*
data
)
{
{
// Windows requires the 'b' (binary) as part of the mode so that line endings
// Windows requires the 'b' (binary) as part of the mode so that line endings
// are not truncated. POSIX ignores this.
// are not truncated. POSIX ignores this.
FILE
*
fileHandle
=
fopen
(
filepath
,
FILE
*
fileHandle
=
fopen
(
filepath
,
"r+b"
);
"r+b"
);
EmberAfOtaStorageStatus
status
=
EMBER_AF_OTA_STORAGE_ERROR
;
EmberAfOtaStorageStatus
status
=
EMBER_AF_OTA_STORAGE_ERROR
;
int
whence
=
SEEK_SET
;
int
whence
=
SEEK_SET
;
if
(
fileHandle
==
NULL
)
{
if
(
fileHandle
==
NULL
)
{
error
(
"Could not open file '%s' for writing: %s
\n
"
,
error
(
"Could not open file '%s' for writing: %s
\n
"
,
filepath
,
filepath
,
strerror
(
errno
));
strerror
(
errno
));
goto
writeEnd
;
goto
writeEnd
;
}
}
if
(
offset
==
APPEND_OFFSET
)
{
if
(
offset
==
APPEND_OFFSET
)
{
offset
=
0
;
offset
=
0
;
whence
=
SEEK_END
;
whence
=
SEEK_END
;
}
}
if
(
0
!=
fseek
(
fileHandle
,
offset
,
whence
))
{
if
(
0
!=
fseek
(
fileHandle
,
offset
,
whence
))
{
error
(
"Could not seek to offset 0x%08X (%s) in file '%s': %s
\n
"
,
error
(
"Could not seek to offset 0x%08X (%s) in file '%s': %s
\n
"
,
offset
,
offset
,
(
whence
==
SEEK_END
?
"SEEK_END"
:
"SEEK_SET"
),
(
whence
==
SEEK_END
?
"SEEK_END"
:
"SEEK_SET"
),
filepath
,
filepath
,
strerror
(
errno
));
strerror
(
errno
));
goto
writeEnd
;
goto
writeEnd
;
}
}
size_t
written
=
fwrite
(
data
,
1
,
length
,
fileHandle
);
size_t
written
=
fwrite
(
data
,
1
,
length
,
fileHandle
);
if
(
written
!=
length
)
{
if
(
written
!=
length
)
{
error
(
"Tried to write %d bytes but wrote %d
\n
"
,
length
,
written
);
error
(
"Tried to write %d bytes but wrote %d
\n
"
,
length
,
written
);
goto
writeEnd
;
goto
writeEnd
;
}
}
status
=
EMBER_AF_OTA_STORAGE_SUCCESS
;
status
=
EMBER_AF_OTA_STORAGE_SUCCESS
;
writeEnd:
writeEnd:
if
(
fileHandle
)
{
if
(
fileHandle
)
{
fclose
(
fileHandle
);
fclose
(
fileHandle
);
}
}
return
status
;
return
status
;
}
}
static
void
removeImage
(
OtaImage
*
image
)
static
void
removeImage
(
OtaImage
*
image
)
{
{
OtaImage
*
before
=
(
OtaImage
*
)
image
->
prev
;
OtaImage
*
before
=
(
OtaImage
*
)
image
->
prev
;
OtaImage
*
after
=
(
OtaImage
*
)
image
->
next
;
OtaImage
*
after
=
(
OtaImage
*
)
image
->
next
;
if
(
before
)
{
if
(
before
)
{
before
->
next
=
(
struct
OtaImage
*
)
after
;
before
->
next
=
(
struct
OtaImage
*
)
after
;
}
}
if
(
after
)
{
if
(
after
)
{
after
->
prev
=
(
struct
OtaImage
*
)
before
;
after
->
prev
=
(
struct
OtaImage
*
)
before
;
}
}
if
(
image
==
imageListFirst
)
{
if
(
image
==
imageListFirst
)
{
imageListFirst
=
after
;
imageListFirst
=
after
;
}
}
if
(
image
==
imageListLast
)
{
if
(
image
==
imageListLast
)
{
imageListLast
=
before
;
imageListLast
=
before
;
}
}
freeOtaImage
(
image
);
freeOtaImage
(
image
);
imageCount
--
;
imageCount
--
;
}
}
static
void
printEui64
(
uint8_t
*
eui64
)
static
void
printEui64
(
uint8_t
*
eui64
)
{
{
note
(
"%02X%02X%02X%02X%02X%02X%02X%02X"
,
note
(
"%02X%02X%02X%02X%02X%02X%02X%02X"
,
eui64
[
0
],
eui64
[
0
],
eui64
[
1
],
eui64
[
1
],
eui64
[
2
],
eui64
[
2
],
eui64
[
3
],
eui64
[
3
],
eui64
[
4
],
eui64
[
4
],
eui64
[
5
],
eui64
[
5
],
eui64
[
6
],
eui64
[
6
],
eui64
[
7
]);
eui64
[
7
]);
}
}
static
void
printHeaderInfo
(
const
EmberAfOtaHeader
*
header
)
static
void
printHeaderInfo
(
const
EmberAfOtaHeader
*
header
)
{
{
if
(
!
config
.
printFileDiscoveryOrRemoval
)
{
if
(
!
config
.
printFileDiscoveryOrRemoval
)
{
return
;
return
;
}
}
note
(
" Manufacturer ID: 0x%04X
\n
"
,
// printf(" Header Version: 0x%04X\n",
header
->
manufacturerId
);
// header->headerVersion);
note
(
" Image Type ID: 0x%04X
\n
"
,
// printf(" Header Length: 0x%04X\n",
header
->
imageTypeId
);
// header->headerLength);
note
(
" Version: 0x%08X
\n
"
,
// printf(" Field Control: 0x%04X\n",
header
->
firmwareVersion
);
// header->fieldControl);
note
(
" Header String: %s
\n
"
,
note
(
" Manufacturer ID: 0x%04X
\n
"
,
header
->
headerString
);
header
->
manufacturerId
);
note
(
" Image Type ID: 0x%04X
\n
"
,
header
->
imageTypeId
);
note
(
" Version: 0x%08X
\n
"
,
header
->
firmwareVersion
);
note
(
" Header String: %s
\n
"
,
header
->
headerString
);
// printf("\n");
}
}
static
OtaImage
*
addImageFileToList
(
const
char
*
filename
,
static
OtaImage
*
addImageFileToList
(
const
char
*
filename
,
bool
printImageInfo
)
bool
printImageInfo
)
{
{
OtaImage
*
newImage
=
(
OtaImage
*
)
myMalloc
(
sizeof
(
OtaImage
),
OtaImage
*
newImage
=
(
OtaImage
*
)
myMalloc
(
sizeof
(
OtaImage
),
"addImageFileToList():OtaImage"
);
"addImageFileToList():OtaImage"
);
if
(
newImage
==
NULL
)
{
if
(
newImage
==
NULL
)
{
return
NULL
;
return
NULL
;
}
}
memset
(
newImage
,
0
,
sizeof
(
OtaImage
));
memset
(
newImage
,
0
,
sizeof
(
OtaImage
));
struct
stat
statInfo
;
struct
stat
statInfo
;
if
(
0
!=
stat
(
filename
,
&
statInfo
))
{
if
(
0
!=
stat
(
filename
,
&
statInfo
))
{
myFree
(
newImage
);
myFree
(
newImage
);
return
NULL
;
return
NULL
;
}
}
newImage
->
fileSize
=
statInfo
.
st_size
;
newImage
->
fileSize
=
statInfo
.
st_size
;
int
length
=
1
+
strnlen
(
filename
,
OTA_MAX_FILENAME_LENGTH
);
int
length
=
1
+
strnlen
(
filename
,
OTA_MAX_FILENAME_LENGTH
);
newImage
->
filepath
=
myMalloc
(
length
,
"filename"
);
newImage
->
filepath
=
myMalloc
(
length
,
"filename"
);
if
(
newImage
->
filepath
==
NULL
)
{
if
(
newImage
->
filepath
==
NULL
)
{
goto
dontAdd
;
goto
dontAdd
;
}
}
strncpy
(
newImage
->
filepath
,
filename
,
length
);
strncpy
(
newImage
->
filepath
,
filename
,
length
);
newImage
->
filepath
[
length
-
1
]
=
'\0'
;
newImage
->
filepath
[
length
-
1
]
=
'\0'
;
newImage
->
filenameStart
=
strrchr
(
newImage
->
filepath
,
newImage
->
filenameStart
=
strrchr
(
newImage
->
filepath
,
'/'
);
'/'
);
if
(
newImage
->
filenameStart
==
NULL
)
{
if
(
newImage
->
filenameStart
==
NULL
)
{
newImage
->
filenameStart
=
newImage
->
filepath
;
newImage
->
filenameStart
=
newImage
->
filepath
;
}
else
{
}
else
{
newImage
->
filenameStart
++
;
// +1 for the '/' character
newImage
->
filenameStart
++
;
// +1 for the '/' character
}
}
newImage
->
header
=
readImageHeader
(
filename
);
newImage
->
header
=
readImageHeader
(
filename
);
if
(
newImage
->
header
==
NULL
)
{
if
(
newImage
->
header
==
NULL
)
{
goto
dontAdd
;
goto
dontAdd
;
}
}
EmberAfOtaImageId
new
=
{
EmberAfOtaImageId
new
=
{
newImage
->
header
->
manufacturerId
,
newImage
->
header
->
manufacturerId
,
...
@@ -924,7 +916,7 @@ static OtaImage* addImageFileToList(const char* filename,
...
@@ -924,7 +916,7 @@ static OtaImage* addImageFileToList(const char* filename,
INVALID_FIRMWARE_VERSION
,
INVALID_FIRMWARE_VERSION
,
INVALID_EUI64
,
INVALID_EUI64
,
};
};
OtaImage
*
test
;
OtaImage
*
test
;
if
(
headerHasUpgradeFileDest
(
newImage
->
header
))
{
if
(
headerHasUpgradeFileDest
(
newImage
->
header
))
{
MEMCOPY
(
new
.
deviceSpecificFileEui64
,
MEMCOPY
(
new
.
deviceSpecificFileEui64
,
&
newImage
->
header
->
upgradeFileDestination
,
&
newImage
->
header
->
upgradeFileDestination
,
...
@@ -990,241 +982,241 @@ static OtaImage* addImageFileToList(const char* filename,
...
@@ -990,241 +982,241 @@ static OtaImage* addImageFileToList(const char* filename,
imageCount
++
;
imageCount
++
;
return
newImage
;
return
newImage
;
dontAdd:
dontAdd:
freeOtaImage
(
newImage
);
freeOtaImage
(
newImage
);
return
NULL
;
return
NULL
;
}
}
// This function assumes that the file pointer is at the start of the
// This function assumes that the file pointer is at the start of the
// file. It will modify the pointer in the passed FILE*
// file. It will modify the pointer in the passed FILE*
static
bool
checkMagicNumber
(
FILE
*
fileHandle
,
bool
printError
)
static
bool
checkMagicNumber
(
FILE
*
fileHandle
,
bool
printError
)
{
{
uint8_t
magicNumber
[
4
];
uint8_t
magicNumber
[
4
];
if
(
1
!=
fread
((
void
*
)
&
magicNumber
,
4
,
1
,
fileHandle
))
{
if
(
1
!=
fread
((
void
*
)
&
magicNumber
,
4
,
1
,
fileHandle
))
{
return
false
;
return
false
;
}
}
if
(
0
!=
memcmp
(
magicNumber
,
otaFileMagicNumberBytes
,
4
))
{
if
(
0
!=
memcmp
(
magicNumber
,
otaFileMagicNumberBytes
,
4
))
{
if
(
printError
)
{
if
(
printError
)
{
error
(
"File has bad magic number.
\n
"
);
error
(
"File has bad magic number.
\n
"
);
}
}
return
false
;
return
false
;
}
}
return
true
;
return
true
;
}
}
static
EmberAfOtaStorageStatus
initImageDirectory
(
void
)
static
EmberAfOtaStorageStatus
initImageDirectory
(
void
)
{
{
DIR
*
dir
=
opendir
(
storageDevice
);
DIR
*
dir
=
opendir
(
storageDevice
);
if
(
dir
==
NULL
)
{
if
(
dir
==
NULL
)
{
error
(
"Could not open directory: %s
\n
"
,
strerror
(
errno
));
error
(
"Could not open directory: %s
\n
"
,
strerror
(
errno
));
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
debug
(
config
.
fileDebug
,
"Opened Storage Directory: %s
\n
"
,
storageDevice
);
debug
(
config
.
fileDebug
,
"Opened Storage Directory: %s
\n
"
,
storageDevice
);
struct
dirent
*
dirEntry
=
readdir
(
dir
);
struct
dirent
*
dirEntry
=
readdir
(
dir
);
while
(
dirEntry
!=
NULL
)
{
while
(
dirEntry
!=
NULL
)
{
FILE
*
fileHandle
=
NULL
;
FILE
*
fileHandle
=
NULL
;
debug
(
config
.
fileDebug
,
"Considering file '%s'
\n
"
,
dirEntry
->
d_name
);
debug
(
config
.
fileDebug
,
"Considering file '%s'
\n
"
,
dirEntry
->
d_name
);
// +2 for trailing '/' and '\0'
// +2 for trailing '/' and '\0'
int
pathLength
=
strlen
(
storageDevice
)
+
strlen
(
dirEntry
->
d_name
)
+
2
;
int
pathLength
=
strlen
(
storageDevice
)
+
strlen
(
dirEntry
->
d_name
)
+
2
;
if
(
pathLength
>
MAX_FILEPATH_LENGTH
)
{
if
(
pathLength
>
MAX_FILEPATH_LENGTH
)
{
error
(
"Filepath too long (max: %d) skipping file '%s'"
,
error
(
"Filepath too long (max: %d) skipping file '%s'"
,
MAX_FILEPATH_LENGTH
,
MAX_FILEPATH_LENGTH
,
dirEntry
->
d_name
);
dirEntry
->
d_name
);
goto
continueReadingDir
;
goto
continueReadingDir
;
}
}
char
*
filePath
=
myMalloc
(
pathLength
,
"initImageDirectory(): filepath"
);
char
*
filePath
=
myMalloc
(
pathLength
,
"initImageDirectory(): filepath"
);
if
(
filePath
==
NULL
)
{
if
(
filePath
==
NULL
)
{
error
(
"Failed to allocate memory for filepath.
\n
"
);
error
(
"Failed to allocate memory for filepath.
\n
"
);
goto
continueReadingDir
;
goto
continueReadingDir
;
}
}
sprintf
(
filePath
,
"%s%s"
,
sprintf
(
filePath
,
"%s%s"
,
storageDevice
,
storageDevice
,
dirEntry
->
d_name
);
dirEntry
->
d_name
);
debug
(
config
.
fileDebug
,
"Full filepath: '%s'
\n
"
,
filePath
);
debug
(
config
.
fileDebug
,
"Full filepath: '%s'
\n
"
,
filePath
);
struct
stat
buffer
;
struct
stat
buffer
;
if
(
0
!=
stat
(
filePath
,
&
buffer
))
{
if
(
0
!=
stat
(
filePath
,
&
buffer
))
{
fprintf
(
stderr
,
fprintf
(
stderr
,
"Error: Could not stat file '%s': %s
\n
"
,
"Error: Could not stat file '%s': %s
\n
"
,
filePath
,
filePath
,
strerror
(
errno
));
strerror
(
errno
));
goto
continueReadingDir
;
goto
continueReadingDir
;
}
else
if
(
S_ISDIR
(
buffer
.
st_mode
)
||
!
S_ISREG
(
buffer
.
st_mode
))
{
}
else
if
(
S_ISDIR
(
buffer
.
st_mode
)
||
!
S_ISREG
(
buffer
.
st_mode
))
{
debug
(
config
.
fileDebug
,
debug
(
config
.
fileDebug
,
"Ignoring '%s' because it is not a regular file.
\n
"
,
"Ignoring '%s' because it is not a regular file.
\n
"
,
dirEntry
->
d_name
);
dirEntry
->
d_name
);
goto
continueReadingDir
;
goto
continueReadingDir
;
}
}
// NOTE: dirent.d_name may have a limited length due to POSIX compliance.
// NOTE: dirent.d_name may have a limited length due to POSIX compliance.
// Not sure if it will work for all possible filenames. However
// Not sure if it will work for all possible filenames. However
// the length does NOT include the directory portion, so it should be
// the length does NOT include the directory portion, so it should be
// able to store most all filenames (<256 characters).
// able to store most all filenames (<256 characters).
// Windows requires the 'b' (binary) as part of the mode so that line endings
// Windows requires the 'b' (binary) as part of the mode so that line endings
// are not truncated. POSIX ignores this.
// are not truncated. POSIX ignores this.
fileHandle
=
fopen
(
filePath
,
"rb"
);
fileHandle
=
fopen
(
filePath
,
"rb"
);
if
(
fileHandle
==
NULL
)
{
if
(
fileHandle
==
NULL
)
{
error
(
"Could not open file '%s' for reading: %s
\n
"
,
error
(
"Could not open file '%s' for reading: %s
\n
"
,
filePath
,
filePath
,
strerror
(
errno
));
strerror
(
errno
));
goto
continueReadingDir
;
goto
continueReadingDir
;
}
}
if
(
!
checkMagicNumber
(
fileHandle
,
false
))
{
if
(
!
checkMagicNumber
(
fileHandle
,
false
))
{
goto
continueReadingDir
;
goto
continueReadingDir
;
}
}
if
(
config
.
ignoreFilesWithUnderscorePrefix
if
(
config
.
ignoreFilesWithUnderscorePrefix
&&
dirEntry
->
d_name
[
0
]
==
'_'
)
{
&&
dirEntry
->
d_name
[
0
]
==
'_'
)
{
// As a means of making this program omit certain OTA files from
// As a means of making this program omit certain OTA files from
// processing, we arbitrarily choose to ignore files starting with '_'.
// processing, we arbitrarily choose to ignore files starting with '_'.
// This is done in part to be able to store multiple OTA files in
// This is done in part to be able to store multiple OTA files in
// the same directory that have the same unique manufacturer and image
// the same directory that have the same unique manufacturer and image
// type ID. Normally when this code finds a second image with the
// type ID. Normally when this code finds a second image with the
// same manufacturer and image type ID it picks the one with latest
// same manufacturer and image type ID it picks the one with latest
// version number.
// version number.
// By changing the file name we can keep the file intact and
// By changing the file name we can keep the file intact and
// have this code just skip it.
// have this code just skip it.
printf
(
"Ignoring OTA file '%s' since it starts with '_'.
\n
"
,
printf
(
"Ignoring OTA file '%s' since it starts with '_'.
\n
"
,
dirEntry
->
d_name
);
dirEntry
->
d_name
);
goto
continueReadingDir
;
goto
continueReadingDir
;
}
}
if
(
config
.
printFileDiscoveryOrRemoval
)
{
if
(
config
.
printFileDiscoveryOrRemoval
)
{
note
(
"Found OTA file '%s'
\n
"
,
dirEntry
->
d_name
);
note
(
"Found OTA file '%s'
\n
"
,
dirEntry
->
d_name
);
}
}
// We don't really care about the return code because we want to keep trying
// We don't really care about the return code because we want to keep trying
// to add files.
// to add files.
OtaImage
*
newImage
=
addImageFileToList
(
filePath
,
true
);
OtaImage
*
newImage
=
addImageFileToList
(
filePath
,
true
);
if
(
config
.
fileAddedHandler
!=
NULL
if
(
config
.
fileAddedHandler
!=
NULL
&&
newImage
!=
NULL
)
{
&&
newImage
!=
NULL
)
{
(
config
.
fileAddedHandler
)(
newImage
->
header
);
(
config
.
fileAddedHandler
)(
newImage
->
header
);
}
}
continueReadingDir:
continueReadingDir:
if
(
fileHandle
)
{
if
(
fileHandle
)
{
fclose
(
fileHandle
);
fclose
(
fileHandle
);
fileHandle
=
NULL
;
fileHandle
=
NULL
;
}
}
if
(
filePath
)
{
if
(
filePath
)
{
myFree
(
filePath
);
myFree
(
filePath
);
filePath
=
NULL
;
filePath
=
NULL
;
}
}
dirEntry
=
readdir
(
dir
);
dirEntry
=
readdir
(
dir
);
}
}
if
(
config
.
printFileDiscoveryOrRemoval
)
{
if
(
config
.
printFileDiscoveryOrRemoval
)
{
printf
(
"Found %d files
\n\n
"
,
imageCount
);
printf
(
"Found %d files
\n\n
"
,
imageCount
);
}
}
closedir
(
dir
);
closedir
(
dir
);
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
static
void
freeIfNotNull
(
void
**
ptr
)
static
void
freeIfNotNull
(
void
**
ptr
)
{
{
if
(
*
ptr
!=
NULL
)
{
if
(
*
ptr
!=
NULL
)
{
myFree
(
*
ptr
);
myFree
(
*
ptr
);
*
ptr
=
NULL
;
*
ptr
=
NULL
;
}
}
}
}
static
void
freeOtaImage
(
OtaImage
*
image
)
static
void
freeOtaImage
(
OtaImage
*
image
)
{
{
if
(
image
==
NULL
)
{
if
(
image
==
NULL
)
{
return
;
return
;
}
}
freeIfNotNull
((
void
**
)
&
(
image
->
header
));
freeIfNotNull
((
void
**
)
&
(
image
->
header
));
freeIfNotNull
((
void
**
)
&
(
image
->
filepath
));
freeIfNotNull
((
void
**
)
&
(
image
->
filepath
));
myFree
(
image
);
myFree
(
image
);
}
}
const
EmberAfOtaHeaderFieldDefinition
*
emGetOtaHeaderFieldDefinition
(
uint16_t
headerVersion
,
EmberAfOtaBootloadFileHeaderFieldIndex_t
headerIndex
)
const
EmberAfOtaHeaderFieldDefinition
*
emGetOtaHeaderFieldDefinition
(
uint16_t
headerVersion
,
EmberAfOtaBootloadFileHeaderFieldIndex_t
headerIndex
)
{
{
const
EmberAfOtaHeaderFieldDefinition
invalidField
=
{
NULL
,
INVALID_FIELD
,
0
,
0
};
const
EmberAfOtaHeaderFieldDefinition
invalidField
=
{
NULL
,
INVALID_FIELD
,
0
,
0
};
if
((
!
isValidHeaderVersion
(
headerVersion
))
&&
(
headerIndex
!=
MAGIC_NUMBER_INDEX
)
&&
(
headerIndex
!=
HEADER_VERSION_INDEX
))
{
if
((
!
isValidHeaderVersion
(
headerVersion
))
&&
(
headerIndex
!=
MAGIC_NUMBER_INDEX
)
&&
(
headerIndex
!=
HEADER_VERSION_INDEX
))
{
return
&
otaHeaderFieldDefinitions
[
INVALID_FIELD_INDEX
];
return
&
otaHeaderFieldDefinitions
[
INVALID_FIELD_INDEX
];
}
}
if
((
headerIndex
==
UPGRADE_FILE_DESTINATION_INDEX
)
&&
(
headerVersion
==
OTA_HEADER_VERSION_THREAD
))
{
if
((
headerIndex
==
UPGRADE_FILE_DESTINATION_INDEX
)
&&
(
headerVersion
==
OTA_HEADER_VERSION_THREAD
))
{
static
const
EmberAfOtaHeaderFieldDefinition
threadUpgradeFileDestination
=
{
"Upgrade File Destination"
,
BYTE_ARRAY_FIELD
,
UID_SIZE
,
DEVICE_SPECIFIC_FILE_PRESENT_MASK
};
static
const
EmberAfOtaHeaderFieldDefinition
threadUpgradeFileDestination
=
{
"Upgrade File Destination"
,
BYTE_ARRAY_FIELD
,
UID_SIZE
,
DEVICE_SPECIFIC_FILE_PRESENT_MASK
};
return
&
threadUpgradeFileDestination
;
return
&
threadUpgradeFileDestination
;
}
}
return
&
otaHeaderFieldDefinitions
[
headerIndex
];
return
&
otaHeaderFieldDefinitions
[
headerIndex
];
}
}
static
EmberAfOtaHeader
*
readImageHeader
(
const
char
*
filename
)
static
EmberAfOtaHeader
*
readImageHeader
(
const
char
*
filename
)
{
{
EmberAfOtaHeader
*
header
=
NULL
;
EmberAfOtaHeader
*
header
=
NULL
;
// Windows requires the 'b' (binary) as part of the mode so that line endings
// Windows requires the 'b' (binary) as part of the mode so that line endings
// are not truncated. POSIX ignores this.
// are not truncated. POSIX ignores this.
FILE
*
fileHandle
=
fopen
(
filename
,
"rb"
);
FILE
*
fileHandle
=
fopen
(
filename
,
"rb"
);
if
(
fileHandle
==
NULL
)
{
if
(
fileHandle
==
NULL
)
{
goto
imageReadError
;
goto
imageReadError
;
}
}
header
=
(
EmberAfOtaHeader
*
)
myMalloc
(
sizeof
(
EmberAfOtaHeader
),
"readImageHeader():OtaImage"
);
header
=
(
EmberAfOtaHeader
*
)
myMalloc
(
sizeof
(
EmberAfOtaHeader
),
"readImageHeader():OtaImage"
);
if
(
header
==
NULL
)
{
if
(
header
==
NULL
)
{
goto
imageReadError
;
goto
imageReadError
;
}
}
memset
(
header
,
0
,
sizeof
(
EmberAfOtaHeader
));
memset
(
header
,
0
,
sizeof
(
EmberAfOtaHeader
));
if
(
!
checkMagicNumber
(
fileHandle
,
true
))
{
if
(
!
checkMagicNumber
(
fileHandle
,
true
))
{
goto
imageReadError
;
goto
imageReadError
;
}
}
// In all the following code, we subtract 4 from the lengths because we have
// In all the following code, we subtract 4 from the lengths because we have
// already read the magic number and therefore do not need to include it in
// already read the magic number and therefore do not need to include it in
// our calculations.
// our calculations.
uint8_t
buffer
[
OTA_MAXIMUM_HEADER_LENGTH
-
4
];
uint8_t
buffer
[
OTA_MAXIMUM_HEADER_LENGTH
-
4
];
uint8_t
*
bufferPtr
=
buffer
;
uint8_t
*
bufferPtr
=
buffer
;
int
dataRead
=
fread
((
void
*
)
bufferPtr
,
int
dataRead
=
fread
((
void
*
)
bufferPtr
,
1
,
// block size (bytes)
1
,
// block size (bytes)
OTA_MAXIMUM_HEADER_LENGTH
-
4
,
// count
OTA_MAXIMUM_HEADER_LENGTH
-
4
,
// count
fileHandle
);
fileHandle
);
if
(
dataRead
<
(
OTA_MINIMUM_HEADER_LENGTH
-
4
))
{
if
(
dataRead
<
(
OTA_MINIMUM_HEADER_LENGTH
-
4
))
{
error
(
"OTA header is too short (length = %d but should be a minimum of %d)
\n
"
,
error
(
"OTA header is too short (length = %d but should be a minimum of %d)
\n
"
,
dataRead
,
dataRead
,
OTA_MINIMUM_HEADER_LENGTH
-
4
);
OTA_MINIMUM_HEADER_LENGTH
-
4
);
goto
imageReadError
;
goto
imageReadError
;
}
}
mapHeaderFieldDefinitionToDataStruct
(
header
);
mapHeaderFieldDefinitionToDataStruct
(
header
);
// Read the Version and length first so we can use those to validate the rest
// Read the Version and length first so we can use those to validate the rest
// of the image.
// of the image.
EmberAfOtaStorageStatus
status
;
EmberAfOtaStorageStatus
status
;
uint16_t
headerVersionLength
=
emGetOtaHeaderFieldDefinition
(
0
,
HEADER_VERSION_INDEX
)
->
length
;
uint16_t
headerVersionLength
=
emGetOtaHeaderFieldDefinition
(
0
,
HEADER_VERSION_INDEX
)
->
length
;
status
=
readHeaderDataFromBuffer
(
HEADER_VERSION_INDEX
,
status
=
readHeaderDataFromBuffer
(
HEADER_VERSION_INDEX
,
0
,
// we don't know the version yet
0
,
// we don't know the version yet
bufferPtr
,
bufferPtr
,
headerVersionLength
,
headerVersionLength
,
headerVersionLength
);
headerVersionLength
);
if
(
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
if
(
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
goto
imageReadError
;
goto
imageReadError
;
}
}
if
(
!
isValidHeaderVersion
(
header
->
headerVersion
))
{
if
(
!
isValidHeaderVersion
(
header
->
headerVersion
))
{
error
(
"Unknown header version number 0x%04X in file, cannot parse.
\n
"
,
header
->
headerVersion
);
error
(
"Unknown header version number 0x%04X in file, cannot parse.
\n
"
,
header
->
headerVersion
);
goto
imageReadError
;
goto
imageReadError
;
}
}
bufferPtr
+=
2
;
// header version field length
bufferPtr
+=
2
;
// header version field length
uint16_t
headerLengthLength
=
emGetOtaHeaderFieldDefinition
(
header
->
headerVersion
,
HEADER_LENGTH_INDEX
)
->
length
;
uint16_t
headerLengthLength
=
emGetOtaHeaderFieldDefinition
(
header
->
headerVersion
,
HEADER_LENGTH_INDEX
)
->
length
;
status
=
readHeaderDataFromBuffer
(
HEADER_LENGTH_INDEX
,
status
=
readHeaderDataFromBuffer
(
HEADER_LENGTH_INDEX
,
header
->
headerVersion
,
header
->
headerVersion
,
bufferPtr
,
bufferPtr
,
headerLengthLength
,
headerLengthLength
,
headerLengthLength
);
headerLengthLength
);
if
(
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
if
(
status
!=
EMBER_AF_OTA_STORAGE_SUCCESS
)
{
goto
imageReadError
;
goto
imageReadError
;
}
}
bufferPtr
+=
2
;
// header length field length
bufferPtr
+=
2
;
// header length field length
// subtract 4 for length of "header length" and "header version" fields.
// subtract 4 for length of "header length" and "header version" fields.
int32_t
lengthRemaining
=
header
->
headerLength
-
4
;
int32_t
lengthRemaining
=
header
->
headerLength
-
4
;
dataRead
-=
4
;
dataRead
-=
4
;
int
fieldIndex
=
FIELD_CONTROL_INDEX
;
int
fieldIndex
=
FIELD_CONTROL_INDEX
;
while
(
fieldIndex
<
FIELD_INDEX_MAX
&&
dataRead
>
0
&&
lengthRemaining
>
0
)
{
while
(
fieldIndex
<
FIELD_INDEX_MAX
&&
dataRead
>
0
&&
lengthRemaining
>
0
)
{
EmberAfOtaStorageStatus
status
=
readHeaderDataFromBuffer
(
fieldIndex
,
EmberAfOtaStorageStatus
status
=
readHeaderDataFromBuffer
(
fieldIndex
,
header
->
headerVersion
,
header
->
headerVersion
,
...
@@ -1264,230 +1256,230 @@ static EmberAfOtaHeader* readImageHeader(const char* filename)
...
@@ -1264,230 +1256,230 @@ static EmberAfOtaHeader* readImageHeader(const char* filename)
return
header
;
return
header
;
imageReadError:
imageReadError:
unmapHeaderFieldDefinitions
();
unmapHeaderFieldDefinitions
();
freeIfNotNull
((
void
**
)
&
header
);
freeIfNotNull
((
void
**
)
&
header
);
fclose
(
fileHandle
);
fclose
(
fileHandle
);
return
NULL
;
return
NULL
;
}
}
static
EmberAfOtaStorageStatus
readHeaderDataFromBuffer
(
EmberAfOtaBootloadFileHeaderFieldIndex_t
fieldIndex
,
static
EmberAfOtaStorageStatus
readHeaderDataFromBuffer
(
EmberAfOtaBootloadFileHeaderFieldIndex_t
fieldIndex
,
uint16_t
headerVersion
,
uint16_t
headerVersion
,
uint8_t
*
bufferPtr
,
uint8_t
*
bufferPtr
,
int32_t
headerLengthRemaining
,
int32_t
headerLengthRemaining
,
int32_t
actualBufferDataRemaining
)
int32_t
actualBufferDataRemaining
)
{
{
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
headerVersion
,
fieldIndex
);
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
headerVersion
,
fieldIndex
);
if
(
definition
->
maskForOptionalField
!=
ALWAYS_PRESENT_MASK
)
{
if
(
definition
->
maskForOptionalField
!=
ALWAYS_PRESENT_MASK
)
{
uint16_t
fieldControl
=
*
(
uint16_t
*
)(
otaHeaderFieldLocations
[
FIELD_CONTROL_INDEX
].
location
);
uint16_t
fieldControl
=
*
(
uint16_t
*
)(
otaHeaderFieldLocations
[
FIELD_CONTROL_INDEX
].
location
);
if
(
!
(
fieldControl
&
definition
->
maskForOptionalField
))
{
if
(
!
(
fieldControl
&
definition
->
maskForOptionalField
))
{
// No more processing.
// No more processing.
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
}
}
if
(
headerLengthRemaining
<
definition
->
length
if
(
headerLengthRemaining
<
definition
->
length
||
actualBufferDataRemaining
<
definition
->
length
)
{
||
actualBufferDataRemaining
<
definition
->
length
)
{
error
(
"OTA Header does not contain enough data for field '%s'
\n
"
,
error
(
"OTA Header does not contain enough data for field '%s'
\n
"
,
definition
->
name
);
definition
->
name
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
if
(
definition
->
type
==
INTEGER_FIELD
)
{
if
(
definition
->
type
==
INTEGER_FIELD
)
{
// Unfortunately we have to break up parsing of different integer lengths
// Unfortunately we have to break up parsing of different integer lengths
// into separate pieces of code because of the way the data
// into separate pieces of code because of the way the data
// may be packed in the data structure.
// may be packed in the data structure.
// Previously we tried to just use a generic 'uint32_t*' to point
// Previously we tried to just use a generic 'uint32_t*' to point
// to either the location of a 32-bit, 16-bit, or 8-bit value and then write
// to either the location of a 32-bit, 16-bit, or 8-bit value and then write
// the data appropriately. However if the location could only store a 16-bit
// the data appropriately. However if the location could only store a 16-bit
// value and we are referring to it as an uint32_t*, then we may write to the
// value and we are referring to it as an uint32_t*, then we may write to the
// wrong bytes depending on the how the data is packed.
// wrong bytes depending on the how the data is packed.
// Using the correct pointer based on the length sidesteps that problem.
// Using the correct pointer based on the length sidesteps that problem.
if
(
1
==
definition
->
length
)
{
if
(
1
==
definition
->
length
)
{
uint8_t
*
value
=
(
uint8_t
*
)(
otaHeaderFieldLocations
[
fieldIndex
].
location
);
uint8_t
*
value
=
(
uint8_t
*
)(
otaHeaderFieldLocations
[
fieldIndex
].
location
);
*
value
=
bufferPtr
[
0
];
*
value
=
bufferPtr
[
0
];
}
else
if
(
2
==
definition
->
length
)
{
}
else
if
(
2
==
definition
->
length
)
{
uint16_t
*
value
=
(
uint16_t
*
)(
otaHeaderFieldLocations
[
fieldIndex
].
location
);
uint16_t
*
value
=
(
uint16_t
*
)(
otaHeaderFieldLocations
[
fieldIndex
].
location
);
*
value
=
(
bufferPtr
[
0
]
*
value
=
(
bufferPtr
[
0
]
+
(
bufferPtr
[
1
]
<<
8
));
+
(
bufferPtr
[
1
]
<<
8
));
}
else
if
(
4
==
definition
->
length
)
{
}
else
if
(
4
==
definition
->
length
)
{
uint32_t
*
value
=
(
uint32_t
*
)(
otaHeaderFieldLocations
[
fieldIndex
].
location
);
uint32_t
*
value
=
(
uint32_t
*
)(
otaHeaderFieldLocations
[
fieldIndex
].
location
);
*
value
=
(
bufferPtr
[
0
]
*
value
=
(
bufferPtr
[
0
]
+
(
bufferPtr
[
1
]
<<
8
)
+
(
bufferPtr
[
1
]
<<
8
)
+
(
bufferPtr
[
2
]
<<
16
)
+
(
bufferPtr
[
2
]
<<
16
)
+
(
bufferPtr
[
3
]
<<
24
));
+
(
bufferPtr
[
3
]
<<
24
));
}
else
{
}
else
{
error
(
"Unsupported data value length '%d' for type '%s'.
\n
"
,
error
(
"Unsupported data value length '%d' for type '%s'.
\n
"
,
definition
->
length
,
definition
->
length
,
definition
->
name
);
definition
->
name
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
}
else
if
(
definition
->
type
==
BYTE_ARRAY_FIELD
}
else
if
(
definition
->
type
==
BYTE_ARRAY_FIELD
||
definition
->
type
==
STRING_FIELD
)
{
||
definition
->
type
==
STRING_FIELD
)
{
memcpy
(
otaHeaderFieldLocations
[
fieldIndex
].
location
,
bufferPtr
,
definition
->
length
);
memcpy
(
otaHeaderFieldLocations
[
fieldIndex
].
location
,
bufferPtr
,
definition
->
length
);
}
else
{
}
else
{
// Programatic error
// Programatic error
error
(
"Unkown field type '%d'
\n
"
,
definition
->
type
);
error
(
"Unkown field type '%d'
\n
"
,
definition
->
type
);
return
EMBER_AF_OTA_STORAGE_ERROR
;
return
EMBER_AF_OTA_STORAGE_ERROR
;
}
}
otaHeaderFieldLocations
[
fieldIndex
].
found
=
true
;
otaHeaderFieldLocations
[
fieldIndex
].
found
=
true
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
return
EMBER_AF_OTA_STORAGE_SUCCESS
;
}
}
static
void
mapHeaderFieldDefinitionToDataStruct
(
EmberAfOtaHeader
*
header
)
static
void
mapHeaderFieldDefinitionToDataStruct
(
EmberAfOtaHeader
*
header
)
{
{
otaHeaderFieldLocations
[
HEADER_VERSION_INDEX
].
location
=
&
(
header
->
headerVersion
);
otaHeaderFieldLocations
[
HEADER_VERSION_INDEX
].
location
=
&
(
header
->
headerVersion
);
otaHeaderFieldLocations
[
HEADER_LENGTH_INDEX
].
location
=
&
(
header
->
headerLength
);
otaHeaderFieldLocations
[
HEADER_LENGTH_INDEX
].
location
=
&
(
header
->
headerLength
);
otaHeaderFieldLocations
[
FIELD_CONTROL_INDEX
].
location
=
&
(
header
->
fieldControl
);
otaHeaderFieldLocations
[
FIELD_CONTROL_INDEX
].
location
=
&
(
header
->
fieldControl
);
otaHeaderFieldLocations
[
MANUFACTURER_ID_INDEX
].
location
=
&
(
header
->
manufacturerId
);
otaHeaderFieldLocations
[
MANUFACTURER_ID_INDEX
].
location
=
&
(
header
->
manufacturerId
);
otaHeaderFieldLocations
[
IMAGE_TYPE_INDEX
].
location
=
&
(
header
->
imageTypeId
);
otaHeaderFieldLocations
[
IMAGE_TYPE_INDEX
].
location
=
&
(
header
->
imageTypeId
);
otaHeaderFieldLocations
[
FIRMWARE_VERSION_INDEX
].
location
=
&
(
header
->
firmwareVersion
);
otaHeaderFieldLocations
[
FIRMWARE_VERSION_INDEX
].
location
=
&
(
header
->
firmwareVersion
);
otaHeaderFieldLocations
[
ZIGBEE_STACK_VERSION_INDEX
].
location
=
&
(
header
->
zigbeeStackVersion
);
otaHeaderFieldLocations
[
ZIGBEE_STACK_VERSION_INDEX
].
location
=
&
(
header
->
zigbeeStackVersion
);
otaHeaderFieldLocations
[
TOTAL_IMAGE_SIZE_INDEX
].
location
=
&
(
header
->
imageSize
);
otaHeaderFieldLocations
[
TOTAL_IMAGE_SIZE_INDEX
].
location
=
&
(
header
->
imageSize
);
otaHeaderFieldLocations
[
SECURITY_CREDENTIALS_INDEX
].
location
=
&
(
header
->
securityCredentials
);
otaHeaderFieldLocations
[
SECURITY_CREDENTIALS_INDEX
].
location
=
&
(
header
->
securityCredentials
);
otaHeaderFieldLocations
[
MINIMUM_HARDWARE_VERSION_INDEX
].
location
=
&
(
header
->
minimumHardwareVersion
);
otaHeaderFieldLocations
[
MINIMUM_HARDWARE_VERSION_INDEX
].
location
=
&
(
header
->
minimumHardwareVersion
);
otaHeaderFieldLocations
[
MAXIMUM_HARDWARE_VERSION_INDEX
].
location
=
&
(
header
->
maximumHardwareVersion
);
otaHeaderFieldLocations
[
MAXIMUM_HARDWARE_VERSION_INDEX
].
location
=
&
(
header
->
maximumHardwareVersion
);
// For byte arrays and strings, those are already pointers and we do not want
// For byte arrays and strings, those are already pointers and we do not want
// with another layer of indirection
// with another layer of indirection
otaHeaderFieldLocations
[
HEADER_STRING_INDEX
].
location
=
header
->
headerString
;
otaHeaderFieldLocations
[
HEADER_STRING_INDEX
].
location
=
header
->
headerString
;
otaHeaderFieldLocations
[
UPGRADE_FILE_DESTINATION_INDEX
].
location
=
&
header
->
upgradeFileDestination
;
otaHeaderFieldLocations
[
UPGRADE_FILE_DESTINATION_INDEX
].
location
=
&
header
->
upgradeFileDestination
;
}
}
static
void
unmapHeaderFieldDefinitions
(
void
)
static
void
unmapHeaderFieldDefinitions
(
void
)
{
{
for
(
int
i
=
0
;
i
<
FIELD_INDEX_MAX
;
i
++
)
{
for
(
int
i
=
0
;
i
<
FIELD_INDEX_MAX
;
i
++
)
{
otaHeaderFieldLocations
[
i
].
location
=
NULL
;
otaHeaderFieldLocations
[
i
].
location
=
NULL
;
otaHeaderFieldLocations
[
i
].
found
=
false
;
otaHeaderFieldLocations
[
i
].
found
=
false
;
}
}
}
}
static
OtaImage
*
findImageById
(
const
EmberAfOtaImageId
*
id
)
static
OtaImage
*
findImageById
(
const
EmberAfOtaImageId
*
id
)
{
{
OtaImage
*
ptr
=
imageListFirst
;
OtaImage
*
ptr
=
imageListFirst
;
while
(
ptr
!=
NULL
)
{
while
(
ptr
!=
NULL
)
{
if
(
id
->
manufacturerId
==
ptr
->
header
->
manufacturerId
if
(
id
->
manufacturerId
==
ptr
->
header
->
manufacturerId
&&
id
->
imageTypeId
==
ptr
->
header
->
imageTypeId
&&
id
->
imageTypeId
==
ptr
->
header
->
imageTypeId
&&
id
->
firmwareVersion
==
ptr
->
header
->
firmwareVersion
)
{
&&
id
->
firmwareVersion
==
ptr
->
header
->
firmwareVersion
)
{
return
ptr
;
return
ptr
;
}
}
ptr
=
(
OtaImage
*
)
ptr
->
next
;
ptr
=
(
OtaImage
*
)
ptr
->
next
;
}
}
return
NULL
;
return
NULL
;
}
}
static
uint8_t
*
writeHeaderDataToBuffer
(
EmberAfOtaBootloadFileHeaderFieldIndex_t
fieldIndex
,
static
uint8_t
*
writeHeaderDataToBuffer
(
EmberAfOtaBootloadFileHeaderFieldIndex_t
fieldIndex
,
uint16_t
headerVersion
,
uint16_t
headerVersion
,
uint8_t
*
bufferPtr
)
uint8_t
*
bufferPtr
)
{
{
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
headerVersion
,
fieldIndex
);
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
headerVersion
,
fieldIndex
);
if
(
definition
->
maskForOptionalField
!=
ALWAYS_PRESENT_MASK
)
{
if
(
definition
->
maskForOptionalField
!=
ALWAYS_PRESENT_MASK
)
{
uint16_t
fieldControl
=
*
(
uint16_t
*
)(
otaHeaderFieldLocations
[
FIELD_CONTROL_INDEX
].
location
);
uint16_t
fieldControl
=
*
(
uint16_t
*
)(
otaHeaderFieldLocations
[
FIELD_CONTROL_INDEX
].
location
);
if
(
!
(
fieldControl
&
definition
->
maskForOptionalField
))
{
if
(
!
(
fieldControl
&
definition
->
maskForOptionalField
))
{
debug
(
config
.
fieldDebug
,
"Skipping field %s
\n
"
,
definition
->
name
);
debug
(
config
.
fieldDebug
,
"Skipping field %s
\n
"
,
definition
->
name
);
// No more processing.
// No more processing.
return
bufferPtr
;
return
bufferPtr
;
}
}
}
}
debug
(
config
.
fieldDebug
,
debug
(
config
.
fieldDebug
,
"Writing field %s, type %d, length %d
\n
"
,
"Writing field %s, type %d, length %d
\n
"
,
definition
->
name
,
definition
->
name
,
definition
->
type
,
definition
->
type
,
definition
->
length
);
definition
->
length
);
if
(
definition
->
type
==
BYTE_ARRAY_FIELD
if
(
definition
->
type
==
BYTE_ARRAY_FIELD
||
definition
->
type
==
STRING_FIELD
)
{
||
definition
->
type
==
STRING_FIELD
)
{
memcpy
(
bufferPtr
,
otaHeaderFieldLocations
[
fieldIndex
].
location
,
definition
->
length
);
memcpy
(
bufferPtr
,
otaHeaderFieldLocations
[
fieldIndex
].
location
,
definition
->
length
);
}
else
if
(
definition
->
type
==
INTEGER_FIELD
)
{
}
else
if
(
definition
->
type
==
INTEGER_FIELD
)
{
if
(
definition
->
length
==
1
)
{
if
(
definition
->
length
==
1
)
{
uint8_t
*
value
=
otaHeaderFieldLocations
[
fieldIndex
].
location
;
uint8_t
*
value
=
otaHeaderFieldLocations
[
fieldIndex
].
location
;
bufferPtr
[
0
]
=
*
value
;
bufferPtr
[
0
]
=
*
value
;
}
else
if
(
definition
->
length
==
2
)
{
}
else
if
(
definition
->
length
==
2
)
{
uint16_t
*
value
=
otaHeaderFieldLocations
[
fieldIndex
].
location
;
uint16_t
*
value
=
otaHeaderFieldLocations
[
fieldIndex
].
location
;
bufferPtr
[
0
]
=
(
uint8_t
)(
*
value
);
bufferPtr
[
0
]
=
(
uint8_t
)(
*
value
);
bufferPtr
[
1
]
=
(
uint8_t
)(
*
value
>>
8
);
bufferPtr
[
1
]
=
(
uint8_t
)(
*
value
>>
8
);
}
else
if
(
definition
->
length
==
4
)
{
}
else
if
(
definition
->
length
==
4
)
{
uint32_t
*
value
=
otaHeaderFieldLocations
[
fieldIndex
].
location
;
uint32_t
*
value
=
otaHeaderFieldLocations
[
fieldIndex
].
location
;
bufferPtr
[
0
]
=
(
uint8_t
)(
*
value
);
bufferPtr
[
0
]
=
(
uint8_t
)(
*
value
);
bufferPtr
[
1
]
=
(
uint8_t
)(
*
value
>>
8
);
bufferPtr
[
1
]
=
(
uint8_t
)(
*
value
>>
8
);
bufferPtr
[
2
]
=
(
uint8_t
)(
*
value
>>
16
);
bufferPtr
[
2
]
=
(
uint8_t
)(
*
value
>>
16
);
bufferPtr
[
3
]
=
(
uint8_t
)(
*
value
>>
24
);
bufferPtr
[
3
]
=
(
uint8_t
)(
*
value
>>
24
);
}
else
{
}
else
{
assert
(
0
);
assert
(
0
);
}
}
}
}
return
(
bufferPtr
+
definition
->
length
);
return
(
bufferPtr
+
definition
->
length
);
}
}
static
uint16_t
calculateOtaFileHeaderLength
(
EmberAfOtaHeader
*
header
)
static
uint16_t
calculateOtaFileHeaderLength
(
EmberAfOtaHeader
*
header
)
{
{
uint16_t
length
=
4
;
// the size of the magic number
uint16_t
length
=
4
;
// the size of the magic number
int
fieldIndex
=
HEADER_VERSION_INDEX
;
int
fieldIndex
=
HEADER_VERSION_INDEX
;
while
(
fieldIndex
<
FIELD_INDEX_MAX
)
{
while
(
fieldIndex
<
FIELD_INDEX_MAX
)
{
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
header
->
headerVersion
,
fieldIndex
);
const
EmberAfOtaHeaderFieldDefinition
*
definition
=
emGetOtaHeaderFieldDefinition
(
header
->
headerVersion
,
fieldIndex
);
if
(
definition
->
maskForOptionalField
==
ALWAYS_PRESENT_MASK
if
(
definition
->
maskForOptionalField
==
ALWAYS_PRESENT_MASK
||
(
header
->
fieldControl
&
definition
->
maskForOptionalField
))
{
||
(
header
->
fieldControl
&
definition
->
maskForOptionalField
))
{
length
+=
definition
->
length
;
length
+=
definition
->
length
;
}
}
fieldIndex
++
;
fieldIndex
++
;
}
}
return
length
;
return
length
;
}
}
static
OtaImage
*
imageSearchInternal
(
const
EmberAfOtaImageId
*
id
)
static
OtaImage
*
imageSearchInternal
(
const
EmberAfOtaImageId
*
id
)
{
{
OtaImage
*
ptr
=
imageListFirst
;
OtaImage
*
ptr
=
imageListFirst
;
OtaImage
*
newest
=
NULL
;
OtaImage
*
newest
=
NULL
;
while
(
ptr
!=
NULL
)
{
while
(
ptr
!=
NULL
)
{
/*
/*
note("imageSearchInternal: Considering file '%s' (MFG: 0x%04X, Image: 0x%04X)\n",
note("imageSearchInternal: Considering file '%s' (MFG: 0x%04X, Image: 0x%04X)\n",
ptr->filenameStart,
ptr->filenameStart,
ptr->header->manufacturerId,
ptr->header->manufacturerId,
ptr->header->imageTypeId);
ptr->header->imageTypeId);
*/
*/
if
(
ptr
->
header
->
manufacturerId
==
id
->
manufacturerId
if
(
ptr
->
header
->
manufacturerId
==
id
->
manufacturerId
&&
(
ptr
->
header
->
imageTypeId
==
id
->
imageTypeId
))
{
&&
(
ptr
->
header
->
imageTypeId
==
id
->
imageTypeId
))
{
if
((
id
->
firmwareVersion
==
INVALID_FIRMWARE_VERSION
)
if
((
id
->
firmwareVersion
==
INVALID_FIRMWARE_VERSION
)
||
(
ptr
->
header
->
firmwareVersion
==
id
->
firmwareVersion
))
{
||
(
ptr
->
header
->
firmwareVersion
==
id
->
firmwareVersion
))
{
if
(
headerHasUpgradeFileDest
(
ptr
->
header
))
{
if
(
headerHasUpgradeFileDest
(
ptr
->
header
))
{
if
((
ptr
->
header
->
headerVersion
==
OTA_HEADER_VERSION_ZIGBEE
)
if
((
ptr
->
header
->
headerVersion
==
OTA_HEADER_VERSION_ZIGBEE
)
&&
(
doEui64sMatch
(
id
->
deviceSpecificFileEui64
,
&&
(
doEui64sMatch
(
id
->
deviceSpecificFileEui64
,
&
ptr
->
header
->
upgradeFileDestination
)))
{
&
ptr
->
header
->
upgradeFileDestination
)))
{
// Because there is an exact match on the EUI64, we know
// Because there is an exact match on the EUI64, we know
// this is the only one that can match the request and can
// this is the only one that can match the request and can
// return that now.
// return that now.
return
ptr
;
return
ptr
;
}
else
{
}
else
{
assert
(
0
);
// TODO: We need to handle Thread OTA headers
assert
(
0
);
// TODO: We need to handle Thread OTA headers
}
}
}
else
{
}
else
{
if
(
doEui64sMatch
(
emberAfInvalidImageId
.
deviceSpecificFileEui64
,
if
(
doEui64sMatch
(
emberAfInvalidImageId
.
deviceSpecificFileEui64
,
id
->
deviceSpecificFileEui64
))
{
id
->
deviceSpecificFileEui64
))
{
// Save this entry. There is no upgrade file dest in either the
// Save this entry. There is no upgrade file dest in either the
// search criteria or the file. This match may or may not be
// search criteria or the file. This match may or may not be
// the latest version number.
// the latest version number.
newest
=
ptr
;
newest
=
ptr
;
}
}
}
}
}
}
}
}
ptr
=
(
OtaImage
*
)
ptr
->
next
;
ptr
=
(
OtaImage
*
)
ptr
->
next
;
}
}
return
newest
;
return
newest
;
}
}
static
EmberAfOtaImageId
getIteratorImageId
(
void
)
static
EmberAfOtaImageId
getIteratorImageId
(
void
)
{
{
if
(
iterator
==
NULL
)
{
if
(
iterator
==
NULL
)
{
return
emberAfInvalidImageId
;
return
emberAfInvalidImageId
;
}
}
return
emAfOtaStorageGetImageIdFromHeader
(
iterator
->
header
);
return
emAfOtaStorageGetImageIdFromHeader
(
iterator
->
header
);
}
}
uint32_t
emAfOtaStorageGetSlot
(
void
)
uint32_t
emAfOtaStorageGetSlot
(
void
)
{
{
return
INVALID_SLOT
;
return
INVALID_SLOT
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
...
@@ -1495,65 +1487,65 @@ uint32_t emAfOtaStorageGetSlot(void)
...
@@ -1495,65 +1487,65 @@ uint32_t emAfOtaStorageGetSlot(void)
static
void
*
myMalloc
(
size_t
size
,
const
char
*
allocName
)
static
void
*
myMalloc
(
size_t
size
,
const
char
*
allocName
)
{
{
void
*
returnValue
=
malloc
(
size
);
void
*
returnValue
=
malloc
(
size
);
if
(
returnValue
!=
NULL
)
{
if
(
returnValue
!=
NULL
)
{
allocations
++
;
allocations
++
;
debug
(
config
.
memoryDebug
,
debug
(
config
.
memoryDebug
,
"[myMalloc] %s, %d bytes (0x%08X)
\n
"
,
"[myMalloc] %s, %d bytes (0x%08X)
\n
"
,
allocName
,
size
,
returnValue
);
allocName
,
size
,
returnValue
);
}
}
return
returnValue
;
return
returnValue
;
}
}
static
void
myFree
(
void
*
ptr
)
static
void
myFree
(
void
*
ptr
)
{
{
debug
(
config
.
memoryDebug
,
"[myFree] 0x%08X
\n
"
,
ptr
);
debug
(
config
.
memoryDebug
,
"[myFree] 0x%08X
\n
"
,
ptr
);
free
(
ptr
);
free
(
ptr
);
allocations
--
;
allocations
--
;
}
}
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Print routines.
// Print routines.
static
void
message
(
FILE
*
stream
,
static
void
message
(
FILE
*
stream
,
bool
error
,
bool
error
,
const
char
*
formatString
,
const
char
*
formatString
,
va_list
ap
)
va_list
ap
)
{
{
if
(
messagePrefix
)
{
if
(
messagePrefix
)
{
fprintf
(
stream
,
"[%s] "
,
messagePrefix
);
fprintf
(
stream
,
"[%s] "
,
messagePrefix
);
}
}
if
(
error
)
{
if
(
error
)
{
fprintf
(
stream
,
"Error: "
);
fprintf
(
stream
,
"Error: "
);
}
}
vfprintf
(
stream
,
formatString
,
ap
);
vfprintf
(
stream
,
formatString
,
ap
);
fflush
(
stream
);
fflush
(
stream
);
}
}
static
void
note
(
const
char
*
formatString
,
...)
static
void
note
(
const
char
*
formatString
,
...)
{
{
va_list
ap
=
{
0
};
va_list
ap
=
{
0
};
va_start
(
ap
,
formatString
);
va_start
(
ap
,
formatString
);
message
(
stdout
,
false
,
formatString
,
ap
);
message
(
stdout
,
false
,
formatString
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
}
}
static
void
debug
(
bool
debugOn
,
const
char
*
formatString
,
...)
static
void
debug
(
bool
debugOn
,
const
char
*
formatString
,
...)
{
{
if
(
debugOn
)
{
if
(
debugOn
)
{
va_list
ap
=
{
0
};
va_list
ap
=
{
0
};
va_start
(
ap
,
formatString
);
va_start
(
ap
,
formatString
);
message
(
stdout
,
false
,
formatString
,
ap
);
message
(
stdout
,
false
,
formatString
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
}
}
}
}
static
void
error
(
const
char
*
formatString
,
...)
static
void
error
(
const
char
*
formatString
,
...)
{
{
va_list
ap
=
{
0
};
va_list
ap
=
{
0
};
va_start
(
ap
,
formatString
);
va_start
(
ap
,
formatString
);
message
(
stderr
,
true
,
formatString
,
ap
);
message
(
stderr
,
true
,
formatString
,
ap
);
va_end
(
ap
);
va_end
(
ap
);
}
}
#endif // defined(GATEWAY_APP)
#endif // defined(GATEWAY_APP)
platform/zigbee/protocol/zigbee/app/framework/plugin/ota-storage-posix-filesystem/ota-storage-linux.h
View file @
e5cd9e56
...
@@ -3,12 +3,12 @@
...
@@ -3,12 +3,12 @@
typedef
void
(
EmAfOtaStorageFileAddedHandler
)(
const
EmberAfOtaHeader
*
);
typedef
void
(
EmAfOtaStorageFileAddedHandler
)(
const
EmberAfOtaHeader
*
);
typedef
struct
{
typedef
struct
{
bool
memoryDebug
;
bool
memoryDebug
;
bool
fileDebug
;
bool
fileDebug
;
bool
fieldDebug
;
bool
fieldDebug
;
bool
ignoreFilesWithUnderscorePrefix
;
bool
ignoreFilesWithUnderscorePrefix
;
bool
printFileDiscoveryOrRemoval
;
bool
printFileDiscoveryOrRemoval
;
EmAfOtaStorageFileAddedHandler
*
fileAddedHandler
;
EmAfOtaStorageFileAddedHandler
*
fileAddedHandler
;
}
EmAfOtaStorageLinuxConfig
;
}
EmAfOtaStorageLinuxConfig
;
void
emAfOtaStorageGetConfig
(
EmAfOtaStorageLinuxConfig
*
currentConfig
);
void
emAfOtaStorageGetConfig
(
EmAfOtaStorageLinuxConfig
*
currentConfig
);
...
...
platform/zigbee/protocol/zigbee/app/framework/security/af-security-common.c
View file @
e5cd9e56
...
@@ -77,6 +77,6 @@ bool emberAfIsCurrentSecurityProfileSmartEnergy(void)
...
@@ -77,6 +77,6 @@ bool emberAfIsCurrentSecurityProfileSmartEnergy(void)
||
(
emAfCurrentZigbeeProNetwork
->
securityProfile
||
(
emAfCurrentZigbeeProNetwork
->
securityProfile
==
EMBER_AF_SECURITY_PROFILE_SE_FULL
)));
==
EMBER_AF_SECURITY_PROFILE_SE_FULL
)));
#else
#else
return
false
;
return
false
;
#endif
#endif
}
}
platform/zigbee/protocol/zigbee/app/framework/util/af-main-host.c
View file @
e5cd9e56
...
@@ -545,16 +545,12 @@ int emberAfMain(MAIN_FUNCTION_PARAMETERS)
...
@@ -545,16 +545,12 @@ int emberAfMain(MAIN_FUNCTION_PARAMETERS)
halInit
();
halInit
();
INTERRUPTS_ON
();
// Safe to enable interrupts at this point
INTERRUPTS_ON
();
// Safe to enable interrupts at this point
{
int
returnCode
;
int
returnCode
;
if
(
emberAfMainStartCallback
(
&
returnCode
,
if
(
emberAfMainStartCallback
(
&
returnCode
,
APP_FRAMEWORK_MAIN_ARGUMENTS
))
{
//get serial port info
APP_FRAMEWORK_MAIN_ARGUMENTS
))
{
//get serial port info
return
returnCode
;
return
returnCode
;
}
}
}
kk_print
(
"*******************123****************
\r\n
"
);
kk_print_info
(
"
\r\n
-----hello world![%s:%s]-----
\r\n
"
,
__DATE__
,
__TIME__
);
kk_print_version
();
emberSerialInit
(
APP_SERIAL
,
BAUD_RATE
,
PARITY_NONE
,
1
);
//fock child process
emberSerialInit
(
APP_SERIAL
,
BAUD_RATE
,
PARITY_NONE
,
1
);
//fock child process
...
...
platform/zigbee/protocol/zigbee/app/framework/util/client-api.c
View file @
e5cd9e56
...
@@ -379,6 +379,6 @@ EmberApsFrame *emberAfGetCommandApsFrame(void)
...
@@ -379,6 +379,6 @@ EmberApsFrame *emberAfGetCommandApsFrame(void)
void
emberAfSetCommandEndpoints
(
uint8_t
sourceEndpoint
,
uint8_t
destinationEndpoint
)
void
emberAfSetCommandEndpoints
(
uint8_t
sourceEndpoint
,
uint8_t
destinationEndpoint
)
{
{
emAfCommandApsFrame
->
sourceEndpoint
=
sourceEndpoint
;
emAfCommandApsFrame
->
sourceEndpoint
=
sourceEndpoint
;
emAfCommandApsFrame
->
destinationEndpoint
=
destinationEndpoint
;
emAfCommandApsFrame
->
destinationEndpoint
=
destinationEndpoint
;
}
}
platform/zigbee/protocol/zigbee/app/framework/util/process-cluster-message.c
View file @
e5cd9e56
...
@@ -65,11 +65,11 @@ bool emAfProcessClusterSpecificCommand(EmberAfClusterCommand *cmd)
...
@@ -65,11 +65,11 @@ bool emAfProcessClusterSpecificCommand(EmberAfClusterCommand *cmd)
}
}
#endif
#endif
#ifdef ZCL_USING_OTA_BOOTLOAD_CLUSTER_SERVER
#ifdef ZCL_USING_OTA_BOOTLOAD_CLUSTER_SERVER
if
(
cmd
->
apsFrame
->
clusterId
==
ZCL_OTA_BOOTLOAD_CLUSTER_ID
if
(
cmd
->
apsFrame
->
clusterId
==
ZCL_OTA_BOOTLOAD_CLUSTER_ID
&&
cmd
->
direction
==
ZCL_DIRECTION_CLIENT_TO_SERVER
&&
cmd
->
direction
==
ZCL_DIRECTION_CLIENT_TO_SERVER
&&
emberAfOtaServerIncomingMessageRawCallback
(
cmd
))
{
&&
emberAfOtaServerIncomingMessageRawCallback
(
cmd
))
{
return
true
;
return
true
;
}
}
#endif
#endif
// Pass the command to the generated command parser for processing
// Pass the command to the generated command parser for processing
...
...
platform/zigbee/protocol/zigbee/app/framework/util/util.c
View file @
e5cd9e56
...
@@ -688,7 +688,7 @@ EmberStatus emberAfSendResponseWithCallback(EmberAfMessageSentFunction callback)
...
@@ -688,7 +688,7 @@ EmberStatus emberAfSendResponseWithCallback(EmberAfMessageSentFunction callback)
EmberStatus
emberAfSendResponse
(
void
)
EmberStatus
emberAfSendResponse
(
void
)
{
{
return
emberAfSendResponseWithCallback
(
NULL
);
return
emberAfSendResponseWithCallback
(
NULL
);
}
}
EmberStatus
emberAfSendImmediateDefaultResponseWithCallback
(
EmberAfStatus
status
,
EmberStatus
emberAfSendImmediateDefaultResponseWithCallback
(
EmberAfStatus
status
,
...
...
platform/zigbee/protocol/zigbee/app/util/serial/linux-serial.c
View file @
e5cd9e56
...
@@ -162,52 +162,52 @@ static bool sendGoAhead = true;
...
@@ -162,52 +162,52 @@ static bool sendGoAhead = true;
// loop executing ezspTick() and other functionality.
// loop executing ezspTick() and other functionality.
EmberStatus
emberSerialInit
(
uint8_t
port
,
EmberStatus
emberSerialInit
(
uint8_t
port
,
SerialBaudRate
rate
,
SerialBaudRate
rate
,
SerialParity
parity
,
SerialParity
parity
,
uint8_t
stopBits
)
uint8_t
stopBits
)
{
{
static
bool
emberSerialInitCalled
=
false
;
static
bool
emberSerialInitCalled
=
false
;
debugPrint
(
"emberSerialInit()
\n
"
);
debugPrint
(
"emberSerialInit()
\n
"
);
if
(
port
>
1
)
{
if
(
port
>
1
)
{
return
EMBER_SERIAL_INVALID_PORT
;
return
EMBER_SERIAL_INVALID_PORT
;
}
}
if
(
childPid
[
port
]
!=
INVALID_PID
)
{
if
(
childPid
[
port
]
!=
INVALID_PID
)
{
debugPrint
(
"Serial port %d already initialized.
\n
"
,
port
);
debugPrint
(
"Serial port %d already initialized.
\n
"
,
port
);
return
EMBER_SUCCESS
;
return
EMBER_SUCCESS
;
}
}
// Without the backchannel, there is only one serial port available (STDIN).
// Without the backchannel, there is only one serial port available (STDIN).
if
(
!
backchannelEnable
if
(
!
backchannelEnable
&&
emberSerialInitCalled
)
{
&&
emberSerialInitCalled
)
{
return
EMBER_SERIAL_INVALID_PORT
;
return
EMBER_SERIAL_INVALID_PORT
;
}
}
if
(
backchannelEnable
)
{
if
(
backchannelEnable
)
{
// For the CLI, wait here until a new client connects for the first time.
// For the CLI, wait here until a new client connects for the first time.
BackchannelState
state
=
BackchannelState
state
=
backchannelCheckConnection
(
port
,
backchannelCheckConnection
(
port
,
(
port
// waitForConnection?
(
port
// waitForConnection?
==
SERIAL_PORT_CLI
));
==
SERIAL_PORT_CLI
));
if
(
port
==
SERIAL_PORT_CLI
&&
state
!=
NEW_CONNECTION
)
{
if
(
port
==
SERIAL_PORT_CLI
&&
state
!=
NEW_CONNECTION
)
{
debugPrint
(
"Failed to get new backchannel connection.
\n
"
);
debugPrint
(
"Failed to get new backchannel connection.
\n
"
);
return
EMBER_ERR_FATAL
;
return
EMBER_ERR_FATAL
;
}
else
if
(
!
(
state
==
NEW_CONNECTION
||
state
==
CONNECTION_EXISTS
)
)
{
}
else
if
(
!
(
state
==
NEW_CONNECTION
||
state
==
CONNECTION_EXISTS
)
)
{
// We will defer initializing the RAW serial port (spawning the child
// We will defer initializing the RAW serial port (spawning the child
// and that jazz) until we actually have a new client connection.
// and that jazz) until we actually have a new client connection.
return
EMBER_SUCCESS
;
return
EMBER_SUCCESS
;
}
}
}
}
EmberStatus
status
=
serialInitInternal
(
port
);
EmberStatus
status
=
serialInitInternal
(
port
);
if
(
status
==
EMBER_SUCCESS
)
{
if
(
status
==
EMBER_SUCCESS
)
{
installSignalHandler
();
installSignalHandler
();
emberSerialInitCalled
=
true
;
emberSerialInitCalled
=
true
;
}
}
return
status
;
return
status
;
}
}
static
EmberStatus
serialInitInternal
(
uint8_t
port
)
static
EmberStatus
serialInitInternal
(
uint8_t
port
)
...
@@ -263,7 +263,7 @@ static EmberStatus serialInitInternal(uint8_t port)
...
@@ -263,7 +263,7 @@ static EmberStatus serialInitInternal(uint8_t port)
// block indefinitely waiting for debugger to attach
// block indefinitely waiting for debugger to attach
sleep
(
1
);
sleep
(
1
);
}
}
childRun
(
port
);
childRun
(
port
);
return
EMBER_ERR_FATAL
;
// should never get here
return
EMBER_ERR_FATAL
;
// should never get here
}
else
if
(
pid
==
-
1
)
{
}
else
if
(
pid
==
-
1
)
{
fprintf
(
stderr
,
"FATAL: Could not fork! (%d): %s
\n
"
,
fprintf
(
stderr
,
"FATAL: Could not fork! (%d): %s
\n
"
,
...
@@ -311,13 +311,13 @@ static bool handleRemoteConnection(uint8_t port)
...
@@ -311,13 +311,13 @@ static bool handleRemoteConnection(uint8_t port)
static
void
handleBackchannelConnection
(
uint8_t
port
)
static
void
handleBackchannelConnection
(
uint8_t
port
)
{
{
// BugzId:12928 Close out sockets used by other children but not this one
// BugzId:12928 Close out sockets used by other children but not this one
int
i
;
int
i
;
for
(
i
=
0
;
i
<
NUM_PORTS
;
i
++
)
{
for
(
i
=
0
;
i
<
NUM_PORTS
;
i
++
)
{
if
(
i
!=
port
)
{
if
(
i
!=
port
)
{
backchannelCloseConnection
(
i
);
backchannelCloseConnection
(
i
);
}
}
}
}
if
(
EMBER_SUCCESS
if
(
EMBER_SUCCESS
==
backchannelMapStandardInputOutputToRemoteConnection
(
port
))
{
==
backchannelMapStandardInputOutputToRemoteConnection
(
port
))
{
...
@@ -333,10 +333,10 @@ static void handleBackchannelConnection(uint8_t port)
...
@@ -333,10 +333,10 @@ static void handleBackchannelConnection(uint8_t port)
static
void
childRun
(
uint8_t
port
)
static
void
childRun
(
uint8_t
port
)
{
{
childProcessPort
=
port
;
childProcessPort
=
port
;
close
(
DATA_READER
(
port
));
close
(
DATA_READER
(
port
));
close
(
CONTROL_WRITER
(
port
));
close
(
CONTROL_WRITER
(
port
));
if
(
backchannelEnable
)
{
if
(
backchannelEnable
)
{
handleBackchannelConnection
(
port
);
handleBackchannelConnection
(
port
);
...
@@ -364,23 +364,23 @@ static void childRun(uint8_t port)
...
@@ -364,23 +364,23 @@ static void childRun(uint8_t port)
installSignalHandler
();
installSignalHandler
();
processSerialInput
(
port
);
processSerialInput
(
port
);
// Normally the above function NEVER returns
// Normally the above function NEVER returns
// If we get here it is an error.
// If we get here it is an error.
assert
(
0
);
assert
(
0
);
}
}
void
emberSerialSetPrompt
(
const
char
*
thePrompt
)
void
emberSerialSetPrompt
(
const
char
*
thePrompt
)
{
{
if
(
thePrompt
==
NULL
)
{
if
(
thePrompt
==
NULL
)
{
promptSet
=
false
;
promptSet
=
false
;
return
;
return
;
}
}
// Substract one for the '>'
// Substract one for the '>'
snprintf
(
prompt
,
snprintf
(
prompt
,
MAX_PROMPT_LENGTH
-
1
,
MAX_PROMPT_LENGTH
-
1
,
"%s>"
,
"%s>"
,
thePrompt
);
thePrompt
);
}
}
static
void
setNonBlockingFD
(
int
fd
)
static
void
setNonBlockingFD
(
int
fd
)
...
@@ -449,18 +449,18 @@ static void parentCleanupAfterChildDied(void)
...
@@ -449,18 +449,18 @@ static void parentCleanupAfterChildDied(void)
static
void
childCleanupAndExit
(
void
)
static
void
childCleanupAndExit
(
void
)
{
{
if
(
childProcessPort
==
SERIAL_PORT_CLI
)
{
if
(
childProcessPort
==
SERIAL_PORT_CLI
)
{
writeHistory
();
writeHistory
();
}
}
if
(
childProcessPort
!=
-
1
)
{
if
(
childProcessPort
!=
-
1
)
{
if
(
backchannelEnable
)
{
if
(
backchannelEnable
)
{
backchannelStopServer
(
childProcessPort
);
backchannelStopServer
(
childProcessPort
);
}
}
close
(
DATA_WRITER
(
childProcessPort
));
close
(
DATA_WRITER
(
childProcessPort
));
close
(
CONTROL_READER
(
childProcessPort
));
close
(
CONTROL_READER
(
childProcessPort
));
}
}
exit
(
0
);
exit
(
0
);
}
}
// This works only for the command interpreter.
// This works only for the command interpreter.
...
@@ -468,11 +468,11 @@ static void childCleanupAndExit(void)
...
@@ -468,11 +468,11 @@ static void childCleanupAndExit(void)
void
emberSerialCommandCompletionInit
(
EmberCommandEntry
listOfCommands
[])
void
emberSerialCommandCompletionInit
(
EmberCommandEntry
listOfCommands
[])
{
{
#if READLINE_SUPPORT
#if READLINE_SUPPORT
allCommands
=
listOfCommands
;
allCommands
=
listOfCommands
;
rl_attempted_completion_function
=
commandCompletion
;
rl_attempted_completion_function
=
commandCompletion
;
rl_completion_entry_function
=
filenameCompletion
;
rl_completion_entry_function
=
filenameCompletion
;
#endif
#endif
usingCommandInterpreter
=
true
;
usingCommandInterpreter
=
true
;
}
}
// This is for QA's cli
// This is for QA's cli
...
@@ -708,9 +708,9 @@ static void processSerialInput(uint8_t port)
...
@@ -708,9 +708,9 @@ static void processSerialInput(uint8_t port)
char
goAhead
;
char
goAhead
;
char
singleByte
[
2
];
char
singleByte
[
2
];
if
(
port
==
SERIAL_PORT_CLI
)
{
if
(
port
==
SERIAL_PORT_CLI
)
{
initializeHistory
();
initializeHistory
();
}
}
debugPrint
(
"Processing input for port %d.
\n
"
,
port
);
debugPrint
(
"Processing input for port %d.
\n
"
,
port
);
...
@@ -932,18 +932,18 @@ static const char* commandArgumentPtr = NULL;
...
@@ -932,18 +932,18 @@ static const char* commandArgumentPtr = NULL;
static
const
char
*
findNextNonSpaceChar
(
const
char
*
line
)
static
const
char
*
findNextNonSpaceChar
(
const
char
*
line
)
{
{
while
(
*
line
!=
'\0'
&&
*
line
==
' '
)
{
while
(
*
line
!=
'\0'
&&
*
line
==
' '
)
{
line
++
;
line
++
;
}
}
return
line
;
return
line
;
}
}
static
const
char
*
findNextSpaceChar
(
const
char
*
line
)
static
const
char
*
findNextSpaceChar
(
const
char
*
line
)
{
{
while
(
*
line
!=
'\0'
&&
*
line
!=
' '
)
{
while
(
*
line
!=
'\0'
&&
*
line
!=
' '
)
{
line
++
;
line
++
;
}
}
return
line
;
return
line
;
}
}
// Recursive function. Traverses the command-tree
// Recursive function. Traverses the command-tree
...
@@ -1147,57 +1147,57 @@ static char* duplicateString(const char* source)
...
@@ -1147,57 +1147,57 @@ static char* duplicateString(const char* source)
static
void
initializeHistory
(
void
)
static
void
initializeHistory
(
void
)
{
{
int
myErrno
;
int
myErrno
;
char
*
homeDirectory
;
char
*
homeDirectory
;
readlineHistoryPath
[
0
]
=
'\0'
;
readlineHistoryPath
[
0
]
=
'\0'
;
using_history
();
// initialize readline() history.
using_history
();
// initialize readline() history.
homeDirectory
=
getenv
(
"HOME"
);
homeDirectory
=
getenv
(
"HOME"
);
if
(
homeDirectory
==
NULL
)
{
if
(
homeDirectory
==
NULL
)
{
debugPrint
(
"Error: HOME directory env variable is not defined.
\n
"
);
debugPrint
(
"Error: HOME directory env variable is not defined.
\n
"
);
return
;
return
;
}
else
{
}
else
{
debugPrint
(
"Home Directory: %s
\n
"
,
homeDirectory
);
debugPrint
(
"Home Directory: %s
\n
"
,
homeDirectory
);
}
}
snprintf
(
readlineHistoryPath
,
snprintf
(
readlineHistoryPath
,
MAX_STRING_LENGTH
-
1
,
MAX_STRING_LENGTH
-
1
,
"%s/%s"
,
"%s/%s"
,
homeDirectory
,
homeDirectory
,
readlineHistoryFilename
);
readlineHistoryFilename
);
readlineHistoryPath
[
MAX_STRING_LENGTH
-
1
]
=
'\0'
;
readlineHistoryPath
[
MAX_STRING_LENGTH
-
1
]
=
'\0'
;
myErrno
=
read_history
(
readlineHistoryPath
);
myErrno
=
read_history
(
readlineHistoryPath
);
if
(
myErrno
!=
0
)
{
if
(
myErrno
!=
0
)
{
debugPrint
(
"Could not open history file '%s': %s
\n
"
,
debugPrint
(
"Could not open history file '%s': %s
\n
"
,
readlineHistoryPath
,
readlineHistoryPath
,
strerror
(
myErrno
));
strerror
(
myErrno
));
}
else
{
}
else
{
debugPrint
(
"%d history entries read from file '%s'
\n
"
,
debugPrint
(
"%d history entries read from file '%s'
\n
"
,
history_length
,
// readline global
history_length
,
// readline global
readlineHistoryPath
);
readlineHistoryPath
);
}
}
}
}
static
void
writeHistory
(
void
)
static
void
writeHistory
(
void
)
{
{
int
myErrno
;
int
myErrno
;
if
(
readlineHistoryPath
[
0
]
==
'\0'
)
{
if
(
readlineHistoryPath
[
0
]
==
'\0'
)
{
debugPrint
(
"Readline history path is empty, not writing history.
\n
"
);
debugPrint
(
"Readline history path is empty, not writing history.
\n
"
);
return
;
return
;
}
}
myErrno
=
write_history
(
readlineHistoryPath
);
myErrno
=
write_history
(
readlineHistoryPath
);
if
(
myErrno
!=
0
)
{
if
(
myErrno
!=
0
)
{
debugPrint
(
"Failed to write history file '%s': %s
\n
"
,
debugPrint
(
"Failed to write history file '%s': %s
\n
"
,
readlineHistoryPath
,
readlineHistoryPath
,
strerror
(
myErrno
));
strerror
(
myErrno
));
}
else
{
}
else
{
debugPrint
(
"Wrote %d entries to history file '%s'
\n
"
,
debugPrint
(
"Wrote %d entries to history file '%s'
\n
"
,
history_length
,
// readline global
history_length
,
// readline global
readlineHistoryPath
);
readlineHistoryPath
);
}
}
}
}
#endif // #if READLINE_SUPPORT
#endif // #if READLINE_SUPPORT
...
@@ -1227,20 +1227,20 @@ static void writeHistory(void)
...
@@ -1227,20 +1227,20 @@ static void writeHistory(void)
*/
*/
static
void
signalHandler
(
int
signal
)
static
void
signalHandler
(
int
signal
)
{
{
static
bool
reportSigttin
=
true
;
static
bool
reportSigttin
=
true
;
const
char
*
signalName
=
strsignal
(
signal
);
const
char
*
signalName
=
strsignal
(
signal
);
if
(
signal
==
SIGTTOU
)
{
if
(
signal
==
SIGTTOU
)
{
debugOn
=
false
;
debugOn
=
false
;
return
;
return
;
}
}
if
(
signal
!=
SIGTTIN
||
reportSigttin
)
{
if
(
signal
!=
SIGTTIN
||
reportSigttin
)
{
debugPrint
(
"%s caught signal %s (%d)
\n
"
,
debugPrint
(
"%s caught signal %s (%d)
\n
"
,
(
amParent
?
"Parent"
:
"Child"
),
(
amParent
?
"Parent"
:
"Child"
),
(
signalName
==
NULL
?
"???"
:
signalName
),
(
signalName
==
NULL
?
"???"
:
signalName
),
signal
);
signal
);
}
}
if
(
signal
==
SIGPIPE
)
{
if
(
signal
==
SIGPIPE
)
{
// Ignore this.
// Ignore this.
...
@@ -1253,11 +1253,11 @@ static void signalHandler(int signal)
...
@@ -1253,11 +1253,11 @@ static void signalHandler(int signal)
return
;
return
;
}
}
if
(
signal
==
SIGTTIN
)
{
if
(
signal
==
SIGTTIN
)
{
reportSigttin
=
false
;
reportSigttin
=
false
;
return
;
return
;
}
}
/*
/*
if (signal == SIGCHLD) {
if (signal == SIGCHLD) {
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment