⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hcidriver.java

📁 蓝牙协议栈可是要钱的喔
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
*  (c) Copyright 2003 Christian Lorenz  ALL RIGHTS RESERVED.
* 
* This file is part of the JavaBluetooth Stack.
* 
* The JavaBluetooth Stack is free software; you can redistribute it 
* and/or modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2 of
* the License, or (at your option) any later version.
* 
* The JavaBluetooth Stack 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 for more details.
* 
* Created on May 21, 2003
* by Christian Lorenz
*
*/

package org.javabluetooth.stack.hci;

import java.util.*;
import org.javabluetooth.stack.l2cap.L2CAPLink;
import org.javabluetooth.util.Debug;

/** 
 * This interface is implemented by Drivers for specific HCI Transports.
 * Right now only UART is supported, but this interface will allow future drivers for other HCI Transports such as USB.
 * @see org.javabluetooth.stack.hci.UARTTransport
 * @author Christian Lorenz
 */
public abstract class HCIDriver {
    private static final byte PACKET_TYPE_ACL                        = 0x02;
    private static final byte PACKET_TYPE_EVENT                      = 0x04;
    private static final byte HCI_EVENT_INQUIRY_COMPLETE             = 0x01;
    private static final byte HCI_EVENT_INQUIRY_RESULT               = 0x02;
    private static final byte HCI_EVENT_CONNECTION_COMPLETE          = 0x03;
    private static final byte HCI_EVENT_DISCONNECTION_COMPLETE       = 0x05;
    private static final byte HCI_EVENT_REMOTE_NAME_REQUEST_COMPLETE = 0x07;
    private static final byte HCI_EVENT_COMMAND_COMPLETE             = 0x0E;
    private static final byte HCI_EVENT_COMMAND_STATUS               = 0x0F;
    private static final byte HCI_EVENT_NUMBER_OF_COMPLETED_PACKETS  = 0x13;
    private static HCIDriver hciDriver;
    private byte[] commandResponse;
    private short commandResponseOpCode = 0;
    private Hashtable connectionHandels = new Hashtable();
    private Hashtable remoteAddresses   = new Hashtable();
    private Vector hciReceivers         = new Vector();
    private byte[] headerBuffer         = new byte[5];
    private short headerBufferIndex     = 0;
    private byte[] packetBuffer;
    private int packetBufferIndex;

    public static void init(HCIDriver hciTransport) { HCIDriver.hciDriver = hciTransport; }

    public static HCIDriver getHCIDriver() throws HCIException {
        if (hciDriver == null) throw new HCIException("HCITransport not initalized. ");
        return hciDriver;
    }

    public void registerHCIReceiver(HCIReceiver receiver) {
        if (!hciReceivers.contains(receiver)) hciReceivers.addElement(receiver);
    }

    public void unregisterHCIReceiver(HCIReceiver receiver) { hciReceivers.removeElement(receiver); }

    public void registerL2CAPLink(L2CAPLink link) {
        Short handle = new Short(link.connectionHandle);
        connectionHandels.put(handle, link);
        Long remoteAddress = new Long(link.remoteAddress);
        remoteAddresses.put(remoteAddress, link);
    }

    public void unregisterL2CAPLink(L2CAPLink link) {
        connectionHandels.remove(new Short(link.connectionHandle));
        remoteAddresses.remove(new Long(link.remoteAddress));
    }

    public L2CAPLink getL2CAPLink(long remoteAddress, byte pageScanRepMode, byte pageScanMode,
        short clockOffset) throws HCIException {
            Long remoteAddressLong = new Long(remoteAddress);
            L2CAPLink link = (L2CAPLink)remoteAddresses.get(remoteAddressLong);
            if (link == null) {
                byte connResult = send_HCI_LC_Create_Connection(remoteAddress, (short)0x8000, pageScanRepMode, pageScanMode,
                    clockOffset, (byte)0x01);
                if (connResult != 0) throw new HCIException("Create Connection failed. (" + connResult + ")");
                short timeout = 0;
                while (link == null) {
                    try {
                        Thread.sleep(1000);
                        timeout++;
                    }
                    catch (InterruptedException e) { }
                    if (timeout == 50) throw new HCIException("Create Connection timed out.");
                    link = (L2CAPLink)remoteAddresses.get(remoteAddressLong);
                }
            }
            return link;
    }

    public synchronized byte[] send_HCI_Command_Packet(byte[] cmdPacket) throws HCIException {
        short opCode = (short)((cmdPacket[2] << 8) | (cmdPacket[1] & 0xff));
        Debug.println(1, "HCI: Sending Command: " + opCode);
        while (commandResponse != null) {
            try { this.wait(100); }
            catch (InterruptedException e) { }
        }
        commandResponseOpCode = opCode;
        hciDriver.sendPacket(cmdPacket);
        //int timer=0;
        while (commandResponse == null) {
            try {
                this.wait(500);

                /*timer++;
                if(timer==50)
                {	timer=0;
                Debug.println("HCI: Resending Command with opCode:" + opCode + ")");
                hciTransport.sendPacket(cmdPacket);
                }*/
            }
            catch (InterruptedException e) { }
        }
        byte[] result = commandResponse;
        commandResponseOpCode = 0;
        commandResponse = null;

        /* The Brainboxes Bluetooth Host Controller seems to have a bug
        * which causes the module to slow down to an unacceptable speed
        * when an Inquiry Complete Event is send. This is a cheap hack to
        * surpress the sending of this event by simply sending a Cancel
        * Inquiry Command before it naturally Completes.
        * before it completes.
        */

        if ((cmdPacket[1] == 0x01) && (cmdPacket[2] == 0x04)) {
            try { wait(10000); }
            catch (InterruptedException e) { }
            byte[] cancelInquiryPacket = { 0x01, 0x02, 0x04, 0x00 };
            short cancelOpCode = (short)((cancelInquiryPacket[2] << 8) | (cancelInquiryPacket[1] & 0xff));
            while (commandResponse != null) {
                try { wait(100); }
                catch (InterruptedException e) { }
            }
            commandResponseOpCode = cancelOpCode;
            hciDriver.sendPacket(cancelInquiryPacket);
            while (commandResponse == null) {
                try { wait(100); }
                catch (InterruptedException e) { }
            }
            commandResponseOpCode = 0;
            commandResponse = null;
            byte[] dummyPacket = { PACKET_TYPE_EVENT, HCI_EVENT_INQUIRY_COMPLETE, (byte)0x01, (byte)0x00 };
            receive_HCI_Event_Inquiry_Complete(dummyPacket);
        }

        /* end of Hack */

        return result;
    }

    public synchronized void send_HCI_Data_Packet(byte[] dataPacket) throws HCIException {
        Debug.println(1, "HCI: Sending Data Packet.");
        sendPacket(dataPacket);
    }

    /**
     * This command will cause the Link Manager to create a connection
     * to the Bluetooth device with the BD_ADDR specified by the command
     * parameters. It is triggered by <code>HCITransport.getL2CAPLink()</code>.  For details see Page 568 of the Bluetooth
     * Core Specification Version 1.1
     * @param bd_addr
     * @param packetType
     * @param clockOffset
     * @param allowRoleSwitching
     * @return return 0x00 if the command succeeded. 0x01-0xFF if the command failed. See Table 6.1 on page 766
     * for list of Error Codes.
     * @throws HCIException
     */
    public byte send_HCI_LC_Create_Connection(long bd_addr, short packetType, byte pageScanRepMode, byte pageScanMode,
        short clockOffset, byte allowRoleSwitching) throws HCIException {
            byte[] data = {
                0x01, 0x05, 0x04, 0x0d, (byte)((bd_addr) & 0xff), (byte)((bd_addr >> 8) & 0xff), (byte)((bd_addr >> 16) & 0xff),
                    (byte)((bd_addr >> 24) & 0xff), (byte)((bd_addr >> 32) & 0xff), (byte)((bd_addr >> 40) & 0xff), (byte)((packetType) & 0xff),
                    (byte)((packetType >> 8) & 0xff), (byte)pageScanRepMode, // Page scan repetition mode 1 byte
                    (byte)pageScanMode, // Page scan mode 1 byte
                    (byte)((clockOffset) & 0xff), // Clock offset 2 bytes
                    (byte)((clockOffset >> 8) & 0xff), (byte)allowRoleSwitching
            }; // Allow role switch
            byte[] resultData = send_HCI_Command_Packet(data);
            return resultData[3];
    }

    /**
     * The Disconnection command is used to terminate an existing connection.
     * The Connection Handle indicates which connection is to be disconnected.
     * It is triggered by <code>L2CAPLink.close()</code>. When the Host Controller receives the Disconnect command, it sends
     * the Command Status event to the Host. The Disconnection Complete
     * event will occur at each Host when the termination of the connection has
     * completed, and indicates that this command has been completed.
     * For details see Page 571 of the Bluetooth Core Specification Version 1.1
     * @param connectionHandle Connection Handle for the connection being disconnected.
     * @return 0x00 if the command succeeded. 0x01-0xFF if the command failed. See Table 6.1 on page 766
     * for list of Error Codes.
     * @throws HCIException
     */
    public byte send_HCI_LC_Disconnect(short connectionHandle) throws HCIException {
        byte[] data =

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -