
#ifndef __USBDLIB_H
#define __USBDLIB_H

#if __GNUC__ >=3
#pragma GCC system_header
#endif

#ifdef __cplusplus
extern "C"
{
#endif

#pragma pack(push,4)


    typedef struct _USBD_INTERFACE_LIST_ENTRY
    {
        PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor;
        PUSBD_INTERFACE_INFORMATION Interface;
    } USBD_INTERFACE_LIST_ENTRY, *PUSBD_INTERFACE_LIST_ENTRY;


#define URB_STATUS(urb) ((urb)->UrbHeader.Status)

#define GET_SELECT_CONFIGURATION_REQUEST_SIZE(totalInterfaces, totalPipes) \
             (sizeof(struct _URB_SELECT_CONFIGURATION) \
             + ((totalInterfaces - 1) * sizeof(USBD_INTERFACE_INFORMATION)) \
             + ((totalPipes - 1) * sizeof(USBD_PIPE_INFORMATION)))

#define GET_SELECT_INTERFACE_REQUEST_SIZE(totalPipes) \
             (sizeof(struct _URB_SELECT_INTERFACE) \
             + ((totalPipes - 1) * sizeof(USBD_PIPE_INFORMATION)))

#define GET_USBD_INTERFACE_SIZE(numEndpoints) \
             (sizeof(USBD_INTERFACE_INFORMATION) \
             + (sizeof(USBD_PIPE_INFORMATION)*(numEndpoints)) \
             - sizeof(USBD_PIPE_INFORMATION))

#define GET_ISO_URB_SIZE(n) (sizeof(struct _URB_ISOCH_TRANSFER) \
             + sizeof(USBD_ISO_PACKET_DESCRIPTOR) * n)


#define UsbBuildInterruptOrBulkTransferRequest(urb, \
                                               length, \
                                               pipeHandle, \
                                               transferBuffer, \
                                               transferBufferMDL, \
                                               transferBufferLength, \
                                               transferFlags, \
                                               link) { \
            (urb)->UrbHeader.Function = \
                   URB_FUNCTION_BULK_OR_INTERRUPT_TRANSFER; \
            (urb)->UrbHeader.Length = (length); \
            (urb)->UrbBulkOrInterruptTransfer.PipeHandle = (pipeHandle); \
            (urb)->UrbBulkOrInterruptTransfer.TransferBufferLength = \
                   (transferBufferLength); \
            (urb)->UrbBulkOrInterruptTransfer.TransferBufferMDL = \
                   (transferBufferMDL); \
            (urb)->UrbBulkOrInterruptTransfer.TransferBuffer = \
                   (transferBuffer); \
            (urb)->UrbBulkOrInterruptTransfer.TransferFlags = \
                   (transferFlags); \
            (urb)->UrbBulkOrInterruptTransfer.UrbLink = (link); }


#define UsbBuildGetDescriptorRequest(urb, \
                                     length, \
                                     descriptorType, \
                                     descriptorIndex, \
                                     languageId, \
                                     transferBuffer, \
                                     transferBufferMDL, \
                                     transferBufferLength, \
                                     link) { \
            (urb)->UrbHeader.Function =  \
                   URB_FUNCTION_GET_DESCRIPTOR_FROM_DEVICE; \
            (urb)->UrbHeader.Length = (length); \
            (urb)->UrbControlDescriptorRequest.TransferBufferLength = \
                   (transferBufferLength); \
            (urb)->UrbControlDescriptorRequest.TransferBufferMDL = \
                   (transferBufferMDL); \
            (urb)->UrbControlDescriptorRequest.TransferBuffer = \
                   (transferBuffer); \
            (urb)->UrbControlDescriptorRequest.DescriptorType = \
                   (descriptorType); \
            (urb)->UrbControlDescriptorRequest.Index = (descriptorIndex); \
            (urb)->UrbControlDescriptorRequest.LanguageId = (languageId); \
            (urb)->UrbControlDescriptorRequest.UrbLink = (link); }



#define UsbBuildGetStatusRequest(urb, \
                                 op, \
                                 index, \
                                 transferBuffer, \
                                 transferBufferMDL, \
                                 link) { \
            (urb)->UrbHeader.Function =  (op); \
            (urb)->UrbHeader.Length = \
                   sizeof(struct _URB_CONTROL_GET_STATUS_REQUEST); \
            (urb)->UrbControlGetStatusRequest.TransferBufferLength = \
                   sizeof(USHORT); \
            (urb)->UrbControlGetStatusRequest.TransferBufferMDL = \
                   (transferBufferMDL); \
            (urb)->UrbControlGetStatusRequest.TransferBuffer = \
                   (transferBuffer); \
            (urb)->UrbControlGetStatusRequest.Index = (index); \
            (urb)->UrbControlGetStatusRequest.UrbLink = (link); }


#define UsbBuildFeatureRequest(urb, \
                               op, \
                               featureSelector, \
                               index, \
                               link) { \
            (urb)->UrbHeader.Function =  (op); \
            (urb)->UrbHeader.Length = \
                   sizeof(struct _URB_CONTROL_FEATURE_REQUEST); \
            (urb)->UrbControlFeatureRequest.FeatureSelector = \
                   (featureSelector); \
            (urb)->UrbControlFeatureRequest.Index = (index); \
            (urb)->UrbControlFeatureRequest.UrbLink = (link); }



#define UsbBuildSelectConfigurationRequest(urb, \
                                         length, \
                                         configurationDescriptor) { \
            (urb)->UrbHeader.Function =  URB_FUNCTION_SELECT_CONFIGURATION; \
            (urb)->UrbHeader.Length = (length); \
            (urb)->UrbSelectConfiguration.ConfigurationDescriptor = \
                   (configurationDescriptor); }

#define UsbBuildSelectInterfaceRequest(urb, \
                                      length, \
                                      configurationHandle, \
                                      interfaceNumber, \
                                      alternateSetting) { \
            (urb)->UrbHeader.Function =  URB_FUNCTION_SELECT_INTERFACE; \
            (urb)->UrbHeader.Length = (length); \
            (urb)->UrbSelectInterface.Interface.AlternateSetting = \
                   (alternateSetting); \
            (urb)->UrbSelectInterface.Interface.InterfaceNumber = \
                   (interfaceNumber); \
            (urb)->UrbSelectInterface.ConfigurationHandle = \
                   (configurationHandle); }


#define UsbBuildVendorRequest(urb, \
                              cmd, \
                              length, \
                              transferFlags, \
                              reservedbits, \
                              request, \
                              value, \
                              index, \
                              transferBuffer, \
                              transferBufferMDL, \
                              transferBufferLength, \
                              link) { \
            (urb)->UrbHeader.Function =  cmd; \
            (urb)->UrbHeader.Length = (length); \
            (urb)->UrbControlVendorClassRequest.TransferBufferLength = \
                   (transferBufferLength); \
            (urb)->UrbControlVendorClassRequest.TransferBufferMDL = \
                   (transferBufferMDL); \
            (urb)->UrbControlVendorClassRequest.TransferBuffer = \
                   (transferBuffer); \
            (urb)->UrbControlVendorClassRequest.RequestTypeReservedBits = \
                   (reservedbits); \
            (urb)->UrbControlVendorClassRequest.Request = (request); \
            (urb)->UrbControlVendorClassRequest.Value = (value); \
            (urb)->UrbControlVendorClassRequest.Index = (index); \
            (urb)->UrbControlVendorClassRequest.TransferFlags = \
                   (transferFlags); \
            (urb)->UrbControlVendorClassRequest.UrbLink = (link); }


#define UsbBuildOsFeatureDescriptorRequest(urb, \
                              length, \
                              interface, \
                              index, \
                              transferBuffer, \
                              transferBufferMDL, \
                              transferBufferLength, \
                              link) { \
            (urb)->UrbHeader.Function = \
                   URB_FUNCTION_GET_MS_FEATURE_DESCRIPTOR; \
            (urb)->UrbHeader.Length = (length); \
            (urb)->UrbOSFeatureDescriptorRequest.TransferBufferLength = \
                   (transferBufferLength); \
            (urb)->UrbOSFeatureDescriptorRequest.TransferBufferMDL = \
                   (transferBufferMDL); \
            (urb)->UrbOSFeatureDescriptorRequest.TransferBuffer = \
                   (transferBuffer); \
            (urb)->UrbOSFeatureDescriptorRequest.InterfaceNumber = \
                   (interface); \
            (urb)->UrbOSFeatureDescriptorRequest.MS_FeatureDescriptorIndex = \
                   (index); \
            (urb)->UrbOSFeatureDescriptorRequest.UrbLink = (link); }


    VOID
    DDKAPI
    USBD_Debug_LogEntry(
        IN CHAR *Name,
        IN ULONG Info1,
        IN ULONG Info2,
        IN ULONG Info3
    );

    VOID
    DDKAPI
    USBD_GetUSBDIVersion(
        PUSBD_VERSION_INFORMATION VersionInformation
    );


    PUSB_INTERFACE_DESCRIPTOR
    DDKAPI
    USBD_ParseConfigurationDescriptor(
        IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
        IN UCHAR InterfaceNumber,
        IN UCHAR AlternateSetting
    );

    PURB
    DDKAPI
    USBD_CreateConfigurationRequest(
        IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
        IN OUT PUSHORT Siz
    );

    PUSB_COMMON_DESCRIPTOR
    DDKAPI
    USBD_ParseDescriptors(
        IN PVOID DescriptorBuffer,
        IN ULONG TotalLength,
        IN PVOID StartPosition,
        IN LONG DescriptorType
    );

    PUSB_INTERFACE_DESCRIPTOR
    DDKAPI
    USBD_ParseConfigurationDescriptorEx(
        IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
        IN PVOID StartPosition,
        IN LONG InterfaceNumber,
        IN LONG AlternateSetting,
        IN LONG InterfaceClass,
        IN LONG InterfaceSubClass,
        IN LONG InterfaceProtocol
    );

    PURB
    DDKAPI
    USBD_CreateConfigurationRequestEx(
        IN PUSB_CONFIGURATION_DESCRIPTOR ConfigurationDescriptor,
        IN PUSBD_INTERFACE_LIST_ENTRY InterfaceList
    );

    ULONG
    DDKAPI
    USBD_GetInterfaceLength(
        IN PUSB_INTERFACE_DESCRIPTOR InterfaceDescriptor,
        IN PUCHAR BufferEnd
    );

    VOID
    DDKAPI
    USBD_RegisterHcFilter(
        PDEVICE_OBJECT DeviceObject,
        PDEVICE_OBJECT FilterDeviceObject
    );

    NTSTATUS
    DDKAPI
    USBD_GetPdoRegistryParameter(
        IN PDEVICE_OBJECT PhysicalDeviceObject,
        IN OUT PVOID Parameter,
        IN ULONG ParameterLength,
        IN PWCHAR KeyName,
        IN ULONG KeyNameLength
    );

    NTSTATUS
    DDKAPI
    USBD_QueryBusTime(
        IN PDEVICE_OBJECT RootHubPdo,
        IN PULONG CurrentFrame
    );

    ULONG
    DDKAPI
    USBD_CalculateUsbBandwidth(
        ULONG MaxPacketSize,
        UCHAR EndpointType,
        BOOLEAN LowSpeed
    );


#pragma pack(pop)

#ifdef __cplusplus
}
#endif

#endif /* __USBDLIB_H */

