Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions right/src/usb_descriptors/usb_descriptor_configuration.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,8 @@
USB_INTERFACE_ALTERNATE_SETTING_NONE,\
USB_MOUSE_ENDPOINT_COUNT,\
USB_CLASS_HID,\
USB_HID_SUBCLASS_BOOT,\
USB_HID_PROTOCOL_MOUSE,\
USB_HID_SUBCLASS_NONE,\
USB_HID_PROTOCOL_NONE,\
USB_STRING_DESCRIPTOR_NONE,\
\
/* Mouse HID descriptor */\
Expand Down
61 changes: 34 additions & 27 deletions right/src/usb_descriptors/usb_descriptor_mouse_report.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
#define USB_MOUSE_REPORT_DESCRIPTOR_MIN_AXIS_PHYSICAL_VALUE -4096
#define USB_MOUSE_REPORT_DESCRIPTOR_MAX_AXIS_PHYSICAL_VALUE 4096
#define USB_MOUSE_REPORT_DESCRIPTOR_BUTTONS 20
#ifndef __ZEPHYR__
#define USB_MOUSE_REPORT_ID 1
#else
#define USB_MOUSE_REPORT_ID 0 // it is defined elsewhere
#endif

#define USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE 1
#define USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE 120
Expand All @@ -31,6 +36,9 @@
HID_RI_USAGE(8, HID_RI_USAGE_GENERIC_DESKTOP_MOUSE),
HID_RI_COLLECTION(8, HID_RI_COLLECTION_APPLICATION),
HID_RI_USAGE(8, HID_RI_USAGE_GENERIC_DESKTOP_POINTER),
#if USB_MOUSE_REPORT_ID
HID_RI_REPORT_ID(8, USB_MOUSE_REPORT_ID),
#endif
HID_RI_COLLECTION(8, HID_RI_COLLECTION_PHYSICAL),

// Mouse buttons
Expand Down Expand Up @@ -61,25 +69,6 @@
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),

HID_RI_COLLECTION(8, HID_RI_COLLECTION_LOGICAL),

// Scroll wheels

// Resolution multiplier for high-res scroll support
// To have a multiplier apply to a wheel, it must be in the
// same logical collection as the wheel, or else there must
// be no logical collections (according to the USB HID spec);
// so to have a single multiplier apply to the two wheels,
// they must be in the same logical collection (or there
// must be no logical collection at all)
HID_RI_USAGE(8, HID_RI_USAGE_GENERIC_DESKTOP_RESOLUTION_MULTIPLIER),
HID_RI_LOGICAL_MINIMUM(8, 0),
HID_RI_LOGICAL_MAXIMUM(8, 1),
HID_RI_PHYSICAL_MINIMUM(8, USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE),
HID_RI_PHYSICAL_MAXIMUM(8, USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE),
HID_RI_REPORT_COUNT(8, 1),
HID_RI_REPORT_SIZE(8, 8),
HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),

// Vertical wheel
HID_RI_USAGE(8, HID_RI_USAGE_GENERIC_DESKTOP_WHEEL),
HID_RI_LOGICAL_MINIMUM(16, -32767),
Expand All @@ -90,18 +79,36 @@
HID_RI_REPORT_SIZE(8, 16),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),

// Horizontal wheel
HID_RI_USAGE_PAGE(8, HID_RI_USAGE_PAGE_CONSUMER),
HID_RI_USAGE(16, HID_RI_USAGE_CONSUMER_AC_PAN),
HID_RI_LOGICAL_MINIMUM(16, -32767),
HID_RI_LOGICAL_MAXIMUM(16, 32767),
HID_RI_PHYSICAL_MINIMUM(16, -32767),
HID_RI_PHYSICAL_MAXIMUM(16, 32767),
HID_RI_PUSH(0),
HID_RI_USAGE(8, HID_RI_USAGE_GENERIC_DESKTOP_RESOLUTION_MULTIPLIER),
HID_RI_LOGICAL_MINIMUM(8, 0),
HID_RI_LOGICAL_MAXIMUM(8, 1),
HID_RI_PHYSICAL_MINIMUM(8, USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE),
HID_RI_PHYSICAL_MAXIMUM(8, USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE),
HID_RI_REPORT_COUNT(8, 1),
HID_RI_REPORT_SIZE(8, 16),
HID_RI_REPORT_SIZE(8, 2),
HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_POP(0),
HID_RI_END_COLLECTION(0),

HID_RI_COLLECTION(8, HID_RI_COLLECTION_LOGICAL),
// Horizontal wheel
HID_RI_USAGE(32, (HID_RI_USAGE_PAGE_CONSUMER << 16) | HID_RI_USAGE_CONSUMER_AC_PAN),
HID_RI_INPUT(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_RELATIVE),

HID_RI_PUSH(0),
HID_RI_USAGE(8, HID_RI_USAGE_GENERIC_DESKTOP_RESOLUTION_MULTIPLIER),
HID_RI_LOGICAL_MINIMUM(8, 0),
HID_RI_LOGICAL_MAXIMUM(8, 1),
HID_RI_PHYSICAL_MINIMUM(8, USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE),
HID_RI_PHYSICAL_MAXIMUM(8, USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE),
HID_RI_REPORT_COUNT(8, 1),
HID_RI_REPORT_SIZE(8, 2),
HID_RI_FEATURE(8, HID_IOF_DATA | HID_IOF_VARIABLE | HID_IOF_ABSOLUTE),
HID_RI_POP(0),
HID_RI_END_COLLECTION(0),
HID_RI_REPORT_SIZE(8, 4),
HID_RI_FEATURE(8, HID_IOF_CONSTANT),

HID_RI_END_COLLECTION(0),
HID_RI_END_COLLECTION(0)
Expand Down
71 changes: 27 additions & 44 deletions right/src/usb_interfaces/usb_interface_mouse.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ static bool needsResending = false;

static usb_mouse_report_t usbMouseReports[2];

usb_hid_protocol_t usbMouseProtocol;
uint32_t UsbMouseActionCounter;
usb_mouse_report_t* ActiveUsbMouseReport = usbMouseReports;

Expand All @@ -36,19 +35,28 @@ static void SwitchActiveUsbMouseReport(void)

#ifndef __ZEPHYR__

static uint8_t usbMouseFeatBuffer[USB_MOUSE_FEAT_REPORT_LENGTH];
typedef struct {
#if USB_MOUSE_REPORT_ID
uint8_t id;
#endif
uint8_t scrollMultipliers;
} ATTR_PACKED usb_mouse_feature_report_t;

usb_hid_protocol_t UsbMouseGetProtocol(void)
{
return usbMouseProtocol;
}
static usb_mouse_feature_report_t usbMouseFeatureReport = {
#if USB_MOUSE_REPORT_ID
.id = USB_MOUSE_REPORT_ID
#endif
};

usb_status_t UsbMouseAction(void)
{
if (!UsbCompositeDevice.attach) {
return kStatus_USB_Error; // The device is not attached
}

#if USB_MOUSE_REPORT_ID
ActiveUsbMouseReport->id = USB_MOUSE_REPORT_ID;
#endif
usb_status_t usb_status = USB_DeviceHidSend(
UsbCompositeDevice.mouseHandle, USB_MOUSE_ENDPOINT_INDEX,
(uint8_t *)ActiveUsbMouseReport, USB_MOUSE_REPORT_LENGTH);
Expand All @@ -57,20 +65,17 @@ usb_status_t UsbMouseAction(void)
SwitchActiveUsbMouseReport();
}

// latch the active protocol to avoid ISR <-> Thread race
usbMouseProtocol = ((usb_device_hid_struct_t*)UsbCompositeDevice.mouseHandle)->protocol;

return usb_status;
}

float VerticalScrollMultiplier(void)
{
return usbMouseFeatBuffer[0] & 0x01 ? USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE : USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE;
return usbMouseFeatureReport.scrollMultipliers & 0x01 ? USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE : USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE;
}

float HorizontalScrollMultiplier(void)
{
return usbMouseFeatBuffer[0] & 0x01 ? USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE : USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE;
return usbMouseFeatureReport.scrollMultipliers & 0x04 ? USB_MOUSE_REPORT_DESCRIPTOR_MAX_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE : USB_MOUSE_REPORT_DESCRIPTOR_MIN_RESOLUTION_MULTIPLIER_PHYSICAL_VALUE;
}

usb_status_t UsbMouseCallback(class_handle_t handle, uint32_t event, void *param)
Expand All @@ -80,7 +85,7 @@ usb_status_t UsbMouseCallback(class_handle_t handle, uint32_t event, void *param

switch (event) {
case ((uint32_t)-kUSB_DeviceEventSetConfiguration):
usbMouseFeatBuffer[0] = 0;
usbMouseFeatureReport.scrollMultipliers = 0;
error = kStatus_USB_Success;
break;
case ((uint32_t)-kUSB_DeviceEventSetInterface):
Expand All @@ -98,16 +103,17 @@ usb_status_t UsbMouseCallback(class_handle_t handle, uint32_t event, void *param

case kUSB_DeviceHidEventGetReport: {
usb_device_hid_report_struct_t *report = (usb_device_hid_report_struct_t*)param;
if (report->reportId != 0) {
if (report->reportId != USB_MOUSE_REPORT_ID) {
error = kStatus_USB_InvalidRequest;
} else if (report->reportType == USB_DEVICE_HID_REQUEST_GET_REPORT_TYPE_INPUT && report->reportLength <= USB_MOUSE_REPORT_LENGTH) {
} else if (report->reportType == USB_DEVICE_HID_REQUEST_GET_REPORT_TYPE_INPUT) {
report->reportBuffer = (void*)ActiveUsbMouseReport;
report->reportLength == USB_MOUSE_REPORT_LENGTH;
UsbMouseActionCounter++;
SwitchActiveUsbMouseReport();
error = kStatus_USB_Success;
} else if (report->reportType == USB_DEVICE_HID_REQUEST_GET_REPORT_TYPE_FEATURE) {
report->reportBuffer = usbMouseFeatBuffer;
report->reportLength = sizeof(usbMouseFeatBuffer);
report->reportBuffer = (void*)&usbMouseFeatureReport;
report->reportLength = sizeof(usbMouseFeatureReport);
error = kStatus_USB_Success;
} else {
error = kStatus_USB_InvalidRequest;
Expand All @@ -117,12 +123,8 @@ usb_status_t UsbMouseCallback(class_handle_t handle, uint32_t event, void *param

case kUSB_DeviceHidEventSetReport: {
usb_device_hid_report_struct_t *report = (usb_device_hid_report_struct_t*)param;
if (report->reportType == USB_DEVICE_HID_REQUEST_GET_REPORT_TYPE_FEATURE && report->reportId == 0 && report->reportLength <= sizeof(usbMouseFeatBuffer)) {
// With a single resolution multiplier, this case will never be
// hit on Linux (for multiple resolution multipliers, one value
// will be missing, so would have to be inferred from the
// other(s)). But Windows does use this request properly, so it
// needs to be handled appropriately.
if (report->reportType == USB_DEVICE_HID_REQUEST_GET_REPORT_TYPE_FEATURE &&
report->reportLength == sizeof(usbMouseFeatureReport)) {
error = kStatus_USB_Success;
} else {
error = kStatus_USB_InvalidRequest;
Expand All @@ -132,35 +134,16 @@ usb_status_t UsbMouseCallback(class_handle_t handle, uint32_t event, void *param

case kUSB_DeviceHidEventRequestReportBuffer: {
usb_device_hid_report_struct_t *report = (usb_device_hid_report_struct_t*)param;
if (report->reportType == USB_DEVICE_HID_REQUEST_GET_REPORT_TYPE_FEATURE && report->reportId == 0 && report->reportLength <= sizeof(usbMouseFeatBuffer)) {
// The Linux implementation of SetReport when initializing a
// device with a single resolution multiplier value is broken,
// sending an empty report, and as a result the
// kUSB_DeviceHidEventSetReport case above isn't triggered at
// all; but it only sends this report when it detects the
// resolution multiplier, and the intention is to activate the
// feature, so turn high-res mode on here.
report->reportBuffer = usbMouseFeatBuffer;
usbMouseFeatBuffer[0] = 0x1;
if (report->reportType == USB_DEVICE_HID_REQUEST_GET_REPORT_TYPE_FEATURE) {
report->reportBuffer = (void*)&usbMouseFeatureReport;
report->reportLength = sizeof(usbMouseFeatureReport);
error = kStatus_USB_Success;
} else {
error = kStatus_USB_AllocFail;
}
break;
}

case kUSB_DeviceHidEventSetProtocol: {
uint8_t report = *(uint16_t*)param;
if (report <= 1) {
hidHandle->protocol = report;
error = kStatus_USB_Success;
}
else {
error = kStatus_USB_InvalidRequest;
}
break;
}

default:
break;
}
Expand Down
12 changes: 4 additions & 8 deletions right/src/usb_interfaces/usb_interface_mouse.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "usb_api.h"
// #include "usb_descriptors/usb_descriptor_device.h"
#include "usb_descriptors/usb_descriptor_mouse_report.h"

// Macros:

Expand All @@ -18,17 +19,13 @@
#define USB_MOUSE_INTERRUPT_IN_INTERVAL 1

#define USB_MOUSE_REPORT_LENGTH (sizeof(usb_mouse_report_t))
#define USB_MOUSE_FEAT_REPORT_LENGTH 1

// Typedefs:

// Note: We support boot protocol mode in this interface, thus the mouse
// report may not exceed 8 bytes and must conform to the HID mouse boot
// protocol as specified in the USB HID specification. If a different or
// longer format is desired in the future, we will need to translate sent
// reports to the boot protocol format when the host has set boot protocol
// mode.
typedef struct {
#ifdef USB_MOUSE_REPORT_ID
uint8_t id;
#endif
uint32_t buttons : 24;
int16_t x;
int16_t y;
Expand All @@ -46,7 +43,6 @@
#ifndef __ZEPHYR__
usb_status_t UsbMouseCallback(class_handle_t handle, uint32_t event, void *param);
usb_status_t UsbMouseAction(void);
usb_hid_protocol_t UsbMouseGetProtocol(void);
#endif

float VerticalScrollMultiplier(void);
Expand Down