Skip to content

Commit 7b94cb0

Browse files
maxd-nordicnordicjm
authored andcommitted
lib: hw_id
This patch adds the hw_id library which provides a unified way to get a constant, unique ID. Signed-off-by: Maximilian Deubel <maximilian.deubel@nordicsemi.no> Signed-off-by: divya pillai <divya.pillai@nordicsemi.no>
1 parent bba6acb commit 7b94cb0

26 files changed

+727
-0
lines changed

CODEOWNERS

+3
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ Kconfig* @tejlmand
107107
/lib/st25r3911b/ @grochu
108108
/lib/supl/ @rlubos @tokangas
109109
/lib/date_time/ @trantanen @tokangas
110+
/lib/hw_id/ @maxd-nordic
110111
/lib/wave_gen/ @MarekPieta
111112
/lib/hw_unique_key/ @oyvindronningstad @Vge0rge
112113
/lib/identity_key/ @frkv @Vge0rge
@@ -127,6 +128,7 @@ Kconfig* @tejlmand
127128
/samples/matter/ @Damian-Nordic @kkasperczyk-no
128129
/samples/crypto/ @frkv @Vge0rge
129130
/samples/debug/ppi_trace/ @nordic-krch @anangl
131+
/samples/hw_id/ @maxd-nordic
130132
/samples/edge_impulse/ @pdunaj
131133
/samples/esb/ @lemrey
132134
/samples/app_event_manager/ @pdunaj @MarekPieta
@@ -216,6 +218,7 @@ Kconfig* @tejlmand
216218
/tests/lib/date_time/ @trantanen @tokangas
217219
/tests/lib/edge_impulse/ @pdunaj @MarekPieta
218220
/tests/lib/hw_unique_key*/ @oyvindronningstad @Vge0rge
221+
/tests/lib/hw_id/ @maxd-nordic
219222
/tests/lib/location/ @trantanen @hiltunent @jhirsi @tokangas
220223
/tests/lib/lte_lc/ @jtguggedal @tokangas @simensrostad
221224
/tests/lib/modem_jwt/ @SeppoTakalo

doc/nrf/libraries/others/hw_id.rst

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
.. _lib_hw_id:
2+
3+
Hardware ID
4+
###########
5+
6+
.. contents::
7+
:local:
8+
:depth: 2
9+
10+
The hardware ID library provides a simple interface to retrieve a unique hardware ID.
11+
You can retrieve the hardware ID by calling the :c:func:`hw_id_get` function.
12+
13+
The :ref:`hw_id_sample` sample uses this library.
14+
15+
Configuration
16+
*************
17+
18+
To enable the library, set the :kconfig:option:`CONFIG_HW_ID_LIBRARY` Kconfig option to y in the project configuration file :file:`prj.conf`.
19+
20+
You can configure one of the following Kconfig options to choose the hardware ID:
21+
22+
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_IMEI` - This option specifies the :term:`International Mobile (Station) Equipment Identity (IMEI)` of the modem.
23+
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_UUID` - This option specifies the UUID of the modem.
24+
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC` - This option specifies the default Bluetooth® Low Energy MAC address.
25+
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC` - This option specifies the MAC address of the default network interface.
26+
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID` - This option specifies a serial number provided by Zephyr's HW Info API.
27+
28+
API documentation
29+
*****************
30+
31+
| Header file: :file:`include/hw_id.h`
32+
| Source files: :file:`lib/hw_id/`
33+
34+
.. doxygengroup:: hw_id
35+
:project: nrf
36+
:members:

doc/nrf/releases/release-notes-changelog.rst

+2
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ Other samples
312312
* :ref:`esb_prx_ptx` sample:
313313

314314
* Removed the FEM support section.
315+
* Added :ref:`hw_id_sample` sample.
315316

316317
Drivers
317318
=======
@@ -466,6 +467,7 @@ Other libraries
466467

467468
* Added:
468469
* :ref:`lib_sfloat` library.
470+
* :ref:`lib_hw_id` library to retrieve a unique hardware ID.
469471

470472
Common Application Framework (CAF)
471473
----------------------------------

include/hw_id.h

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
/*
2+
* Copyright (c) 2022 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#ifndef HW_ID_H__
8+
#define HW_ID_H__
9+
10+
#include <zephyr/types.h>
11+
12+
/**
13+
* @defgroup hw_id Device ID Library
14+
* @{
15+
* @brief Library that provides a unified interface for fetching a unique device ID from hardware.
16+
*/
17+
18+
#ifdef __cplusplus
19+
extern "C" {
20+
#endif
21+
22+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC)
23+
#define HW_ID_LEN (12 + 1)
24+
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID)
25+
#define HW_ID_LEN (16 + 1)
26+
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID)
27+
#include <modem/modem_jwt.h>
28+
#define HW_ID_LEN (NRF_UUID_V4_STR_LEN + 1)
29+
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI)
30+
#define HW_ID_LEN (15 + 1)
31+
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC)
32+
#define HW_ID_LEN (12 + 1)
33+
#endif
34+
35+
/** @brief Fetch unique device ID
36+
* @note The buffer should be at least HW_ID_LEN bytes long.
37+
*
38+
* @param[out] buf destination buffer
39+
* @param[in] buf_len length of destination buffer
40+
* @return 0 If the operation was successful.
41+
* @return -EINVAL If the passed in pointer is NULL or buffer is too small.
42+
* @return -EIO If requesting platform ID failed.
43+
*/
44+
int hw_id_get(char *buf, size_t buf_len);
45+
46+
#ifdef __cplusplus
47+
}
48+
#endif
49+
50+
/** @} */
51+
52+
#endif /* HW_ID_H__ */

lib/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ add_subdirectory_ifdef(CONFIG_MODEM_KEY_MGMT modem_key_mgmt)
2626
add_subdirectory_ifdef(CONFIG_SMS sms)
2727
add_subdirectory_ifdef(CONFIG_SUPL_CLIENT_LIB supl)
2828
add_subdirectory_ifdef(CONFIG_DATE_TIME date_time)
29+
add_subdirectory_ifdef(CONFIG_HW_ID_LIBRARY hw_id)
2930
add_subdirectory_ifdef(CONFIG_EDGE_IMPULSE edge_impulse)
3031
add_subdirectory_ifdef(CONFIG_WAVE_GEN_LIB wave_gen)
3132
add_subdirectory_ifdef(CONFIG_HW_UNIQUE_KEY_SRC hw_unique_key)

lib/Kconfig

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ rsource "sms/Kconfig"
2626
rsource "modem_key_mgmt/Kconfig"
2727
rsource "supl/Kconfig"
2828
rsource "date_time/Kconfig"
29+
rsource "hw_id/Kconfig"
2930
rsource "ram_pwrdn/Kconfig"
3031
rsource "edge_impulse/Kconfig"
3132
rsource "wave_gen/Kconfig"

lib/hw_id/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#
2+
# Copyright (c) 2022 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
zephyr_library()
8+
zephyr_library_sources(hw_id.c)

lib/hw_id/Kconfig

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#
2+
# Copyright (c) 2022 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
menuconfig HW_ID_LIBRARY
8+
bool "Hardware ID"
9+
select HWINFO
10+
help
11+
Provides a unified interface for fetching a unique device ID from hardware.
12+
13+
if HW_ID_LIBRARY
14+
15+
choice HW_ID_LIBRARY_SOURCE
16+
prompt "HW ID source type"
17+
default HW_ID_LIBRARY_SOURCE_DEVICE_ID
18+
19+
config HW_ID_LIBRARY_SOURCE_IMEI
20+
bool "IMEI"
21+
depends on NRF_MODEM_LIB
22+
23+
config HW_ID_LIBRARY_SOURCE_UUID
24+
bool "UUID"
25+
depends on MODEM_JWT
26+
help
27+
This option requires modem firmware v1.3.0 or higher.
28+
29+
config HW_ID_LIBRARY_SOURCE_BLE_MAC
30+
bool "BLE MAC address"
31+
depends on BT
32+
33+
config HW_ID_LIBRARY_SOURCE_NET_MAC
34+
bool "network MAC address"
35+
depends on NETWORKING
36+
37+
config HW_ID_LIBRARY_SOURCE_DEVICE_ID
38+
bool "Device ID"
39+
depends on HWINFO
40+
41+
endchoice # HW_ID_LIBRARY_SOURCE
42+
43+
endif # HW_ID_LIBRARY

lib/hw_id/hw_id.c

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
/*
2+
* Copyright (c) 2022 Nordic Semiconductor ASA
3+
*
4+
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
*/
6+
7+
#include <hw_id.h>
8+
#include <zephyr/kernel.h>
9+
10+
/* includes for the different HW ID sources */
11+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC)
12+
#include <zephyr/bluetooth/bluetooth.h>
13+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) */
14+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID)
15+
#include <zephyr/drivers/hwinfo.h>
16+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) */
17+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID)
18+
#include <modem/modem_jwt.h>
19+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID) */
20+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI)
21+
#include <nrf_modem_at.h>
22+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI) */
23+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC)
24+
#include <zephyr/net/net_if.h>
25+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC) */
26+
27+
#define IMEI_LEN 15
28+
29+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC)
30+
/* Ask BLE stack for default MAC address */
31+
32+
int hw_id_get(char *buf, size_t buf_len)
33+
{
34+
if (buf == NULL || buf_len < HW_ID_LEN) {
35+
return -EINVAL;
36+
}
37+
38+
struct bt_le_oob oob;
39+
int ret = bt_le_oob_get_local(BT_ID_DEFAULT, &oob);
40+
41+
if (ret) {
42+
return -EIO;
43+
}
44+
45+
snprintk(buf, buf_len, "%02X%02X%02X%02X%02X%02X",
46+
oob.addr.a.val[5],
47+
oob.addr.a.val[4],
48+
oob.addr.a.val[3],
49+
oob.addr.a.val[2],
50+
oob.addr.a.val[1],
51+
oob.addr.a.val[0]);
52+
return 0;
53+
}
54+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) */
55+
56+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID)
57+
/* Directly read Device ID from registers */
58+
59+
int hw_id_get(char *buf, size_t buf_len)
60+
{
61+
if (buf == NULL || buf_len < HW_ID_LEN) {
62+
return -EINVAL;
63+
}
64+
65+
uint8_t device_id[8];
66+
ssize_t ret = hwinfo_get_device_id(device_id, ARRAY_SIZE(device_id));
67+
68+
if (ret != ARRAY_SIZE(device_id)) {
69+
return -EIO;
70+
}
71+
72+
snprintk(buf, buf_len, "%02X%02X%02X%02X%02X%02X%02X%02X",
73+
device_id[0],
74+
device_id[1],
75+
device_id[2],
76+
device_id[3],
77+
device_id[4],
78+
device_id[5],
79+
device_id[6],
80+
device_id[7]);
81+
return 0;
82+
}
83+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) */
84+
85+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID)
86+
/* Request a UUID from the modem */
87+
88+
int hw_id_get(char *buf, size_t buf_len)
89+
{
90+
if (buf == NULL || buf_len < HW_ID_LEN) {
91+
return -EINVAL;
92+
}
93+
94+
struct nrf_device_uuid dev = {0};
95+
96+
int err = modem_jwt_get_uuids(&dev, NULL);
97+
98+
if (err) {
99+
return -EIO;
100+
}
101+
102+
snprintk(buf, buf_len, "%s", dev.str);
103+
return 0;
104+
}
105+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID) */
106+
107+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI)
108+
/* Ask the modem for an IMEI */
109+
110+
int hw_id_get(char *buf, size_t buf_len)
111+
{
112+
if (buf == NULL || buf_len < HW_ID_LEN) {
113+
return -EINVAL;
114+
}
115+
116+
char imei_buf[IMEI_LEN + 6 + 1]; /* Add 6 for \r\nOK\r\n and 1 for \0 */
117+
118+
/* Retrieve device IMEI from modem. */
119+
int err = nrf_modem_at_cmd(imei_buf, ARRAY_SIZE(imei_buf), "AT+CGSN");
120+
121+
if (err) {
122+
return -EIO;
123+
}
124+
125+
/* Set null character at the end of the device IMEI. */
126+
imei_buf[IMEI_LEN] = 0;
127+
128+
snprintk(buf, buf_len, "%s", imei_buf);
129+
return 0;
130+
}
131+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI) */
132+
133+
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC)
134+
/* Use MAC address from default network interface */
135+
136+
int hw_id_get(char *buf, size_t buf_len)
137+
{
138+
if (buf == NULL || buf_len < HW_ID_LEN) {
139+
return -EINVAL;
140+
}
141+
142+
struct net_if *iface = net_if_get_default();
143+
144+
if (iface == NULL) {
145+
return -EIO;
146+
}
147+
148+
struct net_linkaddr *linkaddr = net_if_get_link_addr(iface);
149+
150+
snprintk(buf, buf_len, "%02X%02X%02X%02X%02X%02X",
151+
linkaddr->addr[0],
152+
linkaddr->addr[1],
153+
linkaddr->addr[2],
154+
linkaddr->addr[3],
155+
linkaddr->addr[4],
156+
linkaddr->addr[5]);
157+
return 0;
158+
}
159+
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC) */

samples/hw_id/CMakeLists.txt

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
#
2+
# Copyright (c) 2022 Nordic Semiconductor
3+
#
4+
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
5+
#
6+
7+
cmake_minimum_required(VERSION 3.20.0)
8+
9+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
10+
project("HW ID sample")
11+
12+
# NORDIC SDK APP START
13+
target_sources(app PRIVATE src/main.c)
14+
# NORDIC SDK APP END

0 commit comments

Comments
 (0)