@@ -203,6 +203,14 @@ namespace klib::usb::device {
203203 serial = 3
204204 };
205205
206+ /* *
207+ * @brief All the report ids we have in our descriptor
208+ *
209+ */
210+ enum class report_id : uint8_t {
211+ keyboard = 1 ,
212+ };
213+
206214 // Push the current pack to the stack and set the pack to 1
207215 // as all these structs have specific sizes
208216 #pragma pack(push, 1)
@@ -250,28 +258,27 @@ namespace klib::usb::device {
250258
251259 // report descriptor for the hid keyboard
252260 const __attribute__ ((aligned(4 ))) static inline uint8_t report_desc[] = {
253- 0x05 , 0x01 , // Usage Page (generic desktop)
254- 0x09 , 0x06 , // Usage (keyboard)
255- 0xa1 , 0x01 , // Collection
256- 0x05 , 0x07 , // Usage Page 7 (keyboard/keypad)
257- 0x19 , 0xe0 , // Usage Minimum = 224
258- 0x29 , 0xe7 , // Usage Maximum = 231
259- 0x15 , 0x00 , // Logical Minimum = 0
260- 0x25 , 0x01 , // Logical Maximum = 1
261- 0x75 , 0x01 , // Report Size = 1
262- 0x95 , 0x08 , // Report Count = 8
263- 0x81 , 0x02 , // Input(Data,Variable,Absolute)
264- 0x95 , 0x01 , // Report Count = 1
265- 0x75 , 0x08 , // Report Size = 8
266- 0x81 , 0x01 , // Input(Constant)
267- 0x19 , 0x00 , // Usage Minimum = 0
268- 0x29 , 0x65 , // Usage Maximum = 101
269- 0x15 , 0x00 , // Logical Minimum = 0
270- 0x25 , 0x65 , // Logical Maximum = 101
271- 0x75 , 0x08 , // Report Size = 8
272- 0x95 , 0x01 , // Report Count = 1
273- 0x81 , 0x00 , // Input(Data,Variable,Array)
274- 0xc0 // End Collection
261+ // Keyboard report (Report ID 1)
262+ 0x05 , 0x01 , // Usage Page (Generic Desktop)
263+ 0x09 , 0x06 , // Usage (Keyboard)
264+ 0xa1 , 0x01 , // Collection (Application)
265+ 0x85 , 0x01 , // Report ID (1)
266+ 0x05 , 0x07 , // Usage Page (Keyboard/Keypad)
267+ 0x19 , 0xe0 , // Usage Minimum (224)
268+ 0x29 , 0xe7 , // Usage Maximum (231)
269+ 0x15 , 0x00 , // Logical Minimum (0)
270+ 0x25 , 0x01 , // Logical Maximum (1)
271+ 0x75 , 0x01 , // Report Size (1)
272+ 0x95 , 0x08 , // Report Count (8)
273+ 0x81 , 0x02 , // Input (Data, Variable, Absolute) ; Modifier byte
274+ 0x19 , 0x00 , // Usage Minimum (0)
275+ 0x29 , 0x65 , // Usage Maximum (101)
276+ 0x15 , 0x00 , // Logical Minimum (0)
277+ 0x25 , 0x65 , // Logical Maximum (101)
278+ 0x75 , 0x08 , // Report Size (8)
279+ 0x95 , 0x01 , // Report Count (1)
280+ 0x81 , 0x00 , // Input (Data, Array) ; Keycode byte
281+ 0xc0 , // End Collection
275282 };
276283
277284 // configuration descriptor
@@ -329,22 +336,27 @@ namespace klib::usb::device {
329336 // flag if remote wakeup is supported
330337 static inline bool remote_wakeup = false ;
331338
332- // structure for the report
333- struct report_data {
334- // modifier keys (e.g. ctrl, shift)
335- uint8_t modifier;
339+ // Push the current pack to the stack and set the pack to 1
340+ // as the following structs have specific sizes
341+ #pragma pack(push, 1)
336342
337- // reserved value. Should be 0x00
338- uint8_t reserved;
343+ struct keycode_report_t {
344+ // fixed report id for the keyboard
345+ const report_id id = report_id::keyboard;
339346
340- // the current key that is pressed
347+ // key data
348+ uint8_t modifier;
341349 key_t key;
342350 };
343351
344- static_assert (sizeof (report_data) == 3 , " invalid report size" );
352+ static_assert (sizeof (keycode_report_t ) == 3 , " invalid keyboard report size" );
353+
354+ // release the old pack so the rest of the structs are not
355+ // affected by the pack(1)
356+ #pragma pack(pop)
345357
346358 // storage for the keyboard hid messages
347- static inline report_data report = {};
359+ static inline keycode_report_t keycode_report = {};
348360
349361 // static parameters with data to write to the host
350362 static inline const char *volatile irq_data = nullptr ;
@@ -374,12 +386,13 @@ namespace klib::usb::device {
374386 if ((!irq_size) && (irq_data != nullptr )) {
375387 // we have nothing more to send. Send a empty report
376388 // with no keypresses
377- report = {};
389+ keycode_report.modifier = 0x00 ;
390+ keycode_report.key = key_t ::key_none;
378391
379392 // send the no key pressed to the host
380393 Usb::write (
381394 hid_callback<Usb>, usb::get_endpoint (config.endpoint .bEndpointAddress ),
382- mode, {reinterpret_cast <const uint8_t *>(&report ), sizeof (report )}
395+ mode, {reinterpret_cast <const uint8_t *>(&keycode_report ), sizeof (keycode_report )}
383396 );
384397
385398 // clear the data to notify we are done with the string
@@ -400,12 +413,13 @@ namespace klib::usb::device {
400413 if (irq_size > 0 && irq_data[0 ] == irq_data[1 ] && repeated_key == false ) {
401414 // we have detected a double character. Send a no keys
402415 // pressed in between
403- report = {};
416+ keycode_report.modifier = 0x00 ;
417+ keycode_report.key = key_t ::key_none;
404418
405419 // send the report to the host
406420 Usb::write (
407421 hid_callback<Usb>, usb::get_endpoint (config.endpoint .bEndpointAddress ),
408- mode, {reinterpret_cast <const uint8_t *>(&report ), sizeof (report )}
422+ mode, {reinterpret_cast <const uint8_t *>(&keycode_report ), sizeof (keycode_report )}
409423 );
410424
411425 // mark we have send a no keys between two repeated keys
@@ -421,25 +435,22 @@ namespace klib::usb::device {
421435 irq_data++;
422436
423437 // encode the next character
424- encode_report (irq_data[0 ], report );
438+ encode_report (irq_data[0 ], keycode_report );
425439
426440 // clear we have transmitted a no keys in between two repeated keys
427441 repeated_key = false ;
428442
429443 // send the report to the host
430444 Usb::write (
431445 hid_callback<Usb>, usb::get_endpoint (config.endpoint .bEndpointAddress ),
432- mode, {reinterpret_cast <const uint8_t *>(&report ), sizeof (report )}
446+ mode, {reinterpret_cast <const uint8_t *>(&keycode_report ), sizeof (keycode_report )}
433447 );
434448
435449 // return we are done
436450 return ;
437451 }
438452
439- static void encode_report (const char ch, report_data& report) {
440- // always clear the reserved data
441- report.reserved = 0x00 ;
442-
453+ static void encode_report (const char ch, keycode_report_t & report) {
443454 // check what data we have
444455 if (klib::string::is_character (ch)) {
445456 // offset between the character (in the ascii table) and in the
@@ -540,8 +551,8 @@ namespace klib::usb::device {
540551 return false ;
541552 }
542553
543- template <typename Usb, bool Async = false >
544- static bool write_impl (const report_data & r) {
554+ template <typename Usb, bool Async = false , typename T = keycode_report_t >
555+ static bool write_impl (const T & r) {
545556 // write the first report to the endpoint
546557 if (!Usb::write (hid_callback<Usb>, usb::get_endpoint (config.endpoint .bEndpointAddress ),
547558 usb::get_endpoint_mode (config.endpoint .bEndpointAddress ), {reinterpret_cast <const uint8_t *>(&r), sizeof (r)}))
@@ -577,14 +588,14 @@ namespace klib::usb::device {
577588 }
578589
579590 // encode the first report
580- encode_report (data[0 ], report );
591+ encode_report (data[0 ], keycode_report );
581592
582593 // set the data in the interrupt
583594 irq_size = size - 1 ;
584595 irq_data = data;
585596
586597 // write the data
587- return write_impl<Usb, Async>(report );
598+ return write_impl<Usb, Async, true >(keycode_report );
588599 }
589600
590601 template <typename Usb, bool Async = false >
@@ -599,18 +610,15 @@ namespace klib::usb::device {
599610 }
600611
601612 // set the report
602- report = {
603- .modifier = 0x00 ,
604- .reserved = 0x00 ,
605- .key = key
606- };
613+ keycode_report.modifier = 0x00 ;
614+ keycode_report.key = key;
607615
608616 // set the data in the interrupt
609617 irq_size = 0 ;
610618 irq_data = &dummy;
611619
612620 // write the data
613- return write_impl<Usb, Async>(report );
621+ return write_impl<Usb, Async>(keycode_report );
614622 }
615623
616624 /* *
@@ -849,7 +857,7 @@ namespace klib::usb::device {
849857 usb::get_endpoint (config.endpoint .bEndpointAddress ),
850858 usb::get_endpoint_mode (config.endpoint .bEndpointAddress ),
851859 usb::get_transfer_type (config.endpoint .bmAttributes ),
852- sizeof (report )
860+ sizeof (keycode_report )
853861 );
854862
855863 // store the configuration value
@@ -859,13 +867,14 @@ namespace klib::usb::device {
859867 Usb::configured (true );
860868
861869 // prepare a inital report with no keys pressed
862- report = {};
870+ keycode_report.modifier = 0x00 ;
871+ keycode_report.key = key_t ::key_none;
863872
864873 // write the inital report
865874 if (Usb::write (
866875 hid_callback<Usb>, usb::get_endpoint (config.endpoint .bEndpointAddress ),
867876 usb::get_endpoint_mode (config.endpoint .bEndpointAddress ),
868- {reinterpret_cast <const uint8_t *>(&report ), sizeof (report )}))
877+ {reinterpret_cast <const uint8_t *>(&keycode_report ), sizeof (keycode_report )}))
869878 {
870879 // no issue for now ack
871880 return usb::handshake::ack;
@@ -934,11 +943,12 @@ namespace klib::usb::device {
934943 case hid::class_request::get_report:
935944 // the host should not use this as a substitute for the Interrupt EP
936945 // we simply send a "no keys" report to the host
937- report = {};
946+ keycode_report.modifier = 0x00 ;
947+ keycode_report.key = key_t ::key_none;
938948
939949 // write the data to the control endpoint
940950 if (Usb::write (nullptr , usb::control_endpoint,
941- usb::endpoint_mode::in, {reinterpret_cast <const uint8_t *>(&report ), sizeof (report )}))
951+ usb::endpoint_mode::in, {reinterpret_cast <const uint8_t *>(&keycode_report ), sizeof (keycode_report )}))
942952 {
943953 // no issue for now ack
944954 return usb::handshake::ack;
@@ -949,24 +959,23 @@ namespace klib::usb::device {
949959 }
950960 break ;
951961 case hid::class_request::get_idle:
952- // TODO: add support for report id != 0
953- // for now we only support report id == 0
954- if ((packet. wValue & 0xff ) != 0x00 ) {
955- // not supported for now
956- return usb::handshake::stall;
957- }
958- else {
959- // write the data to the control endpoint
960- if ( Usb::write ( nullptr , usb::control_endpoint, usb::endpoint_mode::in,
961- { reinterpret_cast < const uint8_t *>(&report), sizeof (report)}))
962- {
963- // no issue for now ack
964- return usb::handshake::ack;
965- }
966- else {
967- // something went wrong stall for now
962+ switch ( static_cast <report_id>(packet. wValue & 0xff )) {
963+ case report_id::keyboard:
964+ // write the data to the control endpoint
965+ if ( Usb::write ( nullptr , usb::control_endpoint, usb::endpoint_mode::in,
966+ { reinterpret_cast < const uint8_t *>(&keycode_report), sizeof (keycode_report)}))
967+ {
968+ // no issue for now ack
969+ return usb::handshake::ack;
970+ }
971+ else {
972+ // something went wrong stall for now
973+ return usb::handshake::stall;
974+ }
975+ break ;
976+ default :
977+ // not supported for now
968978 return usb::handshake::stall;
969- }
970979 }
971980 break ;
972981 case hid::class_request::set_report:
0 commit comments