diff --git a/app/src/control_msg.c b/app/src/control_msg.c index 0defda92..e78f0c57 100644 --- a/app/src/control_msg.c +++ b/app/src/control_msg.c @@ -152,8 +152,10 @@ sc_control_msg_serialize(const struct sc_control_msg *msg, uint8_t *buf) { return 2; case SC_CONTROL_MSG_TYPE_UHID_CREATE: sc_write16be(&buf[1], msg->uhid_create.id); + sc_write16be(&buf[3], msg->uhid_create.vendor_id); + sc_write16be(&buf[5], msg->uhid_create.product_id); - size_t index = 3; + size_t index = 7; index += write_string_tiny(&buf[index], msg->uhid_create.name, 127); sc_write16be(&buf[index], msg->uhid_create.report_desc_size); @@ -278,9 +280,13 @@ sc_control_msg_log(const struct sc_control_msg *msg) { // Quote only if name is not null const char *name = msg->uhid_create.name; const char *quote = name ? "\"" : ""; - LOG_CMSG("UHID create [%" PRIu16 "] name=%s%s%s " - "report_desc_size=%" PRIu16, msg->uhid_create.id, - quote, name, quote, msg->uhid_create.report_desc_size); + LOG_CMSG("UHID create [%" PRIu16 "] %04" PRIx16 ":%04" PRIx16 + " name=%s%s%s report_desc_size=%" PRIu16, + msg->uhid_create.id, + msg->uhid_create.vendor_id, + msg->uhid_create.product_id, + quote, name, quote, + msg->uhid_create.report_desc_size); break; } case SC_CONTROL_MSG_TYPE_UHID_INPUT: { diff --git a/app/src/control_msg.h b/app/src/control_msg.h index f0a2e373..74dbcba8 100644 --- a/app/src/control_msg.h +++ b/app/src/control_msg.h @@ -94,6 +94,8 @@ struct sc_control_msg { } set_display_power; struct { uint16_t id; + uint16_t vendor_id; + uint16_t product_id; const char *name; // pointer to static data uint16_t report_desc_size; const uint8_t *report_desc; // pointer to static data diff --git a/app/src/hid/hid_event.h b/app/src/hid/hid_event.h index 37c3611b..b546872c 100644 --- a/app/src/hid/hid_event.h +++ b/app/src/hid/hid_event.h @@ -15,6 +15,8 @@ struct sc_hid_input { struct sc_hid_open { uint16_t hid_id; + uint16_t vendor_id; + uint16_t product_id; const char *name; // pointer to static memory const uint8_t *report_desc; // pointer to static memory size_t report_desc_size; diff --git a/app/src/hid/hid_gamepad.c b/app/src/hid/hid_gamepad.c index 892d21f2..e8075abe 100644 --- a/app/src/hid/hid_gamepad.c +++ b/app/src/hid/hid_gamepad.c @@ -236,7 +236,9 @@ sc_hid_gamepad_slot_get_id(size_t slot_idx) { bool sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid, struct sc_hid_open *hid_open, - uint32_t gamepad_id) { + uint32_t gamepad_id, + uint16_t vendor_id, + uint16_t product_id) { assert(gamepad_id != SC_GAMEPAD_ID_INVALID); ssize_t slot_idx = sc_hid_gamepad_slot_find(hid, SC_GAMEPAD_ID_INVALID); if (slot_idx == -1) { @@ -253,6 +255,8 @@ sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid, uint16_t hid_id = sc_hid_gamepad_slot_get_id(slot_idx); hid_open->hid_id = hid_id; + hid_open->vendor_id = vendor_id; + hid_open->product_id = product_id; hid_open->name = name; hid_open->report_desc = SC_HID_GAMEPAD_REPORT_DESC; hid_open->report_desc_size = sizeof(SC_HID_GAMEPAD_REPORT_DESC); diff --git a/app/src/hid/hid_gamepad.h b/app/src/hid/hid_gamepad.h index b532a703..38b8b808 100644 --- a/app/src/hid/hid_gamepad.h +++ b/app/src/hid/hid_gamepad.h @@ -33,7 +33,9 @@ sc_hid_gamepad_init(struct sc_hid_gamepad *hid); bool sc_hid_gamepad_generate_open(struct sc_hid_gamepad *hid, struct sc_hid_open *hid_open, - uint32_t gamepad_id); + uint32_t gamepad_id, + uint16_t vendor_id, + uint16_t product_id); bool sc_hid_gamepad_generate_close(struct sc_hid_gamepad *hid, diff --git a/app/src/hid/hid_keyboard.c b/app/src/hid/hid_keyboard.c index 2109224a..d7a839c4 100644 --- a/app/src/hid/hid_keyboard.c +++ b/app/src/hid/hid_keyboard.c @@ -335,6 +335,8 @@ sc_hid_keyboard_generate_input_from_mods(struct sc_hid_input *hid_input, void sc_hid_keyboard_generate_open(struct sc_hid_open *hid_open) { hid_open->hid_id = SC_HID_ID_KEYBOARD; + hid_open->vendor_id = 0; + hid_open->product_id = 0; hid_open->name = NULL; // No name specified after "scrcpy" hid_open->report_desc = SC_HID_KEYBOARD_REPORT_DESC; hid_open->report_desc_size = sizeof(SC_HID_KEYBOARD_REPORT_DESC); diff --git a/app/src/hid/hid_mouse.c b/app/src/hid/hid_mouse.c index ac215165..36937fe5 100644 --- a/app/src/hid/hid_mouse.c +++ b/app/src/hid/hid_mouse.c @@ -190,6 +190,8 @@ sc_hid_mouse_generate_input_from_scroll(struct sc_hid_input *hid_input, void sc_hid_mouse_generate_open(struct sc_hid_open *hid_open) { hid_open->hid_id = SC_HID_ID_MOUSE; + hid_open->vendor_id = 0; + hid_open->product_id = 0; hid_open->name = NULL; // No name specified after "scrcpy" hid_open->report_desc = SC_HID_MOUSE_REPORT_DESC; hid_open->report_desc_size = sizeof(SC_HID_MOUSE_REPORT_DESC); diff --git a/app/src/uhid/gamepad_uhid.c b/app/src/uhid/gamepad_uhid.c index ed52ba3b..fde3cddc 100644 --- a/app/src/uhid/gamepad_uhid.c +++ b/app/src/uhid/gamepad_uhid.c @@ -7,6 +7,9 @@ /** Downcast gamepad processor to sc_gamepad_uhid */ #define DOWNCAST(GP) container_of(GP, struct sc_gamepad_uhid, gamepad_processor) +#define SC_GAMEPAD_UHID_VENDOR_ID 0 +#define SC_GAMEPAD_UHID_PRODUCT_ID 0 + static void sc_gamepad_uhid_send_input(struct sc_gamepad_uhid *gamepad, const struct sc_hid_input *hid_input, @@ -30,6 +33,8 @@ sc_gamepad_uhid_send_open(struct sc_gamepad_uhid *gamepad, struct sc_control_msg msg; msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE; msg.uhid_create.id = hid_open->hid_id; + msg.uhid_create.vendor_id = hid_open->vendor_id; + msg.uhid_create.product_id = hid_open->product_id; msg.uhid_create.name = hid_open->name; msg.uhid_create.report_desc = hid_open->report_desc; msg.uhid_create.report_desc_size = hid_open->report_desc_size; @@ -58,7 +63,9 @@ sc_gamepad_processor_process_gamepad_added(struct sc_gamepad_processor *gp, struct sc_hid_open hid_open; if (!sc_hid_gamepad_generate_open(&gamepad->hid, &hid_open, - event->gamepad_id)) { + event->gamepad_id, + SC_GAMEPAD_UHID_VENDOR_ID, + SC_GAMEPAD_UHID_PRODUCT_ID)) { return; } diff --git a/app/src/uhid/keyboard_uhid.c b/app/src/uhid/keyboard_uhid.c index 496da23d..c2395483 100644 --- a/app/src/uhid/keyboard_uhid.c +++ b/app/src/uhid/keyboard_uhid.c @@ -141,6 +141,8 @@ sc_keyboard_uhid_init(struct sc_keyboard_uhid *kb, struct sc_control_msg msg; msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE; msg.uhid_create.id = SC_HID_ID_KEYBOARD; + msg.uhid_create.vendor_id = hid_open.vendor_id; + msg.uhid_create.product_id = hid_open.product_id; msg.uhid_create.name = hid_open.name; msg.uhid_create.report_desc = hid_open.report_desc; msg.uhid_create.report_desc_size = hid_open.report_desc_size; diff --git a/app/src/uhid/mouse_uhid.c b/app/src/uhid/mouse_uhid.c index 1dc02777..79a018df 100644 --- a/app/src/uhid/mouse_uhid.c +++ b/app/src/uhid/mouse_uhid.c @@ -81,6 +81,8 @@ sc_mouse_uhid_init(struct sc_mouse_uhid *mouse, struct sc_control_msg msg; msg.type = SC_CONTROL_MSG_TYPE_UHID_CREATE; msg.uhid_create.id = SC_HID_ID_MOUSE; + msg.uhid_create.vendor_id = hid_open.vendor_id; + msg.uhid_create.product_id = hid_open.product_id; msg.uhid_create.name = hid_open.name; msg.uhid_create.report_desc = hid_open.report_desc; msg.uhid_create.report_desc_size = hid_open.report_desc_size; diff --git a/app/src/usb/gamepad_aoa.c b/app/src/usb/gamepad_aoa.c index f8f15ffa..b521b58d 100644 --- a/app/src/usb/gamepad_aoa.c +++ b/app/src/usb/gamepad_aoa.c @@ -13,7 +13,7 @@ sc_gamepad_processor_process_gamepad_added(struct sc_gamepad_processor *gp, struct sc_hid_open hid_open; if (!sc_hid_gamepad_generate_open(&gamepad->hid, &hid_open, - event->gamepad_id)) { + event->gamepad_id, 0, 0)) { return; } diff --git a/app/tests/test_control_msg_serialize.c b/app/tests/test_control_msg_serialize.c index 9adf2a3d..af97182d 100644 --- a/app/tests/test_control_msg_serialize.c +++ b/app/tests/test_control_msg_serialize.c @@ -329,6 +329,8 @@ static void test_serialize_uhid_create(void) { .type = SC_CONTROL_MSG_TYPE_UHID_CREATE, .uhid_create = { .id = 42, + .vendor_id = 0x1234, + .product_id = 0x5678, .name = "ABC", .report_desc_size = sizeof(report_desc), .report_desc = report_desc, @@ -337,11 +339,13 @@ static void test_serialize_uhid_create(void) { uint8_t buf[SC_CONTROL_MSG_MAX_SIZE]; size_t size = sc_control_msg_serialize(&msg, buf); - assert(size == 20); + assert(size == 24); const uint8_t expected[] = { SC_CONTROL_MSG_TYPE_UHID_CREATE, 0, 42, // id + 0x12, 0x34, // vendor id + 0x56, 0x78, // product id 3, // name size 65, 66, 67, // "ABC" 0, 11, // report desc size diff --git a/server/src/main/java/com/genymobile/scrcpy/control/ControlMessage.java b/server/src/main/java/com/genymobile/scrcpy/control/ControlMessage.java index 7455cdf8..0eb96adc 100644 --- a/server/src/main/java/com/genymobile/scrcpy/control/ControlMessage.java +++ b/server/src/main/java/com/genymobile/scrcpy/control/ControlMessage.java @@ -51,6 +51,8 @@ public final class ControlMessage { private int id; private byte[] data; private boolean on; + private int vendorId; + private int productId; private ControlMessage() { } @@ -131,10 +133,12 @@ public final class ControlMessage { return msg; } - public static ControlMessage createUhidCreate(int id, String name, byte[] reportDesc) { + public static ControlMessage createUhidCreate(int id, int vendorId, int productId, String name, byte[] reportDesc) { ControlMessage msg = new ControlMessage(); msg.type = TYPE_UHID_CREATE; msg.id = id; + msg.vendorId = vendorId; + msg.productId = productId; msg.text = name; msg.data = reportDesc; return msg; @@ -237,4 +241,12 @@ public final class ControlMessage { public boolean getOn() { return on; } + + public int getVendorId() { + return vendorId; + } + + public int getProductId() { + return productId; + } } diff --git a/server/src/main/java/com/genymobile/scrcpy/control/ControlMessageReader.java b/server/src/main/java/com/genymobile/scrcpy/control/ControlMessageReader.java index b82615ed..e503ec61 100644 --- a/server/src/main/java/com/genymobile/scrcpy/control/ControlMessageReader.java +++ b/server/src/main/java/com/genymobile/scrcpy/control/ControlMessageReader.java @@ -142,9 +142,11 @@ public class ControlMessageReader { private ControlMessage parseUhidCreate() throws IOException { int id = dis.readUnsignedShort(); + int vendorId = dis.readUnsignedShort(); + int productId = dis.readUnsignedShort(); String name = parseString(1); byte[] data = parseByteArray(2); - return ControlMessage.createUhidCreate(id, name, data); + return ControlMessage.createUhidCreate(id, vendorId, productId, name, data); } private ControlMessage parseUhidInput() throws IOException { diff --git a/server/src/main/java/com/genymobile/scrcpy/control/Controller.java b/server/src/main/java/com/genymobile/scrcpy/control/Controller.java index a0bdc584..5e64a4c5 100644 --- a/server/src/main/java/com/genymobile/scrcpy/control/Controller.java +++ b/server/src/main/java/com/genymobile/scrcpy/control/Controller.java @@ -290,7 +290,7 @@ public class Controller implements AsyncProcessor, VirtualDisplayListener { Device.rotateDevice(getActionDisplayId()); break; case ControlMessage.TYPE_UHID_CREATE: - getUhidManager().open(msg.getId(), msg.getText(), msg.getData()); + getUhidManager().open(msg.getId(), msg.getVendorId(), msg.getProductId(), msg.getText(), msg.getData()); break; case ControlMessage.TYPE_UHID_INPUT: getUhidManager().writeInput(msg.getId(), msg.getData()); diff --git a/server/src/main/java/com/genymobile/scrcpy/control/UhidManager.java b/server/src/main/java/com/genymobile/scrcpy/control/UhidManager.java index 8121adfc..1d7678ec 100644 --- a/server/src/main/java/com/genymobile/scrcpy/control/UhidManager.java +++ b/server/src/main/java/com/genymobile/scrcpy/control/UhidManager.java @@ -48,7 +48,7 @@ public final class UhidManager { } } - public void open(int id, String name, byte[] reportDesc) throws IOException { + public void open(int id, int vendorId, int productId, String name, byte[] reportDesc) throws IOException { try { FileDescriptor fd = Os.open("/dev/uhid", OsConstants.O_RDWR, 0); try { @@ -58,7 +58,7 @@ public final class UhidManager { close(old); } - byte[] req = buildUhidCreate2Req(name, reportDesc); + byte[] req = buildUhidCreate2Req(vendorId, productId, name, reportDesc); Os.write(fd, req, 0, req.length); registerUhidListener(id, fd); @@ -148,7 +148,7 @@ public final class UhidManager { } } - private static byte[] buildUhidCreate2Req(String name, byte[] reportDesc) { + private static byte[] buildUhidCreate2Req(int vendorId, int productId, String name, byte[] reportDesc) { /* * struct uhid_event { * uint32_t type; @@ -183,8 +183,8 @@ public final class UhidManager { buf.putShort((short) reportDesc.length); buf.putShort(BUS_VIRTUAL); - buf.putInt(0); // vendor id - buf.putInt(0); // product id + buf.putInt(vendorId); + buf.putInt(productId); buf.putInt(0); // version buf.putInt(0); // country; buf.put(reportDesc);