/**
 * Sends a list of scancodes to the keyboard.
 *
 * @returns COM status code
 * @param scancodes   Safe array of scancodes
 * @param codesStored Address of variable to store the number
 *                    of scancodes that were sent to the keyboard.
                      This value can be NULL.
 */
STDMETHODIMP Keyboard::PutScancodes(ComSafeArrayIn (LONG, scancodes),
                                    ULONG *codesStored)
{
    if (ComSafeArrayInIsNull(scancodes))
        return E_INVALIDARG;
    if (!mpDrv)
        return S_OK;

    com::SafeArray <LONG> keys(ComSafeArrayInArg(scancodes));
    int rcVBox = VINF_SUCCESS;

    for (uint32_t i = 0; (i < keys.size()) && RT_SUCCESS(rcVBox); i++)
    {
        rcVBox = mpDrv->pUpPort->pfnPutEvent(mpDrv->pUpPort, (uint8_t)keys[i]);
    }

    if (RT_FAILURE (rcVBox))
        return E_FAIL;

    /// @todo is it actually possible that not all scancodes can be transmitted?
    if (codesStored)
        *codesStored = keys.size();

    return S_OK;
}
Пример #2
0
/**
 * Sends a list of scancodes to the keyboard.
 *
 * @returns COM status code
 * @param scancodes   Pointer to the first scancode
 * @param count       Number of scancodes
 * @param codesStored Address of variable to store the number
 *                    of scancodes that were sent to the keyboard.
                      This value can be NULL.
 */
STDMETHODIMP Keyboard::PutScancodes(ComSafeArrayIn(LONG, scancodes),
                                    ULONG *codesStored)
{
    if (ComSafeArrayInIsNull(scancodes))
        return E_INVALIDARG;

    AutoCaller autoCaller(this);
    if (FAILED(autoCaller.rc())) return autoCaller.rc();

    com::SafeArray<LONG> keys(ComSafeArrayInArg(scancodes));

    AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);

    CHECK_CONSOLE_DRV(mpDrv[0]);

    /* Send input to the last enabled device. Relies on the fact that
     * the USB keyboard is always initialized after the PS/2 keyboard.
     */
    PPDMIKEYBOARDPORT pUpPort = NULL;
    for (int i = KEYBOARD_MAX_DEVICES - 1; i >= 0 ; --i)
    {
        if (mpDrv[i] && (mpDrv[i]->u32DevCaps & KEYBOARD_DEVCAP_ENABLED))
        {
            pUpPort = mpDrv[i]->pUpPort;
            break;
        }
    }
    /* No enabled keyboard - throw the input away. */
    if (!pUpPort)
    {
        if (codesStored)
            *codesStored = (uint32_t)keys.size();
        return S_OK;
    }

    int vrc = VINF_SUCCESS;

    uint32_t sent;
    for (sent = 0; (sent < keys.size()) && RT_SUCCESS(vrc); sent++)
        vrc = pUpPort->pfnPutEvent(pUpPort, (uint8_t)keys[sent]);

    if (codesStored)
        *codesStored = sent;

    /* Only signal the keys in the event which have been actually sent. */
    com::SafeArray<LONG> keysSent(sent);
    memcpy(keysSent.raw(), keys.raw(), sent*sizeof(LONG));

    VBoxEventDesc evDesc;
    evDesc.init(mEventSource, VBoxEventType_OnGuestKeyboard, ComSafeArrayAsInParam(keys));
    evDesc.fire(0);

    if (RT_FAILURE(vrc))
        return setError(VBOX_E_IPRT_ERROR,
                        tr("Could not send all scan codes to the virtual keyboard (%Rrc)"),
                        vrc);

    return S_OK;
}