Skip to content

Commit

Permalink
Merge pull request #1889 from Tails86/master
Browse files Browse the repository at this point in the history
Implemented tuh_hid_send_report
  • Loading branch information
hathach committed Mar 13, 2023
2 parents be21413 + 9247131 commit 7cf67b2
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 14 deletions.
88 changes: 79 additions & 9 deletions examples/host/hid_controller/src/hid_app.c
Expand Up @@ -91,9 +91,8 @@ typedef struct TU_ATTR_PACKED
uint8_t counter : 6; // +1 each report
};

// comment out since not used by this example
// uint8_t l2_trigger; // 0 released, 0xff fully pressed
// uint8_t r2_trigger; // as above
uint8_t l2_trigger; // 0 released, 0xff fully pressed
uint8_t r2_trigger; // as above

// uint16_t timestamp;
// uint8_t battery;
Expand All @@ -105,15 +104,54 @@ typedef struct TU_ATTR_PACKED

} sony_ds4_report_t;

typedef struct TU_ATTR_PACKED {
// First 16 bits set what data is pertinent in this structure (1 = set; 0 = not set)
uint8_t set_rumble : 1;
uint8_t set_led : 1;
uint8_t set_led_blink : 1;
uint8_t set_ext_write : 1;
uint8_t set_left_volume : 1;
uint8_t set_right_volume : 1;
uint8_t set_mic_volume : 1;
uint8_t set_speaker_volume : 1;
uint8_t set_flags2;

uint8_t reserved;

uint8_t motor_right;
uint8_t motor_left;

uint8_t lightbar_red;
uint8_t lightbar_green;
uint8_t lightbar_blue;
uint8_t lightbar_blink_on;
uint8_t lightbar_blink_off;

uint8_t ext_data[8];

uint8_t volume_left;
uint8_t volume_right;
uint8_t volume_mic;
uint8_t volume_speaker;

uint8_t other[9];
} sony_ds4_output_report_t;

static bool ds4_mounted = false;
static uint8_t ds4_dev_addr = 0;
static uint8_t ds4_instance = 0;
static uint8_t motor_left = 0;
static uint8_t motor_right = 0;

// check if device is Sony DualShock 4
static inline bool is_sony_ds4(uint8_t dev_addr)
{
uint16_t vid, pid;
tuh_vid_pid_get(dev_addr, &vid, &pid);

return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
|| (vid == 0x0f0d && pid == 0x005e) // Hori FC4
|| (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
return ( (vid == 0x054c && (pid == 0x09cc || pid == 0x05c4)) // Sony DualShock4
|| (vid == 0x0f0d && pid == 0x005e) // Hori FC4
|| (vid == 0x0f0d && pid == 0x00ee) // Hori PS4 Mini (PS4-099U)
|| (vid == 0x1f4f && pid == 0x1002) // ASW GG xrd controller
);
}
Expand All @@ -124,7 +162,23 @@ static inline bool is_sony_ds4(uint8_t dev_addr)

void hid_app_task(void)
{
// nothing to do
if (ds4_mounted)
{
const uint32_t interval_ms = 200;
static uint32_t start_ms = 0;

uint32_t current_time_ms = board_millis();
if ( current_time_ms - start_ms >= interval_ms)
{
start_ms = current_time_ms;

sony_ds4_output_report_t output_report = {0};
output_report.set_rumble = 1;
output_report.motor_left = motor_left;
output_report.motor_right = motor_right;
tuh_hid_send_report(ds4_dev_addr, ds4_instance, 5, &output_report, sizeof(output_report));
}
}
}

//--------------------------------------------------------------------+
Expand All @@ -149,6 +203,14 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
// Sony DualShock 4 [CUH-ZCT2x]
if ( is_sony_ds4(dev_addr) )
{
if (!ds4_mounted)
{
ds4_dev_addr = dev_addr;
ds4_instance = instance;
motor_left = 0;
motor_right = 0;
ds4_mounted = true;
}
// request to receive report
// tuh_hid_report_received_cb() will be invoked when report is available
if ( !tuh_hid_receive_report(dev_addr, instance) )
Expand All @@ -162,6 +224,10 @@ void tuh_hid_mount_cb(uint8_t dev_addr, uint8_t instance, uint8_t const* desc_re
void tuh_hid_umount_cb(uint8_t dev_addr, uint8_t instance)
{
printf("HID device address = %d, instance = %d is unmounted\r\n", dev_addr, instance);
if (ds4_mounted && ds4_dev_addr == dev_addr && ds4_instance == instance)
{
ds4_mounted = false;
}
}

// check if different than 2
Expand All @@ -179,8 +245,8 @@ bool diff_report(sony_ds4_report_t const* rpt1, sony_ds4_report_t const* rpt2)
result = diff_than_2(rpt1->x, rpt2->x) || diff_than_2(rpt1->y , rpt2->y ) ||
diff_than_2(rpt1->z, rpt2->z) || diff_than_2(rpt1->rz, rpt2->rz);

// check the reset with mem compare
result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-4);
// check the rest with mem compare
result |= memcmp(&rpt1->rz + 1, &rpt2->rz + 1, sizeof(sony_ds4_report_t)-6);

return result;
}
Expand Down Expand Up @@ -234,6 +300,10 @@ void process_sony_ds4(uint8_t const* report, uint16_t len)
printf("\r\n");
}

// The left and right triggers control the intensity of the left and right rumble motors
motor_left = ds4_report.l2_trigger;
motor_right = ds4_report.r2_trigger;

prev_report = ds4_report;
}
}
Expand Down
48 changes: 45 additions & 3 deletions src/class/hid/hid_host.c
@@ -1,4 +1,4 @@
/*
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
Expand Down Expand Up @@ -274,7 +274,49 @@ bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance)
// return !usbh_edpt_busy(dev_addr, hid_itf->ep_in);
//}

//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len);
bool tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, const void* report, uint16_t len)
{
TU_LOG2("HID Send Report %d\r\n", report_id);

hidh_interface_t* hid_itf = get_instance(dev_addr, instance);

if (hid_itf->ep_out == 0)
{
// This HID does not have an out endpoint (other than control)
return false;
}
else if (len > CFG_TUH_HID_EPOUT_BUFSIZE
|| (report_id != 0 && len > (CFG_TUH_HID_EPOUT_BUFSIZE - 1)))
{
// ep_out buffer is not large enough to hold contents
return false;
}

// claim endpoint
TU_VERIFY( usbh_edpt_claim(dev_addr, hid_itf->ep_out) );

if (report_id == 0)
{
// No report ID in transmission
memcpy(&hid_itf->epout_buf[0], report, len);
}
else
{
hid_itf->epout_buf[0] = report_id;
memcpy(&hid_itf->epout_buf[1], report, len);
++len; // 1 more byte for report_id
}

TU_LOG3_MEM(hid_itf->epout_buf, len, 2);

if ( !usbh_edpt_xfer(dev_addr, hid_itf->ep_out, hid_itf->epout_buf, len) )
{
usbh_edpt_release(dev_addr, hid_itf->ep_out);
return false;
}

return true;
}

//--------------------------------------------------------------------+
// USBH API
Expand Down Expand Up @@ -349,7 +391,7 @@ bool hidh_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_interface_t const *de
hidh_device_t* hid_dev = get_dev(dev_addr);
TU_ASSERT(hid_dev->inst_count < CFG_TUH_HID, 0);

hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count);
hidh_interface_t* hid_itf = get_instance(dev_addr, hid_dev->inst_count);

//------------- Endpoint Descriptors -------------//
p_desc = tu_desc_next(p_desc);
Expand Down
4 changes: 2 additions & 2 deletions src/class/hid/hid_host.h
@@ -1,4 +1,4 @@
/*
/*
* The MIT License (MIT)
*
* Copyright (c) 2019 Ha Thach (tinyusb.org)
Expand Down Expand Up @@ -106,7 +106,7 @@ bool tuh_hid_receive_report(uint8_t dev_addr, uint8_t instance);

// Send report using interrupt endpoint
// If report_id > 0 (composite), it will be sent as 1st byte, then report contents. Otherwise only report content is sent.
//void tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, uint8_t const* report, uint16_t len);
bool tuh_hid_send_report(uint8_t dev_addr, uint8_t instance, uint8_t report_id, const void* report, uint16_t len);

//--------------------------------------------------------------------+
// Callbacks (Weak is optional)
Expand Down

0 comments on commit 7cf67b2

Please sign in to comment.