hid_io_protocol/commands/
mod.rs

1/* Copyright (C) 2020-2022 by Jacob Alexander
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to deal
5 * in the Software without restriction, including without limitation the rights
6 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7 * copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19 * THE SOFTWARE.
20 */
21
22// ----- Crates -----
23
24use super::*;
25use core::convert::{TryFrom, TryInto};
26use heapless::{String, Vec};
27
28#[cfg(feature = "defmt")]
29use defmt::trace;
30#[cfg(not(feature = "defmt"))]
31use log::trace;
32
33// ----- Modules -----
34
35mod test;
36
37// ----- Macros -----
38
39// ----- Enumerations -----
40
41#[derive(Debug)]
42#[cfg_attr(feature = "defmt", derive(defmt::Format))]
43pub enum CommandError {
44    BufferInUse,
45    BufferNotReady,
46    CallbackFailed,
47    DataVecNoData,
48    DataVecTooSmall,
49    IdNotImplemented(HidIoCommandId, HidIoPacketType),
50    IdNotMatched(HidIoCommandId),
51    IdNotSupported(HidIoCommandId),
52    IdVecTooSmall,
53    InvalidCStr,
54    InvalidId(u32),
55    InvalidPacketBufferType(HidIoPacketType),
56    InvalidProperty8(u8),
57    InvalidRxMessage(HidIoPacketType),
58    InvalidUtf8(Utf8Error),
59    PacketDecodeError(HidIoParseError),
60    RxFailed,
61    RxTimeout,
62    RxTooManySyncs,
63    SerializationFailed(HidIoParseError),
64    SerializationVecTooSmall,
65    TestFailure,
66    TxBufferSendFailed,
67    TxBufferVecTooSmall,
68    TxNoActiveReceivers,
69}
70
71// ----- Defmt Wrappers -----
72
73/// Defmt wrapper for core::str::Utf8Error
74#[derive(Debug)]
75pub struct Utf8Error {
76    pub inner: core::str::Utf8Error,
77}
78
79impl Utf8Error {
80    pub fn new(e: core::str::Utf8Error) -> Self {
81        Utf8Error { inner: e }
82    }
83}
84
85#[cfg(feature = "defmt")]
86impl defmt::Format for Utf8Error {
87    fn format(&self, fmt: defmt::Formatter) {
88        if let Some(error_len) = self.inner.error_len() {
89            defmt::write!(
90                fmt,
91                "invalid utf-8 sequence of {} bytes from index {}",
92                error_len,
93                self.inner.valid_up_to()
94            )
95        } else {
96            defmt::write!(
97                fmt,
98                "incomplete utf-8 byte sequence from index {}",
99                self.inner.valid_up_to()
100            )
101        }
102    }
103}
104
105#[cfg(not(feature = "defmt"))]
106impl fmt::Display for Utf8Error {
107    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
108        if let Some(error_len) = self.inner.error_len() {
109            write!(
110                fmt,
111                "invalid utf-8 sequence of {} bytes from index {}",
112                error_len,
113                self.inner.valid_up_to()
114            )
115        } else {
116            write!(
117                fmt,
118                "incomplete utf-8 byte sequence from index {}",
119                self.inner.valid_up_to()
120            )
121        }
122    }
123}
124
125// ----- Command Structs -----
126
127/// Supported Ids
128pub mod h0000 {
129    use super::super::HidIoCommandId;
130    use heapless::Vec;
131
132    #[derive(Clone, Debug)]
133    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
134    pub struct Cmd {}
135
136    #[derive(Clone, Debug)]
137    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
138    pub struct Ack<const ID: usize> {
139        pub ids: Vec<HidIoCommandId, ID>,
140    }
141
142    #[derive(Clone, Debug)]
143    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
144    pub struct Nak {}
145}
146
147/// Info Query
148pub mod h0001 {
149    use heapless::String;
150    use num_enum::TryFromPrimitive;
151
152    #[repr(u8)]
153    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
154    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
155    pub enum Property {
156        Unknown = 0x00,
157        MajorVersion = 0x01,
158        MinorVersion = 0x02,
159        PatchVersion = 0x03,
160        DeviceName = 0x04,
161        DeviceSerialNumber = 0x05,
162        DeviceVersion = 0x06,
163        DeviceMcu = 0x07,
164        FirmwareName = 0x08,
165        FirmwareVersion = 0x09,
166        DeviceVendor = 0x0A,
167        OsType = 0x0B,
168        OsVersion = 0x0C,
169        HostSoftwareName = 0x0D,
170    }
171
172    #[repr(u8)]
173    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
174    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
175    pub enum OsType {
176        Unknown = 0x00,
177        Windows = 0x01,
178        Linux = 0x02,
179        Android = 0x03,
180        MacOs = 0x04,
181        Ios = 0x05,
182        ChromeOs = 0x06,
183        FreeBsd = 0x07,
184        OpenBsd = 0x08,
185        NetBsd = 0x09,
186    }
187
188    #[derive(Clone, Debug)]
189    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
190    pub struct Cmd {
191        pub property: Property,
192    }
193
194    #[derive(Clone, Debug)]
195    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
196    pub struct Ack<const S: usize> {
197        pub property: Property,
198
199        /// OS Type field
200        pub os: OsType,
201
202        /// Number is set when the given property specifies a number
203        pub number: u16,
204
205        /// String is set when the given property specifies a string
206        /// Should be 1 byte less than the max hidio data buffer size
207        pub string: String<S>,
208    }
209
210    #[derive(Clone, Debug)]
211    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
212    pub struct Nak {
213        pub property: Property,
214    }
215}
216
217/// Test Message
218pub mod h0002 {
219    use heapless::Vec;
220
221    #[derive(Clone, Debug)]
222    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
223    pub struct Cmd<const D: usize> {
224        pub data: Vec<u8, D>,
225    }
226
227    #[derive(Clone, Debug)]
228    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
229    pub struct Ack<const D: usize> {
230        pub data: Vec<u8, D>,
231    }
232
233    #[derive(Clone, Debug)]
234    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
235    pub struct Nak {}
236}
237
238/// Reset HID-IO
239pub mod h0003 {
240    #[derive(Clone, Debug)]
241    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
242    pub struct Cmd {}
243
244    #[derive(Clone, Debug)]
245    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
246    pub struct Ack {}
247
248    #[derive(Clone, Debug)]
249    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
250    pub struct Nak {}
251}
252
253/// Get Properties
254pub mod h0010 {
255    use heapless::{String, Vec};
256    use num_enum::TryFromPrimitive;
257
258    #[repr(u8)]
259    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
260    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
261    pub enum Command {
262        ListFields = 0x00,
263        GetFieldName = 0x01,
264        GetFieldValue = 0x02,
265        Unknown = 0xFF,
266    }
267
268    #[derive(Clone, Debug)]
269    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
270    pub struct Cmd {
271        pub command: Command,
272
273        /// 8-bit field id
274        /// Ignored by ListFields
275        pub field: u8,
276    }
277
278    #[derive(Clone, Debug)]
279    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
280    pub struct Ack<const S: usize> {
281        pub command: Command,
282
283        /// 8-bit field id
284        /// Ignored by ListFields
285        pub field: u8,
286
287        /// List of field ids
288        pub field_list: Vec<u8, S>,
289
290        /// String payload
291        pub string: String<S>,
292    }
293
294    #[derive(Clone, Debug)]
295    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
296    pub struct Nak {
297        pub command: Command,
298
299        /// 8-bit field id
300        /// Ignored by ListFields
301        pub field: u8,
302    }
303}
304
305/// USB Key State
306/// TODO
307pub mod h0011 {
308    pub struct Cmd {}
309    pub struct Ack {}
310    pub struct Nak {}
311}
312
313/// Keyboard Layout
314/// TODO
315pub mod h0012 {
316    pub struct Cmd {}
317    pub struct Ack {}
318    pub struct Nak {}
319}
320
321/// Button Layout
322/// TODO
323pub mod h0013 {
324    pub struct Cmd {}
325    pub struct Ack {}
326    pub struct Nak {}
327}
328
329/// Keycap Types
330/// TODO
331pub mod h0014 {
332    pub struct Cmd {}
333    pub struct Ack {}
334    pub struct Nak {}
335}
336
337/// LED Layout
338/// TODO
339pub mod h0015 {
340    pub struct Cmd {}
341    pub struct Ack {}
342    pub struct Nak {}
343}
344
345/// Flash Mode
346pub mod h0016 {
347    use num_enum::TryFromPrimitive;
348
349    #[repr(u8)]
350    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
351    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
352    pub enum Error {
353        NotSupported = 0x00,
354        Disabled = 0x01,
355    }
356
357    #[derive(Clone, Debug)]
358    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
359    pub struct Cmd {}
360
361    #[derive(Clone, Debug)]
362    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
363    pub struct Ack {
364        pub scancode: u16,
365    }
366
367    #[derive(Clone, Debug)]
368    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
369    pub struct Nak {
370        pub error: Error,
371    }
372}
373
374/// UTF-8 Character Stream
375pub mod h0017 {
376    use heapless::String;
377
378    #[derive(Clone, Debug)]
379    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
380    pub struct Cmd<const S: usize> {
381        pub string: String<S>,
382    }
383
384    #[derive(Clone, Debug)]
385    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
386    pub struct Ack {}
387
388    #[derive(Clone, Debug)]
389    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
390    pub struct Nak {}
391}
392
393/// UTF-8 State
394pub mod h0018 {
395    use heapless::String;
396
397    #[derive(Clone, Debug)]
398    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
399    pub struct Cmd<const S: usize> {
400        pub symbols: String<S>,
401    }
402
403    #[derive(Clone, Debug)]
404    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
405    pub struct Ack {}
406
407    #[derive(Clone, Debug)]
408    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
409    pub struct Nak {}
410}
411
412/// Trigger Host Macro
413/// TODO
414pub mod h0019 {
415    pub struct Cmd {}
416    pub struct Ack {}
417    pub struct Nak {}
418}
419
420/// Sleep Mode
421pub mod h001a {
422    use num_enum::TryFromPrimitive;
423
424    #[repr(u8)]
425    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
426    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
427    pub enum Error {
428        NotSupported = 0x00,
429        Disabled = 0x01,
430        NotReady = 0x02,
431    }
432
433    #[derive(Clone, Debug)]
434    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
435    pub struct Cmd {}
436
437    #[derive(Clone, Debug)]
438    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
439    pub struct Ack {}
440
441    #[derive(Clone, Debug)]
442    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
443    pub struct Nak {
444        pub error: Error,
445    }
446}
447
448/// KLL Trigger State
449pub mod h0020 {
450    pub struct Cmd {
451        pub event: kll_core::TriggerEvent,
452    }
453    pub struct Ack {}
454    pub struct Nak {}
455}
456
457/// Pixel Settings
458/// Higher level LED operations and access to LED controller functionality
459pub mod h0021 {
460    use num_enum::TryFromPrimitive;
461
462    #[repr(u16)]
463    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
464    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
465    pub enum Command {
466        Control = 0x0001,
467        Reset = 0x0002,
468        Clear = 0x0003,
469        Frame = 0x0004,
470        InvalidCommand = 0xFFFF,
471    }
472
473    #[derive(Clone, Copy)]
474    pub union Argument {
475        pub raw: u16,
476        pub control: args::Control,
477        pub reset: args::Reset,
478        pub clear: args::Clear,
479        pub frame: args::Frame,
480    }
481
482    impl core::fmt::Debug for Argument {
483        fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
484            write!(f, "{}", unsafe { self.raw })
485        }
486    }
487
488    #[cfg(feature = "defmt")]
489    impl defmt::Format for Argument {
490        fn format(&self, fmt: defmt::Formatter) {
491            defmt::write!(fmt, "{}", unsafe { self.raw })
492        }
493    }
494
495    pub mod args {
496        use num_enum::TryFromPrimitive;
497
498        #[repr(u16)]
499        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
500        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
501        pub enum Control {
502            Disable = 0x0000,
503            EnableStart = 0x0001,
504            EnablePause = 0x0002,
505        }
506
507        #[repr(u16)]
508        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
509        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
510        pub enum Reset {
511            SoftReset = 0x0000,
512            HardReset = 0x0001,
513        }
514
515        #[repr(u16)]
516        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
517        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
518        pub enum Clear {
519            Clear = 0x0000,
520        }
521
522        #[repr(u16)]
523        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
524        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
525        pub enum Frame {
526            NextFrame = 0x0000,
527        }
528    }
529
530    #[derive(Clone, Debug)]
531    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
532    pub struct Cmd {
533        pub command: Command,
534        pub argument: Argument,
535    }
536
537    #[derive(Clone, Debug)]
538    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
539    pub struct Ack {}
540
541    #[derive(Clone, Debug)]
542    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
543    pub struct Nak {}
544}
545
546/// Pixel Set (1ch, 8bit)
547/// TODO
548pub mod h0022 {
549    pub struct Cmd {}
550    pub struct Ack {}
551    pub struct Nak {}
552}
553
554/// Pixel Set (3ch, 8bit)
555pub mod h0023 {
556    pub struct Cmd {}
557    pub struct Ack {}
558    pub struct Nak {}
559}
560
561/// Pixel Set (1ch, 16bit)
562/// TODO
563pub mod h0024 {
564    pub struct Cmd {}
565    pub struct Ack {}
566    pub struct Nak {}
567}
568
569/// Pixel Set (3ch, 16bit)
570/// TODO
571pub mod h0025 {
572    pub struct Cmd {}
573    pub struct Ack {}
574    pub struct Nak {}
575}
576
577/// Direct Channel Set
578/// Control the buffer directly (device configuration dependent)
579pub mod h0026 {
580    use heapless::Vec;
581
582    #[derive(Clone, Debug)]
583    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
584    pub struct Cmd<const D: usize> {
585        pub start_address: u16,
586        pub data: Vec<u8, D>,
587    }
588
589    #[derive(Clone, Debug)]
590    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
591    pub struct Ack {}
592
593    #[derive(Clone, Debug)]
594    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
595    pub struct Nak {}
596}
597
598/// Open URL
599pub mod h0030 {
600    use heapless::String;
601
602    #[derive(Clone, Debug)]
603    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
604    pub struct Cmd<const S: usize> {
605        pub url: String<S>,
606    }
607
608    #[derive(Clone, Debug)]
609    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
610    pub struct Ack {}
611
612    #[derive(Clone, Debug)]
613    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
614    pub struct Nak {}
615}
616
617/// Terminal Command
618pub mod h0031 {
619    use heapless::String;
620
621    #[derive(Clone, Debug)]
622    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
623    pub struct Cmd<const S: usize> {
624        pub command: String<S>,
625    }
626
627    #[derive(Clone, Debug)]
628    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
629    pub struct Ack {}
630
631    #[derive(Clone, Debug)]
632    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
633    pub struct Nak {}
634}
635
636/// Get OS Layout
637/// TODO
638pub mod h0032 {
639    pub struct Cmd {}
640    pub struct Ack {}
641    pub struct Nak {}
642}
643
644/// Set OS Layout
645/// TODO
646pub mod h0033 {
647    pub struct Cmd {}
648    pub struct Ack {}
649    pub struct Nak {}
650}
651
652/// Terminal Output
653pub mod h0034 {
654    use heapless::String;
655
656    #[derive(Clone, Debug)]
657    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
658    pub struct Cmd<const S: usize> {
659        pub output: String<S>,
660    }
661
662    #[derive(Clone, Debug)]
663    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
664    pub struct Ack {}
665
666    #[derive(Clone, Debug)]
667    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
668    pub struct Nak {}
669}
670
671/// HID Keyboard State
672/// TODO
673pub mod h0040 {
674    pub struct Cmd {}
675    pub struct Ack {}
676    pub struct Nak {}
677}
678
679/// HID Keyboard LED State
680/// TODO
681pub mod h0041 {
682    pub struct Cmd {}
683    pub struct Ack {}
684    pub struct Nak {}
685}
686
687/// HID Mouse State
688/// TODO
689pub mod h0042 {
690    pub struct Cmd {}
691    pub struct Ack {}
692    pub struct Nak {}
693}
694
695/// HID Joystick State
696/// TODO
697pub mod h0043 {
698    pub struct Cmd {}
699    pub struct Ack {}
700    pub struct Nak {}
701}
702
703/// Manufacturing Test
704pub mod h0050 {
705    use num_enum::TryFromPrimitive;
706
707    #[repr(u16)]
708    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
709    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
710    pub enum Command {
711        TestCommand = 0x0000,
712        LedTestSequence = 0x0001,
713        LedCycleKeypressTest = 0x0002,
714        HallEffectSensorTest = 0x0003,
715        InvalidCommand = 0x9999,
716    }
717
718    pub mod args {
719        use num_enum::TryFromPrimitive;
720
721        #[repr(u16)]
722        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
723        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
724        pub enum LedTestSequence {
725            Disable = 0x0000,
726            Enable = 0x0001,
727            ActivateLedShortTest = 0x0002,
728            ActivateLedOpenCircuitTest = 0x0003,
729        }
730
731        #[repr(u16)]
732        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
733        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
734        pub enum LedCycleKeypressTest {
735            Disable = 0x0000,
736            Enable = 0x0001,
737        }
738
739        #[repr(u16)]
740        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
741        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
742        pub enum HallEffectSensorTest {
743            DisableAll = 0x0000,
744            PassFailTestToggle = 0x0001,
745            LevelCheckToggle = 0x0002,
746            LevelCheckColumn1Toggle = 0x0011,
747            LevelCheckColumn2Toggle = 0x0012,
748            LevelCheckColumn3Toggle = 0x0013,
749            LevelCheckColumn4Toggle = 0x0014,
750            LevelCheckColumn5Toggle = 0x0015,
751            LevelCheckColumn6Toggle = 0x0016,
752            LevelCheckColumn7Toggle = 0x0017,
753            LevelCheckColumn8Toggle = 0x0018,
754            LevelCheckColumn9Toggle = 0x0019,
755            LevelCheckColumn10Toggle = 0x001A,
756            LevelCheckColumn11Toggle = 0x001B,
757            LevelCheckColumn12Toggle = 0x001C,
758            LevelCheckColumn13Toggle = 0x001D,
759            LevelCheckColumn14Toggle = 0x001E,
760            LevelCheckColumn15Toggle = 0x001F,
761            LevelCheckColumn16Toggle = 0x0020,
762            LevelCheckColumn17Toggle = 0x0021,
763            LevelCheckColumn18Toggle = 0x0022,
764            LevelCheckColumn19Toggle = 0x0023,
765            LevelCheckColumn20Toggle = 0x0024,
766            LevelCheckColumn21Toggle = 0x0025,
767            LevelCheckColumn22Toggle = 0x0026,
768            ModeSetNormal = 0x0100,
769            ModeSetLowLatency = 0x0101,
770            ModeSetTest = 0x0102,
771        }
772    }
773
774    #[derive(Clone, Copy)]
775    pub union Argument {
776        pub raw: u16,
777        pub led_test_sequence: args::LedTestSequence,
778        pub led_cycle_keypress_test: args::LedCycleKeypressTest,
779        pub hall_effect_sensor_test: args::HallEffectSensorTest,
780    }
781
782    impl core::fmt::Debug for Argument {
783        fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
784            write!(f, "{}", unsafe { self.raw })
785        }
786    }
787
788    #[cfg(feature = "defmt")]
789    impl defmt::Format for Argument {
790        fn format(&self, fmt: defmt::Formatter) {
791            defmt::write!(fmt, "{}", unsafe { self.raw })
792        }
793    }
794
795    #[derive(Clone, Debug)]
796    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
797    pub struct Cmd {
798        pub command: Command,
799        pub argument: Argument,
800    }
801
802    #[derive(Clone, Debug)]
803    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
804    pub struct Ack {}
805
806    #[derive(Clone, Debug)]
807    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
808    pub struct Nak {}
809}
810
811/// Manufacturing Test Result
812pub mod h0051 {
813    use heapless::Vec;
814    use num_enum::TryFromPrimitive;
815
816    #[repr(u16)]
817    #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
818    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
819    pub enum Command {
820        TestCommand = 0x0000,
821        LedTestSequence = 0x0001,
822        LedCycleKeypressTest = 0x0002,
823        HallEffectSensorTest = 0x0003,
824        InvalidCommand = 0x9999,
825    }
826
827    pub mod args {
828        use num_enum::TryFromPrimitive;
829
830        #[repr(u16)]
831        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
832        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
833        pub enum LedTestSequence {
834            LedShortTest = 0x0002,
835            LedOpenCircuitTest = 0x0003,
836        }
837
838        #[repr(u16)]
839        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
840        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
841        pub enum LedCycleKeypressTest {
842            Enable = 0x0001,
843        }
844
845        #[repr(u16)]
846        #[derive(PartialEq, Eq, Clone, Copy, Debug, TryFromPrimitive)]
847        #[cfg_attr(feature = "defmt", derive(defmt::Format))]
848        pub enum HallEffectSensorTest {
849            PassFailTest = 0x0001,
850            LevelCheck = 0x0002,
851        }
852    }
853
854    #[derive(Clone, Copy)]
855    pub union Argument {
856        pub raw: u16,
857        pub led_test_sequence: args::LedTestSequence,
858        pub led_cycle_keypress_test: args::LedCycleKeypressTest,
859        pub hall_effect_sensor_test: args::HallEffectSensorTest,
860    }
861
862    impl core::fmt::Debug for Argument {
863        fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
864            write!(f, "{}", unsafe { self.raw })
865        }
866    }
867
868    #[cfg(feature = "defmt")]
869    impl defmt::Format for Argument {
870        fn format(&self, fmt: defmt::Formatter) {
871            defmt::write!(fmt, "{}", unsafe { self.raw })
872        }
873    }
874
875    #[derive(Clone, Debug)]
876    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
877    pub struct Cmd<const D: usize> {
878        pub command: Command,
879        pub argument: Argument,
880        pub data: Vec<u8, D>,
881    }
882
883    #[derive(Clone, Debug)]
884    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
885    pub struct Ack {}
886
887    #[derive(Clone, Debug)]
888    #[cfg_attr(feature = "defmt", derive(defmt::Format))]
889    pub struct Nak {}
890}
891
892// ----- Traits -----
893
894/// HID-IO Command Interface
895/// H - Max data payload length (HidIoPacketBuffer)
896/// HSUB1, HSUB2, HSUB4 - Due to current limitations of const generics (missing
897/// const_evaluatable_checked), H - 1, H - 2 and H - 4 must be defined at the top-level.
898/// ID - Max number of HidIoCommandIds
899pub trait Commands<
900    const H: usize,
901    const HSUB1: usize,
902    const HSUB2: usize,
903    const HSUB4: usize,
904    const ID: usize,
905>
906{
907    /// Given a HidIoPacketBuffer serialize (and resulting send bytes)
908    fn tx_packetbuffer_send(&mut self, buf: &mut HidIoPacketBuffer<H>) -> Result<(), CommandError>;
909
910    /// Check if id is valid for this interface
911    /// (By default support all ids)
912    fn supported_id(&self, _id: HidIoCommandId) -> bool {
913        true
914    }
915
916    /// Default packet chunk
917    /// (Usual chunk sizes are 63 or 64)
918    fn default_packet_chunk(&self) -> u32 {
919        64
920    }
921
922    /// Simple empty ack
923    fn empty_ack(&mut self, id: HidIoCommandId) -> Result<(), CommandError> {
924        // Build empty Ack
925        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
926            // Data packet
927            ptype: HidIoPacketType::Ack,
928            // Packet id
929            id,
930            // Detect max size
931            max_len: self.default_packet_chunk(),
932            // Ready to go
933            done: true,
934            // Use defaults for other fields
935            ..Default::default()
936        })
937    }
938
939    /// Simple empty nak
940    fn empty_nak(&mut self, id: HidIoCommandId) -> Result<(), CommandError> {
941        // Build empty Nak
942        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
943            // Data packet
944            ptype: HidIoPacketType::Nak,
945            // Packet id
946            id,
947            // Detect max size
948            max_len: self.default_packet_chunk(),
949            // Ready to go
950            done: true,
951            // Use defaults for other fields
952            ..Default::default()
953        })
954    }
955
956    /// Simple byte ack
957    fn byte_ack(&mut self, id: HidIoCommandId, byte: u8) -> Result<(), CommandError> {
958        // Build Ack
959        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
960            // Data packet
961            ptype: HidIoPacketType::Ack,
962            // Packet id
963            id,
964            // Detect max size
965            max_len: self.default_packet_chunk(),
966            // Byte payload
967            data: Vec::from_slice(&[byte]).unwrap(),
968            // Ready to go
969            done: true,
970        })
971    }
972
973    /// Simple byte nak
974    fn byte_nak(&mut self, id: HidIoCommandId, byte: u8) -> Result<(), CommandError> {
975        // Build Nak
976        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
977            // Data packet
978            ptype: HidIoPacketType::Nak,
979            // Packet id
980            id,
981            // Detect max size
982            max_len: self.default_packet_chunk(),
983            // Byte payload
984            data: Vec::from_slice(&[byte]).unwrap(),
985            // Ready to go
986            done: true,
987        })
988    }
989
990    /// Simple short ack (16-bit)
991    fn short_ack(&mut self, id: HidIoCommandId, val: u16) -> Result<(), CommandError> {
992        // Build Ack
993        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
994            // Data packet
995            ptype: HidIoPacketType::Ack,
996            // Packet id
997            id,
998            // Detect max size
999            max_len: self.default_packet_chunk(),
1000            // Byte payload
1001            data: Vec::from_slice(&val.to_le_bytes()).unwrap(),
1002            // Ready to go
1003            done: true,
1004        })
1005    }
1006
1007    /// Simple short nak (16-bit)
1008    fn short_nak(&mut self, id: HidIoCommandId, val: u16) -> Result<(), CommandError> {
1009        // Build Nak
1010        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
1011            // Data packet
1012            ptype: HidIoPacketType::Nak,
1013            // Packet id
1014            id,
1015            // Detect max size
1016            max_len: self.default_packet_chunk(),
1017            // Byte payload
1018            data: Vec::from_slice(&val.to_le_bytes()).unwrap(),
1019            // Ready to go
1020            done: true,
1021        })
1022    }
1023
1024    /// Process specific packet types
1025    /// Handles matching to interface functions
1026    fn rx_message_handling(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1027        // Make sure we're processing a supported id
1028        if !self.supported_id(buf.id) {
1029            self.empty_nak(buf.id)?;
1030            return Err(CommandError::IdNotSupported(buf.id));
1031        }
1032
1033        // Check for invalid packet types
1034        match buf.ptype {
1035            HidIoPacketType::Data | HidIoPacketType::NaData => {}
1036            HidIoPacketType::Ack => {}
1037            HidIoPacketType::Nak => {}
1038            _ => {
1039                return Err(CommandError::InvalidRxMessage(buf.ptype));
1040            }
1041        }
1042
1043        // Match id
1044        trace!("rx_message_handling: {:?}", buf);
1045        match buf.id {
1046            HidIoCommandId::SupportedIds => self.h0000_supported_ids_handler(buf),
1047            HidIoCommandId::GetInfo => self.h0001_info_handler(buf),
1048            HidIoCommandId::TestPacket => self.h0002_test_handler(buf),
1049            HidIoCommandId::ResetHidIo => self.h0003_resethidio_handler(buf),
1050            HidIoCommandId::FlashMode => self.h0016_flashmode_handler(buf),
1051            HidIoCommandId::UnicodeText => self.h0017_unicodetext_handler(buf),
1052            HidIoCommandId::UnicodeState => self.h0018_unicodestate_handler(buf),
1053            HidIoCommandId::SleepMode => self.h001a_sleepmode_handler(buf),
1054            HidIoCommandId::PixelSetting => self.h0021_pixelsetting_handler(buf),
1055            HidIoCommandId::DirectSet => self.h0026_directset_handler(buf),
1056            HidIoCommandId::OpenUrl => self.h0030_openurl_handler(buf),
1057            HidIoCommandId::TerminalCmd => self.h0031_terminalcmd_handler(buf),
1058            HidIoCommandId::TerminalOut => self.h0034_terminalout_handler(buf),
1059            HidIoCommandId::ManufacturingTest => self.h0050_manufacturing_handler(buf),
1060            HidIoCommandId::ManufacturingResult => self.h0051_manufacturingres_handler(buf),
1061            _ => Err(CommandError::IdNotMatched(buf.id)),
1062        }
1063    }
1064
1065    fn h0000_supported_ids(&mut self, _data: h0000::Cmd) -> Result<(), CommandError> {
1066        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
1067            // Test packet id
1068            id: HidIoCommandId::SupportedIds,
1069            // Detect max size
1070            max_len: self.default_packet_chunk(),
1071            // Ready to go
1072            done: true,
1073            // Use defaults for other fields
1074            ..Default::default()
1075        })
1076    }
1077    fn h0000_supported_ids_cmd(&mut self, _data: h0000::Cmd) -> Result<h0000::Ack<ID>, h0000::Nak> {
1078        Err(h0000::Nak {})
1079    }
1080    fn h0000_supported_ids_ack(&mut self, _data: h0000::Ack<ID>) -> Result<(), CommandError> {
1081        Err(CommandError::IdNotImplemented(
1082            HidIoCommandId::SupportedIds,
1083            HidIoPacketType::Ack,
1084        ))
1085    }
1086    fn h0000_supported_ids_nak(&mut self, _data: h0000::Nak) -> Result<(), CommandError> {
1087        Err(CommandError::IdNotImplemented(
1088            HidIoCommandId::SupportedIds,
1089            HidIoPacketType::Nak,
1090        ))
1091    }
1092    fn h0000_supported_ids_handler(
1093        &mut self,
1094        buf: HidIoPacketBuffer<H>,
1095    ) -> Result<(), CommandError> {
1096        // Handle packet type
1097        match buf.ptype {
1098            HidIoPacketType::Data => {
1099                match self.h0000_supported_ids_cmd(h0000::Cmd {}) {
1100                    Ok(ack) => {
1101                        // Build Ack
1102                        let mut buf = HidIoPacketBuffer {
1103                            // Data packet
1104                            ptype: HidIoPacketType::Ack,
1105                            // Packet id
1106                            id: buf.id,
1107                            // Detect max size
1108                            max_len: self.default_packet_chunk(),
1109                            // Ready to go
1110                            done: true,
1111                            // Use defaults for other fields
1112                            ..Default::default()
1113                        };
1114
1115                        // Build list of ids
1116                        for id in ack.ids {
1117                            if buf
1118                                .data
1119                                .extend_from_slice(&(id as u16).to_le_bytes())
1120                                .is_err()
1121                            {
1122                                return Err(CommandError::IdVecTooSmall);
1123                            }
1124                        }
1125                        self.tx_packetbuffer_send(&mut buf)
1126                    }
1127                    Err(_nak) => self.empty_nak(buf.id),
1128                }
1129            }
1130            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
1131            HidIoPacketType::Ack => {
1132                // Retrieve list of ids
1133                let mut ids: Vec<HidIoCommandId, ID> = Vec::new();
1134                // Ids are always 16-bit le for this command
1135                let mut pos = 0;
1136                while pos <= buf.data.len() - 2 {
1137                    let slice = &buf.data[pos..pos + 2];
1138                    let idnum = u16::from_le_bytes(slice.try_into().unwrap()) as u32;
1139                    // Make sure this is a valid id
1140                    let id = match HidIoCommandId::try_from(idnum) {
1141                        Ok(id) => id,
1142                        Err(_) => {
1143                            return Err(CommandError::InvalidId(idnum));
1144                        }
1145                    };
1146                    // Attempt to push to id list
1147                    // NOTE: If the vector is not large enough
1148                    //       just truncate.
1149                    //       This command won't be called by devices
1150                    //       often.
1151                    // TODO: Add optional fields to request a range
1152                    if ids.push(id).is_err() {
1153                        break;
1154                    }
1155                    pos += 2;
1156                }
1157                self.h0000_supported_ids_ack(h0000::Ack { ids })
1158            }
1159            HidIoPacketType::Nak => self.h0000_supported_ids_nak(h0000::Nak {}),
1160            _ => Ok(()),
1161        }
1162    }
1163
1164    fn h0001_info(&mut self, data: h0001::Cmd) -> Result<(), CommandError> {
1165        // Create appropriately sized buffer
1166        let mut buf = HidIoPacketBuffer {
1167            // Test packet id
1168            id: HidIoCommandId::GetInfo,
1169            // Detect max size
1170            max_len: self.default_packet_chunk(),
1171            // Ready to go
1172            done: true,
1173            // Use defaults for other fields
1174            ..Default::default()
1175        };
1176
1177        // Encode property
1178        if buf.data.push(data.property as u8).is_err() {
1179            return Err(CommandError::DataVecTooSmall);
1180        }
1181        trace!("h0001_info: {:?} - {:?}", data, buf);
1182
1183        self.tx_packetbuffer_send(&mut buf)
1184    }
1185    fn h0001_info_cmd(&mut self, _data: h0001::Cmd) -> Result<h0001::Ack<HSUB1>, h0001::Nak> {
1186        Err(h0001::Nak {
1187            property: h0001::Property::Unknown,
1188        })
1189    }
1190    fn h0001_info_ack(&mut self, _data: h0001::Ack<HSUB1>) -> Result<(), CommandError> {
1191        Err(CommandError::IdNotImplemented(
1192            HidIoCommandId::GetInfo,
1193            HidIoPacketType::Ack,
1194        ))
1195    }
1196    fn h0001_info_nak(&mut self, _data: h0001::Nak) -> Result<(), CommandError> {
1197        Err(CommandError::IdNotImplemented(
1198            HidIoCommandId::GetInfo,
1199            HidIoPacketType::Nak,
1200        ))
1201    }
1202    fn h0001_info_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1203        // Handle packet type
1204        match buf.ptype {
1205            HidIoPacketType::Data => {
1206                if buf.data.is_empty() {
1207                    return Err(CommandError::DataVecNoData);
1208                }
1209                // Attempt to read first byte
1210                let property = match h0001::Property::try_from(buf.data[0]) {
1211                    Ok(property) => property,
1212                    Err(_) => {
1213                        return Err(CommandError::InvalidProperty8(buf.data[0]));
1214                    }
1215                };
1216                match self.h0001_info_cmd(h0001::Cmd { property }) {
1217                    Ok(ack) => {
1218                        // Build Ack
1219                        let mut buf = HidIoPacketBuffer {
1220                            // Data packet
1221                            ptype: HidIoPacketType::Ack,
1222                            // Packet id
1223                            id: buf.id,
1224                            // Detect max size
1225                            max_len: self.default_packet_chunk(),
1226                            // Ready to go
1227                            done: true,
1228                            // Use defaults for other fields
1229                            ..Default::default()
1230                        };
1231
1232                        // Set property
1233                        if buf.data.push(ack.property as u8).is_err() {
1234                            return Err(CommandError::DataVecTooSmall);
1235                        }
1236
1237                        // Depending on the property set the rest
1238                        // of the data field
1239                        match property {
1240                            h0001::Property::Unknown => {}
1241                            // Handle 16-bit number type
1242                            h0001::Property::MajorVersion
1243                            | h0001::Property::MinorVersion
1244                            | h0001::Property::PatchVersion => {
1245                                // Convert to byte le bytes
1246                                for byte in &ack.number.to_le_bytes() {
1247                                    if buf.data.push(*byte).is_err() {
1248                                        return Err(CommandError::DataVecTooSmall);
1249                                    }
1250                                }
1251                            }
1252                            // Handle 8-bit os type
1253                            h0001::Property::OsType => {
1254                                if buf.data.push(ack.os as u8).is_err() {
1255                                    return Err(CommandError::DataVecTooSmall);
1256                                }
1257                            }
1258                            // Handle ascii values
1259                            _ => {
1260                                for byte in ack.string.into_bytes() {
1261                                    if buf.data.push(byte).is_err() {
1262                                        return Err(CommandError::DataVecTooSmall);
1263                                    }
1264                                }
1265                            }
1266                        }
1267
1268                        self.tx_packetbuffer_send(&mut buf)
1269                    }
1270                    Err(_nak) => self.byte_nak(buf.id, property as u8),
1271                }
1272            }
1273            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
1274            HidIoPacketType::Ack => {
1275                if buf.data.is_empty() {
1276                    return Err(CommandError::DataVecNoData);
1277                }
1278                // Attempt to read first byte
1279                let property = match h0001::Property::try_from(buf.data[0]) {
1280                    Ok(property) => property,
1281                    Err(_) => {
1282                        return Err(CommandError::InvalidProperty8(buf.data[0]));
1283                    }
1284                };
1285
1286                // Setup ack struct
1287                let mut ack = h0001::Ack {
1288                    property,
1289                    os: h0001::OsType::Unknown,
1290                    number: 0,
1291                    string: String::new(),
1292                };
1293
1294                // Depending on the property set the rest
1295                // of the ack fields
1296                match property {
1297                    h0001::Property::Unknown => {}
1298                    // Handle 16-bit number type
1299                    h0001::Property::MajorVersion
1300                    | h0001::Property::MinorVersion
1301                    | h0001::Property::PatchVersion => {
1302                        // Convert from le bytes
1303                        ack.number = u16::from_le_bytes(buf.data[1..3].try_into().unwrap());
1304                    }
1305                    // Handle 8-bit os type
1306                    h0001::Property::OsType => {
1307                        let typenum = buf.data[1];
1308                        ack.os = match h0001::OsType::try_from(typenum) {
1309                            Ok(ostype) => ostype,
1310                            Err(_) => {
1311                                return Err(CommandError::InvalidProperty8(typenum));
1312                            }
1313                        };
1314                    }
1315                    // Handle ascii values
1316                    _ => {
1317                        ack.string
1318                            .push_str(match core::str::from_utf8(&buf.data[1..]) {
1319                                Ok(s) => s,
1320                                Err(e) => {
1321                                    return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
1322                                }
1323                            })
1324                            .unwrap();
1325                    }
1326                }
1327
1328                self.h0001_info_ack(ack)
1329            }
1330            HidIoPacketType::Nak => {
1331                if buf.data.is_empty() {
1332                    return Err(CommandError::DataVecNoData);
1333                }
1334                // Attempt to read first byte
1335                let property = match h0001::Property::try_from(buf.data[0]) {
1336                    Ok(property) => property,
1337                    Err(_) => {
1338                        return Err(CommandError::InvalidProperty8(buf.data[0]));
1339                    }
1340                };
1341                self.h0001_info_nak(h0001::Nak { property })
1342            }
1343            _ => Ok(()),
1344        }
1345    }
1346
1347    fn h0002_test(&mut self, data: h0002::Cmd<H>, na: bool) -> Result<(), CommandError> {
1348        // Create appropriately sized buffer
1349        let mut buf = HidIoPacketBuffer {
1350            // Test packet id
1351            id: HidIoCommandId::TestPacket,
1352            // Detect max size
1353            max_len: self.default_packet_chunk(),
1354            // Use defaults for other fields
1355            ..Default::default()
1356        };
1357
1358        // Set NA (no-ack)
1359        if na {
1360            buf.ptype = HidIoPacketType::NaData;
1361        }
1362
1363        // Build payload
1364        if !buf.append_payload(&data.data) {
1365            return Err(CommandError::DataVecTooSmall);
1366        }
1367        buf.done = true;
1368
1369        self.tx_packetbuffer_send(&mut buf)
1370    }
1371    fn h0002_test_cmd(&mut self, _data: h0002::Cmd<H>) -> Result<h0002::Ack<H>, h0002::Nak> {
1372        Err(h0002::Nak {})
1373    }
1374    fn h0002_test_nacmd(&mut self, _data: h0002::Cmd<H>) -> Result<(), CommandError> {
1375        Err(CommandError::IdNotImplemented(
1376            HidIoCommandId::TestPacket,
1377            HidIoPacketType::NaData,
1378        ))
1379    }
1380    fn h0002_test_ack(&mut self, _data: h0002::Ack<H>) -> Result<(), CommandError> {
1381        Err(CommandError::IdNotImplemented(
1382            HidIoCommandId::TestPacket,
1383            HidIoPacketType::Ack,
1384        ))
1385    }
1386    fn h0002_test_nak(&mut self, _data: h0002::Nak) -> Result<(), CommandError> {
1387        Err(CommandError::IdNotImplemented(
1388            HidIoCommandId::TestPacket,
1389            HidIoPacketType::Nak,
1390        ))
1391    }
1392    fn h0002_test_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1393        // Handle packet type
1394        match buf.ptype {
1395            HidIoPacketType::Data => {
1396                // Copy data into struct
1397                let cmd = h0002::Cmd::<H> {
1398                    data: match Vec::from_slice(&buf.data) {
1399                        Ok(data) => data,
1400                        Err(_) => {
1401                            return Err(CommandError::DataVecTooSmall);
1402                        }
1403                    },
1404                };
1405
1406                match self.h0002_test_cmd(cmd) {
1407                    Ok(ack) => {
1408                        // Build Ack (max test data size)
1409                        let mut buf = HidIoPacketBuffer {
1410                            // Data packet
1411                            ptype: HidIoPacketType::Ack,
1412                            // Packet id
1413                            id: buf.id,
1414                            // Detect max size
1415                            max_len: self.default_packet_chunk(),
1416                            ..Default::default()
1417                        };
1418
1419                        // Copy data into buffer
1420                        if !buf.append_payload(&ack.data) {
1421                            return Err(CommandError::DataVecTooSmall);
1422                        }
1423                        buf.done = true;
1424                        self.tx_packetbuffer_send(&mut buf)
1425                    }
1426                    Err(_nak) => self.empty_nak(buf.id),
1427                }
1428            }
1429            HidIoPacketType::NaData => {
1430                // Copy data into struct
1431                let cmd = h0002::Cmd::<H> {
1432                    data: match Vec::from_slice(&buf.data) {
1433                        Ok(data) => data,
1434                        Err(_) => {
1435                            return Err(CommandError::DataVecTooSmall);
1436                        }
1437                    },
1438                };
1439
1440                self.h0002_test_nacmd(cmd)
1441            }
1442            HidIoPacketType::Ack => {
1443                // Copy data into struct
1444                let ack = h0002::Ack::<H> {
1445                    data: match Vec::from_slice(&buf.data) {
1446                        Ok(data) => data,
1447                        Err(_) => {
1448                            return Err(CommandError::DataVecTooSmall);
1449                        }
1450                    },
1451                };
1452
1453                self.h0002_test_ack(ack)
1454            }
1455            HidIoPacketType::Nak => self.h0002_test_nak(h0002::Nak {}),
1456            _ => Ok(()),
1457        }
1458    }
1459
1460    fn h0003_resethidio(&mut self, _data: h0003::Cmd) -> Result<(), CommandError> {
1461        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
1462            // Test packet id
1463            id: HidIoCommandId::ResetHidIo,
1464            // Detect max size
1465            max_len: self.default_packet_chunk(),
1466            // Ready
1467            done: true,
1468            // Use defaults for other fields
1469            ..Default::default()
1470        })
1471    }
1472    fn h0003_resethidio_cmd(&mut self, _data: h0003::Cmd) -> Result<h0003::Ack, h0003::Nak> {
1473        Err(h0003::Nak {})
1474    }
1475    fn h0003_resethidio_ack(&mut self, _data: h0003::Ack) -> Result<(), CommandError> {
1476        Err(CommandError::IdNotImplemented(
1477            HidIoCommandId::ResetHidIo,
1478            HidIoPacketType::Ack,
1479        ))
1480    }
1481    fn h0003_resethidio_nak(&mut self, _data: h0003::Nak) -> Result<(), CommandError> {
1482        Err(CommandError::IdNotImplemented(
1483            HidIoCommandId::ResetHidIo,
1484            HidIoPacketType::Nak,
1485        ))
1486    }
1487    fn h0003_resethidio_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1488        // Handle packet type
1489        match buf.ptype {
1490            HidIoPacketType::Data => match self.h0003_resethidio_cmd(h0003::Cmd {}) {
1491                Ok(_ack) => self.empty_ack(buf.id),
1492                Err(_nak) => self.empty_nak(buf.id),
1493            },
1494            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
1495            HidIoPacketType::Ack => self.h0003_resethidio_ack(h0003::Ack {}),
1496            HidIoPacketType::Nak => self.h0003_resethidio_nak(h0003::Nak {}),
1497            _ => Ok(()),
1498        }
1499    }
1500
1501    fn h0016_flashmode(&mut self, _data: h0016::Cmd) -> Result<(), CommandError> {
1502        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
1503            // Test packet id
1504            id: HidIoCommandId::FlashMode,
1505            // Detect max size
1506            max_len: self.default_packet_chunk(),
1507            // Ready
1508            done: true,
1509            // Use defaults for other fields
1510            ..Default::default()
1511        })
1512    }
1513    fn h0016_flashmode_cmd(&mut self, _data: h0016::Cmd) -> Result<h0016::Ack, h0016::Nak> {
1514        Err(h0016::Nak {
1515            error: h0016::Error::NotSupported,
1516        })
1517    }
1518    fn h0016_flashmode_ack(&mut self, _data: h0016::Ack) -> Result<(), CommandError> {
1519        Err(CommandError::IdNotImplemented(
1520            HidIoCommandId::FlashMode,
1521            HidIoPacketType::Ack,
1522        ))
1523    }
1524    fn h0016_flashmode_nak(&mut self, _data: h0016::Nak) -> Result<(), CommandError> {
1525        Err(CommandError::IdNotImplemented(
1526            HidIoCommandId::FlashMode,
1527            HidIoPacketType::Nak,
1528        ))
1529    }
1530    fn h0016_flashmode_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1531        // Handle packet type
1532        match buf.ptype {
1533            HidIoPacketType::Data => match self.h0016_flashmode_cmd(h0016::Cmd {}) {
1534                Ok(ack) => self.short_ack(buf.id, ack.scancode),
1535                Err(nak) => self.byte_nak(buf.id, nak.error as u8),
1536            },
1537            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
1538            HidIoPacketType::Ack => {
1539                if buf.data.len() < 2 {
1540                    return Err(CommandError::DataVecNoData);
1541                }
1542
1543                let scancode = u16::from_le_bytes(buf.data[0..2].try_into().unwrap());
1544                self.h0016_flashmode_ack(h0016::Ack { scancode })
1545            }
1546            HidIoPacketType::Nak => {
1547                if buf.data.is_empty() {
1548                    return Err(CommandError::DataVecNoData);
1549                }
1550
1551                let error = match h0016::Error::try_from(buf.data[0]) {
1552                    Ok(error) => error,
1553                    Err(_) => {
1554                        return Err(CommandError::InvalidProperty8(buf.data[0]));
1555                    }
1556                };
1557                self.h0016_flashmode_nak(h0016::Nak { error })
1558            }
1559            _ => Ok(()),
1560        }
1561    }
1562
1563    fn h0017_unicodetext(&mut self, data: h0017::Cmd<H>, na: bool) -> Result<(), CommandError> {
1564        // Create appropriately sized buffer
1565        let mut buf = HidIoPacketBuffer {
1566            // Test packet id
1567            id: HidIoCommandId::UnicodeText,
1568            // Detect max size
1569            max_len: self.default_packet_chunk(),
1570            // Use defaults for other fields
1571            ..Default::default()
1572        };
1573
1574        // Set NA (no-ack)
1575        if na {
1576            buf.ptype = HidIoPacketType::NaData;
1577        }
1578
1579        // Build payload
1580        if !buf.append_payload(data.string.as_bytes()) {
1581            return Err(CommandError::DataVecTooSmall);
1582        }
1583        buf.done = true;
1584
1585        self.tx_packetbuffer_send(&mut buf)
1586    }
1587    fn h0017_unicodetext_cmd(&mut self, _data: h0017::Cmd<H>) -> Result<h0017::Ack, h0017::Nak> {
1588        Err(h0017::Nak {})
1589    }
1590    fn h0017_unicodetext_nacmd(&mut self, _data: h0017::Cmd<H>) -> Result<(), CommandError> {
1591        Err(CommandError::IdNotImplemented(
1592            HidIoCommandId::UnicodeText,
1593            HidIoPacketType::NaData,
1594        ))
1595    }
1596    fn h0017_unicodetext_ack(&mut self, _data: h0017::Ack) -> Result<(), CommandError> {
1597        Err(CommandError::IdNotImplemented(
1598            HidIoCommandId::UnicodeText,
1599            HidIoPacketType::Ack,
1600        ))
1601    }
1602    fn h0017_unicodetext_nak(&mut self, _data: h0017::Nak) -> Result<(), CommandError> {
1603        Err(CommandError::IdNotImplemented(
1604            HidIoCommandId::UnicodeText,
1605            HidIoPacketType::Nak,
1606        ))
1607    }
1608    fn h0017_unicodetext_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1609        // Handle packet type
1610        match buf.ptype {
1611            HidIoPacketType::Data => {
1612                // Copy data into struct
1613                let mut cmd = h0017::Cmd::<H> {
1614                    string: String::new(),
1615                };
1616                cmd.string
1617                    .push_str(match core::str::from_utf8(&buf.data) {
1618                        Ok(string) => string,
1619                        Err(e) => {
1620                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
1621                        }
1622                    })
1623                    .unwrap();
1624
1625                match self.h0017_unicodetext_cmd(cmd) {
1626                    Ok(_ack) => self.empty_ack(buf.id),
1627                    Err(_nak) => self.empty_nak(buf.id),
1628                }
1629            }
1630            HidIoPacketType::NaData => {
1631                // Copy data into struct
1632                let mut cmd = h0017::Cmd::<H> {
1633                    string: String::new(),
1634                };
1635                cmd.string
1636                    .push_str(match core::str::from_utf8(&buf.data) {
1637                        Ok(string) => string,
1638                        Err(e) => {
1639                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
1640                        }
1641                    })
1642                    .unwrap();
1643
1644                self.h0017_unicodetext_nacmd(cmd)
1645            }
1646            HidIoPacketType::Ack => self.h0017_unicodetext_ack(h0017::Ack {}),
1647            HidIoPacketType::Nak => self.h0017_unicodetext_nak(h0017::Nak {}),
1648            _ => Ok(()),
1649        }
1650    }
1651
1652    fn h0018_unicodestate(&mut self, data: h0018::Cmd<H>, na: bool) -> Result<(), CommandError> {
1653        // Create appropriately sized buffer
1654        let mut buf = HidIoPacketBuffer {
1655            // Test packet id
1656            id: HidIoCommandId::UnicodeState,
1657            // Detect max size
1658            max_len: self.default_packet_chunk(),
1659            // Use defaults for other fields
1660            ..Default::default()
1661        };
1662
1663        // Set NA (no-ack)
1664        if na {
1665            buf.ptype = HidIoPacketType::NaData;
1666        }
1667
1668        // Build payload
1669        if !buf.append_payload(data.symbols.as_bytes()) {
1670            return Err(CommandError::DataVecTooSmall);
1671        }
1672        buf.done = true;
1673
1674        self.tx_packetbuffer_send(&mut buf)
1675    }
1676    fn h0018_unicodestate_cmd(&mut self, _data: h0018::Cmd<H>) -> Result<h0018::Ack, h0018::Nak> {
1677        Err(h0018::Nak {})
1678    }
1679    fn h0018_unicodestate_nacmd(&mut self, _data: h0018::Cmd<H>) -> Result<(), CommandError> {
1680        Err(CommandError::IdNotImplemented(
1681            HidIoCommandId::UnicodeState,
1682            HidIoPacketType::NaData,
1683        ))
1684    }
1685    fn h0018_unicodestate_ack(&mut self, _data: h0018::Ack) -> Result<(), CommandError> {
1686        Err(CommandError::IdNotImplemented(
1687            HidIoCommandId::UnicodeState,
1688            HidIoPacketType::Ack,
1689        ))
1690    }
1691    fn h0018_unicodestate_nak(&mut self, _data: h0018::Nak) -> Result<(), CommandError> {
1692        Err(CommandError::IdNotImplemented(
1693            HidIoCommandId::UnicodeState,
1694            HidIoPacketType::Nak,
1695        ))
1696    }
1697    fn h0018_unicodestate_handler(
1698        &mut self,
1699        buf: HidIoPacketBuffer<H>,
1700    ) -> Result<(), CommandError> {
1701        // Handle packet type
1702        match buf.ptype {
1703            HidIoPacketType::Data => {
1704                // Copy data into struct
1705                let mut cmd = h0018::Cmd::<H> {
1706                    symbols: String::new(),
1707                };
1708                cmd.symbols
1709                    .push_str(match core::str::from_utf8(&buf.data) {
1710                        Ok(symbols) => symbols,
1711                        Err(e) => {
1712                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
1713                        }
1714                    })
1715                    .unwrap();
1716
1717                match self.h0018_unicodestate_cmd(cmd) {
1718                    Ok(_ack) => self.empty_ack(buf.id),
1719                    Err(_nak) => self.empty_nak(buf.id),
1720                }
1721            }
1722            HidIoPacketType::NaData => {
1723                // Copy data into struct
1724                let mut cmd = h0018::Cmd::<H> {
1725                    symbols: String::new(),
1726                };
1727                cmd.symbols
1728                    .push_str(match core::str::from_utf8(&buf.data) {
1729                        Ok(symbols) => symbols,
1730                        Err(e) => {
1731                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
1732                        }
1733                    })
1734                    .unwrap();
1735
1736                self.h0018_unicodestate_nacmd(cmd)
1737            }
1738            HidIoPacketType::Ack => self.h0018_unicodestate_ack(h0018::Ack {}),
1739            HidIoPacketType::Nak => self.h0018_unicodestate_nak(h0018::Nak {}),
1740            _ => Ok(()),
1741        }
1742    }
1743
1744    fn h001a_sleepmode(&mut self, _data: h001a::Cmd) -> Result<(), CommandError> {
1745        self.tx_packetbuffer_send(&mut HidIoPacketBuffer {
1746            // Test packet id
1747            id: HidIoCommandId::SleepMode,
1748            // Detect max size
1749            max_len: self.default_packet_chunk(),
1750            // Ready
1751            done: true,
1752            // Use defaults for other fields
1753            ..Default::default()
1754        })
1755    }
1756    fn h001a_sleepmode_cmd(&mut self, _data: h001a::Cmd) -> Result<h001a::Ack, h001a::Nak> {
1757        Err(h001a::Nak {
1758            error: h001a::Error::NotSupported,
1759        })
1760    }
1761    fn h001a_sleepmode_ack(&mut self, _data: h001a::Ack) -> Result<(), CommandError> {
1762        Err(CommandError::IdNotImplemented(
1763            HidIoCommandId::SleepMode,
1764            HidIoPacketType::Ack,
1765        ))
1766    }
1767    fn h001a_sleepmode_nak(&mut self, _data: h001a::Nak) -> Result<(), CommandError> {
1768        Err(CommandError::IdNotImplemented(
1769            HidIoCommandId::SleepMode,
1770            HidIoPacketType::Nak,
1771        ))
1772    }
1773    fn h001a_sleepmode_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1774        // Handle packet type
1775        match buf.ptype {
1776            HidIoPacketType::Data => match self.h001a_sleepmode_cmd(h001a::Cmd {}) {
1777                Ok(_ack) => self.empty_ack(buf.id),
1778                Err(nak) => self.byte_nak(buf.id, nak.error as u8),
1779            },
1780            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
1781            HidIoPacketType::Ack => self.h001a_sleepmode_ack(h001a::Ack {}),
1782            HidIoPacketType::Nak => {
1783                if buf.data.is_empty() {
1784                    return Err(CommandError::DataVecNoData);
1785                }
1786
1787                let error = match h001a::Error::try_from(buf.data[0]) {
1788                    Ok(error) => error,
1789                    Err(_) => {
1790                        return Err(CommandError::InvalidProperty8(buf.data[0]));
1791                    }
1792                };
1793                self.h001a_sleepmode_nak(h001a::Nak { error })
1794            }
1795            _ => Ok(()),
1796        }
1797    }
1798
1799    fn h0020_klltrigger(&mut self, data: h0020::Cmd, na: bool) -> Result<(), CommandError> {
1800        // Create appropriately sized buffer
1801        let mut buf = HidIoPacketBuffer {
1802            // KllState id
1803            id: HidIoCommandId::KllState,
1804            // Detect max size
1805            max_len: self.default_packet_chunk(),
1806            // Use defaults for other fields
1807            ..Default::default()
1808        };
1809
1810        // Set NA (no-ack)
1811        if na {
1812            buf.ptype = HidIoPacketType::NaData;
1813        }
1814
1815        // Build payload
1816        if !buf.append_payload(unsafe { data.event.bytes() }) {
1817            return Err(CommandError::DataVecTooSmall);
1818        }
1819        buf.done = true;
1820
1821        self.tx_packetbuffer_send(&mut buf)
1822    }
1823    fn h0020_klltrigger_cmd(&mut self, _data: h0020::Cmd) -> Result<h0020::Ack, h0020::Nak> {
1824        Err(h0020::Nak {})
1825    }
1826    fn h0020_klltrigger_nacmd(&mut self, _data: h0020::Cmd) -> Result<(), CommandError> {
1827        Err(CommandError::IdNotImplemented(
1828            HidIoCommandId::KllState,
1829            HidIoPacketType::NaData,
1830        ))
1831    }
1832    fn h0020_klltrigger_ack(&mut self, _data: h0020::Ack) -> Result<(), CommandError> {
1833        Err(CommandError::IdNotImplemented(
1834            HidIoCommandId::KllState,
1835            HidIoPacketType::Ack,
1836        ))
1837    }
1838    fn h0020_klltrigger_nak(&mut self, _data: h0020::Nak) -> Result<(), CommandError> {
1839        Err(CommandError::IdNotImplemented(
1840            HidIoCommandId::KllState,
1841            HidIoPacketType::Nak,
1842        ))
1843    }
1844    fn h0020_klltrigger_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
1845        // Handle packet type
1846        match buf.ptype {
1847            HidIoPacketType::Data => {
1848                // Copy data into struct
1849                let cmd = h0020::Cmd {
1850                    event: unsafe { kll_core::TriggerEvent::from_bytes(&buf.data) },
1851                };
1852
1853                match self.h0020_klltrigger_cmd(cmd) {
1854                    Ok(_ack) => self.empty_ack(buf.id),
1855                    Err(_nak) => self.empty_nak(buf.id),
1856                }
1857            }
1858            HidIoPacketType::NaData => {
1859                // Copy data into struct
1860                let cmd = h0020::Cmd {
1861                    event: unsafe { kll_core::TriggerEvent::from_bytes(&buf.data) },
1862                };
1863
1864                self.h0020_klltrigger_nacmd(cmd)
1865            }
1866            HidIoPacketType::Ack => self.h0020_klltrigger_ack(h0020::Ack {}),
1867            HidIoPacketType::Nak => self.h0020_klltrigger_nak(h0020::Nak {}),
1868            _ => Ok(()),
1869        }
1870    }
1871
1872    fn h0021_pixelsetting(&mut self, data: h0021::Cmd, na: bool) -> Result<(), CommandError> {
1873        // Create appropriately sized buffer
1874        let mut buf = HidIoPacketBuffer {
1875            // KllState id
1876            id: HidIoCommandId::PixelSetting,
1877            // Detect max size
1878            max_len: self.default_packet_chunk(),
1879            // Use defaults for other fields
1880            ..Default::default()
1881        };
1882
1883        // Set NA (no-ack)
1884        if na {
1885            buf.ptype = HidIoPacketType::NaData;
1886        }
1887
1888        // Build payload
1889        if !buf.append_payload(&(data.command as u16).to_le_bytes()) {
1890            return Err(CommandError::DataVecTooSmall);
1891        }
1892        if !buf.append_payload(unsafe { &data.argument.raw.to_le_bytes() }) {
1893            return Err(CommandError::DataVecTooSmall);
1894        }
1895        buf.done = true;
1896
1897        self.tx_packetbuffer_send(&mut buf)
1898    }
1899    fn h0021_pixelsetting_cmd(&mut self, _data: h0021::Cmd) -> Result<h0021::Ack, h0021::Nak> {
1900        Err(h0021::Nak {})
1901    }
1902    fn h0021_pixelsetting_nacmd(&mut self, _data: h0021::Cmd) -> Result<(), CommandError> {
1903        Err(CommandError::IdNotImplemented(
1904            HidIoCommandId::PixelSetting,
1905            HidIoPacketType::NaData,
1906        ))
1907    }
1908    fn h0021_pixelsetting_ack(&mut self, _data: h0021::Ack) -> Result<(), CommandError> {
1909        Err(CommandError::IdNotImplemented(
1910            HidIoCommandId::PixelSetting,
1911            HidIoPacketType::Ack,
1912        ))
1913    }
1914    fn h0021_pixelsetting_nak(&mut self, _data: h0021::Nak) -> Result<(), CommandError> {
1915        Err(CommandError::IdNotImplemented(
1916            HidIoCommandId::PixelSetting,
1917            HidIoPacketType::Nak,
1918        ))
1919    }
1920    fn h0021_pixelsetting_handler(
1921        &mut self,
1922        buf: HidIoPacketBuffer<H>,
1923    ) -> Result<(), CommandError> {
1924        // Handle packet type
1925        match buf.ptype {
1926            HidIoPacketType::Data => {
1927                // Copy data into struct
1928                let cmd = h0021::Cmd {
1929                    command: h0021::Command::try_from(u16::from_le_bytes(
1930                        buf.data[0..2].try_into().unwrap(),
1931                    ))
1932                    .unwrap(),
1933                    argument: h0021::Argument {
1934                        raw: u16::from_le_bytes(buf.data[2..4].try_into().unwrap()),
1935                    },
1936                };
1937
1938                match self.h0021_pixelsetting_cmd(cmd) {
1939                    Ok(_ack) => self.empty_ack(buf.id),
1940                    Err(_nak) => self.empty_nak(buf.id),
1941                }
1942            }
1943            HidIoPacketType::NaData => {
1944                // Copy data into struct
1945                let cmd = h0021::Cmd {
1946                    command: h0021::Command::try_from(u16::from_le_bytes(
1947                        buf.data[0..2].try_into().unwrap(),
1948                    ))
1949                    .unwrap(),
1950                    argument: h0021::Argument {
1951                        raw: u16::from_le_bytes(buf.data[2..4].try_into().unwrap()),
1952                    },
1953                };
1954
1955                self.h0021_pixelsetting_nacmd(cmd)
1956            }
1957            HidIoPacketType::Ack => self.h0021_pixelsetting_ack(h0021::Ack {}),
1958            HidIoPacketType::Nak => self.h0021_pixelsetting_nak(h0021::Nak {}),
1959            _ => Ok(()),
1960        }
1961    }
1962
1963    fn h0026_directset(&mut self, data: h0026::Cmd<HSUB2>, na: bool) -> Result<(), CommandError> {
1964        // Create appropriately sized buffer
1965        let mut buf = HidIoPacketBuffer {
1966            // KllState id
1967            id: HidIoCommandId::DirectSet,
1968            // Detect max size
1969            max_len: self.default_packet_chunk(),
1970            // Use defaults for other fields
1971            ..Default::default()
1972        };
1973
1974        // Set NA (no-ack)
1975        if na {
1976            buf.ptype = HidIoPacketType::NaData;
1977        }
1978
1979        // Build payload
1980        if !buf.append_payload(&data.start_address.to_le_bytes()) {
1981            return Err(CommandError::DataVecTooSmall);
1982        }
1983        if !buf.append_payload(&data.data) {
1984            return Err(CommandError::DataVecTooSmall);
1985        }
1986        buf.done = true;
1987
1988        self.tx_packetbuffer_send(&mut buf)
1989    }
1990    fn h0026_directset_cmd(&mut self, _data: h0026::Cmd<HSUB2>) -> Result<h0026::Ack, h0026::Nak> {
1991        Err(h0026::Nak {})
1992    }
1993    fn h0026_directset_nacmd(&mut self, _data: h0026::Cmd<HSUB2>) -> Result<(), CommandError> {
1994        Err(CommandError::IdNotImplemented(
1995            HidIoCommandId::DirectSet,
1996            HidIoPacketType::NaData,
1997        ))
1998    }
1999    fn h0026_directset_ack(&mut self, _data: h0026::Ack) -> Result<(), CommandError> {
2000        Err(CommandError::IdNotImplemented(
2001            HidIoCommandId::DirectSet,
2002            HidIoPacketType::Ack,
2003        ))
2004    }
2005    fn h0026_directset_nak(&mut self, _data: h0026::Nak) -> Result<(), CommandError> {
2006        Err(CommandError::IdNotImplemented(
2007            HidIoCommandId::DirectSet,
2008            HidIoPacketType::Nak,
2009        ))
2010    }
2011    fn h0026_directset_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
2012        // Handle packet type
2013        match buf.ptype {
2014            HidIoPacketType::Data => {
2015                // Copy data into struct
2016                let cmd = h0026::Cmd::<HSUB2> {
2017                    start_address: u16::from_le_bytes([buf.data[0], buf.data[1]]),
2018                    data: match Vec::from_slice(&buf.data[2..buf.data.len()]) {
2019                        Ok(data) => data,
2020                        Err(_) => {
2021                            return Err(CommandError::DataVecTooSmall);
2022                        }
2023                    },
2024                };
2025
2026                match self.h0026_directset_cmd(cmd) {
2027                    Ok(_ack) => self.empty_ack(buf.id),
2028                    Err(_nak) => self.empty_nak(buf.id),
2029                }
2030            }
2031            HidIoPacketType::NaData => {
2032                // Copy data into struct
2033                let cmd = h0026::Cmd::<HSUB2> {
2034                    start_address: u16::from_le_bytes([buf.data[0], buf.data[1]]),
2035                    data: match Vec::from_slice(&buf.data[2..buf.data.len()]) {
2036                        Ok(data) => data,
2037                        Err(_) => {
2038                            return Err(CommandError::DataVecTooSmall);
2039                        }
2040                    },
2041                };
2042
2043                self.h0026_directset_nacmd(cmd)
2044            }
2045            HidIoPacketType::Ack => self.h0026_directset_ack(h0026::Ack {}),
2046            HidIoPacketType::Nak => self.h0026_directset_nak(h0026::Nak {}),
2047            _ => Ok(()),
2048        }
2049    }
2050
2051    fn h0030_openurl(&mut self, data: h0030::Cmd<H>) -> Result<(), CommandError> {
2052        // Create appropriately sized buffer
2053        let mut buf = HidIoPacketBuffer {
2054            // Test packet id
2055            id: HidIoCommandId::OpenUrl,
2056            // Detect max size
2057            max_len: self.default_packet_chunk(),
2058            // Use defaults for other fields
2059            ..Default::default()
2060        };
2061
2062        // Build payload
2063        if !buf.append_payload(data.url.as_bytes()) {
2064            return Err(CommandError::DataVecTooSmall);
2065        }
2066        buf.done = true;
2067
2068        self.tx_packetbuffer_send(&mut buf)
2069    }
2070    fn h0030_openurl_cmd(&mut self, _data: h0030::Cmd<H>) -> Result<h0030::Ack, h0030::Nak> {
2071        Err(h0030::Nak {})
2072    }
2073    fn h0030_openurl_nacmd(&mut self, _data: h0030::Cmd<H>) -> Result<(), CommandError> {
2074        Err(CommandError::IdNotImplemented(
2075            HidIoCommandId::OpenUrl,
2076            HidIoPacketType::NaData,
2077        ))
2078    }
2079    fn h0030_openurl_ack(&mut self, _data: h0030::Ack) -> Result<(), CommandError> {
2080        Err(CommandError::IdNotImplemented(
2081            HidIoCommandId::OpenUrl,
2082            HidIoPacketType::Ack,
2083        ))
2084    }
2085    fn h0030_openurl_nak(&mut self, _data: h0030::Nak) -> Result<(), CommandError> {
2086        Err(CommandError::IdNotImplemented(
2087            HidIoCommandId::OpenUrl,
2088            HidIoPacketType::Nak,
2089        ))
2090    }
2091    fn h0030_openurl_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
2092        // Handle packet type
2093        match buf.ptype {
2094            HidIoPacketType::Data => {
2095                // Copy data into struct
2096                let mut cmd = h0030::Cmd::<H> { url: String::new() };
2097                cmd.url
2098                    .push_str(match core::str::from_utf8(&buf.data) {
2099                        Ok(url) => url,
2100                        Err(e) => {
2101                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
2102                        }
2103                    })
2104                    .unwrap();
2105
2106                match self.h0030_openurl_cmd(cmd) {
2107                    Ok(_ack) => self.empty_ack(buf.id),
2108                    Err(_nak) => self.empty_nak(buf.id),
2109                }
2110            }
2111            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
2112            HidIoPacketType::Ack => self.h0030_openurl_ack(h0030::Ack {}),
2113            HidIoPacketType::Nak => self.h0030_openurl_nak(h0030::Nak {}),
2114            _ => Ok(()),
2115        }
2116    }
2117
2118    fn h0031_terminalcmd(&mut self, data: h0031::Cmd<H>, na: bool) -> Result<(), CommandError> {
2119        // Create appropriately sized buffer
2120        let mut buf = HidIoPacketBuffer {
2121            // Test packet id
2122            id: HidIoCommandId::TerminalCmd,
2123            // Detect max size
2124            max_len: self.default_packet_chunk(),
2125            // Use defaults for other fields
2126            ..Default::default()
2127        };
2128
2129        // Set NA (no-ack)
2130        if na {
2131            buf.ptype = HidIoPacketType::NaData;
2132        }
2133
2134        // Build payload
2135        if !buf.append_payload(data.command.as_bytes()) {
2136            return Err(CommandError::DataVecTooSmall);
2137        }
2138        buf.done = true;
2139
2140        self.tx_packetbuffer_send(&mut buf)
2141    }
2142    fn h0031_terminalcmd_cmd(&mut self, _data: h0031::Cmd<H>) -> Result<h0031::Ack, h0031::Nak> {
2143        Err(h0031::Nak {})
2144    }
2145    fn h0031_terminalcmd_nacmd(&mut self, _data: h0031::Cmd<H>) -> Result<(), CommandError> {
2146        Err(CommandError::IdNotImplemented(
2147            HidIoCommandId::TerminalCmd,
2148            HidIoPacketType::NaData,
2149        ))
2150    }
2151    fn h0031_terminalcmd_ack(&mut self, _data: h0031::Ack) -> Result<(), CommandError> {
2152        Err(CommandError::IdNotImplemented(
2153            HidIoCommandId::TerminalCmd,
2154            HidIoPacketType::Ack,
2155        ))
2156    }
2157    fn h0031_terminalcmd_nak(&mut self, _data: h0031::Nak) -> Result<(), CommandError> {
2158        Err(CommandError::IdNotImplemented(
2159            HidIoCommandId::TerminalCmd,
2160            HidIoPacketType::Nak,
2161        ))
2162    }
2163    fn h0031_terminalcmd_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
2164        // Handle packet type
2165        match buf.ptype {
2166            HidIoPacketType::Data => {
2167                // Copy data into struct
2168                let mut cmd = h0031::Cmd::<H> {
2169                    command: String::new(),
2170                };
2171                cmd.command
2172                    .push_str(match core::str::from_utf8(&buf.data) {
2173                        Ok(string) => string,
2174                        Err(e) => {
2175                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
2176                        }
2177                    })
2178                    .unwrap();
2179
2180                match self.h0031_terminalcmd_cmd(cmd) {
2181                    Ok(_ack) => self.empty_ack(buf.id),
2182                    Err(_nak) => self.empty_nak(buf.id),
2183                }
2184            }
2185            HidIoPacketType::NaData => {
2186                // Copy data into struct
2187                let mut cmd = h0031::Cmd::<H> {
2188                    command: String::new(),
2189                };
2190                cmd.command
2191                    .push_str(match core::str::from_utf8(&buf.data) {
2192                        Ok(string) => string,
2193                        Err(e) => {
2194                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
2195                        }
2196                    })
2197                    .unwrap();
2198
2199                self.h0031_terminalcmd_nacmd(cmd)
2200            }
2201            HidIoPacketType::Ack => self.h0031_terminalcmd_ack(h0031::Ack {}),
2202            HidIoPacketType::Nak => self.h0031_terminalcmd_nak(h0031::Nak {}),
2203            _ => Ok(()),
2204        }
2205    }
2206
2207    fn h0034_terminalout(&mut self, data: h0034::Cmd<H>, na: bool) -> Result<(), CommandError> {
2208        // Create appropriately sized buffer
2209        let mut buf = HidIoPacketBuffer {
2210            // Test packet id
2211            id: HidIoCommandId::TerminalOut,
2212            // Detect max size
2213            max_len: self.default_packet_chunk(),
2214            // Use defaults for other fields
2215            ..Default::default()
2216        };
2217
2218        // Set NA (no-ack)
2219        if na {
2220            buf.ptype = HidIoPacketType::NaData;
2221        }
2222
2223        // Build payload
2224        if !buf.append_payload(data.output.as_bytes()) {
2225            return Err(CommandError::DataVecTooSmall);
2226        }
2227        buf.done = true;
2228
2229        self.tx_packetbuffer_send(&mut buf)
2230    }
2231    fn h0034_terminalout_cmd(&mut self, _data: h0034::Cmd<H>) -> Result<h0034::Ack, h0034::Nak> {
2232        Err(h0034::Nak {})
2233    }
2234    fn h0034_terminalout_nacmd(&mut self, _data: h0034::Cmd<H>) -> Result<(), CommandError> {
2235        Err(CommandError::IdNotImplemented(
2236            HidIoCommandId::TerminalOut,
2237            HidIoPacketType::NaData,
2238        ))
2239    }
2240    fn h0034_terminalout_ack(&mut self, _data: h0034::Ack) -> Result<(), CommandError> {
2241        Err(CommandError::IdNotImplemented(
2242            HidIoCommandId::TerminalOut,
2243            HidIoPacketType::Ack,
2244        ))
2245    }
2246    fn h0034_terminalout_nak(&mut self, _data: h0034::Nak) -> Result<(), CommandError> {
2247        Err(CommandError::IdNotImplemented(
2248            HidIoCommandId::TerminalOut,
2249            HidIoPacketType::Nak,
2250        ))
2251    }
2252    fn h0034_terminalout_handler(&mut self, buf: HidIoPacketBuffer<H>) -> Result<(), CommandError> {
2253        // Handle packet type
2254        match buf.ptype {
2255            HidIoPacketType::Data => {
2256                // Copy data into struct
2257                let mut cmd = h0034::Cmd::<H> {
2258                    output: String::new(),
2259                };
2260                cmd.output
2261                    .push_str(match core::str::from_utf8(&buf.data) {
2262                        Ok(string) => string,
2263                        Err(e) => {
2264                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
2265                        }
2266                    })
2267                    .unwrap();
2268
2269                match self.h0034_terminalout_cmd(cmd) {
2270                    Ok(_ack) => self.empty_ack(buf.id),
2271                    Err(_nak) => self.empty_nak(buf.id),
2272                }
2273            }
2274            HidIoPacketType::NaData => {
2275                // Copy data into struct
2276                let mut cmd = h0034::Cmd::<H> {
2277                    output: String::new(),
2278                };
2279                cmd.output
2280                    .push_str(match core::str::from_utf8(&buf.data) {
2281                        Ok(string) => string,
2282                        Err(e) => {
2283                            return Err(CommandError::InvalidUtf8(Utf8Error::new(e)));
2284                        }
2285                    })
2286                    .unwrap();
2287
2288                self.h0034_terminalout_nacmd(cmd)
2289            }
2290            HidIoPacketType::Ack => self.h0034_terminalout_ack(h0034::Ack {}),
2291            HidIoPacketType::Nak => self.h0034_terminalout_nak(h0034::Nak {}),
2292            _ => Ok(()),
2293        }
2294    }
2295
2296    fn h0050_manufacturing(&mut self, data: h0050::Cmd) -> Result<(), CommandError> {
2297        // Create appropriately sized buffer
2298        let mut buf = HidIoPacketBuffer {
2299            // Test packet id
2300            id: HidIoCommandId::ManufacturingTest,
2301            // Detect max size
2302            max_len: self.default_packet_chunk(),
2303            // Use defaults for other fields
2304            ..Default::default()
2305        };
2306
2307        // Build payload
2308        if !buf.append_payload(&(data.command as u16).to_le_bytes()) {
2309            return Err(CommandError::DataVecTooSmall);
2310        }
2311        if !buf.append_payload(unsafe { &data.argument.raw.to_le_bytes() }) {
2312            return Err(CommandError::DataVecTooSmall);
2313        }
2314
2315        buf.done = true;
2316
2317        self.tx_packetbuffer_send(&mut buf)
2318    }
2319    fn h0050_manufacturing_cmd(&mut self, _data: h0050::Cmd) -> Result<h0050::Ack, h0050::Nak> {
2320        Err(h0050::Nak {})
2321    }
2322    fn h0050_manufacturing_ack(&mut self, _data: h0050::Ack) -> Result<(), CommandError> {
2323        Err(CommandError::IdNotImplemented(
2324            HidIoCommandId::ManufacturingTest,
2325            HidIoPacketType::Ack,
2326        ))
2327    }
2328    fn h0050_manufacturing_nak(&mut self, _data: h0050::Nak) -> Result<(), CommandError> {
2329        Err(CommandError::IdNotImplemented(
2330            HidIoCommandId::ManufacturingTest,
2331            HidIoPacketType::Nak,
2332        ))
2333    }
2334    fn h0050_manufacturing_handler(
2335        &mut self,
2336        buf: HidIoPacketBuffer<H>,
2337    ) -> Result<(), CommandError> {
2338        // Handle packet type
2339        match buf.ptype {
2340            HidIoPacketType::Data => {
2341                if buf.data.len() < 4 {
2342                    return Err(CommandError::DataVecNoData);
2343                }
2344
2345                // Retrieve fields
2346                let command = h0050::Command::try_from(u16::from_le_bytes(
2347                    buf.data[0..2].try_into().unwrap(),
2348                ))
2349                .unwrap();
2350                let argument = h0050::Argument {
2351                    raw: u16::from_le_bytes(buf.data[2..4].try_into().unwrap()),
2352                };
2353
2354                match self.h0050_manufacturing_cmd(h0050::Cmd { command, argument }) {
2355                    Ok(_ack) => self.empty_ack(buf.id),
2356                    Err(_nak) => self.empty_nak(buf.id),
2357                }
2358            }
2359            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
2360            HidIoPacketType::Ack => self.h0050_manufacturing_ack(h0050::Ack {}),
2361            HidIoPacketType::Nak => self.h0050_manufacturing_nak(h0050::Nak {}),
2362            _ => Ok(()),
2363        }
2364    }
2365
2366    fn h0051_manufacturingres(&mut self, data: h0051::Cmd<HSUB4>) -> Result<(), CommandError> {
2367        // Create appropriately sized buffer
2368        let mut buf = HidIoPacketBuffer {
2369            // Test packet id
2370            id: HidIoCommandId::ManufacturingResult,
2371            // Detect max size
2372            max_len: self.default_packet_chunk(),
2373            // Use defaults for other fields
2374            ..Default::default()
2375        };
2376
2377        // Build payload
2378        if !buf.append_payload(&(data.command as u16).to_le_bytes()) {
2379            return Err(CommandError::DataVecTooSmall);
2380        }
2381        if !buf.append_payload(unsafe { &data.argument.raw.to_le_bytes() }) {
2382            return Err(CommandError::DataVecTooSmall);
2383        }
2384        if !buf.append_payload(&data.data) {
2385            return Err(CommandError::DataVecTooSmall);
2386        }
2387
2388        buf.done = true;
2389        trace!("h0051_manufacturingres: {:?} - {:?}", data, buf);
2390
2391        self.tx_packetbuffer_send(&mut buf)
2392    }
2393    fn h0051_manufacturingres_cmd(
2394        &mut self,
2395        _data: h0051::Cmd<HSUB4>,
2396    ) -> Result<h0051::Ack, h0051::Nak> {
2397        Err(h0051::Nak {})
2398    }
2399    fn h0051_manufacturingres_ack(&mut self, _data: h0051::Ack) -> Result<(), CommandError> {
2400        Err(CommandError::IdNotImplemented(
2401            HidIoCommandId::ManufacturingResult,
2402            HidIoPacketType::Ack,
2403        ))
2404    }
2405    fn h0051_manufacturingres_nak(&mut self, _data: h0051::Nak) -> Result<(), CommandError> {
2406        Err(CommandError::IdNotImplemented(
2407            HidIoCommandId::ManufacturingResult,
2408            HidIoPacketType::Nak,
2409        ))
2410    }
2411    fn h0051_manufacturingres_handler(
2412        &mut self,
2413        buf: HidIoPacketBuffer<H>,
2414    ) -> Result<(), CommandError> {
2415        // Handle packet type
2416        match buf.ptype {
2417            HidIoPacketType::Data => {
2418                if buf.data.len() < 4 {
2419                    return Err(CommandError::DataVecNoData);
2420                }
2421
2422                // Retrieve fields
2423                let command = h0051::Command::try_from(u16::from_le_bytes(
2424                    buf.data[0..2].try_into().unwrap(),
2425                ))
2426                .unwrap();
2427                let argument = h0051::Argument {
2428                    raw: u16::from_le_bytes(buf.data[2..4].try_into().unwrap()),
2429                };
2430                let data: Vec<u8, HSUB4> = if buf.data.len() > 4 {
2431                    Vec::from_slice(&buf.data[4..]).unwrap()
2432                } else {
2433                    Vec::new()
2434                };
2435
2436                match self.h0051_manufacturingres_cmd(h0051::Cmd {
2437                    command,
2438                    argument,
2439                    data,
2440                }) {
2441                    Ok(_ack) => self.empty_ack(buf.id),
2442                    Err(_nak) => self.empty_nak(buf.id),
2443                }
2444            }
2445            HidIoPacketType::NaData => Err(CommandError::InvalidPacketBufferType(buf.ptype)),
2446            HidIoPacketType::Ack => self.h0051_manufacturingres_ack(h0051::Ack {}),
2447            HidIoPacketType::Nak => self.h0051_manufacturingres_nak(h0051::Nak {}),
2448            _ => Ok(()),
2449        }
2450    }
2451}