(* Lazarus+FPC 2.0.8+3.0.4 on Linux Lazarus+FPC 2.0.8+3.0.4 on Linux Lazarus+FP *)
unit PollTeensyRawhid;
(* This is a placeholder for access to the Teensy rawhid interface. The "Basic" *)
(* firmware supplied as standard reads up to 12x ADCs and writes to 8x digital *)
(* output bits. MarkMLl *)
{$mode objfpc}{$H+}
{ define RAWHID_DEMO }
interface
uses
Classes, SysUtils;
implementation
uses
{$ifdef RAWHID_DEMO }
Keyboard,
{$endif RAWHID_DEMO }
rawhid in './rawhid/rawhid.pp';
{$ifdef RAWHID_DEMO }
(* This is a transcript of the rawhid_test.c demo from TeensyDuino to Pascal.
*)
procedure rawhid_test;
(* As standard, the USB parameters are configured in a conditional portion of *)
(* usb_desc.h, not in usb_private.h Using the latter file might take a bit of *)
(* build-time tweaking. *)
(* *)
(* Linux's dmesg -e output will reliably show connection events, but not the *)
(* corresponding USAGE_PAGE and USAGE values. *)
(*
[Nov26 10:30] usb 3-2: USB disconnect, device number 10
[Nov26 10:31] usb 3-2: new full-speed USB device number 11 using uhci_hcd
[ +0.188011] usb 3-2: New USB device found, idVendor=16c0, idProduct=0486, bcdDevice= 2.76
[ +0.000002] usb 3-2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ +0.000002] usb 3-2: Product: Teensyduino RawHID
[ +0.000001] usb 3-2: Manufacturer: Teensyduino
[ +0.000001] usb 3-2: SerialNumber: 6824370
[ +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
[ +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 *)
(* *)
(* I can confirm that the USAGE_PAGE and USAGE parameters must match before *)
(* this program will work. I've previously looked at HID device reports, but *)
(* these aren't relevant to rawhid endpoints. *)
const
VENDOR_ID= $16C0;
PRODUCT_ID= $0480;
PRODUCT_ID_ALT= $0486;
RAWHID_USAGE_PAGE= $FFAB; // recommended: 0xFF00 to 0xFFFF
RAWHID_USAGE= $0200; // recommended: 0x0100 to 0xFFFF
bufTop= 63;
var
i, r, num: integer;
c: ansichar;
buf: array[0..bufTop] of ansichar;
function get_keystroke(): ansichar;
var
k: TKeyEvent;
begin
result := #0;
k := PollKeyEvent(); (* Does not remove event from buffer *)
if k <> 0 then begin
k := TranslateKeyEvent(GetKeyEvent());
if TKeyRecord(k).Flags = kbASCII then
result := Chr(TKeyRecord(k).KeyCode and $ff)
end
end { get_keystroke } ;
begin
// C-based example is 16C0:0480:FFAB:0200
r := rawhid_open(1, VENDOR_ID, PRODUCT_ID, RAWHID_USAGE_PAGE, RAWHID_USAGE);
if (r <= 0) then begin
// Arduino-based example is 16C0:0486:FFAB:0200
r := rawhid_open(1, VENDOR_ID, PRODUCT_ID_ALT, RAWHID_USAGE_PAGE, RAWHID_USAGE);
if (r <= 0) then begin
WriteLn('no rawhid device found');
Halt(-1)
end
end;
WriteLn('found rawhid device');
while (true) do begin
// check if any Raw HID packet has arrived
num := rawhid_recv(0, @buf, bufTop + 1, 220);
if (num < 0) then begin
WriteLn; WriteLn('error reading, device went offline');
rawhid_close(0);
Halt(0)
end;
if (num > 0) then begin
(* The default ("Basic") Teensy demo sends a packet every two seconds. Expect *)
(* the first two bytes to be 0xab and 0xbc as a signature, followed by 24 bytes *)
(* of 16-bit analogue data MSB first, and the final two bytes to be a big- *)
(* endian packet count. *)
WriteLn; WriteLn('recv ', num, ' bytes:');
for i := 0 to num - 1 do begin
Write(HexStr(Ord(buf[i]), 2));
if (i mod 16 = 15) and (i < num -1 ) then
WriteLn
end;
WriteLn
end;
// check if any input on stdin
c := get_keystroke();
while c >= ' ' do begin
WriteLn; WriteLn('got key ''', c, ''' sending...');
buf[0] := c;
for i := 1 to bufTop do
buf[i] := #0;
rawhid_send(0, @buf, BufTop + 1, 100);
(* The default ("Basic") Teensy demo writes the character directly to digital *)
(* outputs 0 through 7. *)
c := get_keystroke()
end
end
end { rawhid_test } ;
{$endif RAWHID_DEMO }
begin
{$ifdef RAWHID_DEMO }
// InitKeyboard;
rawhid_test;
Halt
{$endif RAWHID_DEMO }
end.