Skip to content

Commit

Permalink
lib: hw_id
Browse files Browse the repository at this point in the history
This patch adds the hw_id library which provides a unified way
to get a constant, unique ID.

Signed-off-by: Maximilian Deubel <[email protected]>
Signed-off-by: divya pillai <[email protected]>
  • Loading branch information
maxd-nordic authored and nordicjm committed Nov 1, 2022
1 parent bba6acb commit 7b94cb0
Show file tree
Hide file tree
Showing 26 changed files with 727 additions and 0 deletions.
3 changes: 3 additions & 0 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Kconfig* @tejlmand
/lib/st25r3911b/ @grochu
/lib/supl/ @rlubos @tokangas
/lib/date_time/ @trantanen @tokangas
/lib/hw_id/ @maxd-nordic
/lib/wave_gen/ @MarekPieta
/lib/hw_unique_key/ @oyvindronningstad @Vge0rge
/lib/identity_key/ @frkv @Vge0rge
Expand All @@ -127,6 +128,7 @@ Kconfig* @tejlmand
/samples/matter/ @Damian-Nordic @kkasperczyk-no
/samples/crypto/ @frkv @Vge0rge
/samples/debug/ppi_trace/ @nordic-krch @anangl
/samples/hw_id/ @maxd-nordic
/samples/edge_impulse/ @pdunaj
/samples/esb/ @lemrey
/samples/app_event_manager/ @pdunaj @MarekPieta
Expand Down Expand Up @@ -216,6 +218,7 @@ Kconfig* @tejlmand
/tests/lib/date_time/ @trantanen @tokangas
/tests/lib/edge_impulse/ @pdunaj @MarekPieta
/tests/lib/hw_unique_key*/ @oyvindronningstad @Vge0rge
/tests/lib/hw_id/ @maxd-nordic
/tests/lib/location/ @trantanen @hiltunent @jhirsi @tokangas
/tests/lib/lte_lc/ @jtguggedal @tokangas @simensrostad
/tests/lib/modem_jwt/ @SeppoTakalo
Expand Down
36 changes: 36 additions & 0 deletions doc/nrf/libraries/others/hw_id.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
.. _lib_hw_id:

Hardware ID
###########

.. contents::
:local:
:depth: 2

The hardware ID library provides a simple interface to retrieve a unique hardware ID.
You can retrieve the hardware ID by calling the :c:func:`hw_id_get` function.

The :ref:`hw_id_sample` sample uses this library.

Configuration
*************

To enable the library, set the :kconfig:option:`CONFIG_HW_ID_LIBRARY` Kconfig option to y in the project configuration file :file:`prj.conf`.

You can configure one of the following Kconfig options to choose the hardware ID:

* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_IMEI` - This option specifies the :term:`International Mobile (Station) Equipment Identity (IMEI)` of the modem.
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_UUID` - This option specifies the UUID of the modem.
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC` - This option specifies the default Bluetooth® Low Energy MAC address.
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC` - This option specifies the MAC address of the default network interface.
* :kconfig:option:`CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID` - This option specifies a serial number provided by Zephyr's HW Info API.

API documentation
*****************

| Header file: :file:`include/hw_id.h`
| Source files: :file:`lib/hw_id/`
.. doxygengroup:: hw_id
:project: nrf
:members:
2 changes: 2 additions & 0 deletions doc/nrf/releases/release-notes-changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,7 @@ Other samples
* :ref:`esb_prx_ptx` sample:

* Removed the FEM support section.
* Added :ref:`hw_id_sample` sample.

Drivers
=======
Expand Down Expand Up @@ -466,6 +467,7 @@ Other libraries

* Added:
* :ref:`lib_sfloat` library.
* :ref:`lib_hw_id` library to retrieve a unique hardware ID.

Common Application Framework (CAF)
----------------------------------
Expand Down
52 changes: 52 additions & 0 deletions include/hw_id.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#ifndef HW_ID_H__
#define HW_ID_H__

#include <zephyr/types.h>

/**
* @defgroup hw_id Device ID Library
* @{
* @brief Library that provides a unified interface for fetching a unique device ID from hardware.
*/

#ifdef __cplusplus
extern "C" {
#endif

#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC)
#define HW_ID_LEN (12 + 1)
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID)
#define HW_ID_LEN (16 + 1)
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID)
#include <modem/modem_jwt.h>
#define HW_ID_LEN (NRF_UUID_V4_STR_LEN + 1)
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI)
#define HW_ID_LEN (15 + 1)
#elif defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC)
#define HW_ID_LEN (12 + 1)
#endif

/** @brief Fetch unique device ID
* @note The buffer should be at least HW_ID_LEN bytes long.
*
* @param[out] buf destination buffer
* @param[in] buf_len length of destination buffer
* @return 0 If the operation was successful.
* @return -EINVAL If the passed in pointer is NULL or buffer is too small.
* @return -EIO If requesting platform ID failed.
*/
int hw_id_get(char *buf, size_t buf_len);

#ifdef __cplusplus
}
#endif

/** @} */

#endif /* HW_ID_H__ */
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ add_subdirectory_ifdef(CONFIG_MODEM_KEY_MGMT modem_key_mgmt)
add_subdirectory_ifdef(CONFIG_SMS sms)
add_subdirectory_ifdef(CONFIG_SUPL_CLIENT_LIB supl)
add_subdirectory_ifdef(CONFIG_DATE_TIME date_time)
add_subdirectory_ifdef(CONFIG_HW_ID_LIBRARY hw_id)
add_subdirectory_ifdef(CONFIG_EDGE_IMPULSE edge_impulse)
add_subdirectory_ifdef(CONFIG_WAVE_GEN_LIB wave_gen)
add_subdirectory_ifdef(CONFIG_HW_UNIQUE_KEY_SRC hw_unique_key)
Expand Down
1 change: 1 addition & 0 deletions lib/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ rsource "sms/Kconfig"
rsource "modem_key_mgmt/Kconfig"
rsource "supl/Kconfig"
rsource "date_time/Kconfig"
rsource "hw_id/Kconfig"
rsource "ram_pwrdn/Kconfig"
rsource "edge_impulse/Kconfig"
rsource "wave_gen/Kconfig"
Expand Down
8 changes: 8 additions & 0 deletions lib/hw_id/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#
# Copyright (c) 2022 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

zephyr_library()
zephyr_library_sources(hw_id.c)
43 changes: 43 additions & 0 deletions lib/hw_id/Kconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#
# Copyright (c) 2022 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

menuconfig HW_ID_LIBRARY
bool "Hardware ID"
select HWINFO
help
Provides a unified interface for fetching a unique device ID from hardware.

if HW_ID_LIBRARY

choice HW_ID_LIBRARY_SOURCE
prompt "HW ID source type"
default HW_ID_LIBRARY_SOURCE_DEVICE_ID

config HW_ID_LIBRARY_SOURCE_IMEI
bool "IMEI"
depends on NRF_MODEM_LIB

config HW_ID_LIBRARY_SOURCE_UUID
bool "UUID"
depends on MODEM_JWT
help
This option requires modem firmware v1.3.0 or higher.

config HW_ID_LIBRARY_SOURCE_BLE_MAC
bool "BLE MAC address"
depends on BT

config HW_ID_LIBRARY_SOURCE_NET_MAC
bool "network MAC address"
depends on NETWORKING

config HW_ID_LIBRARY_SOURCE_DEVICE_ID
bool "Device ID"
depends on HWINFO

endchoice # HW_ID_LIBRARY_SOURCE

endif # HW_ID_LIBRARY
159 changes: 159 additions & 0 deletions lib/hw_id/hw_id.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
/*
* Copyright (c) 2022 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
*/

#include <hw_id.h>
#include <zephyr/kernel.h>

/* includes for the different HW ID sources */
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC)
#include <zephyr/bluetooth/bluetooth.h>
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) */
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID)
#include <zephyr/drivers/hwinfo.h>
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) */
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID)
#include <modem/modem_jwt.h>
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID) */
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI)
#include <nrf_modem_at.h>
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI) */
#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC)
#include <zephyr/net/net_if.h>
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC) */

#define IMEI_LEN 15

#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC)
/* Ask BLE stack for default MAC address */

int hw_id_get(char *buf, size_t buf_len)
{
if (buf == NULL || buf_len < HW_ID_LEN) {
return -EINVAL;
}

struct bt_le_oob oob;
int ret = bt_le_oob_get_local(BT_ID_DEFAULT, &oob);

if (ret) {
return -EIO;
}

snprintk(buf, buf_len, "%02X%02X%02X%02X%02X%02X",
oob.addr.a.val[5],
oob.addr.a.val[4],
oob.addr.a.val[3],
oob.addr.a.val[2],
oob.addr.a.val[1],
oob.addr.a.val[0]);
return 0;
}
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_BLE_MAC) */

#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID)
/* Directly read Device ID from registers */

int hw_id_get(char *buf, size_t buf_len)
{
if (buf == NULL || buf_len < HW_ID_LEN) {
return -EINVAL;
}

uint8_t device_id[8];
ssize_t ret = hwinfo_get_device_id(device_id, ARRAY_SIZE(device_id));

if (ret != ARRAY_SIZE(device_id)) {
return -EIO;
}

snprintk(buf, buf_len, "%02X%02X%02X%02X%02X%02X%02X%02X",
device_id[0],
device_id[1],
device_id[2],
device_id[3],
device_id[4],
device_id[5],
device_id[6],
device_id[7]);
return 0;
}
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_DEVICE_ID) */

#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID)
/* Request a UUID from the modem */

int hw_id_get(char *buf, size_t buf_len)
{
if (buf == NULL || buf_len < HW_ID_LEN) {
return -EINVAL;
}

struct nrf_device_uuid dev = {0};

int err = modem_jwt_get_uuids(&dev, NULL);

if (err) {
return -EIO;
}

snprintk(buf, buf_len, "%s", dev.str);
return 0;
}
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_UUID) */

#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI)
/* Ask the modem for an IMEI */

int hw_id_get(char *buf, size_t buf_len)
{
if (buf == NULL || buf_len < HW_ID_LEN) {
return -EINVAL;
}

char imei_buf[IMEI_LEN + 6 + 1]; /* Add 6 for \r\nOK\r\n and 1 for \0 */

/* Retrieve device IMEI from modem. */
int err = nrf_modem_at_cmd(imei_buf, ARRAY_SIZE(imei_buf), "AT+CGSN");

if (err) {
return -EIO;
}

/* Set null character at the end of the device IMEI. */
imei_buf[IMEI_LEN] = 0;

snprintk(buf, buf_len, "%s", imei_buf);
return 0;
}
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_IMEI) */

#if defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC)
/* Use MAC address from default network interface */

int hw_id_get(char *buf, size_t buf_len)
{
if (buf == NULL || buf_len < HW_ID_LEN) {
return -EINVAL;
}

struct net_if *iface = net_if_get_default();

if (iface == NULL) {
return -EIO;
}

struct net_linkaddr *linkaddr = net_if_get_link_addr(iface);

snprintk(buf, buf_len, "%02X%02X%02X%02X%02X%02X",
linkaddr->addr[0],
linkaddr->addr[1],
linkaddr->addr[2],
linkaddr->addr[3],
linkaddr->addr[4],
linkaddr->addr[5]);
return 0;
}
#endif /* defined(CONFIG_HW_ID_LIBRARY_SOURCE_NET_MAC) */
14 changes: 14 additions & 0 deletions samples/hw_id/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#
# Copyright (c) 2022 Nordic Semiconductor
#
# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
#

cmake_minimum_required(VERSION 3.20.0)

find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project("HW ID sample")

# NORDIC SDK APP START
target_sources(app PRIVATE src/main.c)
# NORDIC SDK APP END
Loading

0 comments on commit 7b94cb0

Please sign in to comment.