All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.oracle.dio.spibus.impl.SPISlaveImpl Maven / Gradle / Ivy

The newest version!
/*
 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package com.oracle.dio.spibus.impl;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.Buffer;
import java.security.AccessController;

import com.oracle.dio.impl.Transaction;
import com.oracle.dio.utils.Constants;
import com.oracle.dio.utils.ExceptionMessage;

import jdk.dio.ClosedDeviceException;
import jdk.dio.DeviceConfig;
import jdk.dio.DeviceDescriptor;
import jdk.dio.DeviceManager;
import jdk.dio.DeviceNotFoundException;
import jdk.dio.DevicePermission;
import jdk.dio.InvalidDeviceConfigException;
import jdk.dio.UnavailableDeviceException;
import jdk.dio.spibus.InvalidWordLengthException;
import jdk.dio.spibus.SPICompositeMessage;
import jdk.dio.spibus.SPIDevice;
import jdk.dio.spibus.SPIDeviceConfig;
import jdk.dio.spibus.SPIPermission;

import romizer.*;
/**
 *Implementation of SPISlave Interface.
 */
class SPISlaveImpl extends Transaction implements SPIDevice {

    //every call checkWordLen updates these two variables
    private int byteNum;
    private int bitNum;   

    public SPISlaveImpl(DeviceDescriptor dscr, int mode) throws
            IOException, DeviceNotFoundException, InvalidDeviceConfigException {
        super(dscr, mode);

        SPIPermission permission = new SPIPermission(getSecurityName());
        AccessController.checkPermission(permission);

        SPIDeviceConfig cfg = dscr.getConfiguration();
        if(cfg.getControllerName() != null) {
            throw new InvalidDeviceConfigException(
                ExceptionMessage.format(ExceptionMessage.DEVICE_OPEN_WITH_DEVICENAME_UNSUPPORTED)
            );
        }

        openSPIDeviceByConfig0(cfg.getControllerNumber(), cfg.getAddress(),
                                        cfg.getCSActiveLevel(), cfg.getClockFrequency(),
                                        cfg.getClockMode(), cfg.getWordLength(),
                                        cfg.getBitOrdering(), mode == DeviceManager.EXCLUSIVE);

        initPowerManagement();

        bitNum = getWordLength0();
        if (bitNum > Constants.MAX_WORD_LEN) {
            throw new IOException (
                ExceptionMessage.format(ExceptionMessage.SPIBUS_SLAVE_WORD_LENGTH, bitNum)
            );
        }
        byteNum = (bitNum - 1)/8 + 1;
    }

    @Override
    public jdk.dio.spibus.SPICompositeMessage createCompositeMessage() {
        return new SPICompositeMessageImpl(this);
    }

    private String getSecurityName(){
        SPIDeviceConfig cfg = dscr.getConfiguration();
        String securityName = (DeviceConfig.DEFAULT == cfg.getControllerNumber()) ? "" : String.valueOf(cfg.getControllerNumber());
        securityName = (DeviceConfig.DEFAULT == cfg.getAddress()) ? securityName : securityName + ":" + Integer.toString(cfg.getAddress(), 16);
        return securityName;
    }

    protected void checkPowerPermission(){
        SPIDeviceConfig cfg = dscr.getConfiguration();

        String securityName = (DeviceConfig.DEFAULT == cfg.getControllerNumber()) ? "" : String.valueOf(cfg.getControllerNumber());
        securityName = (DeviceConfig.DEFAULT == cfg.getAddress()) ? securityName : securityName + ":" + cfg.getAddress();

        SPIPermission permission = new SPIPermission(securityName, DevicePermission.POWER_MANAGE);

        AccessController.checkPermission(permission);
    }

    /**
     * Gets the transfer word length in bits supported by this slave device.
     * 

* If the length of data to be exchanged belies a slave's word length an {@link InvalidWordLengthException} will be * thrown. * * @return this slave's transfer word length in bits. * @throws IOException * if some other I/O error occurs. * @throws UnavailableDeviceException * if this peripheral is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the peripheral has been closed. */ @Override public synchronized int getWordLength() throws IOException, UnavailableDeviceException, ClosedDeviceException { checkPowerState(); return getWordLength0(); } @Override public ByteBuffer prepareBuffer(ByteBuffer buffer, int size) throws IOException, ClosedDeviceException { return (ByteBuffer)super.prepareBufferInt(buffer,size); } /** * Reads one data word of up to 32 bits from this slave device. * * @return the data word read. * @throws IOException * if some other I/O error occurs. * @throws InvalidWordLengthException * if the number of bytes to receive belies word length; that is this slave's word length is bigger than * 32 bits. * @throws UnavailableDeviceException * if this peripheral is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the peripheral has been closed. */ @Override public int read() throws IOException, UnavailableDeviceException, ClosedDeviceException { ByteBuffer dst = ByteBuffer.allocateDirect(byteNum); transferInternal(null, 0, dst); return byteArray2int(dst); } /** * Reads a sequence of bytes from this slave device into the given buffer. *

* Dummy data will be sent to this slave device by the platform. *

* {@inheritDoc} * * @param dst * The buffer into which bytes are to be transferred * * @return The number of bytes read, possibly zero, or {@code -1} if the device has reached end-of-stream * * @throws NullPointerException * If {@code dst} is {@code null}. * @throws InvalidWordLengthException * if the number of bytes to receive belies word length. * @throws UnavailableDeviceException * if this peripheral is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the peripheral has been closed. * @throws IOException * If some other I/O error occurs */ @Override public int read(ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException { return read(0, dst); } /** * Reads a sequence of bytes from this device into the given buffer, skipping the first {@code skip} bytes read. *

* Dummy data will be sent to this slave device by the platform. *

* Apart from skipping the first {@code skip} bytes, this method behaves identically to * {@link #read(java.nio.ByteBuffer)}. * * @param skip * the number of read bytes that must be ignored/skipped before filling in the {@code dst} buffer. * @param dst * The buffer into which bytes are to be transferred * * @return The number of bytes read, possibly zero, or {@code -1} if the device has reached end-of-stream * * @throws NullPointerException * If {@code dst} is {@code null}. * @throws InvalidWordLengthException * if the total number of bytes to receive belies word length. * @throws UnavailableDeviceException * if this peripheral is not currently available - such as it is locked by another application. * @throws ClosedDeviceException * if the peripheral has been closed. * @throws IOException * If some other I/O error occurs */ @Override public int read(int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException { if (0 > skip) { throw new IllegalArgumentException(); } checkBuffer(dst); return transferInternal(null, skip, dst); } @Override public int write(ByteBuffer src) throws IOException, UnavailableDeviceException, ClosedDeviceException { checkBuffer(src); return transferInternal(src, 0, null); } @Override public void write(int txData) throws IOException, UnavailableDeviceException, ClosedDeviceException { writeAndRead(txData); } @Override public int writeAndRead(ByteBuffer src, ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException { return writeAndRead(src, 0, dst); } @Override public int writeAndRead(ByteBuffer src, int skip, ByteBuffer dst) throws IOException, UnavailableDeviceException, ClosedDeviceException { if (0 > skip) { throw new IllegalArgumentException(); } checkBuffer(src); checkBuffer(dst); return transferInternal(src, skip, dst); } @Override public int writeAndRead(int txData) throws IOException, UnavailableDeviceException, ClosedDeviceException{ ByteBuffer tx = int2byteArray(txData); ByteBuffer rx = tx.slice(); transferInternal(tx, 0, rx); return byteArray2int(rx); } protected int getGrpID() { return getGrpID0(); } @Override public ByteBuffer getInputBuffer() throws ClosedDeviceException, IOException { throw new java.lang.UnsupportedOperationException(); } @Override public ByteBuffer getOutputBuffer() throws ClosedDeviceException, IOException { throw new java.lang.UnsupportedOperationException(); } // checkWordLen ought to be called before checkBuffer to get byteNum is up to date @Override protected void checkBuffer(Buffer buffer) { if ((buffer.remaining() % byteNum) != 0) { throw new InvalidWordLengthException( ExceptionMessage.format(ExceptionMessage.SPIBUS_BYTE_NUMBER_BELIES_WORD_LENGTH) ); } } private ByteBuffer int2byteArray(int intVal) { ByteBuffer retA = ByteBuffer.allocateDirect(byteNum); for (int i=0; i< byteNum ; i++) { retA.put((byte)((intVal >> (8*(byteNum-i-1))) & 0xff)); } retA.flip(); return retA; } private int byteArray2int(ByteBuffer byteA) { byteA.rewind(); int retI = 0; int tmp; for (int i = 0; i< byteNum ;i++) { tmp = byteA.get(); retI |= ((tmp & 0xff ) << (8*(byteNum - i - 1))); } return retI; } /* Returns number of recevied bytes if dst is not NULL, or number of sent bytes otherwise */ private int transferInternal(ByteBuffer src, int skip, ByteBuffer dst) throws IOException { int returnCount = dst != null ? dst.remaining() : src.remaining(); SPICompositeMessage message = this.createCompositeMessage(); if(src == null && dst != null) { message.appendRead(skip, dst); } else if(dst == null && src != null) { message.appendWrite(src); } else { message.appendWriteAndRead(src, skip, dst); } message.transfer(); return returnCount; } /** * Performs a SPI transfer operation with locking the SPI peripheral * The both buffers should be direct and same length * * @param src * Direct byte buffer which will be sent to the slave device * @param dst * Direct byte buffer which will used for the saving all the * data from slave * */ void transferWithLock(ByteBuffer src, ByteBuffer dst) throws IOException { try { conditionalLock(); writeAndRead0(src, dst); } finally { conditionalUnlock(); } } void beginTransaction() throws IOException, IllegalStateException { // interapp lock conditionalLock(); begin0(); } void endTransaction() throws IllegalStateException { end0(); // interapp unlock conditionalUnlock(); } @Local(DontRemoveFields = { "com.oracle.dio.impl.Handle.native_handle", "com.oracle.dio.impl.AbstractPeripheral.handle", }) private native int begin0() throws IOException, UnsupportedOperationException, IllegalStateException; @Local(DontRemoveFields = { "com.oracle.dio.impl.Handle.native_handle", "com.oracle.dio.impl.AbstractPeripheral.handle", }) private native int end0() throws IllegalStateException; @Local(DontRemoveFields = { "com.oracle.dio.impl.Handle.unlock_func_ptr", "com.oracle.dio.impl.Handle.native_handle", "com.oracle.dio.impl.Handle.lock_func_ptr", "com.oracle.dio.impl.Handle.close_func_ptr", "com.oracle.dio.impl.AbstractPeripheral.handle", }) private native void openSPIDeviceByConfig0(int deviceNumber, int address, int csActive, int clockFrequency, int clockMode, int wordLen, int bitOrdering, boolean exclusive); /* PREREQUISITES: either dst.len must be equals to src.len or dst must null */ @Local(DontRemoveFields = { "java.nio.Buffer.position", "java.nio.Buffer.limit", "java.nio.Buffer.data", "java.nio.Buffer.arrayOffset", "com.oracle.dio.impl.Handle.native_handle", "com.oracle.dio.impl.AbstractPeripheral.handle", }) private native void writeAndRead0(ByteBuffer src, ByteBuffer dst) throws IOException; @Local(DontRemoveFields = { "com.oracle.dio.impl.Handle.native_handle", "com.oracle.dio.impl.AbstractPeripheral.handle", }) private native int getGrpID0(); @Local(DontRemoveFields = { "com.oracle.dio.impl.Handle.native_handle", "com.oracle.dio.impl.AbstractPeripheral.handle", }) private native int getWordLength0(); @Local(DontRemoveFields = { "com.oracle.dio.impl.Handle.native_handle", "com.oracle.dio.impl.AbstractPeripheral.handle", }) private native int getByteOrdering0(); }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy