[client] usbredir: add parser bridge

Add a serialized bridge between PureSpice USB redirection channels and
libusbredirparser.

Claim one channel and stream borrowed fragments directly through the
parser without packet allocations. Provide an atomic device plug request
for later audio integration.
This commit is contained in:
Geoffrey McRae
2026-08-09 21:09:52 +10:00
parent 4c53f5b9f8
commit 6d1b0c3004
3 changed files with 449 additions and 0 deletions

69
client/src/usbredir.h Normal file
View File

@@ -0,0 +1,69 @@
/**
* Looking Glass
* Copyright © 2017-2026 The Looking Glass Authors
* https://looking-glass.io
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the Free
* Software Foundation; either version 2 of the License, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc., 59
* Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef _H_LG_CLIENT_USBREDIR_
#define _H_LG_CLIENT_USBREDIR_
#include <purespice.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
struct usbredirparser;
typedef struct LG_USBRedir LG_USBRedir;
typedef struct LG_USBRedirDeviceOps
{
/* Install the device packet callbacks on a newly-created parser. */
void (*setup)(void * opaque, struct usbredirparser * parser);
/* Queue the device descriptors and connection announcement. */
void (*plug)(void * opaque, struct usbredirparser * parser);
/* Stop all device activity. The bridge sends the disconnect packet. */
void (*unplug)(void * opaque);
}
LG_USBRedirDeviceOps;
LG_USBRedir * lgUsbRedir_create(
const LG_USBRedirDeviceOps * deviceOps, void * deviceOpaque);
/* The PureSpice session must be stopped before destroying the bridge. */
void lgUsbRedir_destroy(LG_USBRedir * usbredir);
/* This may be called from another thread. The request is applied by
* lgUsbRedir_process on the PureSpice processing thread. */
void lgUsbRedir_setPlugged(LG_USBRedir * usbredir, bool plugged);
bool lgUsbRedir_available(const LG_USBRedir * usbredir);
/* Apply pending device state and flush parser output. This must be called on
* the PureSpice processing thread. */
bool lgUsbRedir_process(LG_USBRedir * usbredir);
void lgUsbRedir_state(PSUSBRedirChannel * channel,
PSUSBRedirState state, void * opaque);
bool lgUsbRedir_data(PSUSBRedirChannel * channel,
const uint8_t * data, size_t size, void * opaque);
/* Parser callbacks receive the bridge as their opaque value. */
void * lgUsbRedir_device(void * parserOpaque);
#endif