Basics
A driver is a composition of framework layers around the product's device description. The description is one table:
#include "version.h"
#include <dx_stream_desc.h>
namespace myproduct{
constexpr desc models[]{
.clocks= 1, .clock{{.settings= 1, .setting{{.name= "Internal"}}, .defaults{.samplerate= 48000, .iosize{.hw_ticks= 5, .hw_min_ticks= 1, .hw_max_ticks= 32}}, .resolution= 1000}},
.streams= 2, .stream{
{.target{.address= 0x02, .interface= 1, .setting= 1}, .group= 1, .configurations= 1, .config{{.channels= 2, .wordlength= 3, .clock{.domain= 1, .sync{.reference= true}}}},
.pins= 1, .pin{{.name=
"Out", .format{.audio=
true, .resolution= 24, .size= 3}, .plug=
dx::stream::plug::line, .channels= 2}}},
{.target{.address= 0x81, .interface= 1, .setting= 1}, .group= 1, .configurations= 1, .config{{.channels= 2, .wordlength= 3, .clock{.domain= 1, .sync{.reference= true}}}},
.pins= 1, .pin{{.name=
"In", .format{.audio=
true, .resolution= 24, .size= 3}, .plug=
dx::stream::plug::line, .channels= 2}}}}},
};
}
#define DX_VERSION32
Definition dx_macros.h:77
@ usb
Definition dx_stream.h:430
@ line
Definition dx_stream.h:506
device streaming interface descriptor
Definition dx_stream.h:651
A model without streams is a class compliant USB audio device: dx::usb::audio::configure() builds its clocks, streams and pins from the configuration descriptor, in user mode and in the kernel alike.
The kernel driver (Windows)
A PortCls audio adapter over a USB device, every audio pin a WaveRT subdevice:
#include "version.h"
#include "drv.h"
extern "C" int _fltused= 0x9875;
namespace myproduct{
class device:
public licensed,
public dxd::portcls::device<dxd::usb::stream::device<dxd::adapter::device, myproduct::desc>>{
try(status= super::launch());
for(const auto& model: models)
if(model.model.id== idProduct){
if(model.streams)
desc= model;
else{
}
break;
}
catch:
return status;
}
public:
using super::super;
};
class adapter: public dxd::adapter{
device*
create(::DEVICE_OBJECT*
object, ::DEVICE_OBJECT* pdo, ::DEVICE_OBJECT* bus)
override {return ::new myproduct::device{*
this, object, pdo,
bus};}
public:
adapter(::DRIVER_OBJECT* driver, ::UNICODE_STRING* registry,
const wchar_t* name,
const dxd::guid& guid): dxd::adapter{
driver, registry,
name, guid} {ports= myproduct::device::capacity;}
};
}
extern "C" ::NTSTATUS DriverEntry(::DRIVER_OBJECT* driver, ::UNICODE_STRING* registry){
}
Definition wdk/dxd_platform.h:192
the adapter device's WaveRT endpoints over its streaming device's rings
Definition dxd_portcls_audio.h:1374
WDM unicode string helper.
Definition dxd_wdm.h:41
#define DX_LSTRINGIFY(x)
Definition dx_macros.h:36
promoted super
Definition dx_pipe.h:154
dx::stream::desc< target, 2, 2 > desc
Definition dx_coremidi_device.h:33
bus
Definition dx_stream.h:426
std::string name()
Definition macOS/dx_sync.h:231
dx::virtuel::driver< device<> > driver
Definition dx_virtual_stream_device.h:207
::IOReturn os_result
defining platform abstract type os_result for IOKit driver
Definition driverkit/dxd_platform.h:49
@ ok
Definition driverkit/dxd_platform.h:51
::NTSTATUS create(::DRIVER_OBJECT *wdm_driver, ::UNICODE_STRING *registry, const wchar_t *name=L"", dxd::guid guid=0)
Definition wdk/dxd_platform.h:278
char serial[0x40]
empty when the device has none
Definition dx_stream.h:669
uint32_t version
Definition dx_stream.h:652
struct dx::stream::desc::name_id model
uint32_t enumerate(const format &format=any) const
enumerate typified pins
Definition dx_stream.h:1031
struct dx::stream::desc::firmware firmware
struct dx::stream::desc::name_id vendor
Kernel code has no exceptions: a function returns dxd::os_result, try(status= ...) jumps to the function's catch: label on failure, dxd::log/warnlog/errorlog report. What the device holds on the stack below goes in conclude(), the destructor frees memory alone. The adapter's device interface (DX_PRODUCT_GUID) is what user mode's proxy device enumerates.
The user mode drivers
drv.h composes the devices from the framework's layers, each templated on the platform's preference store; a product's own base (its license, a doorman asking the daemon for a capture) comes first:
namespace myproduct{
namespace usb{
template<
typename preference_t= dx::preference>
class device:
public licensed,
public dx::usb::stream::device<desc, preference_t>{
public:
using super::super;
};
static const dx::proxy::driver<device<>>::match match{dx::guid{
DX_STRINGIFY(DX_PRODUCT_GUID)}};
}
namespace proxy{
template<typename preference_t= dx::preference> class device: public licensed, public dx::proxy::stream::device<desc, preference_t>{
typedef dx::proxy::stream::device<desc, preference_t>
super;
public:
using super::super;
};
static const dx::proxy::driver<device<>>::match match{dx::guid{
DX_STRINGIFY(DX_PRODUCT_GUID)}};
}
}
one client's attachment to a stream: the pin desc it was made from, the channels it takes of that str...
Definition dx_stream_pin.h:49
the bus's device as a product composes it: the _device above with this bus's pipes and its own tickin...
Definition dx_usb_stream_device.h:294
#define dx_pass(test,...)
Definition dx_exception.h:55
#define DX_STRINGIFY(...)
Definition dx_macros.h:34
@ ok
Definition macOS/dx_platform.h:182
@ not_permitted
Definition macOS/dx_platform.h:200
The hosts wrap them:
The test app
dx::select takes one dx::test::driver per bus and parses the command line - --<bus> --help lists what a bus offers:
std::deque< std::string > args
Definition dx_parser.h:60
select from aggregated drivers
Definition dx_parser.h:351
forwards a braced argument list into a type with no matching constructor - the conversion builds it f...
Definition dx_common.h:544
--<bus> --info lists the devices, --<bus> --0 --streaming-monitor [loopback|pattern-test|generator] <sec> runs a session on the first device, --<bus> --unit-test the driver and device life cycle, --log-level persists into the bus's preference store.