pub struct KM003C { /* private fields */ }Implementations§
Source§impl KM003C
impl KM003C
Sourcepub async fn new(config: DeviceConfig) -> Result<Self, KMError>
pub async fn new(config: DeviceConfig) -> Result<Self, KMError>
Connect to device with the given configuration
The config determines the connection mode:
DeviceConfig::vendor(): Full mode - runs init sequence, all features enabledDeviceConfig::hid(): Basic mode - no init, ADC/PD polling only
§Examples
use km003c_lib::{KM003C, DeviceConfig};
// Full mode (vendor interface) - all features
let device = KM003C::new(DeviceConfig::vendor()).await?;
println!("Model: {}", device.state().unwrap().model());
println!("AdcQueue enabled: {}", device.adcqueue_enabled());
// Basic mode (HID interface) - ADC/PD polling only
let mut device = KM003C::new(DeviceConfig::hid()).await?;
let adc = device.request_adc_data().await?;
// With options
let device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;Examples found in repository?
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let settings = device.request_settings().await?;
9
10 println!("Device name: {}", settings.device_name().unwrap_or("<invalid UTF-8>"));
11 println!("Language selection: {}", settings.language_selection());
12 println!("Uncalibrated: {}", settings.is_uncalibrated());
13 println!("Brightness: {}%", settings.brightness().get::<percent>());
14 println!(
15 "Sample interval: {} us",
16 settings.sample_interval().get::<microsecond>()
17 );
18 println!("Screen orientation: {}", settings.screen_orientation());
19 println!("Mtools device mode: {}", settings.mtools_device_mode());
20 println!("Selected main page: {}", settings.selected_main_page());
21
22 Ok(())
23}More examples
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let initial_level = device.state().map(|state| state.auth_level).unwrap_or(0);
9 println!("Initial authentication level: {initial_level}");
10
11 let result = device.authenticate_calibration().await?;
12 println!(
13 "Calibration authentication level: {} (attribute 0x{:04x})",
14 result.auth_level, result.attribute
15 );
16
17 device.start_graph_mode(GraphSampleRate::Sps50).await?;
18 tokio::time::sleep(Duration::from_millis(200)).await;
19 let response = device.request_data(AttributeSet::single(Attribute::AdcQueue)).await;
20 device.stop_graph_mode().await?;
21
22 let response = response?;
23 let samples = response.get_adc_queue().map(|queue| queue.samples.len()).unwrap_or(0);
24 println!("AdcQueue samples received after level-2 auth: {samples}");
25
26 Ok(())
27}Sourcepub fn next_tid(&mut self) -> u8
pub fn next_tid(&mut self) -> u8
Get the next transaction ID (for auth module and external use)
Sourcepub fn set_transaction_id(&mut self, id: u8)
pub fn set_transaction_id(&mut self, id: u8)
Set the transaction ID counter (for protocol research/sync purposes)
Sourcepub async fn send(&mut self, packet: Packet) -> Result<(), KMError>
pub async fn send(&mut self, packet: Packet) -> Result<(), KMError>
Send a high-level packet without waiting for or correlating its response.
This is a low-level protocol-research API. Prefer command-specific methods
such as Self::request_data and Self::read_memory_block for normal use.
Sourcepub async fn send_raw(&mut self, data: &[u8]) -> Result<(), KMError>
pub async fn send_raw(&mut self, data: &[u8]) -> Result<(), KMError>
Send raw bytes to the device (for protocol research/testing)
Sourcepub async fn receive_raw(&mut self) -> Result<Vec<u8>, KMError>
pub async fn receive_raw(&mut self) -> Result<Vec<u8>, KMError>
Receive raw bytes without transaction correlation.
This is a low-level protocol-research API. Previously received out-of-order responses are returned first.
Sourcepub async fn receive(&mut self) -> Result<Packet, KMError>
pub async fn receive(&mut self) -> Result<Packet, KMError>
Receive the next framed high-level packet without transaction correlation.
Unframed transfers such as encrypted MemoryRead data cannot be parsed by
this method. Use Self::read_memory_block for device memory reads.
Sourcepub async fn request_data(
&mut self,
mask: AttributeSet,
) -> Result<Packet, KMError>
pub async fn request_data( &mut self, mask: AttributeSet, ) -> Result<Packet, KMError>
Request data with a specific attribute set
Examples found in repository?
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let initial_level = device.state().map(|state| state.auth_level).unwrap_or(0);
9 println!("Initial authentication level: {initial_level}");
10
11 let result = device.authenticate_calibration().await?;
12 println!(
13 "Calibration authentication level: {} (attribute 0x{:04x})",
14 result.auth_level, result.attribute
15 );
16
17 device.start_graph_mode(GraphSampleRate::Sps50).await?;
18 tokio::time::sleep(Duration::from_millis(200)).await;
19 let response = device.request_data(AttributeSet::single(Attribute::AdcQueue)).await;
20 device.stop_graph_mode().await?;
21
22 let response = response?;
23 let samples = response.get_adc_queue().map(|queue| queue.samples.len()).unwrap_or(0);
24 println!("AdcQueue samples received after level-2 auth: {samples}");
25
26 Ok(())
27}Sourcepub async fn request_adc_data(&mut self) -> Result<AdcDataSimple, KMError>
pub async fn request_adc_data(&mut self) -> Result<AdcDataSimple, KMError>
Request ADC data only
Sourcepub async fn request_settings(&mut self) -> Result<Settings, KMError>
pub async fn request_settings(&mut self) -> Result<Settings, KMError>
Request and parse the two read-only settings blocks.
Examples found in repository?
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let settings = device.request_settings().await?;
9
10 println!("Device name: {}", settings.device_name().unwrap_or("<invalid UTF-8>"));
11 println!("Language selection: {}", settings.language_selection());
12 println!("Uncalibrated: {}", settings.is_uncalibrated());
13 println!("Brightness: {}%", settings.brightness().get::<percent>());
14 println!(
15 "Sample interval: {} us",
16 settings.sample_interval().get::<microsecond>()
17 );
18 println!("Screen orientation: {}", settings.screen_orientation());
19 println!("Mtools device mode: {}", settings.mtools_device_mode());
20 println!("Selected main page: {}", settings.selected_main_page());
21
22 Ok(())
23}Sourcepub async fn request_pd_trace(&mut self) -> Result<PdTrace, KMError>
pub async fn request_pd_trace(&mut self) -> Result<PdTrace, KMError>
Request and drain the internal USB PD state-machine trace queues.
Sourcepub async fn request_log_metadata(
&mut self,
) -> Result<Vec<LogMetadata>, KMError>
pub async fn request_log_metadata( &mut self, ) -> Result<Vec<LogMetadata>, KMError>
Request metadata for the offline log currently selected on the device.
Returns an empty vector when no offline log is available.
Sourcepub async fn download_offline_log(
&mut self,
metadata: LogMetadata,
) -> Result<OfflineLog, KMError>
pub async fn download_offline_log( &mut self, metadata: LogMetadata, ) -> Result<OfflineLog, KMError>
Download the offline samples described by previously requested metadata.
Sourcepub async fn request_pd_data(&mut self) -> Result<Packet, KMError>
pub async fn request_pd_data(&mut self) -> Result<Packet, KMError>
Request PD data (returns full packet as it can contain PdStatus OR PdEventStream)
The response depends on the device state:
- If payload is 12 bytes: returns PdStatus (use packet.get_pd_status())
- If payload > 12 bytes: returns PdEventStream (use packet.get_pd_events())
Use request_adc_with_pd() to get ADC + PdStatus together (68 bytes).
Sourcepub async fn request_adc_with_pd(&mut self) -> Result<Packet, KMError>
pub async fn request_adc_with_pd(&mut self) -> Result<Packet, KMError>
Request both ADC and PD data in a single request
This typically returns ADC + PdStatus (68 bytes total). Use packet.get_adc() and packet.get_pd_status() to extract data.
Sourcepub fn extract_pd_status(packet: &Packet) -> Option<&PdStatus>
pub fn extract_pd_status(packet: &Packet) -> Option<&PdStatus>
Helper: Try to get PD status from a packet
Returns Some if the packet contains PdStatus (12-byte payload), None otherwise. Useful after request_pd_data() or request_adc_with_pd().
Sourcepub fn extract_pd_events(packet: &Packet) -> Option<&PdEventStream>
pub fn extract_pd_events(packet: &Packet) -> Option<&PdEventStream>
Helper: Try to get PD event stream from a packet
Returns Some if the packet contains PdEventStream (>12 bytes), None otherwise. Useful after request_pd_data().
Sourcepub async fn enable_pd_monitor(&mut self) -> Result<(), KMError>
pub async fn enable_pd_monitor(&mut self) -> Result<(), KMError>
Enable PD monitor/sniffer
Sends the EnablePdMonitor command (0x10) to start capturing PD events.
This may be required before request_pd_data() returns PD events,
especially in Basic mode (HID interface).
Returns Ok(()) on Accept, error otherwise.
Sourcepub async fn disable_pd_monitor(&mut self) -> Result<(), KMError>
pub async fn disable_pd_monitor(&mut self) -> Result<(), KMError>
Disable PD monitor/sniffer
Sends the DisablePdMonitor command (0x11) to stop capturing PD events.
Returns Ok(()) on Accept, error otherwise.
Sourcepub fn mode(&self) -> &ConnectionMode
pub fn mode(&self) -> &ConnectionMode
Get the current connection mode
ConnectionMode::Basic- HID interface, ADC/PD polling onlyConnectionMode::Full(state)- Vendor interface, all features
Sourcepub fn is_full_mode(&self) -> bool
pub fn is_full_mode(&self) -> bool
Check if device is in full mode (vendor interface)
Sourcepub fn is_basic_mode(&self) -> bool
pub fn is_basic_mode(&self) -> bool
Check if device is in basic mode (HID interface)
Sourcepub fn state(&self) -> Option<&DeviceState>
pub fn state(&self) -> Option<&DeviceState>
Get device state (only available in Full mode)
Returns Some when connected via vendor interface (Full mode).
Returns None when connected via HID interface (Basic mode).
Examples found in repository?
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let initial_level = device.state().map(|state| state.auth_level).unwrap_or(0);
9 println!("Initial authentication level: {initial_level}");
10
11 let result = device.authenticate_calibration().await?;
12 println!(
13 "Calibration authentication level: {} (attribute 0x{:04x})",
14 result.auth_level, result.attribute
15 );
16
17 device.start_graph_mode(GraphSampleRate::Sps50).await?;
18 tokio::time::sleep(Duration::from_millis(200)).await;
19 let response = device.request_data(AttributeSet::single(Attribute::AdcQueue)).await;
20 device.stop_graph_mode().await?;
21
22 let response = response?;
23 let samples = response.get_adc_queue().map(|queue| queue.samples.len()).unwrap_or(0);
24 println!("AdcQueue samples received after level-2 auth: {samples}");
25
26 Ok(())
27}Sourcepub fn is_authenticated(&self) -> bool
pub fn is_authenticated(&self) -> bool
Check if device is authenticated (Full mode only)
Returns false in Basic mode or if authentication failed.
Sourcepub fn adcqueue_enabled(&self) -> bool
pub fn adcqueue_enabled(&self) -> bool
Check if AdcQueue streaming is enabled (Full mode only)
Returns false in Basic mode or if not authenticated for streaming.
Sourcepub async fn authenticate_calibration(
&mut self,
) -> Result<StreamingAuthResult, KMError>
pub async fn authenticate_calibration( &mut self, ) -> Result<StreamingAuthResult, KMError>
Authenticate with the device’s calibration credential and enter auth level 2.
KM003C firmware V1.9.9 prefers the first 12 bytes at 0x03000D80.
When that record starts with 0xFFFFFFFF, it falls back to
0x03000C00. This method only reads those known addresses and sends a
StreamingAuth request; it does not write settings or flash memory.
Examples found in repository?
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let initial_level = device.state().map(|state| state.auth_level).unwrap_or(0);
9 println!("Initial authentication level: {initial_level}");
10
11 let result = device.authenticate_calibration().await?;
12 println!(
13 "Calibration authentication level: {} (attribute 0x{:04x})",
14 result.auth_level, result.attribute
15 );
16
17 device.start_graph_mode(GraphSampleRate::Sps50).await?;
18 tokio::time::sleep(Duration::from_millis(200)).await;
19 let response = device.request_data(AttributeSet::single(Attribute::AdcQueue)).await;
20 device.stop_graph_mode().await?;
21
22 let response = response?;
23 let samples = response.get_adc_queue().map(|queue| queue.samples.len()).unwrap_or(0);
24 println!("AdcQueue samples received after level-2 auth: {samples}");
25
26 Ok(())
27}Sourcepub async fn read_memory_block(
&mut self,
address: u32,
size: u32,
) -> Result<Vec<u8>, KMError>
pub async fn read_memory_block( &mut self, address: u32, size: u32, ) -> Result<Vec<u8>, KMError>
Read an encrypted memory block from the device
Sends a MemoryRead request, receives the confirmation, then receives
and decrypts the actual data. Returns exactly size decrypted bytes;
AES block padding received from the device is removed.
§Errors
The encrypted payload arrives unframed, so a response still in flight from another request would be consumed as ciphertext. AdcQueue streaming must therefore be stopped first; calling this while graph mode is active returns an error instead of corrupting the read.
Sourcepub async fn get_device_info(&mut self) -> Result<DeviceInfo, KMError>
pub async fn get_device_info(&mut self) -> Result<DeviceInfo, KMError>
Read device information from memory
Reads and parses:
- DeviceInfo1 (0x420): model, hw_version, mfg_date
- FirmwareInfo (0x4420): fw_version, fw_date
- CalibrationData (0x3000C00): serial_id, uuid
Note: Requires Connect to be sent first. Only works in Full mode.
When using DeviceConfig::vendor(), this info is already available via state().
§Example
// In Full mode, device info is already available
let device = KM003C::new(DeviceConfig::vendor()).await?;
println!("Model: {}", device.state().unwrap().model());Sourcepub async fn start_graph_mode(
&mut self,
rate: GraphSampleRate,
) -> Result<(), KMError>
pub async fn start_graph_mode( &mut self, rate: GraphSampleRate, ) -> Result<(), KMError>
Start AdcQueue graph/streaming mode with specified sample rate
§Arguments
rate- Sample rate (use GraphSampleRate enum)
Requires Full mode (vendor interface) and successful StreamingAuth.
Rate values:
GraphSampleRate::Sps2= 2 samples per secondGraphSampleRate::Sps10= 10 SPSGraphSampleRate::Sps50= 50 SPSGraphSampleRate::Sps1000= 1000 SPS
After calling this, poll with request_data(AttributeSet::single(Attribute::AdcQueue))
to receive buffered samples.
§Example
let mut device = KM003C::new(DeviceConfig::vendor()).await?;
// Start 1000 SPS streaming
device.start_graph_mode(GraphSampleRate::Sps1000).await?;
// Poll for data...
// Stop when done
device.stop_graph_mode().await?;Examples found in repository?
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let initial_level = device.state().map(|state| state.auth_level).unwrap_or(0);
9 println!("Initial authentication level: {initial_level}");
10
11 let result = device.authenticate_calibration().await?;
12 println!(
13 "Calibration authentication level: {} (attribute 0x{:04x})",
14 result.auth_level, result.attribute
15 );
16
17 device.start_graph_mode(GraphSampleRate::Sps50).await?;
18 tokio::time::sleep(Duration::from_millis(200)).await;
19 let response = device.request_data(AttributeSet::single(Attribute::AdcQueue)).await;
20 device.stop_graph_mode().await?;
21
22 let response = response?;
23 let samples = response.get_adc_queue().map(|queue| queue.samples.len()).unwrap_or(0);
24 println!("AdcQueue samples received after level-2 auth: {samples}");
25
26 Ok(())
27}Sourcepub async fn stop_graph_mode(&mut self) -> Result<(), KMError>
pub async fn stop_graph_mode(&mut self) -> Result<(), KMError>
Stop AdcQueue graph/streaming mode
Requires Full mode (vendor interface). Will return error in Basic mode.
Returns device to normal ADC polling mode.
Examples found in repository?
6async fn main() -> Result<(), Box<dyn std::error::Error>> {
7 let mut device = KM003C::new(DeviceConfig::vendor().skip_reset()).await?;
8 let initial_level = device.state().map(|state| state.auth_level).unwrap_or(0);
9 println!("Initial authentication level: {initial_level}");
10
11 let result = device.authenticate_calibration().await?;
12 println!(
13 "Calibration authentication level: {} (attribute 0x{:04x})",
14 result.auth_level, result.attribute
15 );
16
17 device.start_graph_mode(GraphSampleRate::Sps50).await?;
18 tokio::time::sleep(Duration::from_millis(200)).await;
19 let response = device.request_data(AttributeSet::single(Attribute::AdcQueue)).await;
20 device.stop_graph_mode().await?;
21
22 let response = response?;
23 let samples = response.get_adc_queue().map(|queue| queue.samples.len()).unwrap_or(0);
24 println!("AdcQueue samples received after level-2 auth: {samples}");
25
26 Ok(())
27}