/** * 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; }
/** * 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; }