Recent

Author Topic: HID for Teensy 4  (Read 7632 times)

Johan Holstein

  • Jr. Member
  • **
  • Posts: 63
HID for Teensy 4
« on: July 14, 2021, 08:26:14 pm »
Hi all,
I use a Teensy 4 and a com port (/dev/ttyACM0 for the communication send and receive,
but for my application it is better to use a HID.
My test program recognize already the Teensy 4.... perfect, but how can I send and receive serial strings? See also attachment for the raw output.
Is there any solution to solve this ?
Best regards,
Johan
 
Code: Pascal  [Select][+][-]
  1. program demo;
  2.  
  3. // this modeswitch makes the pointers to
  4. // objects more comfortable to use
  5. {$modeswitch autoderef}
  6.  
  7. uses
  8.   sysutils, hidapi;
  9.  
  10.  
  11. procedure EnumerationDemo;
  12. var
  13.   EnumList, EnumItem: PHidDeviceInfo;
  14.   Path: String;
  15.   Vid, Pid: Word;
  16.   ProductName: UnicodeString;
  17.  
  18. begin
  19.   WriteLn('will now enumerate all USB HID devices.');
  20.   WriteLn('Note that it will list more info if you run with sudo,');
  21.   WriteLn('you might want to add an udev rule for your device.');
  22.   WriteLn();
  23.  
  24.   // request the hidapi to build a linked list of all HID devices
  25.   // it will match all of them because VID and PID are zero
  26.   EnumList := THidDeviceInfo.Enumerate(0, 0);
  27.  
  28.   // iterate through linked list
  29.   EnumItem := EnumList;
  30.   while Assigned(EnumItem) do begin
  31.     Path := EnumItem.Path;
  32.     Vid := EnumItem.VendorID;
  33.     Pid := EnumItem.ProductID;
  34.     ProductName := PCWCharToUnicodeString(EnumItem.ProductString);
  35.     WriteLn(Format('Found: %s (%0.4x:%0.4x) at: %s', [ProductName, Vid, Pid, Path]));
  36.     EnumItem := EnumItem.Next;
  37.   end;
  38.   WriteLn();
  39.  
  40.   // dont forget to free the list again, this s done
  41.   // by calling free on the first item of the linked list
  42.   EnumList.Free;
  43. end;
  44.  
  45.  
  46. procedure OpenAndReadDemo;
  47. const
  48.   // This is a Logitech Extreme 3D Joystick, a
  49.   // cheap and popular model, probably you own one,
  50.  
  51.   // if not then try some other VID/PID, try to run
  52.   // as root or make an udev rule for the device.
  53.   DEMO_VID = $16c0;
  54.   DEMO_PID = $0486;
  55.  
  56. var
  57.   Device: PHidDevice;
  58.   I, J, Num: Integer;
  59.   Buffer: array[0..63] of Byte;
  60.  
  61. begin
  62.   WriteLn(Format('Will now try to open device %0.4x:%0.4x', [DEMO_VID, DEMO_PID]));
  63.   WriteLn();
  64.   Device := THidDevice.Open(DEMO_VID, DEMO_PID, '');
  65.   if not Assigned(Device) then begin
  66.     WriteLn('could not open device');
  67.   end
  68.   else begin
  69.     WriteLn('device is open, now going to read data from it');
  70.     WriteLn('Manufacturer: ', Device.GetManufacturerString);
  71.     WriteLn('Product: ', Device.GetProductString);
  72.  
  73.     for I := 1 to 1000 do begin
  74.       Num := Device.Read(Buffer, SizeOf(Buffer));
  75.       for J := 0 to Num - 1 do begin
  76.           Write(Format('%0.2x ', [Buffer[J]]));
  77.  
  78.       end;
  79.  
  80.       Write(#13);
  81.     end;
  82.     WriteLn();
  83.     WriteLn('closing device');
  84.     Device.Close;
  85.   end;
  86.  
  87.  
  88.  
  89. end;
  90.  
  91.  
  92. begin
  93.   EnumerationDemo;
  94.   OpenAndReadDemo;
  95. end.
  96.                                                      

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: HID for Teensy 4
« Reply #1 on: July 14, 2021, 09:02:52 pm »
Rawhid might be useful.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Johan Holstein

  • Jr. Member
  • **
  • Posts: 63
Re: HID for Teensy 4
« Reply #2 on: July 14, 2021, 09:06:52 pm »
So what must be done to read and write to the HID?
Can you help whit that?
Thanks,
Johan

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: HID for Teensy 4
« Reply #3 on: July 14, 2021, 09:25:20 pm »
You need a copy of the rawhid library from the Teensy site, and a binding looking something like

Code: Pascal  [Select][+][-]
  1. unit rawhid;
  2. interface
  3.  
  4. {
  5.   Automatically converted by H2Pas 1.0.0 from hid.h
  6.   The following command line parameters were used:
  7.     hid.h
  8. }
  9.  
  10. {$IFDEF FPC}
  11. {$PACKRECORDS C}
  12. {$ENDIF}
  13.  
  14. {$L hid.o}                      // Built by Makefile from Teensyduino host example
  15. {$LINKLIB libusb }              // Statically-linked prerequisite library
  16.  
  17.   function rawhid_open(max:longint; vid:longint; pid:longint; usage_page:longint; usage:longint):longint;cdecl;external;
  18.  
  19.   function rawhid_recv(num:longint; buf:pointer; len:longint; timeout:longint):longint;cdecl;external;
  20.  
  21.   function rawhid_send(num:longint; buf:pointer; len:longint; timeout:longint):longint;cdecl;external;
  22.  
  23.   procedure rawhid_close(num:longint);cdecl;external;
  24.  
  25.  
  26. implementation
  27.  
  28.  
  29. end.
  30.  

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Johan Holstein

  • Jr. Member
  • **
  • Posts: 63
Re: HID for Teensy 4
« Reply #4 on: July 14, 2021, 09:43:49 pm »
Hi Mark,

I looked at the  https://www.pjrc.com/teensy/rawhid.html  but can not find a library as mentioned.

Best,
Johan

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: HID for Teensy 4
« Reply #5 on: July 14, 2021, 10:03:33 pm »
What's wrong with the link "RawHid Test C source code"?

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Johan Holstein

  • Jr. Member
  • **
  • Posts: 63
Re: HID for Teensy 4
« Reply #6 on: July 15, 2021, 08:44:26 am »
Hi Mark,
I downloaded the the RawHid C code from the PRJC side .... but my question is how to use it and how implement this into the Pascal code?

Thanks for helping!
Best,
Johan

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: HID for Teensy 4
« Reply #7 on: July 15, 2021, 09:32:44 am »
Compile it using the supplied makefile, read the examples, and use the Pascal binding I gave you. You might have problems with paths etc. during Pascal compilation, which I admit I'm a bit dubious about myself.

You might find the below useful, but it's a straight transcript of the C and frankly nothing you couldn't do yourself.

Code: Pascal  [Select][+][-]
  1. (* Lazarus+FPC 2.0.8+3.0.4 on Linux Lazarus+FPC 2.0.8+3.0.4 on Linux Lazarus+FP *)
  2.  
  3. unit PollTeensyRawhid;
  4.  
  5. (* This is a placeholder for access to the Teensy rawhid interface. The "Basic" *)
  6. (* firmware supplied as standard reads up to 12x ADCs and writes to 8x digital  *)
  7. (* output bits.                                                 MarkMLl         *)
  8.  
  9. {$mode objfpc}{$H+}
  10.  
  11. { define RAWHID_DEMO }
  12.  
  13. interface
  14.  
  15. uses
  16.   Classes, SysUtils;
  17.  
  18. implementation
  19.  
  20. uses
  21. {$ifdef RAWHID_DEMO }
  22.   Keyboard,
  23. {$endif RAWHID_DEMO }
  24.   rawhid in './rawhid/rawhid.pp';
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32. {$ifdef RAWHID_DEMO }
  33.  
  34. (* This is a transcript of the rawhid_test.c demo from TeensyDuino to Pascal.
  35. *)
  36. procedure rawhid_test;
  37.  
  38. (* As standard, the USB parameters are configured in a conditional portion of   *)
  39. (* usb_desc.h, not in usb_private.h Using the latter file might take a bit of   *)
  40. (* build-time tweaking.                                                         *)
  41. (*                                                                              *)
  42. (* Linux's  dmesg -e  output will reliably show connection events, but not the  *)
  43. (* corresponding USAGE_PAGE and USAGE values.                                   *)
  44. (*
  45. [Nov26 10:30] usb 3-2: USB disconnect, device number 10
  46. [Nov26 10:31] usb 3-2: new full-speed USB device number 11 using uhci_hcd
  47. [  +0.188011] usb 3-2: New USB device found, idVendor=16c0, idProduct=0486, bcdDevice= 2.76
  48. [  +0.000002] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
  49. [  +0.000002] usb 3-2: Product: Teensyduino RawHID
  50. [  +0.000001] usb 3-2: Manufacturer: Teensyduino
  51. [  +0.000001] usb 3-2: SerialNumber: 6824370
  52. [  +0.008751] hid-generic 0003:16C0:0486.0009: hiddev0,hidraw3: USB HID v1.11 Device [Teensyduino Teensyduino RawHID] on usb-0000:00:1d.1-2/input0
  53. [  +0.003570] hid-generic 0003:16C0:0486.000A: hidraw4: USB HID v1.11 Device [Teensyduino Teensyduino RawHID] on usb-0000:00:1d.1-2/input1         *)
  54. (*                                                                              *)
  55. (* I can confirm that the USAGE_PAGE and USAGE parameters must match before     *)
  56. (* this program will work. I've previously looked at HID device reports, but    *)
  57. (* these aren't relevant to rawhid endpoints.                                   *)
  58.  
  59. const
  60.   VENDOR_ID=            $16C0;
  61.   PRODUCT_ID=           $0480;
  62.   PRODUCT_ID_ALT=       $0486;
  63.   RAWHID_USAGE_PAGE=    $FFAB;  // recommended: 0xFF00 to 0xFFFF
  64.   RAWHID_USAGE=         $0200;  // recommended: 0x0100 to 0xFFFF
  65.   bufTop= 63;
  66.  
  67. var
  68.   i, r, num: integer;
  69.   c: ansichar;
  70.   buf: array[0..bufTop] of ansichar;
  71.  
  72.  
  73.   function get_keystroke(): ansichar;
  74.  
  75.   var
  76.     k: TKeyEvent;
  77.  
  78.   begin
  79.     result := #0;
  80.     k := PollKeyEvent();                (* Does not remove event from buffer    *)
  81.     if k <> 0 then begin
  82.       k := TranslateKeyEvent(GetKeyEvent());
  83.       if TKeyRecord(k).Flags = kbASCII then
  84.         result := Chr(TKeyRecord(k).KeyCode and $ff)
  85.     end
  86.   end { get_keystroke } ;
  87.  
  88.  
  89. begin
  90.   // C-based example is 16C0:0480:FFAB:0200
  91.   r := rawhid_open(1, VENDOR_ID, PRODUCT_ID, RAWHID_USAGE_PAGE, RAWHID_USAGE);
  92.   if (r <= 0) then begin
  93.     // Arduino-based example is 16C0:0486:FFAB:0200
  94.     r := rawhid_open(1, VENDOR_ID, PRODUCT_ID_ALT, RAWHID_USAGE_PAGE, RAWHID_USAGE);
  95.     if (r <= 0) then begin
  96.       WriteLn('no rawhid device found');
  97.       Halt(-1)
  98.     end
  99.   end;
  100.   WriteLn('found rawhid device');
  101.  
  102.   while (true) do begin
  103.     // check if any Raw HID packet has arrived
  104.     num := rawhid_recv(0, @buf, bufTop + 1, 220);
  105.     if (num < 0) then begin
  106.       WriteLn; WriteLn('error reading, device went offline');
  107.       rawhid_close(0);
  108.       Halt(0)
  109.     end;
  110.     if (num > 0) then begin
  111.  
  112. (* The default ("Basic") Teensy demo sends a packet every two seconds. Expect   *)
  113. (* the first two bytes to be 0xab and 0xbc as a signature, followed by 24 bytes *)
  114. (* of 16-bit analogue data MSB first, and the final two bytes to be a big-      *)
  115. (* endian packet count.                                                         *)
  116.  
  117.       WriteLn; WriteLn('recv ', num, ' bytes:');
  118.       for i := 0 to num - 1 do begin
  119.         Write(HexStr(Ord(buf[i]), 2));
  120.         if (i mod 16 = 15) and (i < num -1 ) then
  121.           WriteLn
  122.       end;
  123.       WriteLn
  124.     end;
  125.     // check if any input on stdin
  126.     c := get_keystroke();
  127.     while c >= ' ' do begin
  128.       WriteLn; WriteLn('got key ''', c, ''' sending...');
  129.       buf[0] := c;
  130.       for i := 1 to bufTop do
  131.         buf[i] := #0;
  132.       rawhid_send(0, @buf, BufTop + 1, 100);
  133.  
  134. (* The default ("Basic") Teensy demo writes the character directly to digital   *)
  135. (* outputs 0 through 7.                                                         *)
  136.  
  137.       c := get_keystroke()
  138.     end
  139.   end
  140. end { rawhid_test } ;
  141.  
  142. {$endif RAWHID_DEMO }
  143.  
  144.  
  145. begin
  146. {$ifdef RAWHID_DEMO }
  147. //  InitKeyboard;
  148.   rawhid_test;
  149.   Halt
  150. {$endif RAWHID_DEMO }
  151. end.
  152.  

I'm afraid that I'm not giving you the rest of the program that I've been tinkering with since (a) there's some bits I want to keep proprietary (at least until I'm comfortable documenting them for customers) and (b) it's a working demo that's got "history" and some bits are a mess.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Johan Holstein

  • Jr. Member
  • **
  • Posts: 63
Re: HID for Teensy 4
« Reply #8 on: July 15, 2021, 10:10:35 am »
Hi Mark,

I complied the rawhid from th PRJC side without  any problem.... however my knowledge goes not that far to get this to work. I though there is a simple solution to send and receive strings from my Teensy4 with HID.
Why HID when comport is working perfect.... the reason for that is that I not every time must choose a comport while starting my Power and SWR meter program.

Thanks for helping!
Best,
Johan


MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: HID for Teensy 4
« Reply #9 on: July 15, 2021, 10:25:03 am »
I complied the rawhid from th PRJC side without  any problem.... however my knowledge goes not that far to get this to work.

I've given you all the code- what's your problem?

Quote
I though there is a simple solution to send and receive strings from my Teensy4 with HID.

HID doesn't transfer strings. I suggest starting with something really basic like reading the relevant Wikipaedia article.

Quote
Why HID when comport is working perfect.... the reason for that is that I not every time must choose a comport while starting my Power and SWR meter program.

If you can't understand something simple like the example code I've given you then you're certainly not going to get anywhere with the gymnastics necessary to work out which serial port you need to be looking at if there's multiple /dev/ttyACM* candidates since it involves a lot of device-specific parsing of the /sys tree.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

DonAlfredo

  • Hero Member
  • *****
  • Posts: 1739
Re: HID for Teensy 4
« Reply #10 on: July 15, 2021, 11:18:54 am »
As an alternative, you might want to have a look at:
https://github.com/LongDirtyAnimAlf/FPC-USB-HID

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: HID for Teensy 4
« Reply #11 on: July 15, 2021, 11:29:32 am »
As an alternative, you might want to have a look at:
https://github.com/LongDirtyAnimAlf/FPC-USB-HID

Which I presume works with the demo code which is supplied with the Teensy...

All this reminds me why I'm reluctant to get involved with "How do I talk to an Arduino?" questions.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

DonAlfredo

  • Hero Member
  • *****
  • Posts: 1739
Re: HID for Teensy 4
« Reply #12 on: July 15, 2021, 11:51:54 am »
@MarkMLl
I do not fully understand your reply.
But anyhow, I myself use this lib to talk with many different types of embedded devices, including Arduino.
And naturally, with HID, the lib has to be adapted to suit the device(s) (VID, PID and report length among other things).

MarkMLl

  • Hero Member
  • *****
  • Posts: 6692
Re: HID for Teensy 4
« Reply #13 on: July 15, 2021, 12:09:20 pm »
@MarkMLl
I do not fully understand your reply.
But anyhow, I myself use this lib to talk with many different types of embedded devices, including Arduino.
And naturally, with HID, the lib has to be adapted to suit the device(s) (VID, PID and report length among other things).

There is specific "raw HID" code supplied with the Teensy which reads/writes buttons etc., and a demo application in C to run on a PC. The stuff I've provided is the client-side Pascal stuff specifically tailored (and tested) to talk to that, i.e. is not the sort of HID code you'd use to talk to a device such as a mouse or keyboard.

MarkMLl
MT+86 & Turbo Pascal v1 on CCP/M-86, multitasking with LAN & graphics in 128Kb.
Pet hate: people who boast about the size and sophistication of their computer.
GitHub repositories: https://github.com/MarkMLl?tab=repositories

Johan Holstein

  • Jr. Member
  • **
  • Posts: 63
Re: HID for Teensy 4
« Reply #14 on: July 15, 2021, 01:25:06 pm »
Hi Mark,
My Power and SWR program contains more than 10000 lines of code I know how to handle this stuff, but all with all it was not a clear answer to me. However I managed to send the serial string to rawhid terminal.


 

TinyPortal © 2005-2018