jayakandan
Member
The VP3300 payment reader communicates over USB HID using interrupt IN endpoints, and when interfacing it with the Teensy 4.1 in USB Host mode, commands sent with sendPacket() can appear successful while no response is printed. This happens because device replies are not read using functions like recv() or available()—instead, they are delivered asynchronously through HID parser callback functions such as hid_input_data(). The RawHIDController class on Teensy 4.1 is primarily transmit-focused in host usage and is not intended for receiving standard HID report data, so relying on it for responses will fail. If the callbacks are never triggered, the most common causes are selecting the wrong HID interface, using an incorrect Report ID, or sending the command before the VP3300 has fully booted (the reader typically needs about 3–5 seconds after enumeration). Therefore, the absence of a response usually indicates a HID report or interface mismatch rather than a hardware problem with the Teensy 4.1 or an issue in the USBHost_t36 library.i attached the code below
#include <Arduino.h>
#include <USBHost_t36.h>
// -------------------------------------------------
// USB HOST SETUP
// -------------------------------------------------
USBHost myusb;
USBHub hub1(myusb);
// -------------------------------------------------
// VP3300 IDENTIFIERS
// -------------------------------------------------
const uint16_t VP3300_VID = 0x0ACD;
const uint16_t VP3300_PID = 0x3530;
// -------------------------------------------------
// STATE
// -------------------------------------------------
bool deviceConnected = false;
bool commandSent = false;
// -------------------------------------------------
// RAW INJECTION COMMAND (UNCHANGED)
// -------------------------------------------------
const uint8_t raw_cmd_data[] = {
0x56, 0x69, 0x56, 0x4F, 0x74, 0x65, 0x63, 0x68, 0x32, 0x00,
0x02, 0x40, 0x00, 0x1D, 0xB4, 0x5F, 0x36, 0x01, 0x02, 0x9C,
0x01, 0x00, 0x9F, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0xDF, 0xEF, 0x37, 0x01, 0x07, 0xDF, 0xEF, 0x3C, 0x03,
0x01, 0x00, 0x60, 0xCA, 0x1D};
// -------------------------------------------------
// CUSTOM HID PARSER (YOUR CLASS)
// -------------------------------------------------
class VP3300Parser : public USBHIDParser
{
public:
VP3300Parser(USBHost &host) : USBHIDParser(host) {}
// NO override keyword
void hid_input_data(uint32_t usage, const uint8_t *data, uint32_t len)
{
Serial.print("\n[RX] Received ");
Serial.print(len);
Serial.print(" bytes: ");
for (uint32_t i = 0; i < len; i++)
{
if (data < 16)
Serial.print("0");
Serial.print(data, HEX);
Serial.print(" ");
}
Serial.println();
bool successFound = false;
for (uint32_t i = 0; i < len - 1; i++)
{
if (data == 0x02 && data[i + 1] == 0x63)
{
successFound = true;
}
}
if (successFound)
{
Serial.println(">>> SUCCESS! THE LEDS SHOULD BE BLINKING NOW!");
Serial.println(">>> TAP YOUR CARD.");
}
}
};
// Instantiate parser
VP3300Parser hid1(myusb);
// -------------------------------------------------
void sendInjectionCommand();
// -------------------------------------------------
void setup()
{
Serial.begin(115200);
while (!Serial)
{
}
Serial.println("\n--- Teensy 4.1 VP3300 Injector ---");
myusb.begin();
}
void loop()
{
// Keep USB host alive
myusb.Task();
// Device detection
if (hid1)
{
if (hid1.idVendor() == VP3300_VID &&
hid1.idProduct() == VP3300_PID)
{
if (!deviceConnected)
{
Serial.println("VP3300 Connected!");
deviceConnected = true;
commandSent = false;
delay(300);
}
}
}
else
{
if (deviceConnected)
{
Serial.println("VP3300 Disconnected.");
deviceConnected = false;
}
}
// Send command once
if (deviceConnected && !commandSent)
{
sendInjectionCommand();
commandSent = true;
}
}
// -------------------------------------------------
// SEND RAW HID COMMAND
// -------------------------------------------------
void sendInjectionCommand()
{
Serial.println("Sending Raw Injection Command...");
uint8_t packet[64];
memset(packet, 0, sizeof(packet));
// Report ID
packet[0] = 0x01;
// Copy raw data
memcpy(&packet[1], raw_cmd_data, sizeof(raw_cmd_data));
int result = hid1.sendPacket(packet);
if (result)
{
Serial.println("Command injected. Waiting for response...");
}
else
{
Serial.println("Error sending packet.");
commandSent = false;
}
}
#include <Arduino.h>
#include <USBHost_t36.h>
// -------------------------------------------------
// USB HOST SETUP
// -------------------------------------------------
USBHost myusb;
USBHub hub1(myusb);
// -------------------------------------------------
// VP3300 IDENTIFIERS
// -------------------------------------------------
const uint16_t VP3300_VID = 0x0ACD;
const uint16_t VP3300_PID = 0x3530;
// -------------------------------------------------
// STATE
// -------------------------------------------------
bool deviceConnected = false;
bool commandSent = false;
// -------------------------------------------------
// RAW INJECTION COMMAND (UNCHANGED)
// -------------------------------------------------
const uint8_t raw_cmd_data[] = {
0x56, 0x69, 0x56, 0x4F, 0x74, 0x65, 0x63, 0x68, 0x32, 0x00,
0x02, 0x40, 0x00, 0x1D, 0xB4, 0x5F, 0x36, 0x01, 0x02, 0x9C,
0x01, 0x00, 0x9F, 0x02, 0x06, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0xDF, 0xEF, 0x37, 0x01, 0x07, 0xDF, 0xEF, 0x3C, 0x03,
0x01, 0x00, 0x60, 0xCA, 0x1D};
// -------------------------------------------------
// CUSTOM HID PARSER (YOUR CLASS)
// -------------------------------------------------
class VP3300Parser : public USBHIDParser
{
public:
VP3300Parser(USBHost &host) : USBHIDParser(host) {}
// NO override keyword
void hid_input_data(uint32_t usage, const uint8_t *data, uint32_t len)
{
Serial.print("\n[RX] Received ");
Serial.print(len);
Serial.print(" bytes: ");
for (uint32_t i = 0; i < len; i++)
{
if (data < 16)
Serial.print("0");
Serial.print(data, HEX);
Serial.print(" ");
}
Serial.println();
bool successFound = false;
for (uint32_t i = 0; i < len - 1; i++)
{
if (data == 0x02 && data[i + 1] == 0x63)
{
successFound = true;
}
}
if (successFound)
{
Serial.println(">>> SUCCESS! THE LEDS SHOULD BE BLINKING NOW!");
Serial.println(">>> TAP YOUR CARD.");
}
}
};
// Instantiate parser
VP3300Parser hid1(myusb);
// -------------------------------------------------
void sendInjectionCommand();
// -------------------------------------------------
void setup()
{
Serial.begin(115200);
while (!Serial)
{
}
Serial.println("\n--- Teensy 4.1 VP3300 Injector ---");
myusb.begin();
}
void loop()
{
// Keep USB host alive
myusb.Task();
// Device detection
if (hid1)
{
if (hid1.idVendor() == VP3300_VID &&
hid1.idProduct() == VP3300_PID)
{
if (!deviceConnected)
{
Serial.println("VP3300 Connected!");
deviceConnected = true;
commandSent = false;
delay(300);
}
}
}
else
{
if (deviceConnected)
{
Serial.println("VP3300 Disconnected.");
deviceConnected = false;
}
}
// Send command once
if (deviceConnected && !commandSent)
{
sendInjectionCommand();
commandSent = true;
}
}
// -------------------------------------------------
// SEND RAW HID COMMAND
// -------------------------------------------------
void sendInjectionCommand()
{
Serial.println("Sending Raw Injection Command...");
uint8_t packet[64];
memset(packet, 0, sizeof(packet));
// Report ID
packet[0] = 0x01;
// Copy raw data
memcpy(&packet[1], raw_cmd_data, sizeof(raw_cmd_data));
int result = hid1.sendPacket(packet);
if (result)
{
Serial.println("Command injected. Waiting for response...");
}
else
{
Serial.println("Error sending packet.");
commandSent = false;
}
}