Skip to content
Draft
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
Empty file.
Empty file.
21 changes: 21 additions & 0 deletions usb_protocol/contextmgrs/descriptors/microsoft.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#
# This file is part of usb-protocol.
#

from ...emitters.descriptors.microsoft import (
PlatformDescriptorCollection, PlatformDescriptorEmitter
)
from ...emitters.descriptors.standard import BinaryObjectStoreDescriptorEmitter
from ..manager import DescriptorContextManager

class PlatformDescriptor(DescriptorContextManager):
ParentDescriptor = BinaryObjectStoreDescriptorEmitter

def DescriptorEmitter(self) -> PlatformDescriptorEmitter:
return PlatformDescriptorEmitter(platform_collection = self._platform_collection)

def __init__(
self, parentDesc: ParentDescriptor, platform_collection: PlatformDescriptorCollection
) -> None:
self._platform_collection = platform_collection
super().__init__(parentDesc)
23 changes: 23 additions & 0 deletions usb_protocol/contextmgrs/manager.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#
# This file is part of usb-protocol.
#

from ..emitters.descriptor import ComplexDescriptorEmitter


class DescriptorContextManager:
ParentDescriptor = ComplexDescriptorEmitter
DescriptorEmitter = None

def __init__(self, parentDesc: ParentDescriptor) -> None:
self._parent = parentDesc
self._descriptor = self.DescriptorEmitter()

def __enter__(self):
return self._descriptor

def __exit__(self, exc_type, exc_value, traceback):
# If an exception was raised, fast exit
if not (exc_type is None and exc_value is None and traceback is None):
return
self._parent.add_subordinate_descriptor(self._descriptor)
199 changes: 199 additions & 0 deletions usb_protocol/emitters/descriptors/microsoft.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
#
# This file is part of usb-protocol.
#
""" Convenience emitters for Microsoft OS 2.0 descriptors. """

from contextlib import contextmanager
from typing import Dict

from .. import emitter_for_format
from ..descriptor import ComplexDescriptorEmitter

from ...types.descriptors.microsoft import *

# Create our basic emitters...
FeatureCompatibleIDEmitter = emitter_for_format(FeatureCompatibleID)
FeatureRegPropertyEmitter = emitter_for_format(FeatureRegProperty)
FeatureMinResumeTimeEmitter = emitter_for_format(FeatureMinResumeTime)
FeatureModelIDEmitter = emitter_for_format(FeatureModelID)
FeatureCCGPDeviceEmitter = emitter_for_format(FeatureCCGPDevice)
FeatureVendorRevisionEmitter = emitter_for_format(FeatureVendorRevision)

# ... and complex emitters.
class FeatureDescriptorEmitter(ComplexDescriptorEmitter):
""" Abstract base type for things that can hold Feature Descriptors. """

@contextmanager
def FeatureCompatibleID(self):
descriptor = FeatureCompatibleIDEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


@contextmanager
def FeatureRegProperty(self):
descriptor = FeatureRegPropertyEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


@contextmanager
def FeatureMinResumeTime(self):
descriptor = FeatureMinResumeTimeEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


@contextmanager
def FeatureModelID(self):
descriptor = FeatureModelIDEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


@contextmanager
def FeatureCCGPDevice(self):
descriptor = FeatureCCGPDeviceEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


@contextmanager
def FeatureVendorRevision(self):
descriptor = FeatureVendorRevisionEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


class SubsetHeaderFunctionEmitter(FeatureDescriptorEmitter):
""" Emitter that creates a SubsetHeaderFunctionEmitter. """

DESCRIPTOR_FORMAT = SubsetHeaderFunction

def _pre_emit(self):
# Figure out our total length.
subordinate_length = sum(len(sub) for sub in self._subordinates)
self.wTotalLength = subordinate_length + self.DESCRIPTOR_FORMAT.sizeof()


class SubsetHeaderConfigurationEmitter(FeatureDescriptorEmitter):
""" Emitter that creates a SubsetHeaderConfiguration. """

DESCRIPTOR_FORMAT = SubsetHeaderConfiguration

@contextmanager
def SubsetHeaderFunction(self):
descriptor = SubsetHeaderFunctionEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


def _pre_emit(self):
# Figure out our total length.
subordinate_length = sum(len(sub) for sub in self._subordinates)
self.wTotalLength = subordinate_length + self.DESCRIPTOR_FORMAT.sizeof()


class SetHeaderDescriptorEmitter(FeatureDescriptorEmitter):
""" Emitter that creates a SetHeaderDescriptor. """

DESCRIPTOR_FORMAT = SetHeaderDescriptor

@contextmanager
def SubsetHeaderConfiguration(self):
descriptor = SubsetHeaderConfigurationEmitter()
yield descriptor

self.add_subordinate_descriptor(descriptor)


def _pre_emit(self):
# Figure out our total length.
subordinate_length = sum(len(sub) for sub in self._subordinates)
self.wTotalLength = subordinate_length + self.DESCRIPTOR_FORMAT.sizeof()


class DescriptorSetInformationEmitter(ComplexDescriptorEmitter):
""" Emitter that creates a DescriptorSetInformation. """

DESCRIPTOR_FORMAT = DescriptorSetInformation

@contextmanager
def SetHeaderDescriptor(self):
assert hasattr(self, 'bMS_VendorCode')

descriptor = SetHeaderDescriptorEmitter()
yield descriptor

self._subordinate = descriptor
self._collection.add_descriptor(descriptor, vendor_code = self.bMS_VendorCode)


def _pre_emit(self):
# Figure out our total length.
self.wMSOSDescriptorSetTotalLength = self._subordinate.wTotalLength


class PlatformDescriptorCollection:
""" Object that holds the OS descriptor sets for windows """

def __init__(self):
self._descriptors = {}


def add_descriptor(self, descriptor : SetHeaderDescriptorEmitter, vendor_code : int):
""" Adds a descriptor to our collection.
Parameters:
descriptor -- The set header descriptor to be added.
vendor_code -- The vendor request code for this descriptor tree
"""

assert isinstance(descriptor, SetHeaderDescriptorEmitter)
descriptor = descriptor.emit()

self._descriptors[vendor_code] = descriptor


@property
def descriptors(self) -> Dict[int, bytes]:
return self._descriptors


class PlatformDescriptorEmitter(ComplexDescriptorEmitter):
""" Emitter that creates a PlatformDescriptor. """

DESCRIPTOR_FORMAT = PlatformDescriptor

def __init__(self, platform_collection : PlatformDescriptorCollection, *args, **kwargs):
super().__init__(*args, **kwargs)

self._platform_collection = platform_collection


@contextmanager
def DescriptorSetInformation(self):
""" Context manager that allows addition of the information associated with a descriptor set.
It can be used with a `with` statement; and yields a DescriptorSetInformationEmitter
that can be populated:
with platformDescriptor.DescriptorSetInformation() as dsi:
dsi.bMS_VendorCode = 1
This adds the relevant descriptor, automatically.
"""

descriptor = DescriptorSetInformationEmitter(collection = self._platform_collection)
yield descriptor

self.add_subordinate_descriptor(descriptor)


def _pre_emit(self):
# Figure out our total length.
subordinate_length = sum(len(sub) for sub in self._subordinates)
self.bLength = subordinate_length + self.DESCRIPTOR_FORMAT.sizeof()
50 changes: 49 additions & 1 deletion usb_protocol/emitters/descriptors/standard.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,19 @@ def get_string_descriptor(string):
return emitter.emit()

# ... and complex emitters.
class InterfaceAssociationDescriptorEmitter(ComplexDescriptorEmitter):
""" Emitter that creates an InterfaceAssociationDescriptor. """

DESCRIPTOR_FORMAT = InterfaceAssociationDescriptor

def _pre_emit(self):
# Ensure that our function string is an index, if we can.
if self._collection and hasattr(self, 'iFunction'):
self.iFunction = self._collection.ensure_string_field_is_index(self.iFunction)


class EndpointDescriptorEmitter(ComplexDescriptorEmitter):
""" Emitter that creates an InterfaceDescriptor. """
""" Emitter that creates an EndpointDescriptor. """

DESCRIPTOR_FORMAT = EndpointDescriptor

Expand Down Expand Up @@ -127,6 +137,25 @@ def InterfaceDescriptor(self):
self.add_subordinate_descriptor(descriptor)


@contextmanager
def InterfaceAssociationDescriptor(self):
""" Context manager that allows addition of a subordinate interface association descriptor.

It can be used with a `with` statement; and yields an InterfaceAssociationDescriptorEmitter
that can be populated:

with interface.InterfaceAssociationDescriptor() as d:
d.bFirstInterface = 0
[snip]

This adds the relevant descriptor, automatically.
"""
descriptor = InterfaceAssociationDescriptorEmitter(collection=self._collection)
yield descriptor

self.add_subordinate_descriptor(descriptor)


def _pre_emit(self):

# Count our interfaces. Alternate settings of the same interface do not count multiple times.
Expand Down Expand Up @@ -307,6 +336,25 @@ def ConfigurationDescriptor(self):
self.add_descriptor(descriptor)


@contextmanager
def BOSDescriptor(self):
""" Context manager that allows addition of a Binary Object Store descriptor.

It can be used with a `with` statement; and yields an BinaryObjectStoreDescriptorEmitter
that can be populated:

with collection.BOSDescriptor() as d:
[snip]

This adds the relevant descriptor, automatically. Note that populating derived
fields such as bNumDeviceCaps aren't necessary; they'll be populated automatically.
"""
descriptor = BinaryObjectStoreDescriptorEmitter()
yield descriptor

self.add_descriptor(descriptor)


def _ensure_has_language_descriptor(self):
""" ensures that we have a language descriptor; adding one if necessary."""

Expand Down
1 change: 1 addition & 0 deletions usb_protocol/types/descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ class DescriptorField(construct.Subconstruct):
'id' : construct.Int16ul,
'bm' : construct.Int8ul,
'w' : construct.Int16ul,
'dw' : construct.Int32ul,
}


Expand Down
Loading