6 import java
.io
.IOException
;
7 import java
.io
.InputStream
;
8 import java
.io
.OutputStream
;
9 import java
.util
.Vector
;
11 import javax
.bluetooth
.BluetoothStateException
;
12 import javax
.bluetooth
.DataElement
;
13 import javax
.bluetooth
.DeviceClass
;
14 import javax
.bluetooth
.DiscoveryAgent
;
15 import javax
.bluetooth
.DiscoveryListener
;
16 import javax
.bluetooth
.LocalDevice
;
17 import javax
.bluetooth
.RemoteDevice
;
18 import javax
.bluetooth
.ServiceRecord
;
19 import javax
.bluetooth
.UUID
;
20 import javax
.microedition
.contactless
.ContactlessException
;
21 import javax
.microedition
.contactless
.DiscoveryManager
;
22 import javax
.microedition
.contactless
.TargetListener
;
23 import javax
.microedition
.contactless
.TargetProperties
;
24 import javax
.microedition
.contactless
.TargetType
;
25 import javax
.microedition
.contactless
.sc
.ISO14443Connection
;
26 import javax
.microedition
.io
.Connector
;
27 import javax
.microedition
.io
.StreamConnection
;
28 import javax
.microedition
.io
.StreamConnectionNotifier
;
29 import javax
.microedition
.lcdui
.Command
;
30 import javax
.microedition
.lcdui
.CommandListener
;
31 import javax
.microedition
.lcdui
.Display
;
32 import javax
.microedition
.lcdui
.Displayable
;
33 import javax
.microedition
.lcdui
.Form
;
34 import javax
.microedition
.lcdui
.List
;
35 import javax
.microedition
.lcdui
.TextBox
;
36 import javax
.microedition
.lcdui
.TextField
;
37 import javax
.microedition
.midlet
.MIDlet
;
38 import javax
.microedition
.midlet
.MIDletStateChangeException
;
45 public class BluetoothNFCReader
extends MIDlet
implements TargetListener
,
46 CommandListener
, DiscoveryListener
{
48 private Display display
;
49 private Form formStart
;
50 private Form formServerStart
;
51 private Form formConnect
;
52 private Form formDiscover
;
53 private Form formReader
;
55 private Form formError
;
56 private TextField tfIn
;
57 private TextField tfOut
;
58 private TextField tfReadIn
;
59 private TextField tfWriteOut
;
60 //private TextField msgTf;
61 private Command cmdCancel
;
62 private Command cmdDiscover
;
63 private Command cmdSelect
;
64 private Command cmdExit
;
65 private Command cmdServer
;
66 private Command cmdLog
;
67 private Command cmdBack
;
68 private Command cmdRemove
;
71 /** currently selected target type. cards or tags.*/
72 private TargetType currTargetType
= null;
74 /** connection to use for card communication.*/
75 private ISO14443Connection isoConn
= null;
77 private DiscoveryAgent discoveryAgent
;
78 private Vector devices
;
80 private List deviceList
;
82 private StreamConnection connection
;
84 private String serviceURL
;
85 private byte[] buffer
;
86 //UUID SPP_UUID = new UUID("1101", true);
87 long SPP_UUID
= 0x1101;
88 static int SERVICE_NAME_ATTRID
= 0x0100;
90 private boolean isCardPresent
= false;
92 Reader r
= new Reader();
95 * @see javax.microedition.midlet.MIDlet#destroyApp(boolean)
97 protected void destroyApp(boolean arg0
) throws MIDletStateChangeException
{
98 // TODO Auto-generated method stub
103 * @see javax.microedition.midlet.MIDlet#pauseApp()
105 protected void pauseApp() {
106 // TODO Auto-generated method stub
111 * @see javax.microedition.midlet.MIDlet#startApp()
113 protected void startApp() throws MIDletStateChangeException
{
114 display
= Display
.getDisplay(this);
119 display
.setCurrent(formStart
);
123 private void initCommands() {
124 cmdCancel
= new Command("Cancel", Command
.CANCEL
, 1);
125 cmdDiscover
= new Command("Discover", Command
.ITEM
, 1);
126 cmdSelect
= new Command("Select", Command
.OK
, 1);
127 cmdExit
= new Command("Exit", Command
.EXIT
, 1);
128 cmdServer
= new Command("Server", Command
.ITEM
, 1);
129 cmdLog
= new Command("Log", Command
.ITEM
, 1);
130 cmdBack
= new Command("Back", Command
.BACK
, 1);
131 cmdRemove
= new Command("Remove", Command
.ITEM
, 1);
134 private void initForms() {
135 formStart
= new Form("Bluetooth Reader");
136 formServerStart
= new Form("Server");
137 formConnect
= new Form("Connect");
138 formDiscover
= new Form("Discover");
139 formReader
= new Form("Reader");
140 formLog
= new Form("Log");
141 formError
= new Form("Error");
142 tfIn
= new TextField("Last APDU", "", 520, TextField
.UNEDITABLE
);
143 tfOut
= new TextField("Last RAPDU", "", 520, TextField
.UNEDITABLE
);
144 tfReadIn
= new TextField("APDU size", "", 25, TextField
.UNEDITABLE
);
145 tfWriteOut
= new TextField("RAPDU size and responsecode", "", 12, TextField
.UNEDITABLE
);
149 private void setupForms() {
151 resetFormServerStart();
159 private void resetFormError() {
160 formError
.deleteAll();
161 formError
.setTitle("Error");
162 formError
.addCommand(cmdCancel
);
163 formError
.addCommand(cmdExit
);
164 formError
.addCommand(cmdLog
);
165 formError
.setCommandListener(this);
168 private void resetFormServerStart() {
169 formServerStart
.deleteAll();
170 formServerStart
.setTitle("Server");
171 // msgTf = new TextField("msg:", "", 256, TextField.ANY);
172 // formDisplay.append(msgTf);
173 formServerStart
.addCommand(cmdCancel
);
174 formServerStart
.setCommandListener(this);
177 private void resetFormConnect() {
178 formConnect
.deleteAll();
179 formConnect
.setTitle("Connect");
180 formConnect
.append("\n\n connect card!");
181 formConnect
.addCommand(cmdCancel
);
182 formConnect
.setCommandListener(this);
185 private void resetFormDiscover() {
186 formDiscover
.deleteAll();
187 formDiscover
.setTitle("Discover");
188 formDiscover
.addCommand(cmdCancel
);
189 formDiscover
.setCommandListener(this);
192 private void resetFormReader() {
193 formReader
.deleteAll();
194 formReader
.setTitle("Reader");
195 formReader
.append(tfReadIn
);
196 formReader
.append(tfWriteOut
);
197 formReader
.addCommand(cmdCancel
);
198 formReader
.addCommand(cmdLog
);
199 formReader
.addCommand(cmdRemove
);
200 formReader
.setCommandListener(this);
203 private void resetFormStart() {
204 formStart
.deleteAll();
205 formStart
.setTitle("Bluetooth Reader");
206 formStart
.addCommand(cmdServer
);
207 formStart
.addCommand(cmdDiscover
);
208 formStart
.addCommand(cmdExit
);
209 formStart
.setCommandListener(this);
212 private void resetFormLog() {
214 formLog
.setTitle("Log");
215 formLog
.append(tfIn
);
216 formLog
.append(tfOut
);
217 formLog
.addCommand(cmdBack
);
218 formLog
.setCommandListener(this);
221 private static String
toHexString(byte[] value
, int offset
, int len
) {
225 if (len
< 1 || offset
< 0 || offset
+ 1 > value
.length
) {
229 StringBuffer result
= new StringBuffer();
231 for (int i
= 0; i
+ offset
< value
.length
&& i
< len
; i
++) {
232 result
.append(Integer
.toHexString((value
[i
+ offset
] >>> 4) & 0x0F).toUpperCase());
233 result
.append(Integer
.toHexString(value
[i
+ offset
] & 0xF).toUpperCase());
235 return result
.toString();
238 private static byte[] toByteArray(String string
) {
239 if (string
.length() % 2 != 1) {
240 byte[] result
= new byte[string
.length() / 2];
241 for (int i
= 0; i
< result
.length
; i
++) {
242 result
[i
] = (byte) Integer
.parseInt(string
.substring(2 * i
,
251 // Starts the search for the Bluetooth devices
252 private void btSearch() {
255 deviceList
= new List("Searcing devices", List
.IMPLICIT
);
256 deviceList
.setSelectCommand(cmdSelect
);
257 deviceList
.addCommand(cmdCancel
);
258 deviceList
.setCommandListener(this);
259 display
.setCurrent(deviceList
);
261 devices
= new Vector();
262 // Start an inquiry to find Bluetooth devices
264 LocalDevice local
= LocalDevice
.getLocalDevice();
265 discoveryAgent
= local
.getDiscoveryAgent();
266 discoveryAgent
.startInquiry(DiscoveryAgent
.GIAC
, this);
268 } catch (BluetoothStateException e
) {
269 formLog
.append(e
.getMessage());
274 * @see javax.microedition.lcdui.CommandListener#commandAction(javax.microedition.lcdui.Command, javax.microedition.lcdui.Displayable)
276 public void commandAction(Command cmd
, Displayable displayForm
) {
278 if (displayForm
== formStart
) {
279 if (cmd
== cmdDiscover
) {
280 formStart
.append("starting client\n");
282 } else if (cmd
== cmdServer
) {
283 formStart
.append("starting server\n");
286 } else if (displayForm
== deviceList
) {
287 if (cmd
== cmdCancel
) {
288 discoveryAgent
.cancelInquiry(this);
290 display
.setCurrent(formStart
);
291 } else if (cmd
== cmdExit
) {
293 } else if (cmd
== cmdSelect
) {
294 if (deviceList
.getSelectedIndex() != deviceList
.size() - 1) {
295 RemoteDevice btDevice
= (RemoteDevice
) devices
296 .elementAt(deviceList
.getSelectedIndex());
297 startClient(btDevice
);
300 } else if (displayForm
== formError
) {
301 if (cmd
== cmdCancel
) {
303 disconnectCard(formError
, true);
305 display
.setCurrent(formStart
);
306 } else if (cmd
== cmdLog
) {
307 display
.setCurrent(formLog
);
309 } else if (displayForm
== formReader
) {
310 if (cmd
== cmdCancel
) {
312 disconnectCard(formError
, true);
314 if (connection
!= null) {
317 } catch (IOException e
) {
318 // TODO Auto-generated catch block
323 display
.setCurrent(formStart
);
324 } else if (cmd
== cmdLog
) {
325 display
.setCurrent(formLog
);
326 } else if (cmd
== cmdRemove
) {
327 disconnectCard(formError
, true);
328 startSmartCardDiscovery();
330 display
.setCurrent(formConnect
);
332 } else if (displayForm
== formLog
) {
333 if (cmd
== cmdBack
) {
334 display
.setCurrent(formReader
);
335 } else if (cmd
== cmdCancel
) {
337 disconnectCard(formError
, true);
339 if (connection
!= null) {
342 } catch (IOException e
) {
343 // TODO Auto-generated catch block
348 display
.setCurrent(formStart
);
350 } else if (displayForm
== formServerStart
) {
351 if (cmd
== cmdCancel
) {
354 display
.setCurrent(formStart
);
356 } else if (displayForm
== formConnect
) {
357 if (cmd
== cmdCancel
) {
360 if (connection
!= null) {
363 } catch (IOException e
) {
364 // TODO Auto-generated catch block
369 display
.setCurrent(formStart
);
372 //else if (displayForm == formDisplay) {
373 // if (cmd == cancelCmd) {
374 // display.setCurrent(form);
375 // form.addCommand(discoverCmd);
378 if (cmd
== cmdExit
) {
381 } catch (MIDletStateChangeException e
) {
382 // TODO Auto-generated catch block
390 private void startClient(RemoteDevice btDevice
) {
391 resetFormServerStart();
392 display
.setCurrent(formServerStart
);
393 formServerStart
.append(">>trying to discover remote services\n");
395 LocalDevice localDevice
= LocalDevice
.getLocalDevice();
396 DiscoveryAgent agent
= localDevice
.getDiscoveryAgent();
397 UUID
[] uuids
= new UUID
[] {new UUID(SPP_UUID
)};
398 int[] attrSet
= {SERVICE_NAME_ATTRID
};
399 int id
= agent
.searchServices(attrSet
, uuids
, btDevice
, this);
400 formServerStart
.append(">>got service: " + id
+ "\n");
401 } catch (BluetoothStateException e
) {
402 // TODO Auto-generated catch block
407 private void startServer() {
408 resetFormServerStart();
409 formServerStart
.append(">>starting service\n");
410 display
.setCurrent(formServerStart
);
412 LocalDevice btDevice
= LocalDevice
.getLocalDevice();
413 btDevice
.setDiscoverable(DiscoveryAgent
.GIAC
);
415 serviceURL
= "btspp://localhost:" + new UUID(SPP_UUID
).toString()
416 + ";name=SPPServer1";
417 StreamConnectionNotifier notifier
=
418 (StreamConnectionNotifier
) Connector
.open(serviceURL
);
419 formServerStart
.append(">>waiting for connection on\n" +
421 connection
= notifier
.acceptAndOpen();
422 // RemoteDevice rDev = RemoteDevice.getRemoteDevice(connection);
423 // formServerStart.append(">>remote address: " + rDev.getBluetoothAddress() + "\n");
424 // formServerStart.append(">>remote name: " + rDev.getFriendlyName(true) + "\n");
426 startSmartCardDiscovery();
428 // start thread and detach handler
429 Thread reader
= new Thread(r
);
431 formServerStart
.append("started reader\n");
432 } catch (BluetoothStateException e
) {
433 // TODO Auto-generated catch block
435 } catch (IOException e
) {
436 // TODO Auto-generated catch block
439 formServerStart
.append(">>done\n");
442 private void startSmartCardDiscovery() {
444 display
.setCurrent(formConnect
);
445 initializeCardDiscManager();
449 * @see javax.bluetooth.DiscoveryListener#deviceDiscovered(javax.bluetooth.RemoteDevice, javax.bluetooth.DeviceClass)
451 public void deviceDiscovered(RemoteDevice btDevice
, DeviceClass cod
) {
452 // When device has been found add it to devices Vector..
453 devices
.addElement(btDevice
);
455 // .. and to the deviceList List
458 devName
= btDevice
.getFriendlyName(false);
460 if (devName
== null || devName
.compareTo("") == 0) {
461 devName
= btDevice
.getBluetoothAddress();
463 deviceList
.append(devName
, null);
464 } catch (IOException e
) {
469 * @see javax.bluetooth.DiscoveryListener#inquiryCompleted(int)
471 public void inquiryCompleted(int status
) {
472 // When searching of the devices has completed set title to indicate
474 if (status
== INQUIRY_COMPLETED
) {
475 deviceList
.setTitle("Inquiry completed");
476 } else if (status
== INQUIRY_TERMINATED
) {
477 deviceList
.setTitle("Inquiry terminated");
478 } else if (status
== INQUIRY_ERROR
) {
479 deviceList
.setTitle("Inquiry error");
483 LocalDevice local
= LocalDevice
.getLocalDevice();
484 String name
= local
.getFriendlyName();
485 if (name
== null || name
.compareTo("") == 0) {
486 name
= local
.getBluetoothAddress();
488 devices
.addElement(local
);
489 deviceList
.append(name
, null);
490 } catch (BluetoothStateException e
) {
491 // TODO Auto-generated catch block
495 try { this.notifyAll(); } catch (Exception e
) {}
500 * @see javax.bluetooth.DiscoveryListener#serviceSearchCompleted(int, int)
502 public void serviceSearchCompleted(int transID
, int respCode
) {
503 if (respCode
!= SERVICE_SEARCH_COMPLETED
) {
504 formServerStart
.append(">>service discovery failed " + respCode
+ "\n");
507 formServerStart
.append(">>service discovery done " + transID
+ " " + respCode
+ "\n");
508 if (serviceURL
== null) {
509 formServerStart
.append("!!url empty, abort\n");
512 synchronized (this) {
513 try { this.notifyAll(); } catch (Exception e
) {}
515 formServerStart
.append(">>connecting to service: " + serviceURL
);
517 connection
= (StreamConnection
) Connector
.open(serviceURL
);
518 startSmartCardDiscovery();
519 } catch (IOException e
) {
520 // TODO Auto-generated catch block
526 * Removes targetListener for ISO cards.
528 private void removeCardDiscManager() {
529 currTargetType
= TargetType
.ISO14443_CARD
;
530 DiscoveryManager dm
= DiscoveryManager
.getInstance();
532 dm
.removeTargetListener(this, TargetType
.ISO14443_CARD
);
533 } catch (IllegalStateException e1
) {
534 // TODO Auto-generated catch block
535 e1
.printStackTrace();
540 * Adds Callback for ISO cards.
542 private void initializeCardDiscManager() {
543 currTargetType
= TargetType
.ISO14443_CARD
;
544 DiscoveryManager dm
= DiscoveryManager
.getInstance();
546 dm
.removeTargetListener(this, TargetType
.ISO14443_CARD
);
547 } catch (IllegalStateException e1
) {
548 // TODO Auto-generated catch block
549 e1
.printStackTrace();
552 dm
.addTargetListener(this, TargetType
.ISO14443_CARD
);
555 } catch (IllegalStateException e1
) {
556 // TODO Auto-generated catch block
557 e1
.printStackTrace();
558 } catch (ContactlessException e1
) {
559 // TODO Auto-generated catch block
560 e1
.printStackTrace();
565 * Interface callback, when ICC is detected by reader.
566 * @param target Properties of the detected ICC
568 public final void targetDetected(TargetProperties
[] target
) {
569 if (currTargetType
.equals(TargetType
.ISO14443_CARD
)) {
570 cardDetected(target
);
575 * Handle a detected smartcard.
576 * @param target connection
578 private void cardDetected(final TargetProperties
[] target
) {
579 if (!connectExternalCard(target
, formConnect
)) {
580 display
.setCurrent(formError
);
583 // // TODO start thread and detach handler
585 isCardPresent
= true;
586 display
.setCurrent(formReader
);
590 * Establishes connection to external card.
591 * @param target to make connection
592 * @param currentForm where to display messages
593 * @return success status
595 private boolean connectExternalCard(final TargetProperties
[] target
,
597 Class
[] classes
= target
[0].getConnectionNames();
599 for (int j
= 0; j
< classes
.length
; ++j
) {
601 if (isoConn
!= null) {
602 disconnectCard(currentForm
, false);
604 if (classes
[j
].equals(Class
.forName(
605 "javax.microedition.contactless.sc.ISO14443Connection"))) {
607 String url
= target
[0].getUrl(classes
[j
]);
610 isoConn
= (ISO14443Connection
) Connector
.open(url
);
611 } catch (IOException e
) {
612 currentForm
.append("IOException\n");
616 uid
= target
[0].getUid();
617 currentForm
.append("connected\n");
620 } catch (ClassNotFoundException e
) {
621 // TODO Auto-generated catch block
631 * @param currentForm where to display messages.
632 * @return true if successful
634 private boolean disconnectCard(final Form currentForm
, boolean removeTargetListener
) {
635 isCardPresent
= false;
637 if (isoConn
!= null) {
640 // currentForm.append(disconnectStr);
641 } catch (IOException e
) {
642 currentForm
.append("IOException\n");
645 if (removeTargetListener
) {
646 removeCardDiscManager();
654 * @see javax.bluetooth.DiscoveryListener#servicesDiscovered(int, javax.bluetooth.ServiceRecord[])
656 public void servicesDiscovered(int transID
, ServiceRecord
[] records
) {
657 formServerStart
.append(">>services discovered #: " + records
.length
+ "\n");
658 for (int i
= 0; i
< records
.length
; ++i
) {
659 serviceURL
= records
[i
].getConnectionURL(
660 ServiceRecord
.NOAUTHENTICATE_NOENCRYPT
, false);
661 DataElement serviceNameElement
= records
[i
].getAttributeValue(SERVICE_NAME_ATTRID
);
662 if (serviceNameElement
!= null) {
663 String name
= (String
) serviceNameElement
.getValue();
664 formServerStart
.append(">>" + name
+ "\n");
665 if (serviceURL
.startsWith("btspp")
666 && name
.indexOf("SPPServer1") > -1) {
667 formServerStart
.append(">>got btspp service " + i
+ "\n");
674 public class Reader
extends Thread
{
676 private static final int READER_CMD_LENGTH
= 2;
677 private final byte[] GET_ATTR_CMD
= new byte[] {0x20, 0x21};
678 private final byte[] GET_PRESENCE_CMD
= new byte[] {0x20, 0x22};
679 private final byte[] END_BYTES
= new byte[] {0x20, 0x23};
680 private boolean end
= false;
682 private final byte[] NULL_BYTES
= new byte[] {0x00};
683 private final byte[] ONE_BYTES
= new byte[] {(byte) 1};
690 formLog
.append("started\n");
695 private void startReader() {
697 formReader
.append(" -- communicating -- \n");
698 //display.setCurrent(formReader);
700 buffer
= new byte[258];
702 byte[] responseLength
= new byte[1];
705 OutputStream os
= connection
.openOutputStream();
706 InputStream is
= connection
.openInputStream();
708 int realLen
, readLen
, offset
, len
= 0;
717 while (readLen
!= realLen
) {
718 len
= is
.read(buffer
, realLen
+ 1, 255 - readLen
);
723 } catch (InterruptedException e
) {
724 // TODO Auto-generated catch block
725 formReader
.append("ending\n");
731 realLen
= (int) (buffer
[0] & 0xFF);
741 // byte[] cmd = new byte[len];
742 // for (int i = 0 ; i < readLen; ++i) {
743 // cmd[i] = buffer[i + 1];
746 // write messages to screen
747 if (len
> 1 && len
!= READER_CMD_LENGTH
) {
748 tfReadIn
.setString(">> " + len
+ "\n"
749 + toHexString(buffer
, 1, 8));
750 tfWriteOut
.setString(" \n ");
751 //tfIn.setString(">>got " + len + " " + toHexString(buffer, 1, 8));
757 if (len
== READER_CMD_LENGTH
) {
758 //formLog.append("might have gotten cmd\n");
760 if (isEnd(buffer
, offset
, len
)) {
762 formReader
.append(">>end command\n");
763 formLog
.append(">>end command\n");
767 if (equal(GET_ATTR_CMD
, buffer
, len
)) {
768 formLog
.append(">>atr\n");
769 responseLength
[0] = (byte) (0xFF & uid
.length());
770 os
.write(responseLength
);
771 os
.write(uid
.getBytes());
776 if (equal(GET_PRESENCE_CMD
, buffer
, len
)) {
777 //formLog.append(">>presence\n");
778 responseLength
[0] = 1;
779 os
.write(responseLength
);
783 os
.write(NULL_BYTES
);
790 formLog
.append("matched no cmd\n");
792 //formLog.append("doing real shit\n");
794 tfIn
.setString(toHexString(buffer
, 1, len
));
796 response
= sendAPDU(buffer
, offset
, len
);
798 if (response
!= null && response
.length
> 0) {
799 responseLength
[0] = (byte) (0xFF & response
.length
);
800 os
.write(responseLength
);
803 tfWriteOut
.setString("<< " + response
.length
804 + "\n" + toHexString(response
, response
.length
- 2, 2));
805 tfOut
.setString(toHexString(response
, 0, response
.length
));
807 os
.write(NULL_BYTES
);
811 //formLog.append("nuthing done\n");
812 os
.write(NULL_BYTES
);
819 } catch (IOException e
) {
822 } catch (IOException e
) {
824 formError
.append(e
.getMessage());
825 formError
.append("!!Bluetooth error\nrestart necessary\n");
826 disconnectCard(formError
, true);
827 display
.setCurrent(formError
);
830 if (connection
!= null) {
833 } catch (IOException e
) {
838 if (display
.getCurrent() == formReader
) {
840 display
.setCurrent(formLog
);//Start);
847 // TODO own exception throwing
848 private byte[] sendAPDU(byte[] buffer
, int offset
, int len
) {
849 if (buffer
== null || buffer
.length
== 0 || len
> buffer
.length
) {
853 byte[] cmd
= new byte[len
];
854 for (int i
= 0; i
< len
; ++i
) {
855 cmd
[i
] = buffer
[i
+ offset
];
859 return isoConn
.exchangeData(cmd
);
860 } catch (IOException e
) {
862 formError
.append(e
.getMessage());
863 formError
.append("!!NFC IO error\n");
864 formLog
.append("!!NFC IO error\n");
866 } catch (ContactlessException e
) {
868 formError
.append(e
.getMessage());
869 formError
.append("!!NFC contactless error\nrestart necessary\n");
870 formLog
.append("!!NFC contactless error\n");
871 disconnectCard(formError
, true);
872 display
.setCurrent(formError
);
878 private boolean isEnd(byte [] buffer
, int offset
, int length
) {
879 return equal(END_BYTES
, 0, END_BYTES
.length
, buffer
, offset
, length
);
882 private boolean equal(byte[] constCmd
, byte[] second
, int secondLength
) {
883 return equal(constCmd
, 0, constCmd
.length
, second
, 1, secondLength
);
886 private boolean equal(byte[] first
, int firstOffset
, int firstLength
,
887 byte[] second
, int secondOffset
, int secondLength
) {
888 if (first
== null && second
== null) {
889 //formLog.append("both null\n");
892 if (first
== null || second
== null) {
893 //formLog.append("one null\n");
896 if (firstLength
< 1 || firstOffset
< 0
897 || secondLength
< 1 || secondOffset
< 0) {
900 if (firstLength
+ firstOffset
> first
.length
901 || secondLength
+ secondOffset
> second
.length
) {
902 //formLog.append("wrong length specified\n");
905 if (firstLength
!= secondLength
) {
906 //formLog.append("length wrong " + first.length + " " + second.length + "\n");
909 for (int i
= 0; i
< firstLength
; ++i
) {
910 if (first
[i
+ firstOffset
] != second
[i
+ secondOffset
]) {
911 //formLog.append("different " + i + " " + first[i] + " != " + second[i] + "\n");