001package com.pi4j.io.i2c.impl;
002
003/*
004 * #%L
005 * **********************************************************************
006 * ORGANIZATION  :  Pi4J
007 * PROJECT       :  Pi4J :: Java Library (Core)
008 * FILENAME      :  I2CBusImpl.java  
009 * 
010 * This file is part of the Pi4J project. More information about 
011 * this project can be found here:  http://www.pi4j.com/
012 * **********************************************************************
013 * %%
014 * Copyright (C) 2012 - 2013 Pi4J
015 * %%
016 * Licensed under the Apache License, Version 2.0 (the "License");
017 * you may not use this file except in compliance with the License.
018 * You may obtain a copy of the License at
019 * 
020 *      http://www.apache.org/licenses/LICENSE-2.0
021 * 
022 * Unless required by applicable law or agreed to in writing, software
023 * distributed under the License is distributed on an "AS IS" BASIS,
024 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
025 * See the License for the specific language governing permissions and
026 * limitations under the License.
027 * #L%
028 */
029
030import java.io.IOException;
031
032import com.pi4j.io.i2c.I2CBus;
033import com.pi4j.io.i2c.I2CDevice;
034import com.pi4j.jni.I2C;
035
036/**
037 * This is implementation of i2c bus. This class keeps underlying linux file descriptor of
038 * particular bus. As all reads and writes from/to i2c bus are blocked I/Os current implementation uses only 
039 * one file per bus for all devices. Device implementations use this class file handle.
040 * 
041 * @author Daniel Sendula
042 *
043 */
044public class I2CBusImpl implements I2CBus {
045
046    /** Singleton instance of bus 0 */
047    private static I2CBus bus0 = null;
048
049    /** Singleton instance of bus 1 */
050    private static I2CBus bus1 = null;
051    
052    /** 
053     * Factory method that returns bus implementation.
054     * 
055     * @param busNumber bus number
056     * @return appropriate bus implementation
057     * @throws IOException thrown in case there is a problem opening bus file or bus number is not 0 or 1.
058     */
059    public static I2CBus getBus(int busNumber) throws IOException {
060        I2CBus bus = null;
061        if (busNumber == 0) {
062            bus = bus0;
063            if (bus == null) {
064                bus = new I2CBusImpl("/dev/i2c-0");
065                bus0 = bus;
066            }
067        } else if (busNumber == 1) {
068            bus = bus1;
069            if (bus == null) {
070                bus = new I2CBusImpl("/dev/i2c-1");
071                bus1 = bus;
072            }
073        } else {
074            throw new IOException("Unknown bus number " + busNumber);
075        }
076        return bus;
077    }
078
079    /** File handle for this i2c bus */
080    protected int fd;
081    
082    /** File name of this i2c bus */
083    protected String filename;
084    
085    /**
086     * Constructor of i2c bus implementation.
087     * 
088     * @param filename file name of device to be opened.
089     * 
090     * @throws IOException thrown in case that file cannot be opened
091     */
092    public I2CBusImpl(String filename) throws IOException {
093        this.filename = filename;
094        fd = I2C.i2cOpen(filename);
095        if (fd < 0) {
096            throw new IOException("Cannot open file handle for " + filename + " got " + fd + " back.");
097        }
098    }
099
100    /**
101     * Returns i2c device implementation ({@link I2CDeviceImpl}).
102     * 
103     * @param address address of i2c device
104     * 
105     * @return implementation of i2c device with given address
106     * 
107     * @throws IOException never in this implementation
108     */
109    @Override
110    public I2CDevice getDevice(int address) throws IOException {
111        return new I2CDeviceImpl(this, address);
112    }
113
114    /**
115     * Closes this i2c bus
116     * 
117     * @throws IOException never in this implementation
118     */
119    @Override
120    public void close() throws IOException {
121        I2C.i2cClose(fd);
122    }
123}