1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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 }