View Javadoc

1   /**
2    *  BlueCove - Java library for Bluetooth
3    *  Copyright (C) 2008 Michael Lifshits
4    *  Copyright (C) 2008 Vlad Skarzhevskyy
5    *
6    *  Licensed to the Apache Software Foundation (ASF) under one
7    *  or more contributor license agreements.  See the NOTICE file
8    *  distributed with this work for additional information
9    *  regarding copyright ownership.  The ASF licenses this file
10   *  to you under the Apache License, Version 2.0 (the
11   *  "License"); you may not use this file except in compliance
12   *  with the License.  You may obtain a copy of the License at
13   *
14   *    http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing,
17   *  software distributed under the License is distributed on an
18   *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
19   *  KIND, either express or implied.  See the License for the
20   *  specific language governing permissions and limitations
21   *  under the License.
22   *
23   *  @author vlads
24   *  @version $Id: EmulatorLocalDevice.java 2525 2008-12-09 03:48:51Z skarzhevskyy $
25   */
26  package com.intel.bluetooth;
27  
28  import java.io.IOException;
29  import java.util.Hashtable;
30  import java.util.Map;
31  import java.util.Vector;
32  
33  import javax.bluetooth.BluetoothConnectionException;
34  import javax.bluetooth.BluetoothStateException;
35  
36  import com.intel.bluetooth.BluetoothConsts.DeviceClassConsts;
37  import com.intel.bluetooth.emu.DeviceDescriptor;
38  import com.intel.bluetooth.emu.DeviceManagerService;
39  import com.intel.bluetooth.emu.EmulatorConfiguration;
40  import com.intel.bluetooth.emu.EmulatorUtils;
41  
42  /**
43   * 
44   */
45  class EmulatorLocalDevice {
46  
47  	private DeviceManagerService service;
48  
49  	private DeviceDescriptor deviceDescriptor;
50  
51  	private int bluetooth_sd_attr_retrievable_max = 0;
52  
53  	private int bluetooth_l2cap_receiveMTU_max = 0;
54  
55  	private int bluetooth_connected_devices_max = 0;
56  
57  	private EmulatorConfiguration configuration;
58  
59  	private Map<String, String> propertiesMap;
60  
61  	private Vector<Long> channels = new Vector<Long>();
62  
63  	private Vector<Long> pcms = new Vector<Long>();
64  
65  	private long connectionCount = 0;
66  
67  	private Map<Long, EmulatorConnection> connections = new Hashtable<Long, EmulatorConnection>();
68  
69  	EmulatorLocalDevice(DeviceManagerService service, DeviceDescriptor deviceDescriptor) throws BluetoothStateException {
70  		this.service = service;
71  		this.deviceDescriptor = deviceDescriptor;
72  
73  		propertiesMap = new Hashtable<String, String>();
74  		propertiesMap.put("bluecove.radio.version", BlueCoveImpl.version);
75  		propertiesMap.put("bluecove.radio.manufacturer", "pyx4j.com");
76  		propertiesMap.put("bluecove.stack.version", BlueCoveImpl.version);
77  
78  		updateConfiguration();
79  	}
80  
81  	void destroy() {
82  		service = null;
83  		deviceDescriptor = null;
84  	}
85  
86  	DeviceManagerService getDeviceManagerService() {
87  		return service;
88  	}
89  
90  	void updateConfiguration() throws BluetoothStateException {
91  		configuration = service.getEmulatorConfiguration(deviceDescriptor.getAddress());
92  		bluetooth_sd_attr_retrievable_max = configuration.getIntProperty(BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX);
93  		bluetooth_l2cap_receiveMTU_max = configuration.getIntProperty(BluetoothConsts.PROPERTY_BLUETOOTH_L2CAP_RECEIVEMTU_MAX);
94  		bluetooth_connected_devices_max = configuration.getIntProperty(BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX);
95  
96  		if (bluetooth_l2cap_receiveMTU_max + 2 > configuration.getConnectionBufferSize()) {
97  			throw new BluetoothStateException("l2cap.receiveMTU.max larger then connection buffer");
98  		}
99  
100 		String[] property = { BluetoothConsts.PROPERTY_BLUETOOTH_MASTER_SWITCH, BluetoothConsts.PROPERTY_BLUETOOTH_SD_ATTR_RETRIEVABLE_MAX,
101 				BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_DEVICES_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_L2CAP_RECEIVEMTU_MAX, BluetoothConsts.PROPERTY_BLUETOOTH_SD_TRANS_MAX,
102 				BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY_SCAN, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE_SCAN, BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_INQUIRY,
103 				BluetoothConsts.PROPERTY_BLUETOOTH_CONNECTED_PAGE };
104 		for (int i = 0; i < property.length; i++) {
105 			propertiesMap.put(property[i], configuration.getProperty(property[i]));
106 		}
107 	}
108 
109 	void updateLocalDeviceProperties() {
110 		this.deviceDescriptor = service.getDeviceDescriptor(deviceDescriptor.getAddress());
111 		try {
112 			updateConfiguration();
113 		} catch (BluetoothStateException ignore) {
114 		}
115 	}
116 
117 	long getAddress() {
118 		return deviceDescriptor.getAddress();
119 	}
120 
121 	String getName() {
122 		return deviceDescriptor.getName();
123 	}
124 
125 	int getDeviceClass() {
126 		return deviceDescriptor.getDeviceClass();
127 	}
128 
129 	void setLocalDeviceServiceClasses(int classOfDevice) {
130 		int c = deviceDescriptor.getDeviceClass();
131 		c &= DeviceClassConsts.MAJOR_MASK | DeviceClassConsts.MINOR_MASK;
132 		c |= classOfDevice;
133 		deviceDescriptor.setDeviceClass(c);
134 		service.setLocalDeviceServiceClasses(deviceDescriptor.getAddress(), c);
135 	}
136 
137 	boolean isActive() {
138 		if (deviceDescriptor == null) {
139 			return false;
140 		}
141 		return deviceDescriptor.isPoweredOn();
142 	}
143 
144 	boolean isLocalDevicePowerOn() {
145 		deviceDescriptor.setPoweredOn(service.isLocalDevicePowerOn(deviceDescriptor.getAddress()));
146 		return deviceDescriptor.isPoweredOn();
147 	}
148 
149 	void setLocalDevicePower(boolean on) {
150 		deviceDescriptor.setPoweredOn(on);
151 	}
152 
153 	public boolean isConnectable() {
154 		return deviceDescriptor.isPoweredOn() && deviceDescriptor.isConnectable();
155 	}
156 
157 	String getLocalDeviceProperty(String property) {
158 		return (String) propertiesMap.get(property);
159 	}
160 
161 	int getBluetooth_sd_attr_retrievable_max() {
162 		return bluetooth_sd_attr_retrievable_max;
163 	}
164 
165 	int getBluetooth_l2cap_receiveMTU_max() {
166 		return this.bluetooth_l2cap_receiveMTU_max;
167 	}
168 
169 	int getLocalDeviceDiscoverable() {
170 		return service.getLocalDeviceDiscoverable(getAddress());
171 	}
172 
173 	boolean setLocalDeviceDiscoverable(int mode) throws BluetoothStateException {
174 		return service.setLocalDeviceDiscoverable(getAddress(), mode);
175 	}
176 
177 	EmulatorConfiguration getConfiguration() {
178 		return configuration;
179 	}
180 
181 	EmulatorConnection getConnection(long handle) throws IOException {
182 		Object c = connections.get(new Long(handle));
183 		if (c == null) {
184 			throw new IOException("Invalid connection handle " + handle);
185 		}
186 		return (EmulatorConnection) c;
187 	}
188 
189 	void removeConnection(EmulatorConnection c) {
190 		connections.remove(new Long(c.getHandle()));
191 		if (c instanceof EmulatorRFCOMMService) {
192 			channels.remove(new Long(((EmulatorRFCOMMService) c).getChannel()));
193 		} else if (c instanceof EmulatorL2CAPService) {
194 			pcms.remove(new Long(((EmulatorL2CAPService) c).getPcm()));
195 		}
196 	}
197 
198 	private long nextConnectionId() {
199 		long id;
200 		synchronized (connections) {
201 			connectionCount++;
202 			id = connectionCount;
203 		}
204 		return id;
205 	}
206 
207 	EmulatorRFCOMMService createRFCOMMService() {
208 		EmulatorRFCOMMService s;
209 		synchronized (connections) {
210 			long handle = nextConnectionId();
211 			int channel = (int) EmulatorUtils.getNextAvailable(channels, 1, 1);
212 			s = new EmulatorRFCOMMService(this, handle, channel);
213 			connections.put(new Long(handle), s);
214 			channels.addElement(new Long(channel));
215 		}
216 		return s;
217 	}
218 
219 	private void validateCanConnect(long remoteAddress) throws IOException {
220 		if ((RemoteDeviceHelper.connectedDevices() >= bluetooth_connected_devices_max)
221 				&& RemoteDeviceHelper.openConnections(remoteAddress) == 0) {
222 			throw new BluetoothConnectionException(BluetoothConnectionException.NO_RESOURCES,
223 					"Number of connected device exceeded");
224 		}
225 	}
226 
227 	EmulatorRFCOMMClient createRFCOMMClient(long remoteAddress) throws IOException {
228 		validateCanConnect(remoteAddress);
229 		EmulatorRFCOMMClient c;
230 		synchronized (connections) {
231 			long handle = nextConnectionId();
232 			c = new EmulatorRFCOMMClient(this, handle);
233 			connections.put(new Long(handle), c);
234 		}
235 		return c;
236 	}
237 
238 	EmulatorL2CAPService createL2CAPService(int bluecove_ext_psm) throws IOException {
239 		EmulatorL2CAPService s;
240 		synchronized (connections) {
241 			int pcm;
242 			if (bluecove_ext_psm != 0) {
243 				if (pcms.contains(new Long(bluecove_ext_psm))) {
244 					throw new IOException("Server PCM " + Integer.toHexString(bluecove_ext_psm) + " already reserved");
245 				}
246 				pcm = bluecove_ext_psm;
247 			} else {
248 				pcm = (int) EmulatorUtils.getNextAvailable(pcms, 0x1001, 2);
249 			}
250 			long handle = nextConnectionId();
251 			s = new EmulatorL2CAPService(this, handle, pcm);
252 			connections.put(new Long(handle), s);
253 			pcms.addElement(new Long(pcm));
254 		}
255 		return s;
256 	}
257 
258 	EmulatorL2CAPClient createL2CAPClient(long remoteAddress) throws IOException {
259 		validateCanConnect(remoteAddress);
260 		EmulatorL2CAPClient c;
261 		synchronized (connections) {
262 			long handle = nextConnectionId();
263 			c = new EmulatorL2CAPClient(this, handle);
264 			connections.put(new Long(handle), c);
265 		}
266 		return c;
267 	}
268 
269 }