/* * Copyright 2011 Ytai Ben-Tsvi. All rights reserved. * * * Redistribution and use in source and binary forms, with or without modification, are * permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, this list of * conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright notice, this list * of conditions and the following disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ARSHAN POURSOHI OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * The views and conclusions contained in the software and documentation are those of the * authors and should not be interpreted as representing official policies, either expressed * or implied. */ package ioio.lib.impl; import android.util.Log; import ioio.lib.api.TwiMaster; import ioio.lib.api.exception.ConnectionLostException; import ioio.lib.impl.FlowControlledPacketSender.Packet; import ioio.lib.impl.FlowControlledPacketSender.Sender; import ioio.lib.impl.IncomingState.DataModuleListener; import java.io.IOException; import java.util.Queue; import java.util.concurrent.ConcurrentLinkedQueue; class TwiMasterImpl extends AbstractResource implements TwiMaster, DataModuleListener, Sender { class TwiResult implements Result { boolean ready_ = false; boolean success_; final byte[] data_; public TwiResult(byte[] data) { data_ = data; } @Override public synchronized boolean waitReady() throws ConnectionLostException, InterruptedException { while (!ready_ && state_ != State.DISCONNECTED) { wait(); } checkState(); return success_; } } class OutgoingPacket implements Packet { int writeSize_; byte[] writeData_; boolean tenBitAddr_; int addr_; int readSize_; @Override public int getSize() { return writeSize_ + 4; } } private final Queue<TwiResult> pendingRequests_ = new ConcurrentLinkedQueue<TwiResult>(); private final FlowControlledPacketSender outgoing_ = new FlowControlledPacketSender( this); private final int twiNum_; TwiMasterImpl(IOIOImpl ioio, int twiNum) throws ConnectionLostException { super(ioio); twiNum_ = twiNum; } @Override synchronized public void disconnected() { super.disconnected(); outgoing_.kill(); for (TwiResult tr : pendingRequests_) { synchronized (tr) { tr.notify(); } } } @Override public boolean writeRead(int address, boolean tenBitAddr, byte[] writeData, int writeSize, byte[] readData, int readSize) throws ConnectionLostException, InterruptedException { Result result = writeReadAsync(address, tenBitAddr, writeData, writeSize, readData, readSize); return result.waitReady(); } @Override public Result writeReadAsync(int address, boolean tenBitAddr, byte[] writeData, int writeSize, byte[] readData, int readSize) throws ConnectionLostException { checkState(); TwiResult result = new TwiResult(readData); OutgoingPacket p = new OutgoingPacket(); p.writeSize_ = writeSize; p.writeData_ = writeData; p.tenBitAddr_ = tenBitAddr; p.readSize_ = readSize; p.addr_ = address; synchronized (this) { pendingRequests_.add(result); try { outgoing_.write(p); } catch (IOException e) { Log.e("SpiMasterImpl", "Exception caught", e); } } return result; } @Override public void dataReceived(byte[] data, int size) { TwiResult result = pendingRequests_.remove(); synchronized (result) { result.ready_ = true; result.success_ = (size != 0xFF); if (result.success_) { System.arraycopy(data, 0, result.data_, 0, size); } result.notify(); } } @Override public void reportAdditionalBuffer(int bytesRemaining) { outgoing_.readyToSend(bytesRemaining); } @Override synchronized public void close() { super.close(); outgoing_.close(); ioio_.closeTwi(twiNum_); } @Override public void send(Packet packet) { OutgoingPacket p = (OutgoingPacket) packet; try { ioio_.protocol_.i2cWriteRead(twiNum_, p.tenBitAddr_, p.addr_, p.writeSize_, p.readSize_, p.writeData_); } catch (IOException e) { Log.e("TwiImpl", "Caught exception", e); } } }