/** * BlueCove - Java library for Bluetooth * Copyright (C) 2008-2009 Michael Lifshits * Copyright (C) 2008-2009 Vlad Skarzhevskyy * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. * * @author vlads * @version $Id$ */ package com.intel.bluetooth; import java.io.IOException; import java.util.Hashtable; import java.util.Map; import java.util.Vector; import javax.bluetooth.BluetoothConnectionException; import javax.bluetooth.BluetoothStateException; import com.intel.bluetooth.BluetoothConsts.DeviceClassConsts; import com.intel.bluetooth.emu.DeviceDescriptor; import com.intel.bluetooth.emu.DeviceManagerService; import com.intel.bluetooth.emu.EmulatorConfiguration; import com.intel.bluetooth.emu.EmulatorUtils; /** * */ class EmulatorLocalDevice { private DeviceManagerService service; private DeviceDescriptor deviceDescriptor; private int bluetooth_sd_attr_retrievable_max = 0; private int bluetooth_l2cap_receiveMTU_max = 0; private int bluetooth_connected_devices_max = 0; private EmulatorConfiguration configuration; private Map<String, String> propertiesMap; private Vector<Long> channels = new Vector<Long>(); private Vector<Long> pcms = new Vector<Long>(); private long connectionCount = 0; private Map<Long, EmulatorConnection> connections = new Hashtable<Long, EmulatorConnection>(); EmulatorLocalDevice(DeviceManagerService service, DeviceDescriptor deviceDescriptor) throws BluetoothStateException { this.service = service; this.deviceDescriptor = deviceDescriptor; propertiesMap = new Hashtable<String, String>(); propertiesMap.put("bluecove.radio.version", BlueCoveImpl.version); propertiesMap.put("bluecove.radio.manufacturer", "pyx4j.com"); propertiesMap.put("bluecove.stack.version", BlueCoveImpl.version); updateConfiguration(); } void destroy() { service = null; deviceDescriptor = null; } DeviceManagerService getDeviceManagerService() { return service; } void updateConfiguration() throws BluetoothStateException { configuration = service.getEmulatorConfiguration(deviceDescriptor.getAddress()); bluetooth_sd_attr_retrievable_max = configuration.getIntProperty(BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX); bluetooth_l2cap_receiveMTU_max = configuration.getIntProperty(BluetoothConsts.PROPERTY_BLUETOOTH_L2CAP_RECEIVEMTU_MAX); bluetooth_connected_devices_max = configuration.getIntProperty(BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX); if (bluetooth_l2cap_receiveMTU_max + 2 > configuration.getConnectionBufferSize()) { throw new BluetoothStateException("l2cap.receiveMTU.max larger then connection buffer"); } String[] property = { BluetoothConsts.PROPERTY_BLUETOOTH_MASTER_SWITCH, BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_L2CAP_RECEIVEMTU_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_SD_TRANS_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY_SCAN, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE_SCAN, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE }; for (int i = 0; i < property.length; i++) { propertiesMap.put(property[i], configuration.getProperty(property[i])); } } void updateLocalDeviceProperties() { this.deviceDescriptor = service.getDeviceDescriptor(deviceDescriptor.getAddress()); try { updateConfiguration(); } catch (BluetoothStateException ignore) { } } long getAddress() { return deviceDescriptor.getAddress(); } String getName() { return deviceDescriptor.getName(); } int getDeviceClass() { return deviceDescriptor.getDeviceClass(); } void setLocalDeviceServiceClasses(int classOfDevice) { int c = deviceDescriptor.getDeviceClass(); c &= DeviceClassConsts.MAJOR_MASK | DeviceClassConsts.MINOR_MASK; c |= classOfDevice; deviceDescriptor.setDeviceClass(c); service.setLocalDeviceServiceClasses(deviceDescriptor.getAddress(), c); } boolean isActive() { if (deviceDescriptor == null) { return false; } return deviceDescriptor.isPoweredOn(); } boolean isLocalDevicePowerOn() { deviceDescriptor.setPoweredOn(service.isLocalDevicePowerOn(deviceDescriptor.getAddress())); return deviceDescriptor.isPoweredOn(); } void setLocalDevicePower(boolean on) { deviceDescriptor.setPoweredOn(on); } public boolean isConnectable() { return deviceDescriptor.isPoweredOn() && deviceDescriptor.isConnectable(); } String getLocalDeviceProperty(String property) { return (String) propertiesMap.get(property); } int getBluetooth_sd_attr_retrievable_max() { return bluetooth_sd_attr_retrievable_max; } int getBluetooth_l2cap_receiveMTU_max() { return this.bluetooth_l2cap_receiveMTU_max; } int getLocalDeviceDiscoverable() { return service.getLocalDeviceDiscoverable(getAddress()); } boolean setLocalDeviceDiscoverable(int mode) throws BluetoothStateException { return service.setLocalDeviceDiscoverable(getAddress(), mode); } EmulatorConfiguration getConfiguration() { return configuration; } EmulatorConnection getConnection(long handle) throws IOException { Object c = connections.get(new Long(handle)); if (c == null) { throw new IOException("Invalid connection handle " + handle); } return (EmulatorConnection) c; } void removeConnection(EmulatorConnection c) { connections.remove(new Long(c.getHandle())); if (c instanceof EmulatorRFCOMMService) { channels.remove(new Long(((EmulatorRFCOMMService) c).getChannel())); } else if (c instanceof EmulatorL2CAPService) { pcms.remove(new Long(((EmulatorL2CAPService) c).getPcm())); } } private long nextConnectionId() { long id; synchronized (connections) { connectionCount++; id = connectionCount; } return id; } EmulatorRFCOMMService createRFCOMMService() { EmulatorRFCOMMService s; synchronized (connections) { long handle = nextConnectionId(); int channel = (int) EmulatorUtils.getNextAvailable(channels, 1, 1); s = new EmulatorRFCOMMService(this, handle, channel); connections.put(new Long(handle), s); channels.addElement(new Long(channel)); } return s; } private void validateCanConnect(long remoteAddress) throws IOException { if ((RemoteDeviceHelper.connectedDevices() >= bluetooth_connected_devices_max) && RemoteDeviceHelper.openConnections(remoteAddress) == 0) { throw new BluetoothConnectionException(BluetoothConnectionException.NO_RESOURCES, "Number of connected device exceeded"); } } EmulatorRFCOMMClient createRFCOMMClient(long remoteAddress) throws IOException { validateCanConnect(remoteAddress); EmulatorRFCOMMClient c; synchronized (connections) { long handle = nextConnectionId(); c = new EmulatorRFCOMMClient(this, handle); connections.put(new Long(handle), c); } return c; } EmulatorL2CAPService createL2CAPService(int bluecove_ext_psm) throws IOException { EmulatorL2CAPService s; synchronized (connections) { int pcm; if (bluecove_ext_psm != 0) { if (pcms.contains(new Long(bluecove_ext_psm))) { throw new IOException("Server PCM " + Integer.toHexString(bluecove_ext_psm) + " already reserved"); } pcm = bluecove_ext_psm; } else { pcm = (int) EmulatorUtils.getNextAvailable(pcms, 0x1001, 2); } long handle = nextConnectionId(); s = new EmulatorL2CAPService(this, handle, pcm); connections.put(new Long(handle), s); pcms.addElement(new Long(pcm)); } return s; } EmulatorL2CAPClient createL2CAPClient(long remoteAddress) throws IOException { validateCanConnect(remoteAddress); EmulatorL2CAPClient c; synchronized (connections) { long handle = nextConnectionId(); c = new EmulatorL2CAPClient(this, handle); connections.put(new Long(handle), c); } return c; } }