bool HIDDevice::openDevice() { memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); Device = HIDManager->CreateHIDFile(DevDesc.Path.ToCStr()); if (Device == INVALID_HANDLE_VALUE) { OVR_DEBUG_LOG(("Failed 'CreateHIDFile' while opening device, error = 0x%X.", ::GetLastError())); Device = 0; return false; } if (!HIDManager->HidD_SetNumInputBuffers(Device, 128)) { OVR_ASSERT_LOG(false, ("Failed 'HidD_SetNumInputBuffers' while initializing device.")); ::CloseHandle(Device); Device = 0; return false; } // Create a manual-reset non-signaled event. ReadOverlapped.hEvent = ::CreateEvent(0, TRUE, FALSE, 0); if (!ReadOverlapped.hEvent) { OVR_ASSERT_LOG(false, ("Failed to create event.")); ::CloseHandle(Device); Device = 0; return false; } if (!initInfo()) { OVR_ASSERT_LOG(false, ("Failed to get HIDDevice info.")); ::CloseHandle(ReadOverlapped.hEvent); memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); ::CloseHandle(Device); Device = 0; return false; } if (!initializeRead()) { OVR_ASSERT_LOG(false, ("Failed to get intialize read for HIDDevice.")); ::CloseHandle(ReadOverlapped.hEvent); memset(&ReadOverlapped, 0, sizeof(OVERLAPPED)); ::CloseHandle(Device); Device = 0; return false; } return true; }
void HIDDevice::OnOverlappedEvent(HANDLE hevent) { OVR_UNUSED(hevent); OVR_ASSERT(hevent == ReadOverlapped.hEvent); if (processReadResult()) { // Proceed to read again. initializeRead(); } }
// ---------------------------------------------------------------------------- extern "C" void I2C1_EV_IRQHandler(void) { DEBUG_STREAM("\n--- interrupt ---"); uint16_t sr1 = I2C1->SR1; if (sr1 & I2C_SR1_SB) { // EV5: SB=1, cleared by reading SR1 register followed by writing DR register with Address. DEBUG_STREAM("startbit set"); xpcc::i2c::Delegate::Starting s = delegate->started(); uint8_t address; switch (s.next) { case xpcc::i2c::Delegate::READ_OP: address = (s.address & 0xfe) | xpcc::i2c::READ; initializeRead(delegate->reading()); if (readBytesLeft <= 2) { DEBUG_STREAM("NACK"); I2C1->CR1 &= ~I2C_CR1_ACK; } else { DEBUG_STREAM("ACK"); I2C1->CR1 |= I2C_CR1_ACK; } if (readBytesLeft == 2) { DEBUG_STREAM("POS"); I2C1->CR1 |= I2C_CR1_POS; } DEBUG_STREAM("read op: reading=" << readBytesLeft); break; case xpcc::i2c::Delegate::WRITE_OP: address = (s.address & 0xfe) | xpcc::i2c::WRITE; initializeWrite(delegate->writing()); DEBUG_STREAM("write op: writing=" << writeBytesLeft); break; case xpcc::i2c::Delegate::RESTART_OP: address = (s.address & 0xfe) | xpcc::i2c::WRITE; initializeRestartAfterAddress(); DEBUG_STREAM("restart op"); break; default: case xpcc::i2c::Delegate::STOP_OP: address = (s.address & 0xfe) | xpcc::i2c::WRITE; initializeStopAfterAddress(); DEBUG_STREAM("stop op"); break; } I2C1->DR = address; } else if (sr1 & I2C_SR1_ADDR) { // EV6: ADDR=1, cleared by reading SR1 register followed by reading SR2. DEBUG_STREAM("address sent"); DEBUG_STREAM("writeBytesLeft=" << writeBytesLeft); DEBUG_STREAM("readBytesLeft=" << readBytesLeft); if (writeBytesLeft > 0 || readBytesLeft > 3) { DEBUG_STREAM("enable buffers"); I2C1->CR2 |= I2C_CR2_ITBUFEN; } if (!readBytesLeft && !writeBytesLeft) { checkNextOperation = CHECK_NEXT_OPERATION_YES; } DEBUG_STREAM("clearing ADDR"); uint16_t sr2 = I2C1->SR2; (void) sr2; if (readBytesLeft == 1) { DEBUG_STREAM("STOP"); I2C1->CR1 |= I2C_CR1_STOP; #if WAIT_FOR_STOP_LOW DEBUG_STREAM("waiting for stop"); while (I2C1->CR1 & I2C_CR1_STOP) ; #endif uint16_t dr = I2C1->DR; *readPointer++ = dr & 0xff; readBytesLeft = 0; checkNextOperation = CHECK_NEXT_OPERATION_YES_NO_STOP_BIT; } } else if (sr1 & I2C_SR1_TXE) { // EV8_1: TxE=1, shift register empty, data register empty, write Data1 in DR // EV8: TxE=1, shift register not empty, data register empty, cleared by writing DR if (writeBytesLeft > 0) { DEBUG_STREAM("tx more bytes"); I2C1->DR = *writePointer++; // write data writeBytesLeft--; DEBUG_STREAM("TXE: writeBytesLeft=" << writeBytesLeft); checkNextOperation = CHECK_NEXT_OPERATION_NO_WAIT_FOR_BTF; } // no else! if (writeBytesLeft == 0) { // disable TxE, and wait for EV8_2 DEBUG_STREAM("last byte transmitted, wait for btf"); I2C1->CR2 &= ~I2C_CR2_ITBUFEN; } } else if (sr1 & I2C_SR1_RXNE) { if (readBytesLeft > 3) { // EV7: RxNE=1, cleared by reading DR register uint16_t dr = I2C1->DR; *readPointer++ = dr & 0xff; readBytesLeft--; DEBUG_STREAM("RXNE: readBytesLeft=" << readBytesLeft); } if (readBytesLeft <= 3) { // disable RxNE, and wait for BTF DEBUG_STREAM("fourth last byte received, wait for btf"); I2C1->CR2 &= ~I2C_CR2_ITBUFEN; } } if (sr1 & I2C_SR1_BTF) { // EV8_2 DEBUG_STREAM("BTF"); if (readBytesLeft == 2) { // EV7_1: RxNE=1, cleared by reading DR register, programming STOP=1 DEBUG_STREAM("STOP"); I2C1->CR1 |= I2C_CR1_STOP; DEBUG_STREAM("reading data1"); uint16_t dr = I2C1->DR; *readPointer++ = dr & 0xff; #if WAIT_FOR_STOP_LOW DEBUG_STREAM("waiting for stop"); while (I2C1->CR1 & I2C_CR1_STOP) ; #endif DEBUG_STREAM("reading data2"); dr = I2C1->DR; *readPointer++ = dr & 0xff; readBytesLeft = 0; checkNextOperation = CHECK_NEXT_OPERATION_YES_NO_STOP_BIT; } if (readBytesLeft == 3) { // EV7_1: RxNE=1, cleared by reading DR register, programming ACK=0 I2C1->CR1 &= ~I2C_CR1_ACK; DEBUG_STREAM("NACK"); uint16_t dr = I2C1->DR; *readPointer++ = dr & 0xff; readBytesLeft--; DEBUG_STREAM("BTF: readBytesLeft=2"); } if (checkNextOperation == CHECK_NEXT_OPERATION_NO_WAIT_FOR_BTF && writeBytesLeft == 0) { // EV8_2: TxE=1, BTF = 1, Program Stop request. // TxE and BTF are cleared by hardware by the Stop condition DEBUG_STREAM("BTF, write=0"); checkNextOperation = CHECK_NEXT_OPERATION_YES; } } if (checkNextOperation > CHECK_NEXT_OPERATION_NO_WAIT_FOR_BTF) { switch (nextOperation) { case xpcc::i2c::Delegate::WRITE_OP: if (checkNextOperation != CHECK_NEXT_OPERATION_YES_NO_STOP_BIT) { initializeWrite(delegate->writing()); // reenable TXE I2C1->CR2 |= I2C_CR2_ITBUFEN; DEBUG_STREAM("write op"); } break; case xpcc::i2c::Delegate::RESTART_OP: callStarting(); DEBUG_STREAM("restart op"); break; default: if (checkNextOperation != CHECK_NEXT_OPERATION_YES_NO_STOP_BIT) { I2C1->CR1 |= I2C_CR1_STOP; DEBUG_STREAM("STOP"); } DEBUG_STREAM("disable interrupts"); I2C1->CR2 &= ~(I2C_CR2_ITEVTEN | I2C_CR2_ITBUFEN | I2C_CR2_ITERREN); if (delegate) delegate->stopped(xpcc::i2c::Delegate::NORMAL_STOP); delegate = 0; DEBUG_STREAM("write finished"); break; } checkNextOperation = CHECK_NEXT_OPERATION_NO; } }