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}, .group= 1, .clock{.sync{.reference= true}}, .configurations= 1, .config{{.id= 1, .channels= 2, .format= dx::stream::pcm24, .clock{.domain= 1}}},
.pins= 1, .pin{{.name=
"Out", .format{.audio=
true, .resolution= 24, .size= 3}, .plug=
dx::stream::plug::line, .channels= 2}}},
{.target{.address= 0x81}, .group= 1, .clock{.sync{.reference= true}}, .configurations= 1, .config{{.id= 1, .channels= 2, .format= dx::stream::pcm24, .clock{.domain= 1}}},
.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:89
@ usb
Definition dx_stream.h:506
@ line
Definition dx_stream.h:582
device streaming interface descriptor
Definition dx_stream.h:731
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::portcls::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::power<dxd::portcls::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): power{
driver, registry,
name, guid} {ports= myproduct::device::capacity;}
};
}
extern "C" ::NTSTATUS DriverEntry(::DRIVER_OBJECT* driver, ::UNICODE_STRING* registry){
}
Definition wdm/dxd_platform.h:201
the adapter device's WaveRT endpoints over its streaming device's rings
Definition dxd_portcls_audio.h:1370
WDM unicode string helper.
Definition dxd_wdm.h:41
#define DX_LSTRINGIFY(x)
Definition dx_macros.h:47
dx::stream::desc< target, 2, 2 > desc
Definition dx_coremidi_device.h:33
@ create
create a device: its id zero terminated, its desc after it
Definition macOS/dx_platform.h:136
dx::stream::driver< proxy::driver< device_t > > driver
Definition dx_proxy_stream_driver.h:33
bus
Definition dx_stream.h:502
std::string name()
Definition macOS/dx_sync.h:230
portcls::device< streaming_device_t > device
Definition wdm/portcls/dxd_audio.h:32
platform::device * create(driver &driver, ::IOService *service)
the product's device factory, called when a device's shell starts - what dxd::create<adapter> in Driv...
::IOReturn os_result
defining platform abstract type os_result for IOKit driver
Definition driverkit/dxd_platform.h:74
@ ok
Definition driverkit/dxd_platform.h:76
char serial[0x40]
empty when the device has none
Definition dx_stream.h:746
uint32_t version
Definition dx_stream.h:732
struct dx::stream::desc::name_id model
uint32_t enumerate(const format &format=any) const
enumerate typified pins
Definition dx_stream.h:1168
struct dx::stream::desc::firmware firmware
struct dx::stream::desc::name_id vendor
promoted super
Definition windows/service/dx_service.h:270
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::match
match{models};
}
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::match
match{};
}
}
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
@ match
IR contexts alone.
Definition dx_firewire_ohci.h:101
@ ok
Definition macOS/dx_platform.h:205
@ not_permitted
Definition macOS/dx_platform.h:223
The hosts wrap them:
- the CoreAudio server plugin (macOS): dx::coreaudio::server::plugin<dx::coreaudio::server::pin<myproduct::usb::audio::pin<dx::coreaudio::server::preference>>>, exported as create_plugin
- the device tree service (Windows): dx::service::driver<dx::asio::service::driver<dx::proxy::stream::driver<dx::asio::service::device<device>>>> hosting the WinUSB device, its streams over shared memory, or the kernel driver's; it registers the ASIO driver on a device's arrival
- the ASIO driver (Windows): dx::asio::driver<dx::stream::engine::device<client>, client_driver> over the service client or the proxy
- a service of a driver's own: dx::service::driver<dx::proxy::driver<device>>, a product's driver answering its own IOCTLs ahead (ioctl(peer&, ...)), its peer per client (peer_create()) - dxd_service and dxd_daemon(... SERVICE) build it, the launchd daemon of the product's id on macOS
- the doorman daemon (macOS): dx::daemon::app{argc, argv}.run(), capturing the listed devices for an Apple signed peer
- the driver package installer (Windows): dx::install::parser{name, class, hwids}<< args - the .msi's custom actions and a command line
The test app
dx::select takes one dx::test::stream::driver per bus - dx::test::driver where a device streams nothing - and parses the command line - --<bus> --help lists what a bus offers:
std::deque< std::string > args
Definition dx_parser.h:64
select from aggregated drivers
Definition dx_parser.h:377
#define DX_STRINGIFY(...)
Definition dx_macros.h:45
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.