예제 #1
0
STDMETHODIMP CSoftKeyboard::HitKeyOnce(KBD_KEYS KeyCode)
/*++
Routine Description:
    Implement the HitKeyOnce method for the interface
    ISoftKeyboard. This simulate a key being hit.

Synchronization: 
    None
 
Arguments:
    KeyCode - keycode of "pressed" key.
    
Return Value:
    E_FAIL
        Could not queue request for processing.
    E_INVALIDARG
        Returned if supplied keycode is out of supported range of keys.
    S_OK
        Success.
  
--*/
{
    HRESULT hr = S_OK;

    // Check for faulty input
    IfFalseHrGo(KeyCode > KEY_NONE && KeyCode <= KEY_PAUSE, E_INVALIDARG);

    IfFailHrGo(PostMessage2Task(m_KeyPressedMsg, KeyCode, 0));
    IfFailHrGo(PostMessage2Task(m_KeyReleasedMsg, KeyCode, 0));

Exit:
    return hr;

} // CSoftKeyboard::HitKeyOnce
HRESULT CLoopbackDevice::SetupConnectionPoint(IUnknown* punkObject,
                                              REFIID iidConnectionPoint) {
  HRESULT hr = S_OK;
  IConnectionPointContainer* piConnectionPointContainer = NULL;
  IUnknown* punkSink = NULL;

  //If there is already connection point enabled, disable it
  if(NULL != m_piConnectionPoint) {
    IfFailHrGo(ReleaseConnectionPoint());
  }
        
  IfFailHrGo(punkObject->QueryInterface(IID_IConnectionPointContainer,
                                        reinterpret_cast<void **>(&piConnectionPointContainer)));

  IfFailHrGo(piConnectionPointContainer->FindConnectionPoint(iidConnectionPoint,
                                                             &m_piConnectionPoint));

  // Get the IUknown of this interface as this is the event sink
  punkSink = (this)->GetUnknown(); 

  if(NULL == punkSink) {
    IfFailHrGo(E_UNEXPECTED);
  }

  IfFailHrGo(m_piConnectionPoint->Advise(punkSink, &m_dwConnectionCookie));


Exit:
  return hr;
}
STDMETHODIMP CLoopbackDevice::OnWriteTransfer(BYTE DataToggle,
                                              BYTE* pbDataBuffer,
                                              ULONG cbDataBuffer,
                                              BYTE * pbStatus) {
    
  HRESULT hr = S_OK;
  BYTE bINStatus = USB_ACK;
  UNREFERENCED_PARAMETER(DataToggle);

  // Check that the IN endpoint is valid
  if (NULL == m_piINEndpoint) {
    IfFailHrGo(E_UNEXPECTED);
  }

  // Send the data to the IN Endpoint
  IfFailHrGo(m_piINEndpoint->QueueINData(pbDataBuffer,
                                         cbDataBuffer,
                                         bINStatus,
                                         SOFTUSB_FOREVER));

  // ACK the status as the data was successfully sent to the IN endpoint
  *pbStatus = USB_ACK;

Exit:
  if (FAILED(hr))
    *pbStatus = USB_STALL;

  return hr;
}
예제 #4
0
HRESULT CSoftHIDInputKbdMapper::SetupEventSink
(
    IUnknown         *punkObject,
    IUnknown         *punkSink,
    REFIID            iidConnectionPoint,
    IConnectionPoint *&rpiConnectionPoint,
    DWORD             &rdwCookie
)
/*++

Routine Description:
    If punkObject is non-NULL installs event sink on specific
    connection point and returns IConnectionPoint and cookie.

Arguments:
    punkObject - IUnknown on object

    punkSink - IUnknown of event sink to install

    iidConnectionPoint - IID of desired connection point

    rpiConnectionPoint - connection point returned here

    rdwCookie - connection point cookie returned here

Synchronization:
    None

Return value:
    S_OK - success
    other - from called routines
--*/
{
    HRESULT                    hr = S_OK;
    IConnectionPointContainer *piConnectionPointContainer = NULL;

    rpiConnectionPoint = NULL;
    rdwCookie = 0;

    IfFalseHrGo(NULL != punkObject, S_OK);

    IfFailHrGo(punkObject->QueryInterface(IID_IConnectionPointContainer,
                                          reinterpret_cast<void **>(&piConnectionPointContainer)));

    IfFailHrGo(piConnectionPointContainer->FindConnectionPoint(iidConnectionPoint,
                                                               &rpiConnectionPoint));

    IfFailHrGo(rpiConnectionPoint->Advise(punkSink, &rdwCookie));

Exit:
    if (FAILED(hr))
    {
        RELEASE(rpiConnectionPoint);
        rdwCookie = 0;
    }
    RELEASE(piConnectionPointContainer);

    return hr;
}
예제 #5
0
HRESULT CSoftHIDInputKbdMapper::ProcessKbdOutput(SAFEARRAY* psa)
/*++
Routine Description:
    Processes keyboard output report.

Synchronization: 
    None
 
Arguments:
    psa - pointer to safearray containing Output Report data
    
Return Value:
    S_OK
        Success
    E_UNEXPECTED
        Unxpected size of Output Report data buffer
    E_FAIL
        Could not report indicator status to keyboard object.
--*/
{
    BYTE HUGEP*                   pArrayData = NULL;
    LONG                          lLBound = 0;
    LONG                          lUBound = 0;
    HRESULT                       hr = S_OK;
    KEYBOARD_INDICATOR_PARAMETERS Indicator; ZeroMemory(&Indicator, sizeof(Indicator));

    IfFalseHrGo(NULL != m_piSoftKeyboard, E_FAIL);

    // Get SAFEARRAY size
    IfFailHrGo(SafeArrayGetLBound(psa, 1, &lLBound));
    IfFailHrGo(SafeArrayGetUBound(psa, 1, &lUBound));
    // Check the size of Output Report data
    IfFalseHrGo(1 == (lUBound - lLBound + 1), E_UNEXPECTED);

    IfFailHrGo(::SafeArrayAccessData(psa, (void HUGEP**)&pArrayData));

    // Only 5 least significant bits are valid in output report byte.
    // TODO: this would be controlled by OutputReportMask property later.
    Indicator.usLedFlags = pArrayData[0] & 0xE0;

    IfFailHrGo(::SafeArrayUnaccessData(psa));

    IfFailHrGo(m_piSoftKeyboard->put_Indicators(&Indicator));

Exit:
    // the safe array was allocated by the call to
    // m_piSoftProtXlator->ReadOutputPort in CSoftHID::Run.
    // Now we are done with it so we should free it here.
    if (NULL != psa)
    {
        (void)::SafeArrayDestroy(psa);
    }

    return hr;

} // CSoftHIDInputKbdMapper::ProcessKbdOutput
예제 #6
0
HRESULT CSoftHIDInputKbdMapper::SendInputReport
(
    PVOID pbReportData,
    ULONG cbReportData
)
/*++
Routine Description:
    Prepares safearray and sends it as Input Report to lower layer.

Synchronization: 
    None
 
Arguments:
    pbReportData - pointer to data buffer with Input Report
    cbReportData - size of the data buffer
    
Return Value:
    S_OK
        Success
    E_OUTOFMEMORY
        Could not allocate enough memory for safearray
    From called function
--*/
{
    SAFEARRAY*  psa = NULL;
    BYTE HUGEP* pArrayData = NULL;
    HRESULT     hr = S_OK;

    // Create safearray
    psa = SafeArrayCreateVector(VT_UI1, 0, cbReportData);
    IfFalseHrGo(NULL != psa, E_OUTOFMEMORY);

    IfFailHrGo(::SafeArrayAccessData(psa, (void HUGEP**)&pArrayData));

    CopyMemory(pArrayData, pbReportData, cbReportData);

    IfFailHrGo(::SafeArrayUnaccessData(psa));

    // Send Input Report
    IfFailHrGo(m_piSoftProtXlator->WriteInputReport(psa));


Exit:
    if (NULL != psa)
    {
        // Delete safearray
        ::SafeArrayDestroy(psa);
        psa = NULL;
    }

    return hr;

} // CSoftHIDInputKbdMapper::SendInputReport
HRESULT CLoopbackDevice::ConfigureConfig(ISoftUSBConfiguration* piConfig) {
  HRESULT hr = S_OK;
  // config number passed to SetConfig
  IfFailHrGo(piConfig->put_ConfigurationValue(1));
  // Index of string descriptor
  IfFailHrGo(piConfig->put_Configuration((BYTE)m_iConfigString));
  // Self powered
  IfFailHrGo(piConfig->put_Attributes(0x40));
  // Max power in 2mA units: 50 = 100mA
  IfFailHrGo(piConfig->put_MaxPower(50));

Exit:
  return hr;
}
HRESULT CLoopbackDevice::FinalConstruct() {
  // Perform tasks which may fail when the class CLoopbackDevice
  // is finally constructed. This involves creating the USB device 
  // object and initializing the device so that it is recognized
  // as a valid USB device by the controller
  HRESULT hr = S_OK;

  hr = CreateUSBDevice();
  IfFailHrGo(hr);

  hr = ConfigureDevice();
  IfFailHrGo(hr);

Exit:
    return hr;
}
예제 #9
0
STDMETHODIMP CSoftHIDInputKbdMapper::KeyTouched(void)
/*++
Routine Description:
    Implements the KeyTouched event from ISoftInputKbdDeviceEvents 
    interface. Called by SoftKeyboard object when it gets new
    input in its buffer. 
    Schedules processing of contents of keyboard buffer.

Synchronization: 
    None
 
Arguments:
    None

Return Value:
    E_FAIL
        Could not send message to task
    S_OK
        Success
--*/
{
    HRESULT hr = S_OK;

    IfFailHrGo(PostMessage2Task(m_KeyTouchedMsg, 0, 0));

Exit:
    return hr;    

} // CSoftHIDInputKbdMapper::KeyTouched
예제 #10
0
STDMETHODIMP CSoftKeyboard::get_Translator(
                SoftKbdTranslator **ppTranslator)
/*++
Routine Description:
    Implement the get Translator propery for the interface
    ISoftKeyboard.

Synchronization: 
    None
 
Arguments:
    ppTranslator - caller allocated space to hold the property value.
    
Return Value:
    E_POINTER
        Invalid pointer for output parameter
    From called function
  
--*/
{
    HRESULT hr = S_OK;

    // Check if we have valid pointer to returned parameter
    IfFalseHrGo(NULL != ppTranslator, E_POINTER);
    *ppTranslator = NULL;

    ADDREF(m_piSoftKbdTranslator);
    *ppTranslator  = reinterpret_cast<SoftKbdTranslator *>(m_piSoftKbdTranslator);

    IfFailHrGo(hr);

Exit:
    return hr;

} // CSoftKeyboard::get_Translator
예제 #11
0
HRESULT CSoftKeyboard::FinalConstruct()
/*++
Routine Description:
    Overwrites the default FinalConstruct. Creates the default
    properties, gets pointer to COM task memory allocator.

Synchronization: 
    None
 
Arguments:
    None
    
Return Value:
    From called function
--*/
{
    HRESULT hr = S_OK;
    ISoftKbdTranslator* piDefaultASCIIXlator = NULL;

    // Acquire COM memory management interface
    IfFailHrGo(CoGetMalloc(1, &m_pMalloc));

    // Register notification messages
    IfFailHrGo(RegisterMessage(MSG_KEYPRESSED, &m_KeyPressedMsg));
    IfFailHrGo(RegisterMessage(MSG_KEYRELEASED, &m_KeyReleasedMsg));

    // Construct default translator object
    //pcDefaultASCIIXlator = new CDefaultASCIIXlator();
    hr = CDefaultASCIIXlator::CreateInstance(&piDefaultASCIIXlator);
    IfFailHrGo(hr);

    m_piSoftKbdTranslator = piDefaultASCIIXlator;

    // Set default values to properties
    m_KbdAttributes.usKeyboardMode = KEYBOARD_SCAN_CODE_SET2;

    m_KbdTypematicParam.ulRate = KEYBOARD_TYPEMATIC_RATE_DEFAULT;
    m_KbdTypematicParam.ulDelay = KEYBOARD_TYPEMATIC_DELAY_DEFAULT;
    
    // Start internal thread
    IfFailHrGo(Start(60000));

Exit:
    return hr;

} // CSoftKeyboard::FinalConstruct
STDMETHODIMP CLoopbackDevice::StopAsyncEventProcessing() {
  HRESULT hr = S_OK;
  // Remove the event sink on the OUT endpoint
  IfFailHrGo(ReleaseConnectionPoint());

Exit:
  return hr;
}
예제 #13
0
STDMETHODIMP CSoftHIDInputKbdMapper::AttachProtocolXlator(SoftHIDProtocolXlator* pSoftProtXlator)
/*++
Routine Description:
    Implements the AttachProtocolXlator method for the interface
    ISoftHIDInputKdbMapper. Allows a SoftHIDUSBDevice object
    to attach to the HID device object.

Synchronization: 
    None
 
Arguments:
    m_piProtocolXlator - protocol translator to be attached

Return Value:
    S_OK    
    
--*/
{
    HRESULT hr = S_OK;

    // Disconnect from the old object
    IfFailHrGo(Disconnect());

    // Set reference to ISoftHIDProtocolXlator interface
    RELEASE(m_piSoftProtXlator);
    if (NULL != pSoftProtXlator)
    {
        IfFailHrGo(reinterpret_cast<IUnknown *>(pSoftProtXlator)->QueryInterface(__uuidof(ISoftHIDProtocolXlator),
                                           reinterpret_cast<void **>(&m_piSoftProtXlator)));
      
        // Write Report Descriptor
        IfFailHrGo(m_piSoftProtXlator->WriteReportDescriptor(m_psaReportDescriptor));

        // Connect to the new object
        IfFailHrGo(Connect(m_piSoftProtXlator));

        // Set device type as keyboard
        IfFailHrGo(m_piSoftProtXlator->put_DeviceType(DEVICE_TYPE_KEYBOARD));
    }

Exit:
    return hr;

} // CSoftHIDInputKbdMapper::AttachProtocolXlator
STDMETHODIMP CLoopbackDevice::get_DSFDevice(DSFDevice** ppDSFDevice) {
  HRESULT hr = S_OK;
  DSFDevice* pDSFDevice = NULL;

  //Validate the the UDB device exists else this is an
  //internal error
  if (NULL == m_piSoftUSBDevice) {
    IfFailHrGo(E_UNEXPECTED);
  }    

  if (NULL == ppDSFDevice) {
    IfFailHrGo(E_POINTER);
  }

  IfFailHrGo(m_piSoftUSBDevice->get_DSFDevice(&pDSFDevice));
  IfFailHrGo(reinterpret_cast<IDSFDevice *>(pDSFDevice)->QueryInterface(__uuidof(IDispatch), reinterpret_cast<void **>(ppDSFDevice)));

Exit:
  if (NULL != pDSFDevice)
    reinterpret_cast<IDSFDevice *>(pDSFDevice)->Release();

  return hr;
}
STDMETHODIMP CLoopbackDevice::StartEventProcessing() {
/*
   Demonstrates how to setup event sinks so that the 
   event mechanism can be used to control data flow to and
   from the USB controller. In this example an event sink
   is installed on the OUT USB endpoint, when the controller
   has data to send to the device the OnWriteTransfer event
   will fire, this will occur on an arbitrary thread. The 
   device then simply copies this data and passes it the
   IN queue of the IN Endpoint.
*/
  HRESULT               hr                = S_OK;
  BOOL                  fKeepLooping      = TRUE;
  VARIANT_BOOL          fvarContinue      = VARIANT_TRUE;

  // Set up event sink on the OUT endpoint
  IfFailHrGo(SetupConnectionPoint(m_piOUTEndpoint, __uuidof(ISoftUSBEndpointEvents)));

  // Loop waiting for Events to be fired
  while (TRUE == fKeepLooping) {
    // Context switch to allow other threads to process
    ::Sleep(1);

    // Fire Event to check if the caller want to continue processing
    IfFailHrGo(Fire_ContinueEventProcessing(&fvarContinue));

    // Check to see if the return value is VARIANT_FALSE
    if (VARIANT_FALSE == fvarContinue)
      fKeepLooping = FALSE;
  }

  // Remove the event sink from the OUT endpoint
  IfFailHrGo(ReleaseConnectionPoint());
    
Exit:
  return hr;
}
예제 #16
0
HRESULT CSoftHIDInputKbdMapper::FinalConstruct()
/*++
Routine Description:
    Overwrites the default FinalConstruct. Creates the default
    properties, gets pointer to COM task memory allocator.

Synchronization: 
    None
 
Arguments:
    None
    
Return Value:
    E_OUTOFMEMORY
        Could not create safearray for Report Descriptor data
    From called function
--*/
{
    BYTE HUGEP* pArrayData = NULL;
    HRESULT     hr = S_OK;

    IfFailHrGo(CoGetMalloc(1, &m_pMalloc));

    // Register notification messages
    IfFailHrGo(RegisterMessage(MSG_KEYTOUCHED, &m_KeyTouchedMsg));
    IfFailHrGo(RegisterMessage(MSG_OUTREPORTREADY, &m_OutReportReadyMsg));

    // Create safearray with Report Descriptor data
    m_psaReportDescriptor = SafeArrayCreateVector(VT_UI1, 0, sizeof(m_ReportDescriptor));
    IfFalseHrGo(NULL != m_psaReportDescriptor, E_OUTOFMEMORY);

    IfFailHrGo(::SafeArrayAccessData(m_psaReportDescriptor, (void HUGEP**)&pArrayData));

    // Copy Report Descriptor data into safearray
    CopyMemory(pArrayData, &m_ReportDescriptor, sizeof(m_ReportDescriptor));

    IfFailHrGo(::SafeArrayUnaccessData(m_psaReportDescriptor));

    // Start internal thread
    IfFailHrGo(CMessageTask::Start(DEFAULT_SYNC_DELAY));

    // Call OnConstruct method of CSoftHIDDevice class
    IfFailHrGo(CSoftHID::OnConstruct(this, m_OutReportReadyMsg));

Exit:
    return hr;

} // CSoftHIDInputKbdMapper::FinalConstruct
STDMETHODIMP CLoopbackDevice::StartAsyncEventProcessing() {
/*
   Demonstrates how to setup event sinks so that the event mechanism can
   be used to control data flow to and from the USB controller. In this
   example an event sink is installed on the OUT USB endpoint, when the
   controller has data to send to the device the OnWriteTransfer event
   will fire, this will occur on an arbitrary thread. The device then
   simply copies this data and passes it the IN queue of the IN
   Endpoint. Control returns to the caller and event processing
   continues in an arbitrary thread. To terminate event processing call
   StopAsyncEventProcessing.
*/
  HRESULT hr = S_OK;

  // Set up event sink on the OUT endpoint
  IfFailHrGo(SetupConnectionPoint(m_piOUTEndpoint, __uuidof(ISoftUSBEndpointEvents)));

Exit:
  return hr;
}
HRESULT CLoopbackDevice::ConfigureOUTEndpoint() {
  HRESULT hr = S_OK;

  if (NULL == m_piOUTEndpoint) {
    IfFailHrGo(E_UNEXPECTED);
  }

  // Endpoint #2 OUT
  IfFailHrGo(m_piOUTEndpoint->put_EndpointAddress(0x02));
  // Bulk data endpoint
  IfFailHrGo(m_piOUTEndpoint->put_Attributes(0x02));
  IfFailHrGo(m_piOUTEndpoint->put_MaxPacketSize(1024));
  IfFailHrGo(m_piOUTEndpoint->put_Interval(0));
  IfFailHrGo(m_piOUTEndpoint->put_Halted(FALSE));
  //back pointer to the device
  IfFailHrGo(m_piOUTEndpoint->put_USBDevice(reinterpret_cast<SoftUSBDevice*>(m_piSoftUSBDevice)));
    
Exit:    
  return hr;
}
HRESULT CLoopbackDevice::ConfigureInterface(ISoftUSBInterface* piInterface) {
  HRESULT hr = S_OK;

  IfFailHrGo(piInterface->put_InterfaceNumber(0));
  IfFailHrGo(piInterface->put_AlternateSetting(0));
  // Vendor specific class code
  IfFailHrGo(piInterface->put_InterfaceClass(0xFF));
  // Vendor specific sub class code
  IfFailHrGo(piInterface->put_InterfaceSubClass(0xFF));
  // Vendor specific protcol
  IfFailHrGo(piInterface->put_InterfaceProtocol(0xFF));
  //Index for string describing the interface
  IfFailHrGo(piInterface->put_Interface((BYTE)m_iInterfaceString));

Exit:
  return hr;
}
STDMETHODIMP CLoopbackDevice::AreKeystrokesWaiting(
    VARIANT_BOOL* pfvarKeyWaiting) {
/*
   Implements IDeviceEmulator::AreKeystrokesWaiting. It calls the low level 
   IO function _kbhit to see if the keyboard has been struck. If the Keyboard
   has been hit the function return VARIANT_TRUE otherwise it returns VARIANT_FALSE
*/
  HRESULT hr = S_OK;
  int iKeyHit = 0;

  if (NULL == pfvarKeyWaiting) {
    IfFailHrGo(E_POINTER);
  }
    
  *pfvarKeyWaiting = VARIANT_FALSE;

  iKeyHit = _kbhit();

  if (0 != iKeyHit)
    *pfvarKeyWaiting = VARIANT_TRUE;

Exit:
  return hr;
}
예제 #21
0
STDMETHODIMP CSoftKeyboard::put_Translator(
                SoftKbdTranslator *pTranslator)
/*++
Routine Description:
    Implement the put Translator propery for the interface
    ISoftKeyboard.

Synchronization: 
    None
 
Arguments:
    pTranslator - new value of the property.
    
Return Value:
    From called function
  
--*/
{
    HRESULT hr = S_OK;
    ISoftKbdTranslator *piNewInterface = NULL;
    ISoftKbdTranslator *piOldInterface = m_piSoftKbdTranslator;
    
    
    if (NULL != pTranslator)
    {
        IfFailHrGo(reinterpret_cast<IUnknown *>(pTranslator)->QueryInterface(__uuidof(ISoftKbdTranslator),
                                                                           reinterpret_cast<void **>(&piNewInterface)));
    }

    (void)InterlockedExchangePointer((void**)m_piSoftKbdTranslator, piNewInterface);
    RELEASE(piOldInterface);

Exit:
    return hr;

} // CSoftKeyboard::put_Translator
HRESULT CLoopbackDevice::ConfigureDevice() {
  HRESULT hr = S_OK;
  ISoftUSBConfiguration* piConfig = NULL;
  ISoftUSBInterface* piInterface = NULL;
  ISoftUSBConfigList* piConfigList = NULL;
  ISoftUSBInterfaceList* piInterfaceList = NULL;
  ISoftUSBEndpointList* piEndpointList= NULL; 
  VARIANT varIndex;
  VariantInit(&varIndex);

  // All members of the collection will be added at the default locations
  // so set up the index appropriately
  varIndex.vt = VT_ERROR;
  varIndex.scode = DISP_E_PARAMNOTFOUND;

  // Create the IN Endpoint
  hr = CoCreateInstance(CLSID_SoftUSBEndpoint, 
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBEndpoint),     
                        reinterpret_cast<void**>(&m_piINEndpoint));
  IfFailHrGo(hr);

  // Setup the IN Endpoint
  IfFailHrGo(ConfigureINEndpoint());

  // Create the OUT Endpoint
  hr = CoCreateInstance(CLSID_SoftUSBEndpoint, 
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBEndpoint),     
                        reinterpret_cast<void**>(&m_piOUTEndpoint));
  IfFailHrGo(hr);

  // Setup the OUT Endpoint
  IfFailHrGo(ConfigureOUTEndpoint());

  // Create the device interface
  hr = CoCreateInstance(CLSID_SoftUSBInterface, 
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBInterface),     
                        reinterpret_cast<void**>(&piInterface));
  IfFailHrGo(hr);

  // Setup the device interface
  IfFailHrGo(ConfigureInterface(piInterface));

  // Add the Endpoints to the endpoint list
  IfFailHrGo(piInterface->get_Endpoints(&piEndpointList));
  IfFailHrGo(piEndpointList->Add(reinterpret_cast<SoftUSBEndpoint*>(m_piINEndpoint), varIndex));
  IfFailHrGo(piEndpointList->Add(reinterpret_cast<SoftUSBEndpoint*>(m_piOUTEndpoint), varIndex));

  // Create the configuration
  hr = CoCreateInstance(CLSID_SoftUSBConfiguration, 
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBConfiguration),     
                        reinterpret_cast<void**>(&piConfig));
  IfFailHrGo(hr);

  // Set the configuration data up
  IfFailHrGo(ConfigureConfig(piConfig));

  // Add the interface to the interface collection
  IfFailHrGo(piConfig->get_Interfaces(&piInterfaceList));
  IfFailHrGo(piInterfaceList->Add(reinterpret_cast<SoftUSBInterface*>(piInterface), varIndex));

  // Add the configuration to the configuration collection
  IfFailHrGo(m_piSoftUSBDevice->get_Configurations(&piConfigList));
  IfFailHrGo(piConfigList->Add(reinterpret_cast<SoftUSBConfiguration*>(piConfig), varIndex));

Exit:
  RELEASE(piConfig);
  RELEASE(piInterface);
  RELEASE(piConfigList);
  RELEASE(piInterfaceList);
  RELEASE(piEndpointList);
  return hr;
}
예제 #23
0
HRESULT CSoftHIDInputKbdMapper::ProcessKbdInput()
/*++
Routine Description:
    Reads and handles data from input keyboard buffer.

Synchronization: 
    None
 
Arguments:
    None
    
Return Value:
    S_OK
        Success
    E_FAIL
        Could not read data from keyboard buffer
--*/
{
    USHORT               usUnits = 0;
    KEYBOARD_INPUT_DATA* pKbdData = NULL;
    HRESULT              hr = S_OK;

    // Read data from keyboard buffer
    IfFalseHrGo(NULL != m_piSoftKeyboard, E_FAIL);
    IfFailHrGo(m_piSoftKeyboard->Read(&usUnits, &pKbdData));
    IfFalseHrGo(NULL != pKbdData, E_FAIL);

    // Check whether Protocol Translator interface pointer is set
    // If not, do not fail the function, but dispose the data
    IfFalseHrGo(NULL != m_piSoftProtXlator, S_OK);

    // Process keyboard data
    for(USHORT i = 0; i < usUnits; i++)
    {
        // Generate Input Report
        if (GenInputReport((USHORT)pKbdData[i].ulMakeCode, pKbdData[i].usFlags))
        {
            // Send Input Report
            IfFailHrGo(SendInputReport(&m_InputReport, sizeof(m_InputReport)));
        }
        // Report phantom state
        else
        {
            HID_INPUTREPORT PhantomReport;

            // Initialize Phantom report. Modifier byte is still reported.
            FillMemory(&PhantomReport, sizeof(PhantomReport), 1);
            PhantomReport.bReserved = 0;
            PhantomReport.bModifier = m_InputReport.bModifier;

            // Send Phantom Report
            IfFailHrGo(SendInputReport(&PhantomReport, sizeof(PhantomReport)));
        }
    }

Exit:
    // Release COM buffer
    if (NULL != pKbdData)
    {
        m_pMalloc->Free(pKbdData);
    }

    return hr;

} // CSoftHIDInputKbdMapper::ProcessKbdInput
예제 #24
0
STDMETHODIMP CSoftKeyboard::PressAndReleaseKeys(
                BSTR bstrKeyStrokes)

/*++
Routine Description:
    Implement the PressAndRelease method for the interface
    ISoftKeyboard. This simulate a key stroke for a UNICODE character

Synchronization: 
    None
 
Arguments:
    bstrKeyStrokes - Keystrokes to be simulated
    
Return Value:
    E_FAIL 
        Could not generate a sequence of keycodes to simulate a keystroke.
    E_INVALIDARG
        Invalid keystroke length.
    S_OK
        Success.
--*/
{
    HRESULT hr = S_OK;
    UINT nUnits = 0;
    KBD_KEYCODE* pKeyCodes = NULL;

    UINT nSize = SysStringLen(bstrKeyStrokes);

    // Check if string is not NULL
    IfFalseHrGo(nSize != 0, E_INVALIDARG);

    // Check is Translator property is set
    IfFalseHrGo(NULL != m_piSoftKbdTranslator, E_UNEXPECTED);

    hr = m_piSoftKbdTranslator->TranslateString2Keycodes(nSize, bstrKeyStrokes, &nUnits, &pKeyCodes);
    IfFailHrGo(hr);

    // Go through returned sequence and queue it for processing
    for(UINT i = 0; i < nUnits; i++)
    {
        // Call PressKey method
        if (KEY_MAKE == pKeyCodes[i].ucFlag) {
            IfFailHrGo(PressKey(pKeyCodes[i].KeyCode));
        }
        // Call ReleaseKey method
        else if (KEY_BREAK == pKeyCodes[i].ucFlag) {
            IfFailHrGo(ReleaseKey(pKeyCodes[i].KeyCode));
        }
        // Call HitKeyOnce method
        else if ((KEY_BREAK | KEY_MAKE) == pKeyCodes[i].ucFlag) {
            IfFailHrGo(HitKeyOnce(pKeyCodes[i].KeyCode));
        }
        // Should never hit this code, but check anyway
        else {
            IfFailHrGo(E_FAIL);
        }
    }

Exit:
    m_pMalloc->Free(pKeyCodes);
    return hr;

} // CSoftKeyboard::PressAndReleaseKeys
HRESULT CLoopbackDevice::CreateStrings() {
  HRESULT hr = S_OK;
  ISoftUSBStringList* piStringList = NULL;
  ISoftUSBString* piStringManufacturer = NULL;
  ISoftUSBString* piStringProductDesc = NULL;
  ISoftUSBString* piStringSerialNo = NULL;
  ISoftUSBString* piStringConfig = NULL;
  ISoftUSBString* piStringEndpoint = NULL;
  BSTR bstrManufacturer = ::SysAllocString(L"Google, Inc");
  BSTR bstrProductDesc = ::SysAllocString(L"USB Emulating Device");
  BSTR bstrSerialNo = ::SysAllocString(L"123456789ABCDEF");
  BSTR bstrConfig = ::SysAllocString(L"Configuration with a single interface");
  BSTR bstrEndpoint = ::SysAllocString(L"Interface with bulk IN endpoint and bulk OUT endpoint");
  VARIANT varIndex;
  VariantInit(&varIndex);

  // Check that all BSTR allocations succeeded
  IfFalseHrGo(0 != ::SysStringLen(bstrManufacturer), E_OUTOFMEMORY);
  IfFalseHrGo(0 != ::SysStringLen(bstrProductDesc), E_OUTOFMEMORY);
  IfFalseHrGo(0 != ::SysStringLen(bstrSerialNo), E_OUTOFMEMORY);
  IfFalseHrGo(0 != ::SysStringLen(bstrConfig), E_OUTOFMEMORY);
  IfFalseHrGo(0 != ::SysStringLen(bstrEndpoint), E_OUTOFMEMORY);

  //Set up the varaint used as the index
  varIndex.vt = VT_I4;
  varIndex.lVal = STRING_IDX_MANUFACTURER;

  //Create and initialize the string descriptors. Also create a string 
  //descriptor index for each. This index is used both to set the string's
  //descriptors position in the m_piSoftUSBDevice.Strings and is the index value 
  //the GetDescriptors request from the host. Note that we don't use 
  //string descriptor index zero because that is a reserved value for a 
  //device's language ID descriptor.

  //Get the string list from the device
  hr = m_piSoftUSBDevice->get_Strings(&piStringList);
  IfFailHrGo(hr);

  hr = CoCreateInstance(CLSID_SoftUSBString,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBString),     
                        reinterpret_cast<void**>(&piStringManufacturer));
  IfFailHrGo(hr);

  IfFailHrGo(piStringManufacturer->put_Value(bstrManufacturer));
  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringManufacturer), varIndex));
    
  hr = CoCreateInstance(CLSID_SoftUSBString,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBString),     
                        reinterpret_cast<void**>(&piStringProductDesc));

  IfFailHrGo(hr);
  IfFailHrGo(piStringProductDesc->put_Value(bstrProductDesc));
  varIndex.lVal = STRING_IDX_PRODUCT_DESC;
  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringProductDesc), varIndex));

  hr = CoCreateInstance(CLSID_SoftUSBString,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBString),     
                        reinterpret_cast<void**>(&piStringSerialNo));
  IfFailHrGo(hr);
  IfFailHrGo(piStringSerialNo->put_Value(bstrSerialNo));
  varIndex.lVal = STRING_IDX_SERIAL_NO;
  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringSerialNo), varIndex));

  hr = CoCreateInstance(CLSID_SoftUSBString,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBString),     
                        reinterpret_cast<void**>(&piStringConfig));
  IfFailHrGo(hr);
  IfFailHrGo(piStringConfig->put_Value(bstrConfig));
  varIndex.lVal = STRING_IDX_CONFIG;
  m_iConfigString = varIndex.lVal;
  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringConfig), varIndex));

  hr = CoCreateInstance(CLSID_SoftUSBString,
                        NULL,
                        CLSCTX_INPROC_SERVER,
                        __uuidof(ISoftUSBString),     
                        reinterpret_cast<void**>(&piStringEndpoint));
  IfFailHrGo(hr);
  IfFailHrGo(piStringEndpoint->put_Value(bstrEndpoint));
  varIndex.lVal = STRING_IDX_INTERFACE;
  m_iInterfaceString = varIndex.lVal;
  IfFailHrGo(piStringList->Add(reinterpret_cast<SoftUSBString*>(piStringEndpoint), varIndex));

Exit:
  RELEASE(piStringList);
  RELEASE(piStringManufacturer);
  RELEASE(piStringProductDesc);
  RELEASE(piStringSerialNo);
  RELEASE(piStringConfig);
  RELEASE(piStringEndpoint);
  ::SysFreeString(bstrManufacturer);
  ::SysFreeString(bstrProductDesc);
  ::SysFreeString(bstrSerialNo);
  ::SysFreeString(bstrConfig);
  ::SysFreeString(bstrEndpoint);

  return hr;
}
예제 #26
0
STDMETHODIMP CSoftHIDInputKbdMapper::AttachKbd(SoftKeyboard *pSoftKbd)
/*++
Routine Description:
    Implements the AttachKbd method for the interface
    ISoftHIDInputKdbMapper. Allows a keyboard input device
    to attach to the HID device object.

Synchronization: 
    None
 
Arguments:
    pSoftKbd - device to be attached

Return Value:
    S_OK    
    
--*/
{
    HRESULT hr = S_OK;

    KEYBOARD_ATTRIBUTES* pKbdAttrib = NULL;
    KEYBOARD_TYPEMATIC_PARAMETERS* pTypematic = NULL;

    // Disconnect event sink from the old source
    TearDownEventSink(m_piConnectionPointKbd, m_dwKbdSinkCookie);

    // Set reference to ISoftKeyboard interface
    RELEASE(m_piSoftKeyboard);
    if (NULL != pSoftKbd)
    {
        IfFailHrGo(reinterpret_cast<IUnknown *>(pSoftKbd)->QueryInterface(__uuidof(ISoftInputKbdDevice),
                                           reinterpret_cast<void **>(&m_piSoftKeyboard)));

        // Set HID settings
        IfFailHrGo(m_piSoftKeyboard->get_Attributes(&pKbdAttrib));
        pKbdAttrib->usKeyboardMode = KEYBOARD_HID_USAGE;
        IfFailHrGo(m_piSoftKeyboard->put_Attributes(pKbdAttrib));

        // Disable autorepeat function
        IfFailHrGo(m_piSoftKeyboard->get_Typematic(&pTypematic));
        pTypematic->ulDelay = KEYBOARD_TYPEMATIC_DELAY_INFINITE;
        IfFailHrGo(m_piSoftKeyboard->put_Typematic(pTypematic));

        // Install event sink
        IfFailHrGo(SetupEventSink(
                        m_piSoftKeyboard,
                        GetUnknown(),
                        __uuidof(ISoftInputKbdDeviceEvents),
                        m_piConnectionPointKbd,
                        m_dwKbdSinkCookie));
    }

Exit:
    if (NULL != pKbdAttrib)
    {
        m_pMalloc->Free(pKbdAttrib);
    }

    if (NULL != pTypematic)
    {
        m_pMalloc->Free(pTypematic);
    }

    return hr;

} // CSoftHIDInputKbdMapper::AttachKbd
HRESULT CLoopbackDevice::CreateUSBDevice() {
  // Creates the USB device and initializes the device member variables
  // and creates and initializes the device qualifier. The device qualifier
  // is required for USB2.0 devices.

  HRESULT hr = S_OK;
  ISoftUSBDeviceQualifier* piDeviceQual = NULL;
  USHORT prod_id = DEVICE_EMULATOR_PROD_ID;

  hr = ::CoCreateInstance(CLSID_SoftUSBDevice, 
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          __uuidof(ISoftUSBDevice),     
                          reinterpret_cast<void**>(&m_piSoftUSBDevice));

  IfFailHrGo(hr);

  // Create the device qualifer
  hr = ::CoCreateInstance(CLSID_SoftUSBDeviceQualifier, 
                          NULL,
                          CLSCTX_INPROC_SERVER,
                          __uuidof(ISoftUSBDeviceQualifier),     
                          reinterpret_cast<void**>(&piDeviceQual));

  IfFailHrGo(hr);

  // Setup the device qualifier
  // binary coded decimal USB version 2.0
  IfFailHrGo(piDeviceQual->put_USB(0x0200));
  // FF=Vendor specfic device class
  IfFailHrGo(piDeviceQual->put_DeviceClass(0xff)); 
  // FF = Vendor specific device sub-class
  IfFailHrGo(piDeviceQual->put_DeviceSubClass(0xff));
  // FF = Vendor specific device protocol
  IfFailHrGo(piDeviceQual->put_DeviceProtocol(0xff)); 
  // Max packet size endpoint 0
  IfFailHrGo(piDeviceQual->put_MaxPacketSize0(64)); 
  // Number of configurations
  IfFailHrGo(piDeviceQual->put_NumConfigurations(1));

  // Setup the device 
  // binary coded decimal USB version 2.0
  IfFailHrGo(m_piSoftUSBDevice->put_USB(0x0200));
  // FF=Vendor specfic device class
  IfFailHrGo(m_piSoftUSBDevice->put_DeviceClass(0xff));
  // FF = Vendor specific device sub-class
  IfFailHrGo(m_piSoftUSBDevice->put_DeviceSubClass(0xff));
  // FF = Vendor specific device protocol
  IfFailHrGo(m_piSoftUSBDevice->put_DeviceProtocol(0xff)); 
  // Max packet size endpoint 0
  IfFailHrGo(m_piSoftUSBDevice->put_MaxPacketSize0(64)); 
  // Vendor ID - Google
  IfFailHrGo(m_piSoftUSBDevice->put_Vendor(DEVICE_VENDOR_ID));
  // product id - Device Emulator
  IfFailHrGo(m_piSoftUSBDevice->put_Product(static_cast<SHORT>(prod_id))); 
  // Binary decimal coded version 1.0
  IfFailHrGo(m_piSoftUSBDevice->put_Device(0x0100));
  // Device does not suppport remote wake up
  IfFailHrGo(m_piSoftUSBDevice->put_RemoteWakeup(VARIANT_FALSE));
  // Index of the manufacturer string
  IfFailHrGo(m_piSoftUSBDevice->put_Manufacturer(STRING_IDX_MANUFACTURER));
  // Index of the product descripton string
  IfFailHrGo(m_piSoftUSBDevice->put_ProductDesc(STRING_IDX_PRODUCT_DESC)); 
  // Index of the serial number string
  IfFailHrGo(m_piSoftUSBDevice->put_SerialNumber(STRING_IDX_SERIAL_NO));
  // Indicate that the device is self-powered
  IfFailHrGo(m_piSoftUSBDevice->put_SelfPowered(VARIANT_TRUE));
  // Indicate that the device has power
  IfFailHrGo(m_piSoftUSBDevice->put_Powered(VARIANT_TRUE));

  // Create the strings associated with the device
  IfFailHrGo(CreateStrings());

  // Add the device qualifier
  IfFailHrGo(m_piSoftUSBDevice->put_DeviceQualifier(piDeviceQual));

Exit:
  RELEASE(piDeviceQual);
  return hr;
}
STDMETHODIMP CLoopbackDevice::DoPolledLoopback(long lTimeInterval) {
/*
   Demonstrates how to use the drain OUT queue and queue IN data
   methods to communicate with the host controller. 

   The code checks to see if there is any data in the OUT, if no 
   data is present an event is fired to indicate if the function 
   should exit. If the function should not exit then the function 
   sleeps for the time interval before re-checking the queue.

   If there is data then the function reads the data and passes the
   data to the IN queue. This simply provides a loopback mechanism
   to the host controller.
*/
  HRESULT hr = S_OK;
  BOOL fKeepLooping = TRUE;
  // Number of items currently in the queue
  ULONG ulNoOfQueuedItems = 0;
  // Only going to read one transfer at a time
  ULONG ulTransfers = 1;
  SOFTUSB_OUT_TRANSFER* pOUTTransfer = NULL;
  // Copied the message status
  BYTE bStatus = 0;
  // Copied the message data
  BYTE* pDataBuffer = NULL;
  // Holds the size of the data buffer
  ULONG cbDataBuffer      = 0;
  VARIANT_BOOL fvarContinue = VARIANT_TRUE;

  if (NULL == m_piINEndpoint || NULL == m_piOUTEndpoint) {
    IfFailHrGo(E_UNEXPECTED);
  }

  while (fKeepLooping) {
    // Reset the number of queued items
    ulNoOfQueuedItems = 0;
        
    // Check to see if there is any data in the out queue
    IfFailHrGo(m_piOUTEndpoint->DrainOUTQueue(0, &ulNoOfQueuedItems, NULL));

    if (0 == ulNoOfQueuedItems) {
      // There is no data in the list so we need to check
      // If we should continue to loop
      // Fire Event to check if more processing is required
      IfFailHrGo(Fire_ContinueToPoll(&fvarContinue));

      // Check to see if the return value is VARIANT_FALSE
      if (VARIANT_FALSE == fvarContinue)
        fKeepLooping = FALSE;
            
      if (fKeepLooping)
        ::Sleep(lTimeInterval);
    } else {
      // There is data to read, loop until we have moved all 
      // the data from the OUT queue to the IN queue moving
      // one data item at a time
      do {
        // Get the OUT data
        IfFailHrGo(m_piOUTEndpoint->DrainOUTQueue(ulTransfers, 
                                                  &ulNoOfQueuedItems, 
                                                  &pOUTTransfer));

        // Setup the IN data
        bStatus= pOUTTransfer->bStatus;
        cbDataBuffer = pOUTTransfer->cbData;
        pDataBuffer =&pOUTTransfer->Data[0];
                
        // Send the data to the out queue
        IfFailHrGo(m_piINEndpoint->QueueINData(pDataBuffer,
                                               cbDataBuffer,
                                               bStatus,
                                               SOFTUSB_FOREVER));

        // Free the memory used by pOUTTransfer   
        m_piOUTEndpoint->FreeOUTQueue(pOUTTransfer);
        pOUTTransfer = NULL;

        // Force a context switch 
        ::Sleep(1);
      } while (0 != ulNoOfQueuedItems);
    }
  }

Exit:
  // If one of the calls failed pOUTTransfer will be NON-NULL 
  // And needs to be freed
  if (NULL != pOUTTransfer) {
    // Free the memory used by pOUTTransfer   
    m_piOUTEndpoint->FreeOUTQueue(pOUTTransfer);
    pOUTTransfer = NULL;
  }

  return hr;
}