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