rktk_drivers_nrf/softdevice/ble/services/
device_information.rs1use nrf_softdevice::{
2 ble::{
3 gatt_server::{
4 builder::ServiceBuilder,
5 characteristic::{Attribute, Metadata, Properties},
6 CharacteristicHandles, RegisterError,
7 },
8 Uuid,
9 },
10 Softdevice,
11};
12
13use super::super::constant::{
14 DEVICE_INFORMATION, FIRMWARE_REVISION, HARDWARE_REVISION, MANUFACTURER_NAME, MODEL_NUMBER,
15 PNP_ID, SERIAL_NUMBER, SOFTWARE_REVISION,
16};
17
18#[repr(u8)]
19#[derive(Clone, Copy)]
20#[allow(dead_code)]
21pub enum VidSource {
22 BluetoothSIG = 1,
23 UsbIF = 2,
24}
25
26#[repr(C, packed)]
27#[derive(Clone, Copy)]
28pub struct PnPID {
29 pub vid_source: VidSource,
30 pub vendor_id: u16,
31 pub product_id: u16,
32 pub product_version: u16,
33}
34
35#[derive(Debug, Default)]
36pub struct DeviceInformation {
37 pub manufacturer_name: Option<&'static str>,
38 pub model_number: Option<&'static str>,
39 pub serial_number: Option<&'static str>,
40 pub hw_rev: Option<&'static str>,
41 pub fw_rev: Option<&'static str>,
42 pub sw_rev: Option<&'static str>,
43}
44
45pub struct DeviceInformationService {}
46
47impl DeviceInformationService {
48 pub fn new(
49 sd: &mut Softdevice,
50 pnp_id: &PnPID,
51 info: DeviceInformation,
52 ) -> Result<Self, RegisterError> {
53 let mut sb = ServiceBuilder::new(sd, DEVICE_INFORMATION)?;
54
55 Self::add_pnp_characteristic(&mut sb, pnp_id)?;
56 Self::add_opt_str_characteristic(&mut sb, MANUFACTURER_NAME, info.manufacturer_name)?;
57 Self::add_opt_str_characteristic(&mut sb, MODEL_NUMBER, info.model_number)?;
58 Self::add_opt_str_characteristic(&mut sb, SERIAL_NUMBER, info.serial_number)?;
59 Self::add_opt_str_characteristic(&mut sb, HARDWARE_REVISION, info.hw_rev)?;
60 Self::add_opt_str_characteristic(&mut sb, FIRMWARE_REVISION, info.fw_rev)?;
61 Self::add_opt_str_characteristic(&mut sb, SOFTWARE_REVISION, info.sw_rev)?;
62
63 let _service_handle = sb.build();
64
65 Ok(DeviceInformationService {})
66 }
67
68 fn add_opt_str_characteristic(
69 sb: &mut ServiceBuilder,
70 uuid: Uuid,
71 val: Option<&'static str>,
72 ) -> Result<Option<CharacteristicHandles>, RegisterError> {
73 if let Some(val) = val {
74 let attr = Attribute::new(val);
75 let md = Metadata::new(Properties::new().read());
76 Ok(Some(sb.add_characteristic(uuid, attr, md)?.build()))
77 } else {
78 Ok(None)
79 }
80 }
81
82 fn add_pnp_characteristic(
83 sb: &mut ServiceBuilder,
84 pnp_id: &PnPID,
85 ) -> Result<CharacteristicHandles, RegisterError> {
86 let val = unsafe {
88 core::slice::from_raw_parts(
89 pnp_id as *const _ as *const u8,
90 core::mem::size_of::<PnPID>(),
91 )
92 };
93
94 let attr = Attribute::new(val);
95 let md = Metadata::new(Properties::new().read());
96 Ok(sb.add_characteristic(PNP_ID, attr, md)?.build())
97 }
98}