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();
    }
}
Exemple #3
0
// ----------------------------------------------------------------------------
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;
	}
}