Part one of undating the bluetooth code to the newest version
Submitted by: Maksim Yevmenkin <m_evmenkin@yahoo.com> Approved by: re@
This commit is contained in:
parent
7bdf1805b1
commit
f2bb1cae36
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=114878
@ -232,6 +232,7 @@ MAN= aac.4 \
|
||||
txp.4 \
|
||||
ubsa.4 \
|
||||
ubsec.4 \
|
||||
ubtbcmfw.4 \
|
||||
ucom.4 \
|
||||
udbp.4 \
|
||||
udp.4 \
|
||||
|
@ -1,6 +1,8 @@
|
||||
.\" ng_bluetooth.4
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
@ -9,7 +11,7 @@
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@ -21,97 +23,81 @@
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" $Id: ng_bluetooth.4,v 1.2 2003/04/26 22:38:25 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 9, 2002
|
||||
.Dt NG_BLUETOOTH 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ng_bluetooth
|
||||
.Nm bluetooth
|
||||
.Nd placeholder for global Bluetooth variables
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In ng_bluetooth.h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
module is a placeholder for global Bluetooth variables.
|
||||
All Bluetooth variables can be examined and changed via
|
||||
.Nm
|
||||
module is a placeholder for global Bluetooth variables. All Bluetooth
|
||||
variables can be examined and changed via
|
||||
.Xr sysctl 8 .
|
||||
.Ss Bluetooth Variables
|
||||
Below is the description of default variables.
|
||||
Each Bluetooth module might add its own variables to the tree.
|
||||
.Bl -tag -width indent
|
||||
.It Va net.bluetooth.version
|
||||
A read-only integer variable that shows the current version of the
|
||||
.Sh BLUETOOTH VARIABLES
|
||||
Below is the description of default variables. Each Bluetooth module
|
||||
might add its own variables to the tree.
|
||||
.Bl -tag -width foobar
|
||||
.It net.bluetooth.version
|
||||
A read only integer variable that shows the current version of the
|
||||
Bluetooth stack.
|
||||
.It Va net.bluetooth.hci.command_timeout
|
||||
.It net.bluetooth.hci.command_timeout
|
||||
A read-write interger variable that controls the Host Controller Interface
|
||||
(HCI) command timeout (in seconds), i.e. how long the HCI layer will wait
|
||||
(HCI) command timeout (in seconds), i.e. how long the HCI layer will wait
|
||||
for the
|
||||
.Dv Command_Complete
|
||||
or
|
||||
.Dv Command_Status
|
||||
event from a Bluetooth device.
|
||||
.It Va net.bluetooth.hci.connection_timeout
|
||||
A read-write integer variable that controls the HCI connection timeout, i.e.\&
|
||||
how long the HCI layer will wait for the
|
||||
.It net.bluetooth.hci.connection_timeout
|
||||
A read-write integer variable that controls the HCI connection timeout, i.e.
|
||||
how long the HCI layer will wait for the
|
||||
.Dv Connection_Complete
|
||||
event.
|
||||
Normally this should not be required as Bluetooth devices have
|
||||
connection timeout of their own and will send event back.
|
||||
This timeout
|
||||
is required to ensure that no connection will stall in case when the HCI
|
||||
transport layer is broken.
|
||||
Be careful when changing this variable.
|
||||
event. Normaly this should not be required as Bluetooth devices have
|
||||
connection timeout of their own and will send event back. This timeout
|
||||
is required to ensure that no connection will stall in case when the HCI
|
||||
transport layer is broken. Be careful when changing this variable.
|
||||
Make sure you understand what you are doing.
|
||||
.It Va net.bluetooth.hci.watchdog_timeout
|
||||
A read-write integer variable that controls the HCI connection watchdog
|
||||
timeout in seconds), i.e. how long the HCI layer should wait before
|
||||
disconnecting an inactive baseband connection.
|
||||
.Bf -emphasis
|
||||
This has not been implemented yet.
|
||||
.Ef
|
||||
.It Va net.bluetooth.hci.max_neighbor_age
|
||||
.It net.bluetooth.hci.max_neighbor_age
|
||||
A read-write integer variable that controls time-to-live (in seconds) for
|
||||
entries in the HCI neighbor cache.
|
||||
Every time a Bluetooth device performs an
|
||||
entries in the HCI neighbor cache. Every time a Bluetooth device performs
|
||||
an
|
||||
.Dv Inquiry
|
||||
operation, the results will be put in cache.
|
||||
Later when a Bluetooth device
|
||||
establishes a baseband connection, it will try to find the matching entry in
|
||||
the cache and use it.
|
||||
This might speed up establishment of the baseband
|
||||
operation, the results will be put in cache. Later when a Bluetooth device
|
||||
establishes a baseband connection, it will try to find the matching entry in
|
||||
the cache and use it. This might speed up establishment of the baseband
|
||||
connection.
|
||||
.It Va net.bluetooth.l2cap.rtx_timeout
|
||||
A read-write integer variable that controls the Link Layer Control and
|
||||
Adaptation Protocol (L2CAP) Retransmission Timeout (RTX) (in seconds).
|
||||
Every time the L2CAP layer submits a control command, the RTX timeout is set.
|
||||
The value of the RTX timeout should be greater or equal to the value of
|
||||
the HCI connection timeout.
|
||||
Be careful when changing this variable.
|
||||
Make sure you understand what you are doing.
|
||||
.It Va net.bluetooth.l2cap.ertx_timeout
|
||||
A read-write integer variable that controls the L2CAP Extended Retransmission
|
||||
Timeout (ERTX) (in seconds).
|
||||
In some cases remote peer may respond with
|
||||
.It net.bluetooth.l2cap.rtx_timeout
|
||||
A read-write integer variable that controls the Link Layer Control and
|
||||
Adaptation Protocol (L2CAP) Retransmission Timeout (RTX) (in seconds).
|
||||
Every time the L2CAP layer submits a control command, the RTX timeout is set.
|
||||
The value of the RTX timeout should be greater or equal to the value of
|
||||
the HCI connection timeout. Be careful when changing this variable. Make
|
||||
sure you understand what you are doing.
|
||||
.It net.bluetooth.l2cap.ertx_timeout
|
||||
A read-write integer variable that controls the L2CAP Extended Retransmission
|
||||
Timeout (ERTX) (in seconds). In some cases remote peer may respond with
|
||||
.Dv PENDING
|
||||
status to the L2CAP control command.
|
||||
In this case the L2CAP command timeout is reset to the ERTX timeout value.
|
||||
The value of the ERTX timeout should be
|
||||
greater or equal to the value of the RTX timeout.
|
||||
Be careful when changing this variable.
|
||||
Make sure you understand what you are doing.
|
||||
status to the L2CAP control command. In this case the L2CAP command timeout
|
||||
is reset to the ERTX timeout value. The value of the ERTX timeout should be
|
||||
greater or equal to the value of the RTX timeout. Be careful when changing
|
||||
this variable. Make sure you understand what you are doing.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr ng_btsocket 4 ,
|
||||
.Xr sysctl 8 ,
|
||||
.Xr ng_hci 4 ,
|
||||
.Xr ng_l2cap 4 ,
|
||||
.Xr sysctl 8
|
||||
.Xr ng_btsocket 4
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
.Nm
|
||||
module was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
|
@ -1,6 +1,8 @@
|
||||
.\" ng_bt3c.4
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
@ -9,7 +11,7 @@
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@ -21,46 +23,40 @@
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" $Id: ng_bt3c.4,v 1.1 2002/11/24 19:37:54 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 14, 2002
|
||||
.Dt NG_BT3C 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ng_bt3c
|
||||
.Nm BTCCC
|
||||
.Nd Netgraph node type that is also a 3Com Bluetooth PC card driver
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In ng_bt3c.h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm btccc
|
||||
.Nm BTCCC
|
||||
node type is both a persistent Netgraph node type and a driver for
|
||||
3Com Bluetooth PC card (3CRWB6096-HP).
|
||||
It implements a Bluetooth HCI
|
||||
3Com Bluetooth PC card (3CRWB6096-HP). It implements a Bluetooth HCI
|
||||
UART transport layer as per chapter H4 of the Bluetooth Specification
|
||||
Book v1.1.
|
||||
A new node is created when the card is plugged.
|
||||
Book v1.1. A new node is created when the card is plugged.
|
||||
.Pp
|
||||
In order to use the card one
|
||||
.Em MUST
|
||||
download firmware first.
|
||||
Due to copyright issues I will no longer provide firmware with the driver.
|
||||
The firmware can be obtained
|
||||
from the Windows driver package that can be downloaded from the 3COM web
|
||||
site at no charge.
|
||||
The firmware name is
|
||||
.Pa BT3CPCC.BIN .
|
||||
To load firmware into the card, use
|
||||
download firmware first. Due to copyright issues I will no longer
|
||||
provide firmware with the driver. The firmware can be obtained
|
||||
from the Windows driver package that can be downloaded from the 3COM web
|
||||
site at no charge. The firmware name is BT3CPCC.BIN. To load firmware
|
||||
info the card use
|
||||
.Xr bt3cfw 8 .
|
||||
I am using original firmware that came with the card on CD-ROM.
|
||||
I'm using original firmware that came with the card on CD-ROM.
|
||||
.Bd -literal -offset indent
|
||||
MD5 (BT3CPCC.BIN) = 36170fda56ea9fdbf1702c966f8a97f1
|
||||
.Ed
|
||||
.Pp
|
||||
.Dl "MD5 (BT3CPCC.BIN) = 36170fda56ea9fdbf1702c966f8a97f1"
|
||||
.Pp
|
||||
For
|
||||
.Pa OLDCARD
|
||||
systems the entry in
|
||||
For OLDCARD systems the entry in
|
||||
.Xr pccard.conf 5
|
||||
might look like this
|
||||
.Bd -literal -offset indent
|
||||
@ -70,30 +66,29 @@ card "3COM" "3CRWB60-A" "Bluetooth PC Card"
|
||||
insert /usr/sbin/bt3cfw -n $device -f /etc/BT3CPCC.bin
|
||||
.Ed
|
||||
.Pp
|
||||
Do not forget to load module and
|
||||
.Dv SIGHUP
|
||||
Do not forget to load module and SIGHUP
|
||||
.Xr pccardd 8 .
|
||||
.Pp
|
||||
The node has a single hook called
|
||||
.Dv hook .
|
||||
Incoming bytes received on the device are re-assembled into HCI frames
|
||||
(according to the length).
|
||||
Full HCI frames are sent out on the hook.
|
||||
HCI frames received on
|
||||
(according to the length). Full HCI frames are sent out on the hook. HCI
|
||||
frames received on
|
||||
.Dv hook
|
||||
are transmitted out.
|
||||
No modification to the data is performed in either direction.
|
||||
are transmitted out. No modification to the data is performed in
|
||||
either direction.
|
||||
.Sh HOOKS
|
||||
This node type supports the following hooks:
|
||||
.Bl -tag -width indent
|
||||
.Pp
|
||||
.Bl -tag -width foobar
|
||||
.It Dv hook
|
||||
single HCI frame contained in single
|
||||
.Vt mbuf
|
||||
.Dv mbuf
|
||||
structure.
|
||||
.El
|
||||
.Sh CONTROL MESSAGES
|
||||
This node type supports the generic control messages, plus the following:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv NGM_BT3C_NODE_GET_STATE
|
||||
Returns current receiving state for the node.
|
||||
.It Dv NGM_BT3C_NODE_GET_DEBUG
|
||||
@ -102,15 +97,15 @@ Returns an integer containing the current debug level for the node.
|
||||
This command takes an integer argument and sets current debug level
|
||||
for the node.
|
||||
.It Dv NGM_BT3C_NODE_GET_QLEN
|
||||
This command takes a parameter that specifies queue number and returns
|
||||
This command takes a parameter that specifies queue number and returns
|
||||
current length of the queue for the node.
|
||||
.It Dv NGM_BT3C_NODE_SET_QLEN
|
||||
This command takes two parameters that specify queue number and and
|
||||
maximum length of the queue and sets maximum length of the queue for
|
||||
This command takes two parameters that specify queue number and and
|
||||
maximum length of the queue and sets maximum length of the queue for
|
||||
the node.
|
||||
.It Dv NGM_BT3C_NODE_GET_STAT
|
||||
Returns various statistic information for the node, such as: number of
|
||||
bytes (frames) sent, number of bytes (frames) received and number of
|
||||
Returns various statistic information for the node, such as: number of
|
||||
bytes (frames) sent, number of bytes (frames) received and number of
|
||||
input (output) errors.
|
||||
.It Dv NGM_BT3C_NODE_RESET_STAT
|
||||
Reset all statistic counters to zero.
|
||||
@ -120,22 +115,21 @@ Download card firmware.
|
||||
.Sh SHUTDOWN
|
||||
This node shuts down when the corresponding card is un-plugged.
|
||||
.Sh BUGS
|
||||
The driver is based on information obtained from
|
||||
.An Jose Orlando Pereira Aq jop@di.uminho.pt
|
||||
and disassembled W2K driver.
|
||||
The driver is based on information obrained from Jose Orlando Pereira
|
||||
<jop@di.uminho.pt> and disassembled W2K driver.
|
||||
.Sh SEE ALSO
|
||||
.Xr cardbus 4 ,
|
||||
.Xr netgraph 4 ,
|
||||
.Xr pccbb 4 ,
|
||||
.Xr pcic 4 ,
|
||||
.Xr pccard.conf 5 ,
|
||||
.Xr bt3cfw 8 ,
|
||||
.Xr ngctl 8 ,
|
||||
.Xr pccardc 8 ,
|
||||
.Xr pccardd 8
|
||||
.Xr pccardd 8 ,
|
||||
.Xr pccard.conf 5 ,
|
||||
.Xr netgraph 4 ,
|
||||
.Xr ngctl 8 ,
|
||||
.Xr bt3cfw 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm btccc
|
||||
.Nm BTCCC
|
||||
node type was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
|
@ -1,3 +1,5 @@
|
||||
.\" ng_btsocket.4
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
@ -22,8 +24,8 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id: ng_btsocket.4,v 1.6 2003/03/18 00:09:34 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 8, 2002
|
||||
.Dt NG_BTSOCKET 4
|
||||
.Os
|
||||
@ -41,23 +43,23 @@
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
module implements three Netgraph node types.
|
||||
Each type in its turn implements one protocol within
|
||||
module implements three Netgraph node types. Each type in its turn implements
|
||||
one protocol within
|
||||
.Dv PF_BLUETOOTH
|
||||
domain.
|
||||
.Sh Dv BLUETOOTH_PROTO_HCI Sh protocol
|
||||
.Ss Dv SOCK_RAW Ss HCI sockets
|
||||
.Pp
|
||||
.Sh BLUETOOTH_PROTO_HCI protocol
|
||||
.Ss SOCK_RAW HCI sockets
|
||||
Implemented by
|
||||
.Nm btsock_hci_raw
|
||||
Netgraph type.
|
||||
Raw HCI sockets allow sending of raw HCI command datagrams
|
||||
.Cm btsock_hci_raw
|
||||
Netgraph type. Raw HCI sockets allow sending of raw HCI command datagrams
|
||||
only to correspondents named in
|
||||
.Xr send 2
|
||||
calls.
|
||||
Raw HCI datagrams (HCI commands, events and data) are generally received with
|
||||
calls. Raw HCI datagrams (HCI commands, events and data) are generally
|
||||
received with
|
||||
.Xr recvfrom 2 ,
|
||||
which returns the next datagram with its return address.
|
||||
Raw HCI sockets can also be used to control HCI nodes.
|
||||
which returns the next datagram with its return address. Also raw HCI
|
||||
sockets can be used to control HCI nodes.
|
||||
.Pp
|
||||
The Bluetooth raw HCI socket address is defined as follows:
|
||||
.Bd -literal -offset indent
|
||||
@ -69,14 +71,14 @@ struct sockaddr_hci {
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
Raw HCI sockets support number of
|
||||
.Xr ioctl 2
|
||||
Raw HCI sockets support number of
|
||||
.Xr ioctl 2
|
||||
requests such as:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv SIOC_HCI_RAW_NODE_GET_STATE
|
||||
Returns current state for the HCI node.
|
||||
.It Dv SIOC_HCI_RAW_NODE_INIT
|
||||
Turn on
|
||||
Turn on
|
||||
.Dq inited
|
||||
bit for the HCI node.
|
||||
.It Dv SIOC_HCI_RAW_NODE_GET_DEBUG
|
||||
@ -108,12 +110,21 @@ Sets current link policy settings mask for the HCI node.
|
||||
Returns current packet mask for the HCI node.
|
||||
.It SIOC_HCI_RAW_NODE_SET_PACKET_MASK
|
||||
Sets current packet mask for the HCI node.
|
||||
.It SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH
|
||||
Returns current value of the role switch parameter for the HCI node.
|
||||
.It SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH
|
||||
Sets new value of the role switch parameter for the HCI node.
|
||||
.El
|
||||
.Pp
|
||||
Raw HCI sockets support filters.
|
||||
The application can filter certain HCI datagram types.
|
||||
For HCI event datagrams the application can set additional filter.
|
||||
The raw HCI socket filter defined as follows:
|
||||
The
|
||||
.Dv net.bluetooth.hci.sockets.raw.ioctl_timeout
|
||||
variable, that can be examined and set via
|
||||
.Xr sysctl 8 ,
|
||||
controls the control request timeout (in seconds) for raw HCI sockets.
|
||||
.Pp
|
||||
Raw HCI sockets support filters. The application can filter certain
|
||||
HCI datagram types. For HCI event datagrams the application can set
|
||||
additional filter. The raw HCI socket filter defined as follows:
|
||||
.Bd -literal -offset indent
|
||||
/*
|
||||
* Raw HCI socket filter.
|
||||
@ -128,16 +139,17 @@ struct ng_btsocket_hci_raw_filter {
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
The
|
||||
.Dv SO_HCI_RAW_FILTER
|
||||
option defined at
|
||||
.Dv SOL_HCI_RAW
|
||||
.Dv SOL_HCI_RAW
|
||||
level can be used to obtain via
|
||||
.Xr getsockopt 2
|
||||
or change via
|
||||
.Xr setsockopt 2
|
||||
or change via
|
||||
.Xr setsockopt 2
|
||||
raw HCI socket's filter.
|
||||
.Sh Dv BLUETOOTH_PROTO_L2CAP Sh protocol
|
||||
.Pp
|
||||
.Sh BLUETOOTH_PROTO_L2CAP protocol
|
||||
The Bluetooth L2CAP socket address is defined as follows:
|
||||
.Bd -literal -offset indent
|
||||
/* Bluetooth version of struct sockaddr for L2CAP sockets */
|
||||
@ -148,23 +160,19 @@ struct sockaddr_l2cap {
|
||||
bdaddr_t l2cap_bdaddr; /* address */
|
||||
};
|
||||
.Ed
|
||||
.Ss Dv SOCK_RAW Ss L2CAP sockets
|
||||
Implemented by
|
||||
.Nm btsock_l2c_raw
|
||||
Netgraph type.
|
||||
Raw L2CAP sockets do not provide access to raw L2CAP datagrams.
|
||||
These
|
||||
sockets used to control L2CAP nodes and to issue special L2CAP requests
|
||||
such as
|
||||
.Dv ECHO_REQUEST
|
||||
and
|
||||
.Dv GET_INFO
|
||||
request.
|
||||
.Pp
|
||||
Raw L2CAP sockets support number of
|
||||
.Xr ioctl 2
|
||||
.Ss SOCK_RAW L2CAP sockets
|
||||
Implemented by
|
||||
.Cm btsock_l2c_raw
|
||||
Netgraph type.
|
||||
Raw L2CAP sockets do not provide access to raw L2CAP datagrams. These
|
||||
sockets used to control L2CAP nodes and to issue special L2CAP requests
|
||||
such as ECHO_REQUEST and GET_INFO request.
|
||||
.Pp
|
||||
Raw L2CAP sockets support number of
|
||||
.Xr ioctl 2
|
||||
requests such as:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv SIOC_L2CAP_NODE_GET_FLAGS
|
||||
Returns current state for the L2CAP node.
|
||||
.It Dv SIOC_L2CAP_NODE_GET_DEBUG
|
||||
@ -177,97 +185,150 @@ node.
|
||||
.It Dv SIOC_L2CAP_NODE_GET_CHAN_LIST
|
||||
Returns list of active channels for the L2CAP node.
|
||||
.It Dv SIOC_L2CAP_L2CA_PING
|
||||
Issues L2CAP
|
||||
.Dv ECHO_REQUEST .
|
||||
Issues L2CAP ECHO_REQUEST.
|
||||
.It Dv SIOC_L2CAP_L2CA_GET_INFO
|
||||
Issues L2CAP
|
||||
.Dv GET_INFO
|
||||
request.
|
||||
Issues L2CAP GET_INFO request.
|
||||
.El
|
||||
.Ss Dv SOCK_SEQPACKET Ss L2CAP sockets
|
||||
.Pp
|
||||
The
|
||||
.Dv net.bluetooth.l2cap.sockets.raw.ioctl_timeout
|
||||
variable, that can be examined and set via
|
||||
.Xr sysctl 8 ,
|
||||
controls the control request timeout (in seconds) for raw L2CAP sockets.
|
||||
.Pp
|
||||
.Ss SOCK_SEQPACKET L2CAP sockets
|
||||
Implemented by
|
||||
.Nm btsock_l2c
|
||||
.Cm btsock_l2c
|
||||
Netgraph type.
|
||||
L2CAP sockets are either
|
||||
L2CAP sockets are either
|
||||
.Dq active
|
||||
or
|
||||
.Dq passive .
|
||||
Active sockets initiate connections to passive sockets.
|
||||
By default L2CAP sockets are created active; to create a passive socket the
|
||||
Active sockets initiate connections to passive sockets. By default L2CAP
|
||||
sockets are created active; to create a passive socket the
|
||||
.Xr listen 2
|
||||
system call must be used after binding the socket with the
|
||||
system call must be used after binding the socket with the
|
||||
.Xr bind 2
|
||||
system call.
|
||||
Only passive sockets may use the
|
||||
.Xr accept 2
|
||||
call to accept incoming connections.
|
||||
Only active sockets may use the
|
||||
.Xr connect 2
|
||||
call to initiate connections.
|
||||
system call. Only passive sockets may use the
|
||||
.Xr accept 2
|
||||
call to accept incoming connections. Only active sockets may use the
|
||||
.Xr connect 2
|
||||
call to initiate connections.
|
||||
.Pp
|
||||
L2CAP sockets support
|
||||
.Dq "wildcard addressing" .
|
||||
In this case, socket must be bound to
|
||||
.Dv NG_HCI_BDADDR_ANY
|
||||
address.
|
||||
Note that PSM (Protocol/Service Multiplexor) filed is always
|
||||
required.
|
||||
Once a connection has been established the socket's address is
|
||||
fixed by the peer entity's location.
|
||||
The address assigned the socket is
|
||||
the address associated with the Bluetooth device through which packets are
|
||||
.Dq wildcard addressing .
|
||||
In this case socket must be bound to
|
||||
.Dv NG_HCI_BDADDR_ANY
|
||||
address. Note that PSM (Protocol/Service Multiplexor) field is always
|
||||
required. Once a connection has been established the socket's address is
|
||||
fixed by the peer entity's location. The address assigned the socket is
|
||||
the address associated with the Bluetooth device through which packets are
|
||||
being transmitted and received, and PSM (Protocol/Service Multiplexor).
|
||||
.Pp
|
||||
L2CAP sockets support number of options defined at
|
||||
.Dv SOL_L2CAP
|
||||
level which can be set with
|
||||
.Xr setsockopt 2
|
||||
and tested with
|
||||
.Dv SOL_L2CAP
|
||||
level which can be set with
|
||||
.Xr setsockopt 2
|
||||
and tested with
|
||||
.Xr getsockopt 2 :
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv SO_L2CAP_IMTU
|
||||
Get (set) maximum payload size the local socket is capable of accepting.
|
||||
.It Dv SO_L2CAP_OMTU
|
||||
Get maximum payload size the remote socket is capable of accepting.
|
||||
.It Dv SO_L2CAP_IFLOW
|
||||
Get incoming flow specification for the socket.
|
||||
.Bf -emphasis
|
||||
Not implemented.
|
||||
.Ef
|
||||
Get incoming flow specification for the socket.
|
||||
.Em Not implemented at the L2CAP layer .
|
||||
.It Dv SO_L2CAP_OFLOW
|
||||
Get (set) outgoing flow specification for the socket.
|
||||
.Bf -emphasis
|
||||
Not implemented.
|
||||
.Ef
|
||||
.Em Not implemented at the L2CAP layer .
|
||||
.It Dv SO_L2CAP_FLUSH
|
||||
Get (set) value of the flush timeout.
|
||||
.Bf -emphasis
|
||||
Not implemented.
|
||||
.Ef
|
||||
.Em Not implemeted at the L2CAP layer .
|
||||
.El
|
||||
.Pp
|
||||
.Sh BLUETOOTH_PROTO_RFCOMM protocol
|
||||
The Bluetooth RFCOMM socket address is defined as follows:
|
||||
.Bd -literal -offset indent
|
||||
/* Bluetooth version of struct sockaddr for RFCOMM sockets */
|
||||
struct sockaddr_rfcomm {
|
||||
u_char rfcomm_len; /* total length */
|
||||
u_char rfcomm_family; /* address family */
|
||||
bdaddr_t rfcomm_bdaddr; /* address */
|
||||
u_int8_t rfcomm_channel; /* channel */
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
.Ss SOCK_STREAM RFCOMM sockets
|
||||
Note that RFCOMM sockets do not have associated Netgraph node type. RFCOMM
|
||||
sockets are implemented as additional layer on top of L2CAP sockets. RFCOMM
|
||||
sockets are either
|
||||
.Dq active
|
||||
or
|
||||
.Dq passive .
|
||||
Active sockets initiate connections to passive sockets. By default RFCOMM
|
||||
sockets are created active; to create a passive socket the
|
||||
.Xr listen 2
|
||||
system call must be used after binding the socket with the
|
||||
.Xr bind 2
|
||||
system call. Only passive sockets may use the
|
||||
.Xr accept 2
|
||||
call to accept incoming connections. Only active sockets may use the
|
||||
.Xr connect 2
|
||||
call to initiate connections.
|
||||
.Pp
|
||||
RFCOMM sockets support
|
||||
.Dq wildcard addressing .
|
||||
In this case socket must be bound to
|
||||
.Dv NG_HCI_BDADDR_ANY
|
||||
address. Note that RFCOMM channel field is always required. Once a connection
|
||||
has been established the socket's address is fixed by the peer entity's
|
||||
location. The address assigned the socket is the address associated with the
|
||||
Bluetooth device through which packets are being transmitted and received,
|
||||
and RFCOMM channel.
|
||||
.Pp
|
||||
The following options, which can be tested with
|
||||
.Xr getsockopt 2
|
||||
call, are defined at
|
||||
.Dv SOL_RFCOMM
|
||||
level for RFCOMM sockets:
|
||||
.Bl -tag -width foo
|
||||
.It SO_RFCOMM_MTU
|
||||
Returns the maximum transfer unit size (in bytes) for the underlying RFCOMM
|
||||
channel. Note that application still can write/read bigger chunks to/from the
|
||||
socket.
|
||||
.It SO_RFCOMM_FC_INFO
|
||||
Return the flow control information for the underlying RFCOMM channel.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Dv net.bluetooth.rfcomm.sockets.stream.timeout
|
||||
variable, that can be examined and set via
|
||||
.Xr sysctl 8 ,
|
||||
controls the connection timeout (in seconds) for RFCOMM sockets.
|
||||
.Pp
|
||||
.Sh HOOKS
|
||||
This node type supports hooks with arbitrary names (as long as they are
|
||||
unique) and always accepts hook connection requests.
|
||||
These node types support hooks with arbitrary names (as long as they are
|
||||
unique) and always accept hook connection requests.
|
||||
.Sh NETGRAPH CONTROL MESSAGES
|
||||
This node type supports the generic control messages.
|
||||
These node types support the generic control messages.
|
||||
.Sh SHUTDOWN
|
||||
These nodes are persistent and cannot be shut down.
|
||||
.Sh BUGS
|
||||
Most likely.
|
||||
Please report if found.
|
||||
Most likely. Please report if found.
|
||||
.Sh SEE ALSO
|
||||
.Xr btsockstat 1 ,
|
||||
.Xr socket 2 ,
|
||||
.Xr netgraph 4 ,
|
||||
.Xr ngctl 8 ,
|
||||
.Xr sysctl 8 ,
|
||||
.Xr ng_bluetooth 4 ,
|
||||
.Xr ng_hci 4 ,
|
||||
.Xr ng_l2cap 4 ,
|
||||
.Xr ngctl 8
|
||||
.Xr btsockstat 1
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm btsock_hci_raw , btsock_l2c_raw ,
|
||||
and
|
||||
.Nm btsock_l2c
|
||||
node types were implemented in
|
||||
.Nm
|
||||
module was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
|
||||
|
@ -1,6 +1,8 @@
|
||||
.\" ng_h4.4
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
@ -9,7 +11,7 @@
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@ -21,15 +23,15 @@
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" $Id: ng_h4.4,v 1.1 2002/11/24 19:37:54 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 14, 2002
|
||||
.Dt NG_H4 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ng_h4
|
||||
.Nd Netgraph node type that is also an H4 line discipline
|
||||
.Nm h4
|
||||
.Nd Netgraph node type that is also a H4 line discipline
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In sys/ttycom.h
|
||||
@ -37,22 +39,20 @@
|
||||
.In netgraph/ng_h4.h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm h4
|
||||
node type is both a persistent Netgraph node type and a H4 line
|
||||
discipline.
|
||||
It implements a Bluetooth HCI UART transport layer as
|
||||
per chapter H4 of the Bluetooth Specification Book v1.1.
|
||||
A new node is created when the corresponding line discipline,
|
||||
.Nm
|
||||
node type is both a persistent Netgraph node type and a H4 line
|
||||
discipline. It implements a Bluetooth HCI UART transport layer as
|
||||
per chapter H4 of the Bluetooth Specification Book v1.1. A new
|
||||
node is created when the corresponding line discipline,
|
||||
.Dv H4DISC ,
|
||||
is registered on a tty device (see
|
||||
.Xr tty 4 ) .
|
||||
.Pp
|
||||
The node has a single hook called
|
||||
.Dv hook .
|
||||
Incoming bytes received on the tty device are re-assembled into
|
||||
HCI frames (according to the length).
|
||||
Full HCI frames are sent out on the hook.
|
||||
HCI frames received on
|
||||
Incoming bytes received on the tty device are re-assembled into
|
||||
HCI frames (according to the length). Full HCI frames are sent out on
|
||||
the hook. HCI frames received on
|
||||
.Dv hook
|
||||
are transmitted out on the tty device.
|
||||
No modification to the data is performed in either direction.
|
||||
@ -65,22 +65,22 @@ Information about the node is available via the netgraph
|
||||
command
|
||||
.Dv NGIOCGINFO .
|
||||
This command returns a
|
||||
.Vt "struct nodeinfo"
|
||||
.Dv "struct nodeinfo"
|
||||
similar to the
|
||||
.Dv NGM_NODEINFO
|
||||
.Xr netgraph 4
|
||||
control message.
|
||||
netgraph control message.
|
||||
.Sh HOOKS
|
||||
This node type supports the following hooks:
|
||||
.Bl -tag -width indent
|
||||
.Pp
|
||||
.Bl -tag -width foobar
|
||||
.It Dv hook
|
||||
single HCI frame contained in single
|
||||
.Vt mbuf
|
||||
.Dv mbuf
|
||||
structure.
|
||||
.El
|
||||
.Sh CONTROL MESSAGES
|
||||
This node type supports the generic control messages, plus the following:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv NGM_H4_NODE_RESET
|
||||
Reset the node.
|
||||
.It Dv NGM_H4_NODE_GET_STATE
|
||||
@ -96,8 +96,8 @@ Returns current length of outgoing queue for the node.
|
||||
This command takes an integer argument and sets maximum length of
|
||||
outgoing queue for the node.
|
||||
.It Dv NGM_H4_NODE_GET_STAT
|
||||
Returns various statistic information for the node, such as: number of
|
||||
bytes (frames) sent, number of bytes (frames) received and number of
|
||||
Returns various statistic information for the node, such as: number of
|
||||
bytes (frames) sent, number of bytes (frames) received and number of
|
||||
input (output) errors.
|
||||
.It Dv NGM_H4_NODE_RESET_STAT
|
||||
Reset all statistic counters to zero.
|
||||
@ -106,10 +106,7 @@ Reset all statistic counters to zero.
|
||||
This node shuts down when the corresponding device is closed
|
||||
(or the line discipline is uninstalled on the device).
|
||||
.Sh BUGS
|
||||
This node still uses
|
||||
.Xr spltty 9
|
||||
to lock tty layer.
|
||||
This is wrong.
|
||||
This node still uses spltty() to lock tty layer. This is wrong.
|
||||
.Sh SEE ALSO
|
||||
.Xr ioctl 2 ,
|
||||
.Xr netgraph 4 ,
|
||||
@ -117,7 +114,7 @@ This is wrong.
|
||||
.Xr ngctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm h4
|
||||
.Nm
|
||||
node type was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
|
@ -1,6 +1,8 @@
|
||||
.\" ng_hci.4
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
@ -9,7 +11,7 @@
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@ -21,15 +23,15 @@
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" $Id: ng_hci.4,v 1.2 2003/03/18 00:09:34 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 25, 2002
|
||||
.Dt NG_HCI 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ng_hci
|
||||
.Nd Netgraph node type that is also a Bluetooth Host Controller Interface
|
||||
.Nm hci
|
||||
.Nd Netgraph node type that is also a Bluetooth Host Controller Interface
|
||||
(HCI) layer
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
@ -38,100 +40,78 @@
|
||||
.In netgraph/ng_hci.h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm hci
|
||||
.Nm
|
||||
node type is a Netgraph node type that implements Bluetooth Host Controller
|
||||
Interface (HCI) layer as per chapter H1 of the Bluetooth Specification Book
|
||||
Interface (HCI) layer as per chapter H1 of the Bluetooth Specification Book
|
||||
v1.1.
|
||||
.Sh INTRODUCTION TO BLUETOOTH
|
||||
Bluetooth is a short-range radio link intended to replace the cable(s)
|
||||
connecting portable and/or fixed electronic devices.
|
||||
Bluetooth operates in the unlicensed ISM band at 2.4 GHz.
|
||||
The Bluetooth protocol uses a
|
||||
combination of circuit and packet switching.
|
||||
Bluetooth can support an
|
||||
Bluetooth is a short-range radio link intended to replace the cable(s)
|
||||
connecting portable and/or fixed electronic devices. Bluetooth operates
|
||||
in the unlicensed ISM band at 2.4 GHz. The Bluetooth protocol uses a
|
||||
combination of circuit and packet switching. Bluetooth can support an
|
||||
asynchronous data channel, up to three simultaneous synchronous voice
|
||||
channels, or a channel which simultaneously supports asynchronous data
|
||||
and synchronous voice.
|
||||
Each voice channel supports a 64 kb/s synchronous
|
||||
(voice) channel in each direction.
|
||||
The asynchronous channel can support
|
||||
maximal 723.2 kb/s asymmetric (and still up to 57.6 kb/s in the return
|
||||
channels, or a channel which simultaneously supports asynchronous data
|
||||
and synchronous voice. Each voice channel supports a 64 kb/s synchronous
|
||||
(voice) channel in each direction. The asynchronous channel can support
|
||||
maximal 723.2 kb/s asymmetric (and still up to 57.6 kb/s in the return
|
||||
direction), or 433.9 kb/s symmetric.
|
||||
.Pp
|
||||
The Bluetooth system provides a point-to-point connection (only two
|
||||
Bluetooth units involved), or a point-to-multipoint connection.
|
||||
In the point-to-multipoint connection,
|
||||
the channel is shared among several Bluetooth units.
|
||||
Two or more units sharing the same channel form a
|
||||
.Dq piconet .
|
||||
One Bluetooth unit acts as the master of the piconet, whereas the other
|
||||
unit(s) acts as slave(s).
|
||||
Up to seven slaves can be active in the piconet.
|
||||
The Bluetooth system provides a point-to-point connection (only two
|
||||
Bluetooth units involved), or a point-to-multipoint connection. In the
|
||||
point-to-multipoint connection, the channel is shared among several
|
||||
Bluetooth units. Two or more units sharing the same channel form a
|
||||
.Em piconet .
|
||||
One Bluetooth unit acts as the master of the piconet, whereas the other
|
||||
unit(s) acts as slave(s). Up to seven slaves can be active in the piconet.
|
||||
In addition, many more slaves can remain locked to the master in a so-called
|
||||
parked state.
|
||||
These parked slaves cannot be active on the channel, but remain
|
||||
synchronized to the master.
|
||||
Both for active and parked slaves, the channel
|
||||
parked state. These parked slaves cannot be active on the channel, but remain
|
||||
synchronized to the master. Both for active and parked slaves, the channel
|
||||
access is controlled by the master.
|
||||
.Pp
|
||||
Multiple piconets with overlapping coverage areas form a
|
||||
.Dq scatternet .
|
||||
Each piconet can only have a single master.
|
||||
However, slaves can participate
|
||||
in different piconets on a time-division multiplex basis.
|
||||
In addition, a master in one piconet can be a slave in another piconet.
|
||||
The piconets shall not be frequency-synchronized.
|
||||
Each piconet has its own hopping channel.
|
||||
.Ss Time Slots
|
||||
The channel is divided into time slots, each 625 usec in length.
|
||||
The time
|
||||
slots are numbered according to the Bluetooth clock of the piconet master.
|
||||
The slot numbering ranges from 0 to 2^27 -1 and is cyclic with a cycle length
|
||||
of 2^27.
|
||||
In the time slots, master and slave can transmit packets.
|
||||
.Ss SCO Link
|
||||
The SCO link is a symmetric, point-to-point link between the master and a
|
||||
specific slave.
|
||||
The SCO link reserves slots and can therefore be considered
|
||||
as a circuit-switched connection between the master and the slave.
|
||||
The SCO link typically supports time-bounded information like voice.
|
||||
The master can
|
||||
support up to three SCO links to the same slave or to different slaves.
|
||||
A
|
||||
slave can support up to three SCO links from the same master, or two SCO
|
||||
links if the links originate from different masters.
|
||||
SCO packets are never retransmitted.
|
||||
.Ss ACL Link
|
||||
In the slots not reserved for SCO links, the master can exchange packets
|
||||
with any slave on a per-slot basis.
|
||||
The ACL link provides a packet-switched
|
||||
connection between the master and all active slaves participating in the
|
||||
piconet.
|
||||
Both asynchronous and isochronous services are supported.
|
||||
Between a master and a slave only a single ACL link can exist.
|
||||
For most ACL packets,
|
||||
.Pp
|
||||
Multiple piconets with overlapping coverage areas form a
|
||||
.Em scatternet .
|
||||
Each piconet can only have a single master. However, slaves can participate
|
||||
in different piconets on a time-division multiplex basis. In addition, a
|
||||
master in one piconet can be a slave in another piconet. The piconets shall
|
||||
not be frequency-synchronized. Each piconet has its own hopping channel.
|
||||
.Ss Time slots
|
||||
The channel is divided into time slots, each 625 usec in length. The time
|
||||
slots are numbered according to the Bluetooth clock of the piconet master.
|
||||
The slot numbering ranges from 0 to 2^27 -1 and is cyclic with a cycle length
|
||||
of 2^27. In the time slots, master and slave can transmit packets.
|
||||
.Ss SCO link
|
||||
The SCO link is a symmetric, point-to-point link between the master and a
|
||||
specific slave. The SCO link reserves slots and can therefore be considered
|
||||
as a circuit-switched connection between the master and the slave. The SCO
|
||||
link typically supports time-bounded information like voice. The master can
|
||||
support up to three SCO links to the same slave or to different slaves. A
|
||||
slave can support up to three SCO links from the same master, or two SCO
|
||||
links if the links originate from different masters. SCO packets are never
|
||||
retransmitted.
|
||||
.Ss ACL link
|
||||
In the slots not reserved for SCO links, the master can exchange packets
|
||||
with any slave on a per-slot basis. The ACL link provides a packet-switched
|
||||
connection between the master and all active slaves participating in the
|
||||
piconet. Both asynchronous and isochronous services are supported. Between
|
||||
a master and a slave only a single ACL link can exist. For most ACL packets,
|
||||
packet retransmission is applied to assure data integrity.
|
||||
.Sh HOST CONTROLLER INTERFACE (HCI)
|
||||
The HCI provides a command interface to the baseband controller and link
|
||||
manager, and access to hardware status and control registers.
|
||||
This interface
|
||||
The HCI provides a command interface to the baseband controller and link
|
||||
manager, and access to hardware status and control registers. This interface
|
||||
provides a uniform method of accessing the Bluetooth baseband capabilities.
|
||||
.Pp
|
||||
The HCI layer on the Host exchanges data and commands with the HCI firmware
|
||||
on the Bluetooth hardware.
|
||||
The Host Controller Transport Layer (i.e. physical
|
||||
on the Bluetooth hardware. The Host Controller Transport Layer (i.e. physical
|
||||
bus) driver provides both HCI layers with the ability to exchange information
|
||||
with each other.
|
||||
.Pp
|
||||
The Host will receive asynchronous notifications of HCI events independent
|
||||
of which Host Controller Transport Layer is used.
|
||||
HCI events are used for
|
||||
notifying the Host when something occurs.
|
||||
When the Host discovers that an
|
||||
event has occurred it will then parse the received event packet to determine
|
||||
The Host will receive asynchronous notifications of HCI events independent
|
||||
of which Host Controller Transport Layer is used. HCI events are used for
|
||||
notifying the Host when something occurs. When the Host discovers that an
|
||||
event has occurred it will then parse the received event packet to determine
|
||||
which event occurred.
|
||||
The next sections specify the HCI packet formats.
|
||||
.Ss HCI Command Packet
|
||||
.Ss HCI command packet
|
||||
.Bd -literal -offset indent
|
||||
#define NG_HCI_CMD_PKT 0x01
|
||||
typedef struct {
|
||||
@ -142,19 +122,15 @@ typedef struct {
|
||||
.Ed
|
||||
.Pp
|
||||
The HCI command packet is used to send commands to the Host Controller
|
||||
from the Host.
|
||||
When the Host Controller completes most of the commands,
|
||||
a Command Complete event is sent to the Host.
|
||||
Some commands do not receive
|
||||
a Command Complete event when they have been completed.
|
||||
Instead, when the
|
||||
Host Controller receives one of these commands the Host Controller sends
|
||||
a Command Status event back to the Host when it has begun to execute the
|
||||
command.
|
||||
Later on, when the actions associated with the command have finished,
|
||||
an event that is associated with the sent command will be sent by the Host
|
||||
from the Host. When the Host Controller completes most of the commands,
|
||||
a Command Complete event is sent to the Host. Some commands do not receive
|
||||
a Command Complete event when they have been completed. Instead, when the
|
||||
Host Controller receives one of these commands the Host Controller sends
|
||||
a Command Status event back to the Host when it has begun to execute the
|
||||
command. Later on, when the actions associated with the command have finished,
|
||||
an event that is associated with the sent command will be sent by the Host
|
||||
Controller to the Host.
|
||||
.Ss HCI Event Packet
|
||||
.Ss HCI event packet
|
||||
.Bd -literal -offset indent
|
||||
#define NG_HCI_EVENT_PKT 0x04
|
||||
typedef struct {
|
||||
@ -164,9 +140,9 @@ typedef struct {
|
||||
} __attribute__ ((packed)) ng_hci_event_pkt_t;
|
||||
.Ed
|
||||
.Pp
|
||||
The HCI event packet is used by the Host Controller to notify the Host
|
||||
The HCI event packet is used by the Host Controller to notify the Host
|
||||
when events occur.
|
||||
.Ss HCI ACL Data Packet
|
||||
.Ss HCI ACL data packet
|
||||
.Bd -literal -offset indent
|
||||
#define NG_HCI_ACL_DATA_PKT 0x02
|
||||
typedef struct {
|
||||
@ -176,9 +152,9 @@ typedef struct {
|
||||
} __attribute__ ((packed)) ng_hci_acldata_pkt_t;
|
||||
.Ed
|
||||
.Pp
|
||||
HCI ACL data packets are used to exchange ACL data between the Host and
|
||||
HCI ACL data packets are used to exchange ACL data between the Host and
|
||||
Host Controller.
|
||||
.Ss HCI SCO Data Packet
|
||||
.Ss HCI SCO data packet
|
||||
.Bd -literal -offset indent
|
||||
#define NG_HCI_SCO_DATA_PKT 0x03
|
||||
typedef struct {
|
||||
@ -188,31 +164,29 @@ typedef struct {
|
||||
} __attribute__ ((packed)) ng_hci_scodata_pkt_t;
|
||||
.Ed
|
||||
.Pp
|
||||
HCI SCO data packets are used to exchange SCO data between the Host and
|
||||
HCI SCO data packets are used to exchange SCO data between the Host and
|
||||
Host Controller.
|
||||
.Sh HCI INITIALIZATION
|
||||
On initialization, HCI control application must issue the following HCI
|
||||
commands (in any order).
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foobar
|
||||
.It Dv Read_BD_ADDR
|
||||
To obtain BD_ADDR of the Bluetooth unit.
|
||||
.It Dv Read_Local_Supported_Features
|
||||
To obtain the list of features supported by Bluetooth unit.
|
||||
.It Dv Read_Buffer_Size
|
||||
To determine the maximum size of HCI ACL and SCO HCI data packets (excluding
|
||||
header) that can be sent from the Host to the Host Controller.
|
||||
There are also
|
||||
two additional return parameters that specify the total number of HCI ACL and
|
||||
SCO data packets that the Host Controller can have waiting for transmission in
|
||||
its buffers.
|
||||
To determine the maximum size of HCI ACL and SCO HCI data packets (excluding
|
||||
header) that can be sent from the Host to the Host Controller. There are also
|
||||
two additional return parameters that specify the total number of HCI ACL and
|
||||
SCO data packets that the Host Controller can have waiting for transmission in
|
||||
its buffers.
|
||||
.El
|
||||
.Pp
|
||||
As soon as HCI initialization has been successfully performed, HCI control
|
||||
As soon as HCI initialization has been successfuly performed, HCI control
|
||||
application must turn on
|
||||
.Dq inited
|
||||
bit for the node.
|
||||
Once HCI node has been initialized all upsteam hooks
|
||||
will receive a
|
||||
bit for the node. Once HCI node has been initialized all upsteam hooks
|
||||
will receive a
|
||||
.Dv NGM_HCI_NODE_UP
|
||||
Netgraph message defined as follows.
|
||||
.Bd -literal -offset indent
|
||||
@ -226,22 +200,17 @@ typedef struct {
|
||||
.Ed
|
||||
.Sh HCI FLOW CONTROL
|
||||
HCI layer performs flow control on baseband connection basis (i.e. ACL and
|
||||
SCO link).
|
||||
Each baseband connection has
|
||||
.Dq "connection handle"
|
||||
and queue of outgoing data packets.
|
||||
Upper layers protocols are allowed to
|
||||
send up to
|
||||
.Dv ( num_pkts
|
||||
\-
|
||||
SCO link). Each baseband connection has
|
||||
.Em connection handle
|
||||
and queue of outgoing data packets. Upper layers protocols are allowed to
|
||||
send up to (
|
||||
.Dv num_pkts -
|
||||
.Dv pending )
|
||||
packets at one time.
|
||||
HCI layer will send
|
||||
.Dv NGM_HCI_SYNC_CON_QUEUE
|
||||
Netgraph messages to inform upper layers about current queue state for each
|
||||
connection handle.
|
||||
The
|
||||
.Dv NGM_HCI_SYNC_CON_QUEUE
|
||||
packets at one time. HCI layer will send
|
||||
.Dv NGM_HCI_SYNC_CON_QUEUE
|
||||
Netgraph messages to inform upper layers about current queue state for each
|
||||
connection handle. The
|
||||
.Dv NGM_HCI_SYNC_CON_QUEUE
|
||||
Netgraph message is defined as follows.
|
||||
.Bd -literal -offset indent
|
||||
#define NGM_HCI_SYNC_CON_QUEUE 113 /* HCI -> Upper */
|
||||
@ -252,73 +221,71 @@ typedef struct {
|
||||
.Ed
|
||||
.Sh HOOKS
|
||||
This node type supports the following hooks:
|
||||
.Bl -tag -width indent
|
||||
.Pp
|
||||
.Bl -tag -width foobar
|
||||
.It Dv drv
|
||||
Bluetooth Host Controller Transport Layer hook.
|
||||
Single HCI packet contained in single
|
||||
.Vt mbuf
|
||||
Bluetooth Host Controller Transport Layer hook. Single HCI packet contained in
|
||||
single
|
||||
.Dv mbuf
|
||||
structure.
|
||||
.It Dv acl
|
||||
Upper layer protocol/node is connected to the hook.
|
||||
Single HCI ACL data packet contained in single
|
||||
.Vt mbuf
|
||||
Upper layer protocol/node is connected to the hook. Single HCI ACL
|
||||
data packet contained in single
|
||||
.Dv mbuf
|
||||
structure.
|
||||
.It Dv sco
|
||||
Upper layer protocol/node is connected to the hook.
|
||||
Single HCI SCO data packet contained in single
|
||||
.Vt mbuf
|
||||
Upper layer protocol/node is connected to the hook. Single HCI SCO
|
||||
data packet contained in single
|
||||
.Dv mbuf
|
||||
structure.
|
||||
.It Dv raw
|
||||
Raw hook.
|
||||
Every HCI frame (including HCI command frame) that goes in
|
||||
or out will be delivered to the hook.
|
||||
Usually the Bluetooth raw HCI socket layer is connected to the hook.
|
||||
Single HCI frame contained in single
|
||||
.Vt mbuf
|
||||
Raw hook. Every HCI frame (including HCI command frame) that goes in
|
||||
or out will be delivired to the hook. Usually Bluetooth raw HCI sockets
|
||||
layer is connected to the hook. Single HCI frame contained in single
|
||||
. Dv mbuf
|
||||
structure.
|
||||
.El
|
||||
.Sh BLUETOOTH UPPER LAYER PROTOCOLS INTERFACE (LP CONTROL MESSAGES)
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv NGM_HCI_LP_CON_REQ
|
||||
Requests the lower protocol to create a connection.
|
||||
If a physical link
|
||||
Requests the lower protocol to create a connection. If a physical link
|
||||
to the remote device does not exist, this message must be sent to the lower
|
||||
protocol (baseband) to establish the physical connection.
|
||||
.It Dv NGM_HCI_LP_DISCON_REQ
|
||||
Requests the lower protocol (baseband) to terminate a connection.
|
||||
Requests the lower protocol (baseband) to terminate a connection.
|
||||
.It Dv NGM_HCI_LP_CON_CFM
|
||||
Confirms success or failure of the
|
||||
.Dv NGM_HCI_LP_CON_REQ
|
||||
request to establish a lower layer (baseband) connection.
|
||||
This includes passing the authentication challenge if authentication is
|
||||
.Dv
|
||||
NGM_HCI_LP_CON_REQ request to establish a lower layer (baseband) connection.
|
||||
This includes passing the authentication challenge if authentication is
|
||||
required to establish the physical link.
|
||||
.It Dv NGM_HCI_LP_CON_IND
|
||||
Indicates the lower protocol (baseband) has successfully established
|
||||
incoming connection.
|
||||
Indicates the lower protocol (baseband) has successfully established
|
||||
incoming connection.
|
||||
.It Dv NGM_HCI_LP_CON_RSP
|
||||
A response accepting or rejecting the previous connection indication request.
|
||||
.It Dv NGM_HCI_LP_DISCON_IND
|
||||
Indicates the lower protocol (baseband) has terminated connection.
|
||||
This could be a response to
|
||||
Indicates the lower protocol (baseband) has terminated connection. This
|
||||
could be a response to
|
||||
.Dv NGM_HCI_LP_DISCON_REQ
|
||||
or a timeout event.
|
||||
.It Dv NGM_HCI_LP_QOS_REQ
|
||||
Requests the lower protocol (baseband) to accommodate a particular QoS
|
||||
Requests the lower protocol (baseband) to accommodate a particular QoS
|
||||
parameter set.
|
||||
.It Dv NGM_HCI_LP_QOS_CFM
|
||||
Confirms success or failure of the request for a given quality of service.
|
||||
.It Dv NGM_HCI_LP_QOS_IND
|
||||
Indicates the lower protocol (baseband) has detected a violation of the QoS
|
||||
Indicates the lower protocol (baseband) has detected a violation of the QoS
|
||||
agreement.
|
||||
.El
|
||||
.Sh NETGRAPH CONTROL MESSAGES
|
||||
This node type supports the generic control messages, plus the following:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv NGM_HCI_NODE_GET_STATE
|
||||
Returns current state for the node.
|
||||
.It Dv NGM_HCI_NODE_INIT
|
||||
Turn on
|
||||
.Dq inited
|
||||
.Dq inited
|
||||
bit for the node.
|
||||
.It Dv NGM_HCI_NODE_GET_DEBUG
|
||||
Returns an integer containing the current debug level for the node.
|
||||
@ -342,39 +309,40 @@ Returns various statistic counters.
|
||||
.It Dv NGM_HCI_NODE_RESET_STAT
|
||||
Resets all statistic counters to zero.
|
||||
.It NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK
|
||||
Sets current link policy settings mask.
|
||||
After the new ACL connection is
|
||||
created the HCI node will try set link policy for the ACL connection.
|
||||
By default, every supported Link Manager (LM) mode will be enabled.
|
||||
User can
|
||||
override this by setting link policy settings mask which specifies LM
|
||||
Sets current link policy settings mask. After the new ACL connection is
|
||||
created the HCI node will try set link policy for the ACL connection. By
|
||||
default every supported Link Manager (LM) mode will be enabled. User can
|
||||
override this by setting link policy settings mask which specifies LM
|
||||
modes to be enabled.
|
||||
.It NGM_HCI_NODE_GET_LINK_POLICY_SETTINGS_MASK
|
||||
Returns current link policy settings mask.
|
||||
.It NGM_HCI_NODE_SET_PACKET_MASK
|
||||
Sets current packet mask.
|
||||
When new baseband (ACL or SCO) connection is
|
||||
Sets current packet mask. When new baseband (ACL or SCO) connection is
|
||||
created the HCI node will specify every packet type supported by the device.
|
||||
User can override this by setting packet mask which specifies packet types
|
||||
to be used for new baseband connections.
|
||||
.It NGM_HCI_NODE_GET_PACKET_MASK
|
||||
Returns current packet mask.
|
||||
.It NGM_HCI_NODE_SET_ROLE_SWITCH
|
||||
Sets the value of the role switch. Role switch is enabled when this value is
|
||||
not zero. This is the default state. Note that actual role switch at Bluetooth
|
||||
link level will only be perfomed if hardware supports role switch and it was
|
||||
enabled.
|
||||
.It NGM_HCI_NODE_GET_ROLE_SWITCH
|
||||
Returns the value of the role switch for the node.
|
||||
.El
|
||||
.Sh SHUTDOWN
|
||||
This node shuts down upon receipt of a
|
||||
.Dv NGM_SHUTDOWN
|
||||
control message, or
|
||||
This node shuts down upon receipt of a NGM_SHUTDOWN control message, or
|
||||
when all hooks have been disconnected.
|
||||
.Sh BUGS
|
||||
Most likely.
|
||||
Please report if found.
|
||||
Most likely. Please report if found.
|
||||
.Sh SEE ALSO
|
||||
.Xr netgraph 4 ,
|
||||
.Xr hccontrol 8 ,
|
||||
.Xr ngctl 8
|
||||
.Xr ngctl 8 ,
|
||||
.Xr hccontrol 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm hci
|
||||
.Nm
|
||||
node type was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
|
@ -1,6 +1,8 @@
|
||||
.\" ng_l2cap.4
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
@ -9,7 +11,7 @@
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@ -21,14 +23,14 @@
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" $Id: ng_l2cap.4,v 1.2 2003/04/28 20:16:29 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd July 4, 2002
|
||||
.Dt NG_L2CAP 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ng_l2cap
|
||||
.Nm l2cap
|
||||
.Nd Netgraph node type that implements Bluetooth Logical Link Control and
|
||||
Adaptation Protocol (L2CAP)
|
||||
.Sh SYNOPSIS
|
||||
@ -39,164 +41,123 @@ Adaptation Protocol (L2CAP)
|
||||
.In netgraph/ng_l2cap.h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm l2cap
|
||||
node type is a Netgraph node type that implements Bluetooth Logical Link
|
||||
.Nm
|
||||
node type is a Netgraph node type that implements Bluetooth Logical Link
|
||||
Control and Adaptation Protocol as per chapter D of the Bluetooth Specification
|
||||
Book v1.1.
|
||||
.Pp
|
||||
L2CAP provides connection-oriented and connectionless data services to upper
|
||||
L2CAP provides connection-oriented and connectionless data services to upper
|
||||
layer protocols with protocol multiplexing capability, segmentation and
|
||||
reassembly operation, and group abstractions.
|
||||
L2CAP permits higher level
|
||||
reassembly operation, and group abstractions. L2CAP permits higher level
|
||||
protocols and applications to transmit and receive L2CAP data packets up to
|
||||
64 kilobytes in length.
|
||||
.Ss L2CAP Assumptions
|
||||
.Bl -enum -offset indent
|
||||
.Ss L2CAP assumptions
|
||||
.Bl -enum -offset indent
|
||||
.It
|
||||
The ACL link between two units is set up.
|
||||
The Baseband provides orderly
|
||||
delivery of data packets, although there might be individual packet corruption
|
||||
and duplicates.
|
||||
No more than 1 ACL link exists between any two devices.
|
||||
The ACL link between two units is set up. The Baseband provides orderly
|
||||
delivery of data packets, although there might be individual packet corruption
|
||||
and duplicates. No more than 1 ACL link exists between any two devices.
|
||||
.It
|
||||
The Baseband always provides the impression of full-duplex communication
|
||||
channels.
|
||||
This does not imply that all L2CAP communications are bi-directional.
|
||||
channels. This does not imply that all L2CAP communications are bi-directional.
|
||||
Multicasts and unidirectional traffic (e.g., video) do not require duplex
|
||||
channels.
|
||||
.It
|
||||
L2CAP provides a reliable channel using the mechanisms available at the
|
||||
Baseband layer.
|
||||
The Baseband always performs data integrity checks when
|
||||
Baseband layer. The Baseband always performs data integrity checks when
|
||||
requested and resends data until it has been successfully acknowledged or
|
||||
a timeout occurs.
|
||||
Because acknowledgements may be lost, timeouts may
|
||||
a timeout occurs. Because acknowledgements may be lost, timeouts may
|
||||
occur even after the data has been successfully sent.
|
||||
.El
|
||||
.Sh L2CAP GENERAL OPERATION
|
||||
The Logical Link Control and Adaptation Protocol (L2CAP) is based around the
|
||||
concept of
|
||||
.Dq channels .
|
||||
Each channel is bound to a single protocol in a many-to-one fashion.
|
||||
Multiple
|
||||
channels can be bound to the same protocol, but a channel cannot be bound to
|
||||
multiple protocols.
|
||||
Each L2CAP packet received on a channel is directed to
|
||||
.Em channels .
|
||||
Each channel is bound to a single protocol in a many-to-one fashion. Multiple
|
||||
channels can be bound to the same protocol, but a channel cannot be bound to
|
||||
multiple protocols. Each L2CAP packet received on a channel is directed to
|
||||
the appropriate higher level protocol.
|
||||
.Pp
|
||||
Each one of the end-points of an L2CAP channel is referred to by a channel
|
||||
identifier.
|
||||
Channel identifiers (CIDs) are local names representing a logical
|
||||
channel end-point on the device.
|
||||
Identifiers from 0x0001 to 0x003F are reserved
|
||||
for specific L2CAP functions.
|
||||
The null identifier (0x0000) is defined as an
|
||||
illegal identifier and must never be used as a destination end-point.
|
||||
All L2CAP signalling commands are sent to CID 0x0001.
|
||||
CID 0x0002 is reserved for group-oriented channel.
|
||||
The same CID must not be reused as a local L2CAP
|
||||
channel endpoint for multiple simultaneous L2CAP channels between a local
|
||||
Each one of the end-points of an L2CAP channel is referred to by a channel
|
||||
identifier. Channel identifiers (CIDs) are local names representing a logical
|
||||
channel end-point on the device. Identifiers from 0x0001 to 0x003F are reserved
|
||||
for specific L2CAP functions. The null identifier (0x0000) is defined as an
|
||||
illegal identifier and must never be used as a destination end-point.
|
||||
All L2CAP signalling commands are sent to CID 0x0001. CID 0x0002 is reserved
|
||||
for group-oriented channel. The same CID must not be reused as a local L2CAP
|
||||
channel endpoint for multiple simultaneous L2CAP channels between a local
|
||||
device and some remote device.
|
||||
.Pp
|
||||
CID assignment is relative to a particular device and a device can assign CIDs
|
||||
independently from other devices.
|
||||
Thus, even if the same CID value has been
|
||||
independently from other devices. Thus, even if the same CID value has been
|
||||
assigned to (remote) channel endpoints by several remote devices connected
|
||||
to a single local device, the local device can still uniquely associate each
|
||||
remote CID with a different device.
|
||||
.Ss Channel Operational States
|
||||
.Bl -tag -width indent
|
||||
.Ss Channel operational states
|
||||
.Bl -tag -width foobar
|
||||
.It Dv NG_L2CAP_CLOSED
|
||||
In this state, there is no channel associated with this CID.
|
||||
This is the only
|
||||
state when a link level connection (Baseband) may not exist.
|
||||
Link disconnection
|
||||
forces all other states into the
|
||||
.Dv NG_L2CAP_CLOSED
|
||||
state.
|
||||
In this state, there is no channel associated with this CID. This is the only
|
||||
state when a link level connection (Baseband) may not exist. Link disconnection
|
||||
forces all other states into the NG_L2CAP_CLOSED state.
|
||||
.It Dv NG_L2CAP_W4_L2CAP_CON_RSP
|
||||
In this state, the CID represents a local end-point and an L2CAP Connect
|
||||
Request message has been sent referencing this endpoint and it is now waiting
|
||||
In this state, the CID represents a local end-point and an L2CAP Connect
|
||||
Request message has been sent referencing this endpoint and it is now waiting
|
||||
for the corresponding L2CAP Connect Response message.
|
||||
.It Dv NG_L2CAP_W4_L2CA_CON_RSP
|
||||
In this state, the remote end-point exists and an L2CAP Connect Request has
|
||||
been received by the local L2CAP entity.
|
||||
An L2CA Connect Indication has been
|
||||
been received by the local L2CAP entity. An L2CA Connect Indication has been
|
||||
sent to the upper layer and the part of the local L2CAP entity processing the
|
||||
received L2CAP Connect Request waits for the corresponding response.
|
||||
The response may require a security check to be performed.
|
||||
received L2CAP Connect Request waits for the corresponding response. The
|
||||
response may require a security check to be performed.
|
||||
.It Dv NG_L2CAP_CONFIG
|
||||
In this state, the connection has been established but both sides are still
|
||||
negotiating the channel parameters.
|
||||
The Configuration state may also be
|
||||
entered when the channel parameters are being renegotiated.
|
||||
Prior to entering
|
||||
the
|
||||
.Dv NG_L2CAP_CONFIG
|
||||
state, all outgoing data traffic is suspended since
|
||||
the traffic parameters of the data traffic are to be renegotiated.
|
||||
Incoming
|
||||
negotiating the channel parameters. The Configuration state may also be
|
||||
entered when the channel parameters are being renegotiated. Prior to entering
|
||||
the NG_L2CAP_CONFIG state, all outgoing data traffic is suspended since
|
||||
the traffic parameters of the data traffic are to be renegotiated. Incoming
|
||||
data traffic is accepted until the remote channel endpoint has entered
|
||||
the
|
||||
.Dv NG_L2CAP_CONFIG
|
||||
state.
|
||||
In the
|
||||
.Dv NG_L2CAP_CONFIG
|
||||
state, both sides will issue
|
||||
L2CAP Configuration Request messages if only defaults are being used, a null
|
||||
message will be sent.
|
||||
If a large amount of parameters need to be negotiated,
|
||||
the NG_L2CAP_CONFIG state. In the NG_L2CAP_CONFIG state, both sides will issue
|
||||
L2CAP Configuration Request messages if only defaults are being used, a null
|
||||
message will be sent. If a large amount of parameters need to be negotiated,
|
||||
multiple messages will be sent to avoid any MTU limitations and negotiate
|
||||
incrementally.
|
||||
Moving from the
|
||||
.Dv NG_L2CAP_CONFIG
|
||||
state to the
|
||||
.Dv NG_L2CAP_OPEN
|
||||
state
|
||||
requires both sides to be ready.
|
||||
An L2CAP entity is ready when it has received
|
||||
a positive response to its final request and it has positively responded to
|
||||
incrementally. Moving from the NG_L2CAP_CONFIG state to the NG_L2CAP_OPEN state
|
||||
requires both sides to be ready. An L2CAP entity is ready when it has received
|
||||
a positive response to its final request and it has positively responded to
|
||||
the final request from the remote device.
|
||||
.It Dv NG_L2CAP_OPEN
|
||||
In this state, the connection has been established and configured, and data
|
||||
flow may proceed.
|
||||
.It Dv NG_L2CAP_W4_L2CAP_DISCON_RSP
|
||||
In this state, the connection is shutting down and an L2CAP Disconnect Request
|
||||
message has been sent.
|
||||
This state is now waiting for the corresponding response.
|
||||
message has been sent. This state is now waiting for the corresponding response.
|
||||
.It Dv NG_L2CAP_W4_L2CA_DISCON_RSP
|
||||
In this state, the connection on the remote endpoint is shutting down and an
|
||||
L2CAP Disconnect Request message has been received.
|
||||
An L2CA Disconnect
|
||||
Indication has been sent to the upper layer to notify the owner of the CID
|
||||
that the remote endpoint is being closed.
|
||||
This state is now waiting for the
|
||||
corresponding response from the upper layer before responding to the remote
|
||||
L2CAP Disconnect Request message has been received. An L2CA Disconnect
|
||||
Indication has been sent to the upper layer to notify the owner of the CID
|
||||
that the remote endpoint is being closed. This state is now waiting for the
|
||||
corresponding response from the upper layer before responding to the remote
|
||||
endpoint.
|
||||
.El
|
||||
.Ss Protocol Multiplexing
|
||||
L2CAP supports protocol multiplexing because the Baseband Protocol does not
|
||||
support any
|
||||
.Dq type
|
||||
field identifying the higher layer protocol being multiplexed above it.
|
||||
L2CAP is able to distinguish between upper layer protocols such as the Service
|
||||
L2CAP supports protocol multiplexing because the Baseband Protocol does not
|
||||
support any
|
||||
.Dq type
|
||||
field identifying the higher layer protocol being multiplexed above it.
|
||||
L2CAP is able to distinguish between upper layer protocols such as the Service
|
||||
Discovery Protocol, RFCOMM and Telephony Control.
|
||||
.Ss Segmentation and Reassembly
|
||||
The data packets defined by the Baseband Protocol are limited in size.
|
||||
Large
|
||||
L2CAP packets must be segmented into multiple smaller Baseband packets prior
|
||||
to their transmission over the air.
|
||||
Similarly, multiple received Baseband
|
||||
packets may be reassembled into a single larger L2CAP packet.
|
||||
The data packets defined by the Baseband Protocol are limited in size. Large
|
||||
L2CAP packets must be segmented into multiple smaller Baseband packets prior
|
||||
to their transmission over the air. Similarly, multiple received Baseband
|
||||
packets may be reassembled into a single larger L2CAP packet.
|
||||
.Ss Quality of Service
|
||||
The L2CAP connection establishment process allows the exchange of information
|
||||
regarding the quality of service (QoS) expected between two Bluetooth units.
|
||||
regarding the quality of service (QoS) expected between two Bluetooth units.
|
||||
.Ss Groups
|
||||
The Baseband Protocol supports the concept of a piconet, a group of devices
|
||||
synchronously hopping together using the same clock.
|
||||
The L2CAP group
|
||||
The Baseband Protocol supports the concept of a piconet, a group of devices
|
||||
synchronously hopping together using the same clock. The L2CAP group
|
||||
abstraction permits implementations to efficiently map protocol groups on to
|
||||
piconets.
|
||||
piconets.
|
||||
.Pp
|
||||
The following features are outside the scope of L2CAP responsibilities:
|
||||
.Bl -dash -offset indent
|
||||
@ -217,101 +178,84 @@ This node type supports the following hooks:
|
||||
.It Dv hci
|
||||
Bluetooth Host Controller Interface downstream hook.
|
||||
.It Dv l2c
|
||||
Upper layer protocol upstream hook.
|
||||
Usually Bluetooth L2CAP sockets layer
|
||||
Upper layer protocol upstream hook. Usually Bluetooth L2CAP sockets layer
|
||||
is connected to the hook.
|
||||
.It Dv ctl
|
||||
Control hook.
|
||||
Usually Bluetooth raw L2CAP sockets layer is connected to the hook.
|
||||
Control hook. Usually Bluetooth raw L2CAP sockets layer is connected
|
||||
to the hook.
|
||||
.El
|
||||
.Sh INTERFACE TO THE UPPER LAYER PROTOCOLS (L2CA CONTROL MESSAGES)
|
||||
Bluetooth specification says that L2CA request must block until response
|
||||
is ready.
|
||||
L2CAP node uses
|
||||
.Va token
|
||||
field from Netgraph message header to match L2CA request and response.
|
||||
The upper layer protocol must populate
|
||||
.Va token .
|
||||
L2CAP node will queue request and start processing.
|
||||
Later, when response is
|
||||
ready or timeout has occured, L2CAP node will create new Netgraph message, set
|
||||
.Va token
|
||||
and
|
||||
.Dv NFG_RESP
|
||||
flag and send message to the upper layer.
|
||||
Note that L2CA indication messages
|
||||
will not populate
|
||||
.Va token
|
||||
and will not set
|
||||
.Dv NGF_RESP
|
||||
flag.
|
||||
There is no reason for this, because they are just notifications and do
|
||||
Bluetooth specification says that L2CA request must block until response
|
||||
is ready. L2CAP node uses
|
||||
.Dq token
|
||||
field from Netgraph message header to match L2CA request and response. The
|
||||
upper layer protocol must populate
|
||||
.Dq token .
|
||||
L2CAP node will queue request and start processing. Later, when response is
|
||||
ready or timeout has occur L2CAP node will create new Netgraph message, set
|
||||
.Dq token
|
||||
and
|
||||
.Dv NFG_RESP
|
||||
flag and send message to the upper layer. Note that L2CA indication messages
|
||||
will not populate
|
||||
.Dq token
|
||||
and will not set
|
||||
.Dv NGF_RESP
|
||||
flag. There is no reason for this, because they are just notifications and do
|
||||
not require acknowledgment.
|
||||
.Bl -tag -width indent
|
||||
.Pp
|
||||
.Bl -tag -width foo
|
||||
.It Dv NGM_L2CAP_L2CA_CON
|
||||
Requests the creation of a channel representing a logical connection to a
|
||||
physical address.
|
||||
Input parameters are the target protocol (PSM) and remote
|
||||
device's 48-bit address (BD_ADDR).
|
||||
Output parameters are the local CID (LCID)
|
||||
allocated by the local L2CAP entity, and Result of the request.
|
||||
If Result
|
||||
Requests the creation of a channel representing a logical connection to a
|
||||
physical address. Input parameters are the target protocol (PSM) and remote
|
||||
device's 48-bit address (BD_ADDR). Output parameters are the local CID (LCID)
|
||||
allocated by the local L2CAP entity, and Result of the request. If Result
|
||||
indicates a pending notification, the Status value may contain more information
|
||||
of what processing is delaying the establishment of the connection.
|
||||
.It Dv NGM_L2CAP_L2CA_CON_IND
|
||||
This message includes the parameters for the address of the remote device that
|
||||
issued the connection request, the local CID representing the channel being
|
||||
requested, the Identifier contained in the request, and the PSM value the
|
||||
This message includes the parameters for the address of the remote device that
|
||||
issued the connection request, the local CID representing the channel being
|
||||
requested, the Identifier contained in the request, and the PSM value the
|
||||
request is targeting.
|
||||
.It Dv NGM_L2CAP_L2CA_CON_RSP
|
||||
Issues a response to a connection request event indication.
|
||||
Input parameters
|
||||
are the remote device's 48-bit address, Identifier sent in the request, local
|
||||
CID, the Response code, and the Status attached to the Response code.
|
||||
The output parameter is the Result of the service request.
|
||||
This primitive must be
|
||||
called no more than once after receiving the indication.
|
||||
Issues a response to a connection request event indication. Input parameters
|
||||
are the remote device's 48-bit address, Identifier sent in the request, local
|
||||
CID, the Response code, and the Status attached to the Response code. The
|
||||
output parameter is the Result of the service request. This primitive must be
|
||||
called no more than once after receiving the indication.
|
||||
.It Dv NGM_L2CAP_L2CA_CFG
|
||||
Requests the initial configuration (or reconfiguration) of a channel to a new
|
||||
set of channel parameters.
|
||||
Input parameters are the local CID endpoint, new
|
||||
incoming receivable MTU (InMTU), new outgoing flow spec-ification, and flush
|
||||
and link timeouts.
|
||||
Output parameters are the Result, accepted incoming MTU
|
||||
Requests the initial configuration (or reconfiguration) of a channel to a new
|
||||
set of channel parameters. Input parameters are the local CID endpoint, new
|
||||
incoming receivable MTU (InMTU), new outgoing flow spec-ification, and flush
|
||||
and link timeouts. Output parameters are the Result, accepted incoming MTU
|
||||
(InMTU), the remote side's flow requests, and flush and link timeouts.
|
||||
.It Dv NGM_L2CAP_L2CA_CFG_IND
|
||||
This message includes the parameters indicating the local CID of the channel
|
||||
the request has been sent to, the outgoing MTU size (maximum packet that can
|
||||
be sent across the channel) and the flowspec describing the characteristics of
|
||||
the incoming data.
|
||||
All other channel parameters are set to their default values
|
||||
if not provided by the remote device.
|
||||
This message includes the parameters indicating the local CID of the channel
|
||||
the request has been sent to, the outgoing MTU size (maximum packet that can
|
||||
be sent across the channel) and the flowspec describing the characteristics of
|
||||
the incoming data. All other channel parameters are set to their default values if not provided by the remote device.
|
||||
.It Dv NGM_L2CAP_L2CA_CFG_RSP
|
||||
Issues a response to a configuration request event indication.
|
||||
Input parameters
|
||||
include the local CID of the endpoint being configured, outgoing transmit MTU
|
||||
(which may be equal or less to the OutMTU parameter in the configuration
|
||||
indication event) and the accepted flowspec for incoming traffic.
|
||||
The output parameter is the Result value.
|
||||
Issues a response to a configuration request event indication. Input parameters
|
||||
include the local CID of the endpoint being configured, outgoing transmit MTU
|
||||
(which may be equal or less to the OutMTU parameter in the configuration
|
||||
indication event) and the accepted flowspec for incoming traffic. The output
|
||||
parameter is the Result value.
|
||||
.It Dv NGM_L2CAP_L2CA_QOS_IND
|
||||
This message includes the parameter indicating the address of the remote
|
||||
This message includes the parameter indicating the address of the remote
|
||||
Bluetooth device where the QoS contract has been violated.
|
||||
.It Dv NGM_L2CAP_L2CA_DISCON
|
||||
Requests the disconnection of the channel.
|
||||
Input parameter is the CID representing the local channel endpoint.
|
||||
Output parameter is Result.
|
||||
Result
|
||||
is zero if a L2CAP Disconnect Response is received, otherwise a non-zero value
|
||||
is returned.
|
||||
Once disconnection has been requested, no process will be able to
|
||||
successfully read or write from the CID.
|
||||
Requests the disconnection of the channel. Input parameter is the CID
|
||||
representing the local channel endpoint. Output parameter is Result. Result
|
||||
is zero if a L2CAP Disconnect Response is received, otherwise a non-zero value
|
||||
is returned. Once disconnection has been requested, no process will be able to
|
||||
successfully read or write from the CID.
|
||||
.It Dv NGM_L2CAP_L2CA_DISCON_IND
|
||||
This message includes the parameter indicating the local CID the request has
|
||||
This message includes the parameter indicating the local CID the request has
|
||||
been sent to.
|
||||
.It Dv NGM_L2CAP_L2CA_WRITE
|
||||
Response to transfer of data request.
|
||||
Actual data must be received from
|
||||
Response to transfer of data request. Actual data must be received from
|
||||
appropriate upstream hook and must be prepended with header defined as follows.
|
||||
.Pp
|
||||
.Bd -literal -offset indent
|
||||
/* L2CA data packet header */
|
||||
typedef struct {
|
||||
@ -323,69 +267,49 @@ typedef struct {
|
||||
.Pp
|
||||
The output parameters are Result and Length of data written.
|
||||
.It Dv NGM_L2CAP_L2CA_GRP_CREATE
|
||||
Requests the creation of a CID to represent a logical connection to multiple
|
||||
devices.
|
||||
Input parameter is the PSM value that the outgoing connectionless
|
||||
traffic is labelled with, and the filter used for incoming traffic.
|
||||
Output parameter is the CID representing the local endpoint.
|
||||
On creation, the group
|
||||
Requests the creation of a CID to represent a logical connection to multiple
|
||||
devices. Input parameter is the PSM value that the outgoing connectionless
|
||||
traffic is labelled with, and the filter used for incoming traffic. Output
|
||||
parameter is the CID representing the local endpoint. On creation, the group
|
||||
is empty but incoming traffic destined for the PSM value is readable.
|
||||
.Bf -emphasis
|
||||
This request has not been implemented.
|
||||
.Ef
|
||||
.Em This request has not been implemented .
|
||||
.It Dv NGM_L2CAP_L2CA_GRP_CLOSE
|
||||
The use of this message closes down a Group.
|
||||
.Bf -emphasis
|
||||
This request has not been implemented.
|
||||
.Ef
|
||||
.Em This request has not been implemented .
|
||||
.It Dv NGM_L2CAP_L2CA_GRP_ADD_MEMBER
|
||||
Requests the addition of a member to a group.
|
||||
The input parameter includes the
|
||||
CID representing the group and the BD_ADDR of the group member to be added.
|
||||
Requests the addition of a member to a group. The input parameter includes the
|
||||
CID representing the group and the BD_ADDR of the group member to be added.
|
||||
The output parameter Result confirms the success or failure of the request.
|
||||
.Bf -emphasis
|
||||
This request has not been implemented.
|
||||
.Ef
|
||||
.Em This request has not been implemented .
|
||||
.It Dv NGM_L2CAP_L2CA_GRP_REM_MEMBER
|
||||
Requests the removal of a member from a group.
|
||||
The input parameters include
|
||||
the CID representing the group and BD_ADDR of the group member to be removed.
|
||||
Requests the removal of a member from a group. The input parameters include
|
||||
the CID representing the group and BD_ADDR of the group member to be removed.
|
||||
The output parameter Result confirms the success or failure of the request.
|
||||
.Bf -emphasis
|
||||
This request has not been implemented.
|
||||
.Ef
|
||||
.Em This request has not been implemented .
|
||||
.It Dv NGM_L2CAP_L2CA_GRP_MEMBERSHIP
|
||||
Requests a report of the members of a group.
|
||||
The input parameter CID represents the group being queried.
|
||||
The output parameter Result confirms the success or
|
||||
failure of the operation.
|
||||
If the Result is successful, BD_ADDR_Lst is a list
|
||||
Requests a report of the members of a group. The input parameter CID represents
|
||||
the group being queried. The output parameter Result confirms the success or
|
||||
failure of the operation. If the Result is successful, BD_ADDR_Lst is a list
|
||||
of the Bluetooth addresses of the N members of the group.
|
||||
.Bf -emphasis
|
||||
This request has not been implemented.
|
||||
.Ef
|
||||
.Em This request has not been implemented .
|
||||
.It Dv NGM_L2CAP_L2CA_PING
|
||||
Initiates a L2CA Echo Request message and the reception of the corresponding
|
||||
L2CAP Echo Response message.
|
||||
The input parameters are remote Bluetooth device
|
||||
BD_ADDR, Echo Data and Length of the echo data.
|
||||
The output parameters are
|
||||
L2CAP Echo Response message. The input parameters are remote Bluetooth device
|
||||
BD_ADDR, Echo Data and Length of the echo data. The output parameters are
|
||||
Result, Echo Data and Length of the echo data.
|
||||
.It Dv NGM_L2CAP_L2CA_GET_INFO
|
||||
Initiates a L2CA Information Request message and the reception of the
|
||||
corresponding L2CAP Info Response message.
|
||||
The input parameters are remote Bluetooth device BD_ADDR and Information Type.
|
||||
The output parameters are
|
||||
Initiates a L2CA Information Request message and the reception of the
|
||||
corresponding L2CAP Info Response message. The input parameters are remote
|
||||
Bluetooth device BD_ADDR and Information Type. The output parameters are
|
||||
Result, Information Data and Size of the information data.
|
||||
.It Dv NGM_L2CAP_L2CA_ENABLE_CLT
|
||||
Request to disable (enable) the reception of connectionless packets.
|
||||
The input
|
||||
Request to disable (enable) the reception of connectionless packets. The input
|
||||
parameter is the PSM value indicating service that should be blocked
|
||||
(unblocked) and Enable flag.
|
||||
(unblocked) and Enable flag.
|
||||
.El
|
||||
.Sh NETGRAPH CONTROL MESSAGES
|
||||
This node type supports the generic control messages, plus the following:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv NGM_L2CAP_NODE_GET_FLAGS
|
||||
Returns current state for the node.
|
||||
.It Dv NGM_L2CAP_NODE_GET_DEBUG
|
||||
@ -397,23 +321,27 @@ for the node.
|
||||
Returns list of active baseband connections (i.e. ACL links).
|
||||
.It Dv NGM_L2CAP_NODE_GET_CHAN_LIST
|
||||
Returns list of active L2CAP channels.
|
||||
.It Dv NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO
|
||||
Returns an integer containing the current value of the auto disconnect
|
||||
timeout (in sec).
|
||||
.It Dv NGM_L2CAP_NODE_SET_AUTO_DISCON_TIMO
|
||||
This command accepts an integer and sets the value of the auto disconnect
|
||||
timeout (in sec). The special value of 0 (zero) disables auto disconnect
|
||||
timeout.
|
||||
.El
|
||||
.Sh SHUTDOWN
|
||||
This node shuts down upon receipt of an
|
||||
.Dv NGM_SHUTDOWN
|
||||
control message, or
|
||||
This node shuts down upon receipt of a NGM_SHUTDOWN control message, or
|
||||
when all hooks have been disconnected.
|
||||
.Sh BUGS
|
||||
Most likely.
|
||||
Please report if found.
|
||||
Most likely. Please report if found.
|
||||
.Sh SEE ALSO
|
||||
.Xr netgraph 4 ,
|
||||
.Xr ngctl 8 ,
|
||||
.Xr l2control 8 ,
|
||||
.Xr l2ping 8 ,
|
||||
.Xr ngctl 8
|
||||
.Xr l2ping 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm l2cap
|
||||
.Nm
|
||||
node type was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
|
@ -1,6 +1,8 @@
|
||||
.\" ng_ubt.4
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
@ -9,7 +11,7 @@
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
@ -21,49 +23,47 @@
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\"
|
||||
.\" $Id: ng_ubt.4,v 1.2 2003/03/22 23:44:32 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd June 14, 2002
|
||||
.Dt NG_UBT 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ng_ubt
|
||||
.Nm ubt
|
||||
.Nd Netgraph node type that is also a driver for Bluetooth USB devices
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In ng_ubt.h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm ubt
|
||||
.Nm
|
||||
node type is both a persistent Netgraph node type and a driver for
|
||||
Bluetooth USB devices.
|
||||
It implements a Bluetooth USB transport layer
|
||||
as per chapter H2 of the Bluetooth Specification Book v1.1.
|
||||
A new node is created when supported USB device is plugged.
|
||||
Bluetooth USB devices. It implements a Bluetooth USB transport layer
|
||||
as per chapter H2 of the Bluetooth Specification Book v1.1. A new
|
||||
node is created when supported USB device is plugged.
|
||||
.Pp
|
||||
The node has a single hook called
|
||||
.Dv hook .
|
||||
Incoming bytes received on the device are re-assembled into HCI frames
|
||||
(according to the length).
|
||||
Full HCI frames are sent out on the hook.
|
||||
The node will add HCI frame indicator if device did not send it.
|
||||
HCI frames received on
|
||||
(according to the length). Full HCI frames are sent out on the hook. The node
|
||||
will add HCI frame indicator if device did not send it. HCI frames received
|
||||
on
|
||||
.Dv hook
|
||||
are transmitted out.
|
||||
The node will drop HCI frame indicator unless device
|
||||
requires it to be present.
|
||||
are transmitted out. The node will drop HCI frame indicator unless device
|
||||
requires it to be present.
|
||||
.Sh HOOKS
|
||||
This node type supports the following hooks:
|
||||
.Bl -tag -width indent
|
||||
.Pp
|
||||
.Bl -tag -width foobar
|
||||
.It Dv hook
|
||||
single HCI frame contained in single
|
||||
.Vt mbuf
|
||||
.Dv mbuf
|
||||
structure.
|
||||
.El
|
||||
.Sh CONTROL MESSAGES
|
||||
This node type supports the generic control messages, plus the following:
|
||||
.Bl -tag -width indent
|
||||
.Bl -tag -width foo
|
||||
.It Dv NGM_UBT_NODE_GET_DEBUG
|
||||
Returns an integer containing the current debug level for the node.
|
||||
.It Dv NGM_UBT_NODE_SET_DEBUG
|
||||
@ -73,29 +73,114 @@ for the node.
|
||||
This command takes a parameter that specifies queue number and returns
|
||||
current maximal length of the queue for the node.
|
||||
.It Dv NGM_UBT_NODE_SET_QLEN
|
||||
This command takes two parameters that specify queue number and maximum
|
||||
This command takes two parameters that specify queue number and maximum
|
||||
length of the queue and sets maximal length of the queue for the node.
|
||||
.It Dv NGM_UBT_NODE_GET_STAT
|
||||
Returns various statistic information for the node, such as: number of
|
||||
bytes (frames) sent, number of bytes (frames) received and number of
|
||||
Returns various statistic information for the node, such as: number of
|
||||
bytes (frames) sent, number of bytes (frames) received and number of
|
||||
input (output) errors.
|
||||
.It Dv NGM_UBT_NODE_RESET_STAT
|
||||
Reset all statistic counters to zero.
|
||||
.It Dv NGM_UBT_NODE_DEV_NODES
|
||||
This command takes single integer parameter. If the parameter's value
|
||||
is not zero then the driver will create device nodes for the control,
|
||||
interrupt, bulk-in and bulk-out endpoints. If the parameter's value is
|
||||
zero then the driver will destroy device nodes for the endpoints. The
|
||||
device nodes interface is mutually exclusive with Netgraph interface.
|
||||
.El
|
||||
.Sh DEVICE NODES INTERFACE
|
||||
The
|
||||
.Nm
|
||||
driver can create or destroy endpoint device nodes on request. This
|
||||
feature can be used to implement external firmware download utility.
|
||||
.Pp
|
||||
The control transfers can only happen on the control endpoint which
|
||||
is always endpoint 0. Control request are issued by
|
||||
.Xr ioctl 2
|
||||
calls.
|
||||
.Pp
|
||||
Only incoming transfers are supported on an interrupt endpoint. To perform I/O
|
||||
on an interrupt endpoint
|
||||
.Xr read 2
|
||||
should be used. All I/O operations on a interrupt endpoint are unbuffered.
|
||||
.Pp
|
||||
The bulk transfers can be in or out depending on the endpoint. To perform
|
||||
I/O on a bulk endpoint
|
||||
.Xr read 2
|
||||
and
|
||||
.Xr write 2
|
||||
should be used. All I/O operations on a bulk endpoint are unbuffered.
|
||||
.Pp
|
||||
The control endpoint (endpoint 0) handles the following
|
||||
.Xr ioctl 2
|
||||
calls:
|
||||
.Bl -tag -width foo
|
||||
.It Dv USB_GET_DEVICE_DESC Pq Vt usb_device_descriptor_t
|
||||
Return the device descriptor.
|
||||
.It Dv USB_GET_STRING_DESC Pq Vt "struct usb_string_desc"
|
||||
Get a string descriptor for the given language ID and
|
||||
string index.
|
||||
.Bd -literal
|
||||
struct usb_string_desc {
|
||||
int string_index;
|
||||
int language_id;
|
||||
usb_string_descriptor_t desc;
|
||||
};
|
||||
.Ed
|
||||
.It Dv USB_DO_REQUEST Pq Vt "struct usb_ctl_request"
|
||||
Send a USB request to the device on the control endpoint.
|
||||
Any data sent to/from the device is located at
|
||||
.Va data .
|
||||
The size of the transferred data is determined from the
|
||||
.Va request .
|
||||
The
|
||||
.Va addr
|
||||
field is ignored in this call.
|
||||
The
|
||||
.Va flags
|
||||
field can be used to flag that the request is allowed to
|
||||
be shorter than the requested size, and the
|
||||
.Va actlen
|
||||
will contain the actual size on completion.
|
||||
.Bd -literal
|
||||
struct usb_ctl_request {
|
||||
int addr;
|
||||
usb_device_request_t request;
|
||||
void *data;
|
||||
int flags;
|
||||
#define USBD_SHORT_XFER_OK 0x04 /* allow short reads */
|
||||
int actlen; /* actual length transferred */
|
||||
};
|
||||
.Ed
|
||||
This is a dangerous operation in that it can perform arbitrary operations
|
||||
on the device. Some of the most dangerous (e.g., changing the device
|
||||
address) are not allowed.
|
||||
.It Dv USB_GET_DEVICEINFO Pq Vt "struct usb_device_info"
|
||||
Get an information summary for the device. This call will not issue any USB
|
||||
transactions.
|
||||
.El
|
||||
.Sh SHUTDOWN
|
||||
This node shuts down when the corresponding USB device is un-plugged.
|
||||
.Sh BUGS
|
||||
Isochronous USB transfers are probably broken.
|
||||
It means that USB device probably will not be able to transfer SCO data (voice).
|
||||
Driver does not support firmware upgrade procedure.
|
||||
USB interrupt transfers are implemented as bulk-in transfers (not really a bug).
|
||||
Isochronous USB transfers are broken. It means that USB device will not be able
|
||||
to transfer SCO data (voice). USB interrupt transfers are implemented as bulk-in
|
||||
transfers (not really a bug).
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa /dev/ubt Ns Ar N Ns Pa \&. Ns Ar EE" -compact
|
||||
.It Pa /dev/ubt Ns Ar N Ns Pa \&. Ns Ar EE
|
||||
Endpoint
|
||||
.Ar EE
|
||||
of device
|
||||
.Ar N .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr netgraph 4 ,
|
||||
.Xr usb 4 ,
|
||||
.Xr ugen 4 ,
|
||||
.Xr netgraph 4 ,
|
||||
.Xr ngctl 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm ubt
|
||||
.Nm
|
||||
node type was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
|
92
share/man/man4/ubtbcmfw.4
Normal file
92
share/man/man4/ubtbcmfw.4
Normal file
@ -0,0 +1,92 @@
|
||||
.\" ubtbcmfw.4
|
||||
.\"
|
||||
.\" Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id: ubtbcmfw.4,v 1.1 2003/04/28 17:09:46 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.Dd April 28, 2003
|
||||
.Dt UBTBCMFW 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm ubtbcmfw
|
||||
.Nd Firmware driver for Broadcom BCM2033 chip based Bluetooth USB devices
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
is a firmware driver for Broadcom BCM2033 chip based Bluetooth USB devices.
|
||||
It provides minimal access to the parts of the device required to download
|
||||
firmware.
|
||||
.Pp
|
||||
.Nm
|
||||
driver creates three fixed endpoint device nodes.
|
||||
.Pp
|
||||
The control transfers can only happen on the control endpoint which
|
||||
is always endpoint 0. Control request are issued by
|
||||
.Xr ioctl 2
|
||||
calls.
|
||||
.Pp
|
||||
Only incoming transfers are supported on an interrupt endpoint. To perform I/O
|
||||
on an interrupt endpoint
|
||||
.Xr read 2
|
||||
should be used. All I/O operations on a interrupt endpoint are unbuffered.
|
||||
Interrupt endpoint is always endpoint 1.
|
||||
.Pp
|
||||
Only outgoing bulk transfers are supported on a bulk endpoint. To perform
|
||||
I/O on a bulk endpoint
|
||||
.Xr write 2
|
||||
should be used. All I/O operations on a bulk endpoint are unbuffered. Outgoing
|
||||
bulk endpoint is always enpoint 2.
|
||||
.Pp
|
||||
The control endpoint (endpoint 0) handles the following
|
||||
.Xr ioctl 2
|
||||
calls:
|
||||
.Bl -tag -width foo
|
||||
.It Dv USB_GET_DEVICE_DESC Pq Vt usb_device_descriptor_t
|
||||
Return the device descriptor.
|
||||
.El
|
||||
.Sh BUGS
|
||||
This code
|
||||
.Em was not
|
||||
tested on a real BCM2033 based hardware.
|
||||
.Sh FILES
|
||||
.Bl -tag -width ".Pa /dev/ubtbcmfw Ns Ar N Ns Pa \&. Ns Ar EE" -compact
|
||||
.It Pa /dev/ubtbcmfw Ns Ar N Ns Pa \&. Ns Ar EE
|
||||
Endpoint
|
||||
.Ar EE
|
||||
of device
|
||||
.Ar N .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr usb 4 ,
|
||||
.Xr ugen 4 ,
|
||||
.Xr ng_ubt 4 ,
|
||||
.Xr bcmfw 8
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Nm
|
||||
driver was implemented in
|
||||
.Fx 5.0 .
|
||||
.Sh AUTHORS
|
||||
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
|
@ -1,3 +1,4 @@
|
||||
# $Id: Makefile,v 1.2 2003/04/27 00:22:11 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
SUBDIR= \
|
||||
@ -7,7 +8,8 @@ SUBDIR= \
|
||||
socket \
|
||||
bt3c \
|
||||
h4 \
|
||||
ubt
|
||||
ubt \
|
||||
ubtbcmfw
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
|
@ -1,9 +1,9 @@
|
||||
# $Id: Makefile,v 1.1.1.1 2002/09/04 21:47:41 max Exp $
|
||||
# $Id: Makefile,v 1.1 2002/11/24 20:39:57 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/common
|
||||
|
||||
CFLAGS+= -I${.CURDIR}/../../../../netgraph/bluetooth/include
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include
|
||||
|
||||
KMOD= ng_bluetooth
|
||||
SRCS= ng_bluetooth.c
|
||||
|
@ -1,12 +1,13 @@
|
||||
# $Id: Makefile,v 1.6 2002/09/04 21:42:00 max Exp $
|
||||
# $Id: Makefile,v 1.2 2002/11/24 20:50:56 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/bt3c
|
||||
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/bt3c \
|
||||
-DINVARIANTS=1 -DINVARIANT_SUPPORT=1 \
|
||||
-DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/bt3c
|
||||
|
||||
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
|
||||
KMOD= ng_bt3c
|
||||
SRCS= ng_bt3c_pccard.c bus_if.h card_if.h device_if.h
|
||||
|
@ -1,12 +1,12 @@
|
||||
# $Id: Makefile,v 1.7 2002/11/03 02:15:54 max Exp $
|
||||
# $Id: Makefile,v 1.1 2002/11/24 20:40:04 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/h4
|
||||
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/h4 \
|
||||
-DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
# -DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/h4
|
||||
|
||||
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
|
||||
KMOD= ng_h4
|
||||
SRCS= ng_h4.c
|
||||
|
@ -1,12 +1,12 @@
|
||||
# $Id: Makefile,v 1.5 2002/09/04 21:36:51 max Exp $
|
||||
# $Id: Makefile,v 1.1 2002/11/24 20:40:05 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/hci
|
||||
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/hci \
|
||||
-DINVARIANTS=1 -DINVARIANT_SUPPORT=1 \
|
||||
-DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/hci
|
||||
|
||||
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
|
||||
KMOD= ng_hci
|
||||
SRCS= ng_hci_main.c ng_hci_cmds.c ng_hci_evnt.c \
|
||||
|
@ -1,12 +1,12 @@
|
||||
# $Id: Makefile,v 1.4 2002/09/04 21:38:38 max Exp $
|
||||
# $Id: Makefile,v 1.1 2002/11/24 20:40:11 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/l2cap
|
||||
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/l2cap \
|
||||
-DINVARIANTS=1 -DINVARIANT_SUPPORT=1 \
|
||||
-DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/l2cap
|
||||
|
||||
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
|
||||
KMOD= ng_l2cap
|
||||
SRCS= ng_l2cap_main.c ng_l2cap_cmds.c ng_l2cap_evnt.c \
|
||||
|
@ -1,17 +1,19 @@
|
||||
# $Id: Makefile,v 1.7 2002/09/04 21:43:59 max Exp $
|
||||
# $Id: Makefile,v 1.2 2003/01/12 23:37:31 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/socket
|
||||
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
|
||||
-DINVARIANTS=1 -DINVARIANT_SUPPORT=1 \
|
||||
-DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include
|
||||
|
||||
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
|
||||
KMOD= ng_btsocket
|
||||
SRCS= ng_btsocket.c \
|
||||
ng_btsocket_hci_raw.c \
|
||||
ng_btsocket_l2cap_raw.c \
|
||||
ng_btsocket_l2cap.c
|
||||
ng_btsocket_l2cap.c \
|
||||
ng_btsocket_rfcomm.c
|
||||
MAN4= ng_btsocket.4
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -1,15 +1,16 @@
|
||||
# $Id: Makefile,v 1.5 2002/09/04 21:41:06 max Exp $
|
||||
# $Id: Makefile,v 1.2 2003/03/22 23:44:34 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubt
|
||||
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubt \
|
||||
-DINVARIANTS=1 -DINVARIANT_SUPPORT=1 \
|
||||
-DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubt
|
||||
|
||||
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
|
||||
KMOD= ng_ubt
|
||||
SRCS= ng_ubt.c bus_if.h device_if.h opt_usb.h
|
||||
SRCS= ng_ubt.c bus_if.h device_if.h vnode_if.h opt_usb.h
|
||||
MAN4= ng_ubt.4
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
17
sys/modules/netgraph/bluetooth/ubtbcmfw/Makefile
Normal file
17
sys/modules/netgraph/bluetooth/ubtbcmfw/Makefile
Normal file
@ -0,0 +1,17 @@
|
||||
# $Id: Makefile,v 1.1 2003/04/27 00:22:12 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
.PATH: ${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubtbcmfw
|
||||
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../../netgraph/bluetooth/include \
|
||||
-I${.CURDIR}/../../../../netgraph/bluetooth/drivers/ubtbcmfw
|
||||
|
||||
#CFLAGS+= -DINVARIANTS=1 -DINVARIANT_SUPPORT=1
|
||||
#CFLAGS+= -DWITNESS=1 -DWITNESS_SKIPSPIN=1
|
||||
|
||||
KMOD= ubtbcmfw
|
||||
SRCS= ubtbcmfw.c bus_if.h device_if.h vnode_if.h opt_usb.h
|
||||
MAN4= ubtbcmfw.4
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_bluetooth.c,v 1.1.1.1 2002/09/04 21:47:41 max Exp $
|
||||
* $Id: ng_bluetooth.c,v 1.3 2003/04/26 22:37:31 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -43,7 +43,6 @@
|
||||
|
||||
static u_int32_t bluetooth_hci_command_timeout_value = 5; /* sec */
|
||||
static u_int32_t bluetooth_hci_connect_timeout_value = 60; /* sec */
|
||||
static u_int32_t bluetooth_hci_watchdog_timeout_value = 60; /* sec */
|
||||
static u_int32_t bluetooth_hci_max_neighbor_age_value = 600; /* sec */
|
||||
static u_int32_t bluetooth_l2cap_rtx_timeout_value = 60; /* sec */
|
||||
static u_int32_t bluetooth_l2cap_ertx_timeout_value = 300; /* sec */
|
||||
@ -111,10 +110,6 @@ SYSCTL_PROC(_net_bluetooth_hci, OID_AUTO, connection_timeout,
|
||||
bluetooth_set_hci_connect_timeout_value,
|
||||
"I", "HCI connect timeout (sec)");
|
||||
|
||||
SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, watchdog_timeout, CTLFLAG_RW,
|
||||
&bluetooth_hci_watchdog_timeout_value, 60,
|
||||
"HCI connection watchdog timeout (sec)");
|
||||
|
||||
SYSCTL_INT(_net_bluetooth_hci, OID_AUTO, max_neighbor_age, CTLFLAG_RW,
|
||||
&bluetooth_hci_max_neighbor_age_value, 600,
|
||||
"Maximal HCI neighbor cache entry age (sec)");
|
||||
@ -191,12 +186,6 @@ bluetooth_hci_connect_timeout(void)
|
||||
return (bluetooth_hci_connect_timeout_value * hz);
|
||||
} /* bluetooth_hci_connect_timeout */
|
||||
|
||||
u_int32_t
|
||||
bluetooth_hci_watchdog_timeout(void)
|
||||
{
|
||||
return (bluetooth_hci_watchdog_timeout_value * hz);
|
||||
} /* bluetooth_hci_watchdog_timeout */
|
||||
|
||||
u_int32_t
|
||||
bluetooth_hci_max_neighbor_age(void)
|
||||
{
|
||||
@ -215,6 +204,13 @@ bluetooth_l2cap_ertx_timeout(void)
|
||||
return (bluetooth_l2cap_ertx_timeout_value * hz);
|
||||
} /* bluetooth_l2cap_ertx_timeout */
|
||||
|
||||
/*
|
||||
* RFCOMM
|
||||
*/
|
||||
|
||||
SYSCTL_NODE(_net_bluetooth, OID_AUTO, rfcomm, CTLFLAG_RW,
|
||||
0, "Bluetooth RFCOMM family");
|
||||
|
||||
/*
|
||||
* Handle loading and unloading for this code.
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_bt3c_pccard.c,v 1.2 2002/11/12 00:51:45 max Exp $
|
||||
* $Id: ng_bt3c_pccard.c,v 1.5 2003/04/01 18:15:21 max Exp $
|
||||
* $FreeBSD$
|
||||
*
|
||||
* XXX XXX XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
|
||||
@ -86,7 +86,6 @@ static int bt3c_pccard_detach (device_t);
|
||||
|
||||
static void bt3c_intr (void *);
|
||||
static void bt3c_receive (bt3c_softc_p);
|
||||
static int bt3c_append (struct mbuf *, int);
|
||||
|
||||
static void bt3c_swi_intr (void *);
|
||||
static void bt3c_forward (node_p, hook_p, void *, int);
|
||||
@ -241,8 +240,6 @@ static struct ng_type typestruct = {
|
||||
ng_bt3c_disconnect, /* disconnect hook */
|
||||
ng_bt3c_cmdlist /* node command list */
|
||||
};
|
||||
NETGRAPH_INIT(bt3c, &typestruct);
|
||||
MODULE_VERSION(ng_bt3c, NG_BLUETOOTH_VERSION);
|
||||
|
||||
/*
|
||||
* Netgraph node constructor. Do not allow to create node of this type.
|
||||
@ -840,12 +837,24 @@ bt3c_receive(bt3c_softc_p sc)
|
||||
break; /* XXX lost of sync */
|
||||
}
|
||||
|
||||
MCLGET(sc->m, M_DONTWAIT);
|
||||
if (!(sc->m->m_flags & M_EXT)) {
|
||||
NG_FREE_M(sc->m);
|
||||
|
||||
NG_BT3C_ERR(sc->dev, "Could not get cluster\n");
|
||||
NG_BT3C_STAT_IERROR(sc->stat);
|
||||
|
||||
break; /* XXX lost of sync */
|
||||
}
|
||||
|
||||
sc->m->m_len = sc->m->m_pkthdr.len = 0;
|
||||
}
|
||||
|
||||
/* Read and append character to mbuf */
|
||||
bt3c_read_data(sc, c);
|
||||
if (bt3c_append(sc->m, c) != 0) {
|
||||
if (sc->m->m_pkthdr.len >= MCLBYTES) {
|
||||
NG_BT3C_ERR(sc->dev, "Oversized frame\n");
|
||||
|
||||
NG_FREE_M(sc->m);
|
||||
sc->state = NG_BT3C_W4_PKT_IND;
|
||||
sc->want = 1;
|
||||
@ -853,6 +862,9 @@ bt3c_receive(bt3c_softc_p sc)
|
||||
break; /* XXX lost of sync */
|
||||
}
|
||||
|
||||
mtod(sc->m, u_int8_t *)[sc->m->m_len ++] = (u_int8_t) c;
|
||||
sc->m->m_pkthdr.len ++;
|
||||
|
||||
NG_BT3C_INFO(sc->dev,
|
||||
"Got char %#x, want=%d, got=%d\n", c, sc->want, sc->m->m_pkthdr.len);
|
||||
|
||||
@ -973,43 +985,6 @@ bt3c_receive(bt3c_softc_p sc)
|
||||
bt3c_write(sc, 0x7006, 0x0000);
|
||||
} /* bt3c_receive */
|
||||
|
||||
/*
|
||||
* Append character to the mbuf.
|
||||
* XXX assumes mbuf has header
|
||||
* XXX does not handle external mbuf's
|
||||
* XXX always appends char to the end of chain
|
||||
*/
|
||||
|
||||
static int
|
||||
bt3c_append(struct mbuf *m0, int c)
|
||||
{
|
||||
struct mbuf *m = m0;
|
||||
int len;
|
||||
|
||||
if (m0->m_next == NULL)
|
||||
len = MHLEN;
|
||||
else {
|
||||
len = MLEN;
|
||||
|
||||
while (m->m_next != NULL)
|
||||
m = m->m_next;
|
||||
}
|
||||
|
||||
if (m->m_len >= len) {
|
||||
MGET(m->m_next, M_DONTWAIT, m0->m_type);
|
||||
if (m->m_next == NULL)
|
||||
return (ENOBUFS);
|
||||
|
||||
m = m->m_next;
|
||||
m->m_len = 0;
|
||||
}
|
||||
|
||||
m->m_data[m->m_len ++] = (char) c;
|
||||
m0->m_pkthdr.len ++;
|
||||
|
||||
return (0);
|
||||
} /* bt3c_append */
|
||||
|
||||
/*
|
||||
* SWI interrupt handler
|
||||
* Netgraph part is handled via ng_send_fn() to avoid race with hook
|
||||
@ -1243,5 +1218,37 @@ static driver_t bt3c_pccard_driver = {
|
||||
|
||||
static devclass_t bt3c_devclass;
|
||||
|
||||
DRIVER_MODULE(bt3c, pccard, bt3c_pccard_driver, bt3c_devclass, 0, 0);
|
||||
|
||||
/*
|
||||
* Load/Unload the driver module
|
||||
*/
|
||||
|
||||
static int
|
||||
bt3c_modevent(module_t mod, int event, void *data)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (event) {
|
||||
case MOD_LOAD:
|
||||
error = ng_newtype(&typestruct);
|
||||
if (error != 0)
|
||||
printf("%s: Could not register Netgraph node type, " \
|
||||
"error=%d\n", NG_BT3C_NODE_TYPE, error);
|
||||
break;
|
||||
|
||||
case MOD_UNLOAD:
|
||||
error = ng_rmtype(&typestruct);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
} /* bt3c_modevent */
|
||||
|
||||
DRIVER_MODULE(bt3c, pccard, bt3c_pccard_driver, bt3c_devclass, bt3c_modevent,0);
|
||||
MODULE_VERSION(ng_bt3c, NG_BLUETOOTH_VERSION);
|
||||
MODULE_DEPEND(ng_bt3c, netgraph, NG_ABI_VERSION, NG_ABI_VERSION,NG_ABI_VERSION);
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_bt3c_var.h,v 1.1 2002/11/09 19:07:56 max Exp $
|
||||
* $Id: ng_bt3c_var.h,v 1.1 2002/11/24 19:46:54 max Exp $
|
||||
* $FreeBSD$
|
||||
*
|
||||
* XXX XXX XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
|
||||
|
@ -1,5 +1,5 @@
|
||||
# $FreeBSD$
|
||||
$Id: TODO,v 1.6 2002/06/27 09:50:17 max Exp $
|
||||
$Id: TODO,v 1.1 2002/11/24 19:46:55 max Exp $
|
||||
$FreeBSD$
|
||||
|
||||
FIXME/TODO list
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_h4.c,v 1.25 2002/11/03 02:17:31 max Exp $
|
||||
* $Id: ng_h4.c,v 1.4 2003/04/01 18:15:23 max Exp $
|
||||
* $FreeBSD$
|
||||
*
|
||||
* Based on:
|
||||
@ -170,7 +170,7 @@ ng_h4_open(dev_t dev, struct tty *tp)
|
||||
}
|
||||
|
||||
/* Initialize private struct */
|
||||
MALLOC(sc, ng_h4_info_p, sizeof(*sc), M_NETGRAPH_H4, M_WAITOK | M_ZERO);
|
||||
MALLOC(sc, ng_h4_info_p, sizeof(*sc), M_NETGRAPH_H4, M_ZERO);
|
||||
if (sc == NULL) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_h4_prse.h,v 1.6 2002/09/04 21:35:01 max Exp $
|
||||
* $Id: ng_h4_prse.h,v 1.1 2002/11/24 19:46:55 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_h4_var.h,v 1.14 2002/11/03 02:16:31 max Exp $
|
||||
* $Id: ng_h4_var.h,v 1.1 2002/11/24 19:46:55 max Exp $
|
||||
* $FreeBSD$
|
||||
*
|
||||
* Based on:
|
||||
|
@ -1,5 +1,5 @@
|
||||
# $FreeBSD$
|
||||
$Id: TODO,v 1.1.1.1 2002/06/09 20:21:47 max Exp $
|
||||
$Id: TODO,v 1.1 2002/11/24 19:46:56 max Exp $
|
||||
$FreeBSD$
|
||||
|
||||
1) SMP/Locking
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_ubt_var.h,v 1.1 2002/11/09 19:09:02 max Exp $
|
||||
* $Id: ng_ubt_var.h,v 1.2 2003/03/22 23:44:36 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -62,6 +62,13 @@ struct ubt_softc {
|
||||
#define UBT_CMD_XMIT (1 << 1) /* CMD xmit in progress */
|
||||
#define UBT_ACL_XMIT (1 << 2) /* ACL xmit in progress */
|
||||
#define UBT_SCO_XMIT (1 << 3) /* SCO xmit in progress */
|
||||
#define UBT_EVT_RECV (1 << 4) /* EVN recv in progress */
|
||||
#define UBT_ACL_RECV (1 << 5) /* ACL recv in progress */
|
||||
#define UBT_SCO_RECV (1 << 6) /* SCO recv in progress */
|
||||
#define UBT_CTRL_DEV (1 << 7) /* ctrl device is open */
|
||||
#define UBT_INTR_DEV (1 << 8) /* intr device is open */
|
||||
#define UBT_BULK_DEV (1 << 9) /* bulk device is open */
|
||||
#define UBT_ANY_DEV (UBT_CTRL_DEV|UBT_INTR_DEV|UBT_BULK_DEV)
|
||||
|
||||
ng_ubt_node_stat_ep sc_stat; /* statistic */
|
||||
#define NG_UBT_STAT_PCKTS_SENT(s) (s).pckts_sent ++
|
||||
@ -79,21 +86,16 @@ struct ubt_softc {
|
||||
usbd_interface_handle sc_iface0; /* USB interface 0 */
|
||||
usbd_interface_handle sc_iface1; /* USB interface 1 */
|
||||
|
||||
struct ifqueue sc_inq; /* incoming queue */
|
||||
void *sc_ith; /* SWI interrupt handler */
|
||||
|
||||
/* Interrupt pipe (HCI events) */
|
||||
int sc_intr_ep; /* interrupt endpoint */
|
||||
usbd_pipe_handle sc_intr_pipe; /* interrupt pipe handle */
|
||||
usbd_xfer_handle sc_intr_xfer; /* intr xfer */
|
||||
u_int8_t *sc_intr_buffer; /* interrupt buffer */
|
||||
#define UBT_INTR_BUFFER_SIZE \
|
||||
(sizeof(ng_hci_event_pkt_t) + NG_HCI_EVENT_PKT_SIZE)
|
||||
struct mbuf *sc_intr_buffer; /* interrupt buffer */
|
||||
|
||||
/* Control pipe (HCI commands) */
|
||||
usbd_xfer_handle sc_ctrl_xfer; /* control xfer handle */
|
||||
void *sc_ctrl_buffer; /* control buffer */
|
||||
struct ifqueue sc_cmdq; /* HCI command queue */
|
||||
struct ng_bt_mbufq sc_cmdq; /* HCI command queue */
|
||||
#define UBT_CTRL_BUFFER_SIZE \
|
||||
(sizeof(ng_hci_cmd_pkt_t) + NG_HCI_CMD_PKT_SIZE)
|
||||
|
||||
@ -101,16 +103,16 @@ struct ubt_softc {
|
||||
int sc_bulk_in_ep; /* bulk-in enpoint */
|
||||
usbd_pipe_handle sc_bulk_in_pipe; /* bulk-in pipe */
|
||||
usbd_xfer_handle sc_bulk_in_xfer; /* bulk-in xfer */
|
||||
void *sc_bulk_in_buffer; /* bulk-in buffer */
|
||||
struct mbuf *sc_bulk_in_buffer; /* bulk-in buffer */
|
||||
|
||||
/* Bulk out pipe (ACL data) */
|
||||
int sc_bulk_out_ep; /* bulk-out endpoint */
|
||||
usbd_pipe_handle sc_bulk_out_pipe; /* bulk-out pipe */
|
||||
usbd_xfer_handle sc_bulk_out_xfer; /* bulk-out xfer */
|
||||
void *sc_bulk_out_buffer; /* bulk-out buffer */
|
||||
struct ifqueue sc_aclq; /* ACL data queue */
|
||||
struct ng_bt_mbufq sc_aclq; /* ACL data queue */
|
||||
#define UBT_BULK_BUFFER_SIZE \
|
||||
512 /* XXX should be big enough to hold one frame */
|
||||
MCLBYTES /* XXX should be big enough to hold one frame */
|
||||
|
||||
/* Isoc. in pipe (SCO data) */
|
||||
int sc_isoc_in_ep; /* isoc-in endpoint */
|
||||
@ -125,7 +127,7 @@ struct ubt_softc {
|
||||
usbd_xfer_handle sc_isoc_out_xfer; /* isoc-out xfer */
|
||||
void *sc_isoc_out_buffer; /* isoc-in buffer */
|
||||
u_int16_t *sc_isoc_out_frlen; /* isoc-out. frame length */
|
||||
struct ifqueue sc_scoq; /* SCO data queue */
|
||||
struct ng_bt_mbufq sc_scoq; /* SCO data queue */
|
||||
|
||||
int sc_isoc_size; /* max. size of isoc. packet */
|
||||
u_int32_t sc_isoc_nframes; /* num. isoc. frames */
|
||||
@ -135,6 +137,14 @@ struct ubt_softc {
|
||||
/* Netgraph specific */
|
||||
node_p sc_node; /* pointer back to node */
|
||||
hook_p sc_hook; /* upstream hook */
|
||||
|
||||
/* Device specific */
|
||||
dev_t sc_ctrl_dev; /* control device */
|
||||
dev_t sc_intr_dev; /* interrupt device */
|
||||
dev_t sc_bulk_dev; /* bulk device */
|
||||
|
||||
int sc_refcnt; /* device ref. count */
|
||||
int sc_dying;
|
||||
};
|
||||
typedef struct ubt_softc ubt_softc_t;
|
||||
typedef struct ubt_softc * ubt_softc_p;
|
||||
|
571
sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c
Normal file
571
sys/netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c
Normal file
@ -0,0 +1,571 @@
|
||||
/*
|
||||
* ubtbcmfw.c
|
||||
*
|
||||
* Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ubtbcmfw.c,v 1.1 2003/04/27 00:20:15 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/conf.h>
|
||||
#include <sys/filio.h>
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/vnode.h>
|
||||
|
||||
#include <dev/usb/usb.h>
|
||||
#include <dev/usb/usbdi.h>
|
||||
#include <dev/usb/usbdi_util.h>
|
||||
#include <dev/usb/usbdevs.h>
|
||||
|
||||
/*
|
||||
* Download firmware to BCM2033.
|
||||
*/
|
||||
|
||||
#define UBTBCMFW_CONFIG_NO 1 /* Config number */
|
||||
#define UBTBCMFW_IFACE_IDX 0 /* Control interface */
|
||||
#define UBTBCMFW_INTR_IN_EP 0x81 /* Fixed endpoint */
|
||||
#define UBTBCMFW_BULK_OUT_EP 0x02 /* Fixed endpoint */
|
||||
#define UBTBCMFW_INTR_IN UE_GET_ADDR(UBTBCMFW_INTR_IN_EP)
|
||||
#define UBTBCMFW_BULK_OUT UE_GET_ADDR(UBTBCMFW_BULK_OUT_EP)
|
||||
|
||||
struct ubtbcmfw_softc {
|
||||
USBBASEDEVICE sc_dev; /* base device */
|
||||
usbd_device_handle sc_udev; /* USB device handle */
|
||||
dev_t sc_ctrl_dev; /* control device */
|
||||
dev_t sc_intr_in_dev; /* interrupt device */
|
||||
dev_t sc_bulk_out_dev; /* bulk device */
|
||||
usbd_pipe_handle sc_intr_in_pipe; /* interrupt pipe */
|
||||
usbd_pipe_handle sc_bulk_out_pipe; /* bulk out pipe */
|
||||
int sc_flags;
|
||||
#define UBTBCMFW_CTRL_DEV (1 << 0)
|
||||
#define UBTBCMFW_INTR_IN_DEV (1 << 1)
|
||||
#define UBTBCMFW_BULK_OUT_DEV (1 << 2)
|
||||
int sc_refcnt;
|
||||
int sc_dying;
|
||||
};
|
||||
|
||||
typedef struct ubtbcmfw_softc *ubtbcmfw_softc_p;
|
||||
|
||||
/*
|
||||
* Device methods
|
||||
*/
|
||||
|
||||
#define UBTBCMFW_UNIT(n) ((minor(n) >> 4) & 0xf)
|
||||
#define UBTBCMFW_ENDPOINT(n) (minor(n) & 0xf)
|
||||
#define UBTBCMFW_MINOR(u, e) (((u) << 4) | (e))
|
||||
#define UBTBCMFW_BSIZE 1024
|
||||
|
||||
Static d_open_t ubtbcmfw_open;
|
||||
Static d_close_t ubtbcmfw_close;
|
||||
Static d_read_t ubtbcmfw_read;
|
||||
Static d_write_t ubtbcmfw_write;
|
||||
Static d_ioctl_t ubtbcmfw_ioctl;
|
||||
Static d_poll_t ubtbcmfw_poll;
|
||||
|
||||
#if __FreeBSD_version < 500104
|
||||
#define CDEV_MAJOR 223
|
||||
#else
|
||||
#define CDEV_MAJOR MAJOR_AUTO
|
||||
#endif
|
||||
|
||||
Static struct cdevsw ubtbcmfw_cdevsw = {
|
||||
.d_open = ubtbcmfw_open,
|
||||
.d_close = ubtbcmfw_close,
|
||||
.d_read = ubtbcmfw_read,
|
||||
.d_write = ubtbcmfw_write,
|
||||
.d_ioctl = ubtbcmfw_ioctl,
|
||||
.d_poll = ubtbcmfw_poll,
|
||||
.d_name = "ubtbcmfw",
|
||||
.d_maj = CDEV_MAJOR,
|
||||
};
|
||||
|
||||
/*
|
||||
* Module
|
||||
*/
|
||||
|
||||
USB_DECLARE_DRIVER(ubtbcmfw);
|
||||
DRIVER_MODULE(ubtbcmfw, uhub, ubtbcmfw_driver, ubtbcmfw_devclass,
|
||||
usbd_driver_load, 0);
|
||||
|
||||
/*
|
||||
* Probe for a USB Bluetooth device
|
||||
*/
|
||||
|
||||
USB_MATCH(ubtbcmfw)
|
||||
{
|
||||
#define USB_PRODUCT_BROADCOM_BCM2033NF 0x2033
|
||||
|
||||
USB_MATCH_START(ubtbcmfw, uaa);
|
||||
|
||||
if (uaa->iface != NULL)
|
||||
return (UMATCH_NONE);
|
||||
|
||||
/* Match the boot device. */
|
||||
if (uaa->vendor == USB_VENDOR_BROADCOM &&
|
||||
uaa->product == USB_PRODUCT_BROADCOM_BCM2033NF)
|
||||
return (UMATCH_VENDOR_PRODUCT);
|
||||
|
||||
return (UMATCH_NONE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Attach the device
|
||||
*/
|
||||
|
||||
USB_ATTACH(ubtbcmfw)
|
||||
{
|
||||
USB_ATTACH_START(ubtbcmfw, sc, uaa);
|
||||
usbd_interface_handle iface;
|
||||
usbd_status err;
|
||||
char devinfo[1024];
|
||||
|
||||
sc->sc_udev = uaa->device;
|
||||
usbd_devinfo(sc->sc_udev, 0, devinfo);
|
||||
USB_ATTACH_SETUP;
|
||||
printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
|
||||
|
||||
sc->sc_ctrl_dev = sc->sc_intr_in_dev = sc->sc_bulk_out_dev = NODEV;
|
||||
sc->sc_intr_in_pipe = sc->sc_bulk_out_pipe = NULL;
|
||||
sc->sc_flags = sc->sc_refcnt = sc->sc_dying = 0;
|
||||
|
||||
err = usbd_set_config_no(sc->sc_udev, UBTBCMFW_CONFIG_NO, 1);
|
||||
if (err) {
|
||||
printf("%s: setting config no failed. %s\n",
|
||||
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
err = usbd_device2interface_handle(sc->sc_udev, UBTBCMFW_IFACE_IDX,
|
||||
&iface);
|
||||
if (err) {
|
||||
printf("%s: getting interface handle failed. %s\n",
|
||||
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Will be used as a bulk pipe */
|
||||
err = usbd_open_pipe(iface, UBTBCMFW_INTR_IN_EP, 0,
|
||||
&sc->sc_intr_in_pipe);
|
||||
if (err) {
|
||||
printf("%s: open intr in failed. %s\n",
|
||||
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
err = usbd_open_pipe(iface, UBTBCMFW_BULK_OUT_EP, 0,
|
||||
&sc->sc_bulk_out_pipe);
|
||||
if (err) {
|
||||
printf("%s: open bulk out failed. %s\n",
|
||||
USBDEVNAME(sc->sc_dev), usbd_errstr(err));
|
||||
goto bad;
|
||||
}
|
||||
|
||||
/* Create device nodes */
|
||||
sc->sc_ctrl_dev = make_dev(&ubtbcmfw_cdevsw,
|
||||
UBTBCMFW_MINOR(USBDEVUNIT(sc->sc_dev), 0),
|
||||
UID_ROOT, GID_OPERATOR, 0644,
|
||||
"%s", USBDEVNAME(sc->sc_dev));
|
||||
|
||||
sc->sc_intr_in_dev = make_dev(&ubtbcmfw_cdevsw,
|
||||
UBTBCMFW_MINOR(USBDEVUNIT(sc->sc_dev), UBTBCMFW_INTR_IN),
|
||||
UID_ROOT, GID_OPERATOR, 0644,
|
||||
"%s.%d", USBDEVNAME(sc->sc_dev), UBTBCMFW_INTR_IN);
|
||||
|
||||
sc->sc_bulk_out_dev = make_dev(&ubtbcmfw_cdevsw,
|
||||
UBTBCMFW_MINOR(USBDEVUNIT(sc->sc_dev), UBTBCMFW_BULK_OUT),
|
||||
UID_ROOT, GID_OPERATOR, 0644,
|
||||
"%s.%d", USBDEVNAME(sc->sc_dev), UBTBCMFW_BULK_OUT);
|
||||
|
||||
USB_ATTACH_SUCCESS_RETURN;
|
||||
bad:
|
||||
ubtbcmfw_detach(self);
|
||||
|
||||
USB_ATTACH_ERROR_RETURN;
|
||||
}
|
||||
|
||||
/*
|
||||
* Detach the device
|
||||
*/
|
||||
|
||||
USB_DETACH(ubtbcmfw)
|
||||
{
|
||||
USB_DETACH_START(ubtbcmfw, sc);
|
||||
|
||||
struct vnode *vp = NULL;
|
||||
|
||||
sc->sc_dying = 1;
|
||||
|
||||
if (-- sc->sc_refcnt >= 0) {
|
||||
if (sc->sc_intr_in_pipe != NULL)
|
||||
usbd_abort_pipe(sc->sc_intr_in_pipe);
|
||||
|
||||
if (sc->sc_bulk_out_pipe != NULL)
|
||||
usbd_abort_pipe(sc->sc_bulk_out_pipe);
|
||||
|
||||
usb_detach_wait(USBDEV(sc->sc_dev));
|
||||
}
|
||||
|
||||
/* Destroy device nodes */
|
||||
if (sc->sc_bulk_out_dev != NODEV) {
|
||||
vp = SLIST_FIRST(&sc->sc_bulk_out_dev->si_hlist);
|
||||
if (vp != NULL)
|
||||
VOP_REVOKE(vp, REVOKEALL);
|
||||
|
||||
destroy_dev(sc->sc_bulk_out_dev);
|
||||
sc->sc_bulk_out_dev = NODEV;
|
||||
}
|
||||
|
||||
if (sc->sc_intr_in_dev != NODEV) {
|
||||
vp = SLIST_FIRST(&sc->sc_intr_in_dev->si_hlist);
|
||||
if (vp != NULL)
|
||||
VOP_REVOKE(vp, REVOKEALL);
|
||||
|
||||
destroy_dev(sc->sc_intr_in_dev);
|
||||
sc->sc_intr_in_dev = NODEV;
|
||||
}
|
||||
|
||||
if (sc->sc_ctrl_dev != NODEV) {
|
||||
vp = SLIST_FIRST(&sc->sc_ctrl_dev->si_hlist);
|
||||
if (vp != NULL)
|
||||
VOP_REVOKE(vp, REVOKEALL);
|
||||
|
||||
destroy_dev(sc->sc_ctrl_dev);
|
||||
sc->sc_ctrl_dev = NODEV;
|
||||
}
|
||||
|
||||
/* Close pipes */
|
||||
if (sc->sc_intr_in_pipe != NULL) {
|
||||
usbd_close_pipe(sc->sc_intr_in_pipe);
|
||||
sc->sc_intr_in_pipe = NULL;
|
||||
}
|
||||
|
||||
if (sc->sc_bulk_out_pipe != NULL) {
|
||||
usbd_close_pipe(sc->sc_bulk_out_pipe);
|
||||
sc->sc_intr_in_pipe = NULL;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Open endpoint device
|
||||
* XXX FIXME softc locking
|
||||
*/
|
||||
|
||||
Static int
|
||||
ubtbcmfw_open(dev_t dev, int flag, int mode, usb_proc_ptr p)
|
||||
{
|
||||
ubtbcmfw_softc_p sc = NULL;
|
||||
int error = 0;
|
||||
|
||||
/* checks for sc != NULL */
|
||||
USB_GET_SC_OPEN(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
|
||||
if (sc->sc_dying)
|
||||
return (ENXIO);
|
||||
|
||||
switch (UBTBCMFW_ENDPOINT(dev)) {
|
||||
case USB_CONTROL_ENDPOINT:
|
||||
if (!(sc->sc_flags & UBTBCMFW_CTRL_DEV))
|
||||
sc->sc_flags |= UBTBCMFW_CTRL_DEV;
|
||||
else
|
||||
error = EBUSY;
|
||||
break;
|
||||
|
||||
case UBTBCMFW_INTR_IN:
|
||||
if (!(sc->sc_flags & UBTBCMFW_INTR_IN_DEV)) {
|
||||
if (sc->sc_intr_in_pipe != NULL)
|
||||
sc->sc_flags |= UBTBCMFW_INTR_IN_DEV;
|
||||
else
|
||||
error = ENXIO;
|
||||
} else
|
||||
error = EBUSY;
|
||||
break;
|
||||
|
||||
case UBTBCMFW_BULK_OUT:
|
||||
if (!(sc->sc_flags & UBTBCMFW_BULK_OUT_DEV)) {
|
||||
if (sc->sc_bulk_out_pipe != NULL)
|
||||
sc->sc_flags |= UBTBCMFW_BULK_OUT_DEV;
|
||||
else
|
||||
error = ENXIO;
|
||||
} else
|
||||
error = EBUSY;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = ENXIO;
|
||||
break;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Close endpoint device
|
||||
* XXX FIXME softc locking
|
||||
*/
|
||||
|
||||
Static int
|
||||
ubtbcmfw_close(dev_t dev, int flag, int mode, usb_proc_ptr p)
|
||||
{
|
||||
ubtbcmfw_softc_p sc = NULL;
|
||||
|
||||
USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
switch (UBTBCMFW_ENDPOINT(dev)) {
|
||||
case USB_CONTROL_ENDPOINT:
|
||||
sc->sc_flags &= ~UBTBCMFW_CTRL_DEV;
|
||||
break;
|
||||
|
||||
case UBTBCMFW_INTR_IN:
|
||||
if (sc->sc_intr_in_pipe != NULL)
|
||||
usbd_abort_pipe(sc->sc_intr_in_pipe);
|
||||
|
||||
sc->sc_flags &= ~UBTBCMFW_INTR_IN_DEV;
|
||||
break;
|
||||
|
||||
case UBTBCMFW_BULK_OUT:
|
||||
if (sc->sc_bulk_out_pipe != NULL)
|
||||
usbd_abort_pipe(sc->sc_bulk_out_pipe);
|
||||
|
||||
sc->sc_flags &= ~UBTBCMFW_BULK_OUT_DEV;
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read from the endpoint device
|
||||
* XXX FIXME softc locking
|
||||
*/
|
||||
|
||||
Static int
|
||||
ubtbcmfw_read(dev_t dev, struct uio *uio, int flag)
|
||||
{
|
||||
ubtbcmfw_softc_p sc = NULL;
|
||||
u_int8_t buf[UBTBCMFW_BSIZE];
|
||||
usbd_xfer_handle xfer;
|
||||
usbd_status err;
|
||||
int n, tn, error = 0;
|
||||
|
||||
USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
|
||||
if (sc == NULL || sc->sc_dying)
|
||||
return (ENXIO);
|
||||
|
||||
if (UBTBCMFW_ENDPOINT(dev) != UBTBCMFW_INTR_IN)
|
||||
return (EOPNOTSUPP);
|
||||
if (sc->sc_intr_in_pipe == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
xfer = usbd_alloc_xfer(sc->sc_udev);
|
||||
if (xfer == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
sc->sc_refcnt ++;
|
||||
|
||||
while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
|
||||
tn = n;
|
||||
err = usbd_bulk_transfer(xfer, sc->sc_intr_in_pipe,
|
||||
USBD_SHORT_XFER_OK, USBD_DEFAULT_TIMEOUT,
|
||||
buf, &tn, "bcmrd");
|
||||
switch (err) {
|
||||
case USBD_NORMAL_COMPLETION:
|
||||
error = uiomove(buf, tn, uio);
|
||||
break;
|
||||
|
||||
case USBD_INTERRUPTED:
|
||||
error = EINTR;
|
||||
break;
|
||||
|
||||
case USBD_TIMEOUT:
|
||||
error = ETIMEDOUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (error != 0 || tn < n)
|
||||
break;
|
||||
}
|
||||
|
||||
usbd_free_xfer(xfer);
|
||||
|
||||
if (-- sc->sc_refcnt < 0)
|
||||
usb_detach_wakeup(USBDEV(sc->sc_dev));
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Write into the endpoint device
|
||||
* XXX FIXME softc locking
|
||||
*/
|
||||
|
||||
Static int
|
||||
ubtbcmfw_write(dev_t dev, struct uio *uio, int flag)
|
||||
{
|
||||
ubtbcmfw_softc_p sc = NULL;
|
||||
u_int8_t buf[UBTBCMFW_BSIZE];
|
||||
usbd_xfer_handle xfer;
|
||||
usbd_status err;
|
||||
int n, error = 0;
|
||||
|
||||
USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
|
||||
if (sc == NULL || sc->sc_dying)
|
||||
return (ENXIO);
|
||||
|
||||
if (UBTBCMFW_ENDPOINT(dev) != UBTBCMFW_BULK_OUT)
|
||||
return (EOPNOTSUPP);
|
||||
if (sc->sc_bulk_out_pipe == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
xfer = usbd_alloc_xfer(sc->sc_udev);
|
||||
if (xfer == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
sc->sc_refcnt ++;
|
||||
|
||||
while ((n = min(sizeof(buf), uio->uio_resid)) != 0) {
|
||||
error = uiomove(buf, n, uio);
|
||||
if (error != 0)
|
||||
break;
|
||||
|
||||
err = usbd_bulk_transfer(xfer, sc->sc_bulk_out_pipe,
|
||||
0, USBD_DEFAULT_TIMEOUT, buf, &n, "bcmwr");
|
||||
switch (err) {
|
||||
case USBD_NORMAL_COMPLETION:
|
||||
break;
|
||||
|
||||
case USBD_INTERRUPTED:
|
||||
error = EINTR;
|
||||
break;
|
||||
|
||||
case USBD_TIMEOUT:
|
||||
error = ETIMEDOUT;
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EIO;
|
||||
break;
|
||||
}
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
usbd_free_xfer(xfer);
|
||||
|
||||
if (-- sc->sc_refcnt < 0)
|
||||
usb_detach_wakeup(USBDEV(sc->sc_dev));
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Process ioctl on the endpoint device
|
||||
* XXX FIXME softc locking
|
||||
*/
|
||||
|
||||
Static int
|
||||
ubtbcmfw_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
|
||||
{
|
||||
ubtbcmfw_softc_p sc = NULL;
|
||||
int error = 0;
|
||||
|
||||
USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
|
||||
if (sc == NULL || sc->sc_dying)
|
||||
return (ENXIO);
|
||||
|
||||
if (UBTBCMFW_ENDPOINT(dev) != USB_CONTROL_ENDPOINT)
|
||||
return (EOPNOTSUPP);
|
||||
|
||||
sc->sc_refcnt ++;
|
||||
|
||||
switch (cmd) {
|
||||
case USB_GET_DEVICE_DESC:
|
||||
*(usb_device_descriptor_t *) data =
|
||||
*usbd_get_device_descriptor(sc->sc_udev);
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
if (-- sc->sc_refcnt < 0)
|
||||
usb_detach_wakeup(USBDEV(sc->sc_dev));
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Poll the endpoint device
|
||||
* XXX FIXME softc locking
|
||||
*/
|
||||
|
||||
Static int
|
||||
ubtbcmfw_poll(dev_t dev, int events, usb_proc_ptr p)
|
||||
{
|
||||
ubtbcmfw_softc_p sc = NULL;
|
||||
int revents = 0;
|
||||
|
||||
USB_GET_SC(ubtbcmfw, UBTBCMFW_UNIT(dev), sc);
|
||||
if (sc == NULL)
|
||||
return (ENXIO);
|
||||
|
||||
switch (UBTBCMFW_ENDPOINT(dev)) {
|
||||
case UBTBCMFW_INTR_IN:
|
||||
if (sc->sc_intr_in_pipe != NULL)
|
||||
revents |= events & (POLLIN | POLLRDNORM);
|
||||
else
|
||||
revents = ENXIO;
|
||||
break;
|
||||
|
||||
case UBTBCMFW_BULK_OUT:
|
||||
if (sc->sc_bulk_out_pipe != NULL)
|
||||
revents |= events & (POLLOUT | POLLWRNORM);
|
||||
else
|
||||
revents = ENXIO;
|
||||
break;
|
||||
|
||||
default:
|
||||
revents = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
|
||||
return (revents);
|
||||
}
|
||||
|
@ -1,6 +1,5 @@
|
||||
# $FreeBSD$
|
||||
|
||||
$Id: TODO,v 1.10 2002/09/06 21:03:57 max Exp $
|
||||
$Id: TODO,v 1.2 2003/04/26 22:36:29 max Exp $
|
||||
$FreeBSD$
|
||||
|
||||
FIXME/TODO list
|
||||
|
||||
@ -12,30 +11,18 @@ This is a list of open issues for HCI node
|
||||
it should be fine as long as Netgraph is SMP safe. Just need to
|
||||
verify it.
|
||||
|
||||
3) HCI QoS handling
|
||||
2) HCI QoS handling
|
||||
|
||||
Some code exists, but i have no idea how it should work. Will
|
||||
understand and fix later. I only have CSR based hardware and
|
||||
it does not support QoS.
|
||||
|
||||
4) Add proper handling for some HCI commands
|
||||
3) Add proper handling for some HCI commands
|
||||
|
||||
HCI testing commands is one example. Also might implement Host to
|
||||
Host Controller flow control (not sure if it is required).
|
||||
|
||||
5) Link security
|
||||
|
||||
Manage link keys and PINs. Options:
|
||||
|
||||
1) manage keys inside HCI node/unit itself
|
||||
2) use user space daemon.
|
||||
3) Mix option 1 and option 2.
|
||||
|
||||
6) Implement watchdog routine for HCI connections
|
||||
|
||||
Some code exists, but it is not used
|
||||
|
||||
7) Code cleanup
|
||||
4) Code cleanup
|
||||
|
||||
Verify return codes from functions
|
||||
Remove some waringns/errors
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_cmds.c,v 1.22 2002/10/30 00:18:18 max Exp $
|
||||
* $Id: ng_hci_cmds.c,v 1.3 2003/04/01 18:15:25 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_cmds.h,v 1.6 2002/09/04 21:36:51 max Exp $
|
||||
* $Id: ng_hci_cmds.h,v 1.1 2002/11/24 19:46:58 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_evnt.c,v 1.18 2002/11/12 22:35:39 max Exp $
|
||||
* $Id: ng_hci_evnt.c,v 1.5 2003/04/01 18:15:25 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -60,6 +60,7 @@ static int inquiry_result (ng_hci_unit_p, struct mbuf *);
|
||||
static int con_compl (ng_hci_unit_p, struct mbuf *);
|
||||
static int con_req (ng_hci_unit_p, struct mbuf *);
|
||||
static int discon_compl (ng_hci_unit_p, struct mbuf *);
|
||||
static int encryption_change (ng_hci_unit_p, struct mbuf *);
|
||||
static int read_remote_features_compl (ng_hci_unit_p, struct mbuf *);
|
||||
static int qos_setup_compl (ng_hci_unit_p, struct mbuf *);
|
||||
static int hardware_error (ng_hci_unit_p, struct mbuf *);
|
||||
@ -100,18 +101,15 @@ ng_hci_process_event(ng_hci_unit_p unit, struct mbuf *event)
|
||||
|
||||
switch (hdr->event) {
|
||||
case NG_HCI_EVENT_INQUIRY_COMPL:
|
||||
/* case NG_HCI_EVENT_MODE_CHANGE: */
|
||||
case NG_HCI_EVENT_RETURN_LINK_KEYS:
|
||||
case NG_HCI_EVENT_PIN_CODE_REQ:
|
||||
case NG_HCI_EVENT_LINK_KEY_REQ:
|
||||
case NG_HCI_EVENT_LINK_KEY_NOTIFICATION:
|
||||
case NG_HCI_EVENT_LOOPBACK_COMMAND:
|
||||
case NG_HCI_EVENT_AUTH_COMPL:
|
||||
case NG_HCI_EVENT_ENCRYPTION_CHANGE:
|
||||
case NG_HCI_EVENT_CHANGE_CON_LINK_KEY_COMPL:
|
||||
case NG_HCI_EVENT_MASTER_LINK_KEY_COMPL:
|
||||
case NG_HCI_EVENT_FLUSH_OCCUR: /* XXX Do we have to handle it? */
|
||||
/* case NG_HCI_EVENT_ROLE_CHANGE: */
|
||||
case NG_HCI_EVENT_MAX_SLOT_CHANGE:
|
||||
case NG_HCI_EVENT_CON_PKT_TYPE_CHANGED:
|
||||
case NG_HCI_EVENT_BT_LOGO:
|
||||
@ -138,6 +136,10 @@ ng_hci_process_event(ng_hci_unit_p unit, struct mbuf *event)
|
||||
error = discon_compl(unit, event);
|
||||
break;
|
||||
|
||||
case NG_HCI_EVENT_ENCRYPTION_CHANGE:
|
||||
error = encryption_change(unit, event);
|
||||
break;
|
||||
|
||||
case NG_HCI_EVENT_READ_REMOTE_FEATURES_COMPL:
|
||||
error = read_remote_features_compl(unit, event);
|
||||
break;
|
||||
@ -518,7 +520,8 @@ con_compl(ng_hci_unit_p unit, struct mbuf *event)
|
||||
lp->cp.con_handle = ep->con_handle;
|
||||
|
||||
lp->cp.settings = 0;
|
||||
if (unit->features[0] & NG_HCI_LMP_SWITCH)
|
||||
if ((unit->features[0] & NG_HCI_LMP_SWITCH) &&
|
||||
unit->role_switch)
|
||||
lp->cp.settings |= 0x1;
|
||||
if (unit->features[0] & NG_HCI_LMP_HOLD_MODE)
|
||||
lp->cp.settings |= 0x2;
|
||||
@ -666,6 +669,50 @@ discon_compl(ng_hci_unit_p unit, struct mbuf *event)
|
||||
return (error);
|
||||
} /* discon_compl */
|
||||
|
||||
/* Encryption change event */
|
||||
static int
|
||||
encryption_change(ng_hci_unit_p unit, struct mbuf *event)
|
||||
{
|
||||
ng_hci_encryption_change_ep *ep = NULL;
|
||||
ng_hci_unit_con_p con = NULL;
|
||||
int error = 0;
|
||||
|
||||
NG_HCI_M_PULLUP(event, sizeof(*ep));
|
||||
if (event == NULL)
|
||||
return (ENOBUFS);
|
||||
|
||||
ep = mtod(event, ng_hci_encryption_change_ep *);
|
||||
|
||||
if (ep->status == 0) {
|
||||
u_int16_t h = NG_HCI_CON_HANDLE(le16toh(ep->con_handle));
|
||||
|
||||
con = ng_hci_con_by_handle(unit, h);
|
||||
if (con == NULL) {
|
||||
NG_HCI_ALERT(
|
||||
"%s: %s - invalid connection handle=%d\n",
|
||||
__func__, NG_NODE_NAME(unit->node), h);
|
||||
error = ENOENT;
|
||||
} else if (con->link_type != NG_HCI_LINK_ACL) {
|
||||
NG_HCI_ALERT(
|
||||
"%s: %s - invalid link type=%d\n",
|
||||
__func__, NG_NODE_NAME(unit->node),
|
||||
con->link_type);
|
||||
error = EINVAL;
|
||||
} else if (ep->encryption_enable)
|
||||
/* XXX is that true? */
|
||||
con->encryption_mode = NG_HCI_ENCRYPTION_MODE_P2P;
|
||||
else
|
||||
con->encryption_mode = NG_HCI_ENCRYPTION_MODE_NONE;
|
||||
} else
|
||||
NG_HCI_ERR(
|
||||
"%s: %s - failed to change encryption mode, status=%d\n",
|
||||
__func__, NG_NODE_NAME(unit->node), ep->status);
|
||||
|
||||
NG_FREE_M(event);
|
||||
|
||||
return (error);
|
||||
} /* encryption_change */
|
||||
|
||||
/* Read remote feature complete event */
|
||||
static int
|
||||
read_remote_features_compl(ng_hci_unit_p unit, struct mbuf *event)
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_evnt.h,v 1.4 2002/09/04 21:36:51 max Exp $
|
||||
* $Id: ng_hci_evnt.h,v 1.1 2002/11/24 19:46:58 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_main.c,v 1.28 2002/11/12 22:35:40 max Exp $
|
||||
* $Id: ng_hci_main.c,v 1.2 2003/03/18 00:09:36 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -119,6 +119,7 @@ ng_hci_constructor(node_p node)
|
||||
|
||||
unit->link_policy_mask = 0xffff; /* Enable all supported modes */
|
||||
unit->packet_mask = 0xffff; /* Enable all packet types */
|
||||
unit->role_switch = 1; /* Enable role switch (if device supports it) */
|
||||
|
||||
/*
|
||||
* Set default buffer info
|
||||
@ -535,7 +536,6 @@ ng_hci_default_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
bcopy(&c->bdaddr, &e2->bdaddr,
|
||||
sizeof(e2->bdaddr));
|
||||
|
||||
|
||||
e2 ++;
|
||||
if (--s <= 0)
|
||||
break;
|
||||
@ -593,6 +593,31 @@ ng_hci_default_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
*((ng_hci_node_packet_mask_ep *)(msg->data));
|
||||
break;
|
||||
|
||||
/* Get role switch */
|
||||
case NGM_HCI_NODE_GET_ROLE_SWITCH:
|
||||
NG_MKRESPONSE(rsp, msg, sizeof(unit->role_switch),
|
||||
M_NOWAIT);
|
||||
if (rsp == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
*((ng_hci_node_role_switch_ep *)(rsp->data)) =
|
||||
unit->role_switch;
|
||||
break;
|
||||
|
||||
/* Set role switch */
|
||||
case NGM_HCI_NODE_SET_ROLE_SWITCH:
|
||||
if (msg->header.arglen !=
|
||||
sizeof(ng_hci_node_role_switch_ep)) {
|
||||
error = EMSGSIZE;
|
||||
break;
|
||||
}
|
||||
|
||||
unit->role_switch =
|
||||
*((ng_hci_node_role_switch_ep *)(msg->data));
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_misc.c,v 1.18 2002/10/30 00:18:19 max Exp $
|
||||
* $Id: ng_hci_misc.c,v 1.4 2003/04/26 22:35:21 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -53,7 +53,6 @@
|
||||
|
||||
static void ng_hci_command_queue_timeout (void *);
|
||||
static void ng_hci_con_queue_timeout (void *);
|
||||
static void ng_hci_con_queue_watchdog_timeout (void *);
|
||||
|
||||
/*
|
||||
* Give packet to RAW hook
|
||||
@ -270,7 +269,6 @@ ng_hci_new_con(ng_hci_unit_p unit, int link_type)
|
||||
NG_BT_ITEMQ_INIT(&con->conq, num_pkts);
|
||||
|
||||
callout_handle_init(&con->con_timo);
|
||||
callout_handle_init(&con->watchdog_timo);
|
||||
|
||||
LIST_INSERT_HEAD(&unit->con_list, con, next);
|
||||
}
|
||||
@ -291,9 +289,6 @@ ng_hci_free_con(ng_hci_unit_con_p con)
|
||||
if (con->flags & NG_HCI_CON_TIMEOUT_PENDING)
|
||||
ng_hci_con_untimeout(con);
|
||||
|
||||
if (con->flags & NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING)
|
||||
ng_hci_con_watchdog_untimeout(con);
|
||||
|
||||
/*
|
||||
* If we have pending packets then assume that Host Controller has
|
||||
* flushed these packets and we can free them too
|
||||
@ -442,59 +437,6 @@ ng_hci_con_queue_timeout(void *context)
|
||||
NG_NODE_UNREF(node);
|
||||
} /* ng_hci_con_queue_timeout */
|
||||
|
||||
/*
|
||||
* Set HCI connection watchdog timeout
|
||||
*/
|
||||
|
||||
void
|
||||
ng_hci_con_watchdog_timeout(ng_hci_unit_con_p con)
|
||||
{
|
||||
if (!(con->flags & NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING)) {
|
||||
NG_NODE_REF(con->unit->node);
|
||||
con->flags |= NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING;
|
||||
con->watchdog_timo = timeout(ng_hci_con_queue_watchdog_timeout,
|
||||
con, bluetooth_hci_watchdog_timeout());
|
||||
} else
|
||||
KASSERT(0,
|
||||
("%s: %s - Duplicated connection watchdog timeout!\n",
|
||||
__func__, NG_NODE_NAME(con->unit->node)));
|
||||
} /* ng_hci_con_watchdog_timeout */
|
||||
|
||||
/*
|
||||
* Unset HCI connection watchdog timeout
|
||||
*/
|
||||
|
||||
void
|
||||
ng_hci_con_watchdog_untimeout(ng_hci_unit_con_p con)
|
||||
{
|
||||
if (con->flags & NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING) {
|
||||
con->flags &= ~NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING;
|
||||
untimeout(ng_hci_con_queue_watchdog_timeout, con,
|
||||
con->watchdog_timo);
|
||||
NG_NODE_UNREF(con->unit->node);
|
||||
} else
|
||||
KASSERT(0,
|
||||
("%s: %s - No connection watchdog timeout!\n",
|
||||
__func__, NG_NODE_NAME(con->unit->node)));
|
||||
} /* ng_hci_con_watchdog_untimeout */
|
||||
|
||||
/*
|
||||
* OK timeout has happend, so queue timeout processing function
|
||||
*/
|
||||
|
||||
static void
|
||||
ng_hci_con_queue_watchdog_timeout(void *context)
|
||||
{
|
||||
ng_hci_unit_con_p con = (ng_hci_unit_con_p) context;
|
||||
node_p node = con->unit->node;
|
||||
|
||||
if (NG_NODE_IS_VALID(node))
|
||||
ng_send_fn(node, NULL, &ng_hci_process_con_watchdog_timeout,
|
||||
con, 0);
|
||||
|
||||
NG_NODE_UNREF(node);
|
||||
} /* ng_hci_con_queue_watchdog_timeout */
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Convert numeric error code/reason to a string
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_misc.h,v 1.8 2002/09/04 21:36:52 max Exp $
|
||||
* $Id: ng_hci_misc.h,v 1.2 2003/04/26 22:35:21 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -51,8 +51,6 @@ void ng_hci_command_timeout (ng_hci_unit_p);
|
||||
void ng_hci_command_untimeout (ng_hci_unit_p);
|
||||
void ng_hci_con_timeout (ng_hci_unit_con_p);
|
||||
void ng_hci_con_untimeout (ng_hci_unit_con_p);
|
||||
void ng_hci_con_watchdog_timeout (ng_hci_unit_con_p);
|
||||
void ng_hci_con_watchdog_untimeout (ng_hci_unit_con_p);
|
||||
|
||||
#endif /* ndef _NETGRAPH_HCI_MISC_H_ */
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_prse.h,v 1.9 2002/11/12 22:35:40 max Exp $
|
||||
* $Id: ng_hci_prse.h,v 1.2 2003/03/18 00:09:36 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -196,6 +196,20 @@ static const struct ng_cmdlist ng_hci_cmdlist[] = {
|
||||
&ng_parse_uint16_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_HCI_COOKIE,
|
||||
NGM_HCI_NODE_GET_ROLE_SWITCH,
|
||||
"get_role_sw",
|
||||
NULL,
|
||||
&ng_parse_uint16_type
|
||||
},
|
||||
{
|
||||
NGM_HCI_COOKIE,
|
||||
NGM_HCI_NODE_SET_ROLE_SWITCH,
|
||||
"set_role_sw",
|
||||
&ng_parse_uint16_type,
|
||||
NULL
|
||||
},
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_ulpi.c,v 1.14 2002/11/12 22:35:40 max Exp $
|
||||
* $Id: ng_hci_ulpi.c,v 1.6 2003/04/26 22:35:21 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -132,30 +132,22 @@ ng_hci_lp_acl_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
|
||||
* 2) We do have connection descriptor. We need to check connection
|
||||
* state:
|
||||
*
|
||||
* 2.1) NG_HCI_CON_CLOSED mean we are in the process of closing
|
||||
* connection to the remote unit. We will reject connection
|
||||
* request until connection is closed.
|
||||
*
|
||||
* 2.2) NG_HCI_CON_W4_LP_CON_RSP means that we are in the middle of
|
||||
* 2.1) NG_HCI_CON_W4_LP_CON_RSP means that we are in the middle of
|
||||
* accepting connection from the remote unit. This is a race
|
||||
* condition. We will ignore this message.
|
||||
*
|
||||
* 2.3) NG_HCI_CON_W4_CONN_COMPLETE means that upper layer already
|
||||
* 2.2) NG_HCI_CON_W4_CONN_COMPLETE means that upper layer already
|
||||
* requested connection or we just accepted it. In any case
|
||||
* all we need to do here is set appropriate notification bit
|
||||
* and wait.
|
||||
*
|
||||
* 2.4) NG_HCI_CON_OPEN means connection is open. Just reply back
|
||||
* 2.3) NG_HCI_CON_OPEN means connection is open. Just reply back
|
||||
* and let upper layer know that we have connection already.
|
||||
*/
|
||||
|
||||
con = ng_hci_con_by_bdaddr(unit, &ep->bdaddr, NG_HCI_LINK_ACL);
|
||||
if (con != NULL) {
|
||||
switch (con->state) {
|
||||
case NG_HCI_CON_CLOSED:
|
||||
error = EBUSY;
|
||||
break;
|
||||
|
||||
case NG_HCI_CON_W4_LP_CON_RSP: /* XXX */
|
||||
error = EALREADY;
|
||||
break;
|
||||
@ -255,12 +247,14 @@ ng_hci_lp_acl_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
|
||||
req->cp.pkt_type |= (NG_HCI_PKT_DM5|NG_HCI_PKT_DH5);
|
||||
|
||||
req->cp.pkt_type &= unit->packet_mask;
|
||||
if (req->cp.pkt_type == 0)
|
||||
if ((req->cp.pkt_type & (NG_HCI_PKT_DM1|NG_HCI_PKT_DH1|
|
||||
NG_HCI_PKT_DM3|NG_HCI_PKT_DH3|
|
||||
NG_HCI_PKT_DM5|NG_HCI_PKT_DH5)) == 0)
|
||||
req->cp.pkt_type = (NG_HCI_PKT_DM1|NG_HCI_PKT_DH1);
|
||||
|
||||
req->cp.pkt_type = htole16(req->cp.pkt_type);
|
||||
|
||||
if (unit->features[0] & NG_HCI_LMP_SWITCH)
|
||||
if ((unit->features[0] & NG_HCI_LMP_SWITCH) && unit->role_switch)
|
||||
req->cp.accept_role_switch = 1;
|
||||
else
|
||||
req->cp.accept_role_switch = 0;
|
||||
@ -376,8 +370,6 @@ ng_hci_lp_sco_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
|
||||
*
|
||||
* 2.2) NG_HCI_CON_W4_CONN_COMPLETE means upper layer already requested
|
||||
* connection or we just accepted it.
|
||||
*
|
||||
* XXX FIXME what to do with connection(s) in CLOSED state?
|
||||
*/
|
||||
|
||||
LIST_FOREACH(sco_con, &unit->con_list, next)
|
||||
@ -450,7 +442,9 @@ ng_hci_lp_sco_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
|
||||
req->cp.pkt_type |= NG_HCI_PKT_HV3;
|
||||
|
||||
req->cp.pkt_type &= unit->packet_mask;
|
||||
if (req->cp.pkt_type == 0)
|
||||
if ((req->cp.pkt_type & (NG_HCI_PKT_HV1|
|
||||
NG_HCI_PKT_HV2|
|
||||
NG_HCI_PKT_HV3)) == 0)
|
||||
req->cp.pkt_type = NG_HCI_PKT_HV1;
|
||||
|
||||
req->cp.pkt_type = htole16(req->cp.pkt_type);
|
||||
@ -479,12 +473,6 @@ ng_hci_lp_sco_con_req(ng_hci_unit_p unit, item_p item, hook_p hook)
|
||||
|
||||
/*
|
||||
* Process LP_DisconnectReq event from the upper layer protocol
|
||||
*
|
||||
* XXX XXX XXX
|
||||
*
|
||||
* NOTE: This is NOT defined by Bluetooth specification (why?) But i think
|
||||
* this might be useful (at least for testing), so please do not depend on
|
||||
* this interface.
|
||||
*/
|
||||
|
||||
int
|
||||
@ -561,13 +549,6 @@ ng_hci_lp_discon_req(ng_hci_unit_p unit, item_p item, hook_p hook)
|
||||
req->cp.con_handle = htole16(ep->con_handle);
|
||||
req->cp.reason = ep->reason;
|
||||
|
||||
/*
|
||||
* Adjust connection state
|
||||
*/
|
||||
|
||||
con->state = NG_HCI_CON_CLOSED;
|
||||
ng_hci_con_timeout(con);
|
||||
|
||||
/*
|
||||
* Queue and send HCI command
|
||||
*/
|
||||
@ -813,16 +794,15 @@ ng_hci_lp_con_rsp(ng_hci_unit_p unit, item_p item, hook_p hook)
|
||||
sizeof(req->cp.acc.bdaddr));
|
||||
|
||||
/*
|
||||
* XXX should be configurable?
|
||||
*
|
||||
* We are accepting connection, so if we support role
|
||||
* switch then set role to NG_HCI_ROLE_MASTER and let
|
||||
* LM peform role switch. Otherwise it is probably
|
||||
* makes sense to remain slave. In this case LM WILL
|
||||
* NOT perform role switch.
|
||||
* switch and role switch was enabled then set role to
|
||||
* NG_HCI_ROLE_MASTER and let LM peform role switch.
|
||||
* Otherwise we remain slave. In this case LM WILL NOT
|
||||
* perform role switch.
|
||||
*/
|
||||
|
||||
if (unit->features[0] & NG_HCI_LMP_SWITCH)
|
||||
if ((unit->features[0] & NG_HCI_LMP_SWITCH) &&
|
||||
unit->role_switch)
|
||||
req->cp.acc.role = NG_HCI_ROLE_MASTER;
|
||||
else
|
||||
req->cp.acc.role = NG_HCI_ROLE_SLAVE;
|
||||
@ -1183,24 +1163,16 @@ ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
* We expect to receive connection timeout in one of the following
|
||||
* states:
|
||||
*
|
||||
* 1) NG_HCI_CON_CLOSED means that upper layer has requested disconnect
|
||||
* via LP_DISCON_REQ and we have not received Disconnect_Complete
|
||||
* event. In this case we will send LP_DISCON_IND to upper layer.
|
||||
*
|
||||
* 2) NG_HCI_CON_W4_LP_CON_RSP means that upper layer has not responded
|
||||
* 1) NG_HCI_CON_W4_LP_CON_RSP means that upper layer has not responded
|
||||
* to our LP_CON_IND. Do nothing and destroy connection. Remote peer
|
||||
* most likely already gave up on us.
|
||||
*
|
||||
* 3) NG_HCI_CON_W4_CONN_COMPLETE means upper layer requested connection
|
||||
* 2) NG_HCI_CON_W4_CONN_COMPLETE means upper layer requested connection
|
||||
* (or we in the process of accepting it) and baseband has timedout
|
||||
* on us. Inform upper layers and send LP_CON_CFM.
|
||||
*/
|
||||
|
||||
switch (con->state) {
|
||||
case NG_HCI_CON_CLOSED:
|
||||
ng_hci_lp_discon_ind(con, 0x16);
|
||||
break;
|
||||
|
||||
case NG_HCI_CON_W4_LP_CON_RSP:
|
||||
break;
|
||||
|
||||
@ -1218,63 +1190,3 @@ ng_hci_process_con_timeout(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
ng_hci_free_con(con);
|
||||
} /* ng_hci_process_con_timeout */
|
||||
|
||||
/*
|
||||
* Process connection watchdog timeout
|
||||
*/
|
||||
|
||||
void
|
||||
ng_hci_process_con_watchdog_timeout(node_p node, hook_p hook,
|
||||
void *arg1, int arg2)
|
||||
{
|
||||
ng_hci_unit_con_p con = (ng_hci_unit_con_p) arg1;
|
||||
struct discon_req {
|
||||
ng_hci_cmd_pkt_t hdr;
|
||||
ng_hci_discon_cp cp;
|
||||
} __attribute__ ((packed)) *req = NULL;
|
||||
struct mbuf *m = NULL;
|
||||
|
||||
KASSERT((con->state == NG_HCI_CON_OPEN),
|
||||
("%s: %s - invalid connection state=%d, handle=%d\n",
|
||||
__func__, NG_NODE_NAME(node), con->state, con->con_handle));
|
||||
|
||||
KASSERT((con->flags & NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING),
|
||||
("%s: %s - No connection watchdog timeout!\n",
|
||||
__func__, NG_NODE_NAME(node)));
|
||||
|
||||
con->flags &= ~NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING;
|
||||
|
||||
/*
|
||||
* Create HCI command
|
||||
*/
|
||||
|
||||
MGETHDR(m, M_DONTWAIT, MT_DATA);
|
||||
if (m == NULL)
|
||||
return; /* XXX this is bad */
|
||||
|
||||
m->m_pkthdr.len = m->m_len = sizeof(*req);
|
||||
req = mtod(m, struct discon_req *);
|
||||
req->hdr.type = NG_HCI_CMD_PKT;
|
||||
req->hdr.length = sizeof(req->cp);
|
||||
req->hdr.opcode = htole16(NG_HCI_OPCODE(NG_HCI_OGF_LINK_CONTROL,
|
||||
NG_HCI_OCF_DISCON));
|
||||
|
||||
req->cp.con_handle = htole16(con->con_handle);
|
||||
req->cp.reason = 0x13; /* User ended connection */
|
||||
|
||||
/*
|
||||
* Queue and send HCI command
|
||||
*/
|
||||
|
||||
NG_BT_MBUFQ_ENQUEUE(&con->unit->cmdq, m);
|
||||
if (!(con->unit->state & NG_HCI_UNIT_COMMAND_PENDING))
|
||||
ng_hci_send_command(con->unit);
|
||||
|
||||
/*
|
||||
* Send LP_DISCON_IND to the upper layers
|
||||
* Connection terminated by local host
|
||||
*/
|
||||
|
||||
ng_hci_lp_discon_ind(con, 0x16);
|
||||
ng_hci_free_con(con);
|
||||
} /* ng_hci_process_con_watchdog_timeout */
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_ulpi.h,v 1.4 2002/09/04 21:36:52 max Exp $
|
||||
* $Id: ng_hci_ulpi.h,v 1.2 2003/04/26 22:35:21 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -47,7 +47,6 @@ int ng_hci_lp_qos_cfm (ng_hci_unit_con_p, int);
|
||||
int ng_hci_lp_qos_ind (ng_hci_unit_con_p);
|
||||
|
||||
void ng_hci_process_con_timeout (node_p, hook_p, void *, int);
|
||||
void ng_hci_process_con_watchdog_timeout (node_p, hook_p, void *, int);
|
||||
|
||||
#endif /* ndef _NETGRAPH_HCI_ULPI_H_ */
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci_var.h,v 1.14 2002/11/12 22:35:40 max Exp $
|
||||
* $Id: ng_hci_var.h,v 1.3 2003/04/26 22:35:21 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -133,6 +133,7 @@ typedef struct ng_hci_unit {
|
||||
|
||||
ng_hci_node_link_policy_mask_ep link_policy_mask; /* link policy mask */
|
||||
ng_hci_node_packet_mask_ep packet_mask; /* packet mask */
|
||||
ng_hci_node_role_switch_ep role_switch; /* role switch */
|
||||
|
||||
ng_hci_node_stat_ep stat; /* statistic */
|
||||
#define NG_HCI_STAT_CMD_SENT(s) (s).cmd_sent ++
|
||||
@ -171,9 +172,8 @@ typedef struct ng_hci_unit_con {
|
||||
u_int16_t state; /* con. state */
|
||||
u_int16_t flags; /* con. flags */
|
||||
#define NG_HCI_CON_TIMEOUT_PENDING (1 << 0)
|
||||
#define NG_HCI_CON_WATCHDOG_TIMEOUT_PENDING (1 << 1)
|
||||
#define NG_HCI_CON_NOTIFY_ACL (1 << 2)
|
||||
#define NG_HCI_CON_NOTIFY_SCO (1 << 3)
|
||||
#define NG_HCI_CON_NOTIFY_ACL (1 << 1)
|
||||
#define NG_HCI_CON_NOTIFY_SCO (1 << 2)
|
||||
|
||||
bdaddr_t bdaddr; /* remote address */
|
||||
u_int16_t con_handle; /* con. handle */
|
||||
@ -184,7 +184,6 @@ typedef struct ng_hci_unit_con {
|
||||
u_int8_t role; /* MASTER/SLAVE */
|
||||
|
||||
struct callout_handle con_timo; /* con. timeout */
|
||||
struct callout_handle watchdog_timo; /* watch dog */
|
||||
|
||||
int pending; /* # of data pkts */
|
||||
ng_bt_itemq_t conq; /* con. queue */
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_bluetooth.h,v 1.1.1.1 2002/09/04 21:47:41 max Exp $
|
||||
* $Id: ng_bluetooth.h,v 1.4 2003/04/26 22:32:34 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -47,6 +47,7 @@
|
||||
SYSCTL_DECL(_net_bluetooth);
|
||||
SYSCTL_DECL(_net_bluetooth_hci);
|
||||
SYSCTL_DECL(_net_bluetooth_l2cap);
|
||||
SYSCTL_DECL(_net_bluetooth_rfcomm);
|
||||
#endif /* SYSCTL_DECL */
|
||||
|
||||
/*
|
||||
@ -84,7 +85,7 @@ typedef struct ng_bt_mbufq * ng_bt_mbufq_p;
|
||||
|
||||
#define NG_BT_MBUFQ_LEN(q) (q)->len
|
||||
|
||||
#define NG_BT_MBUFQ_FULL(q) (q)->len >= (q)->maxlen
|
||||
#define NG_BT_MBUFQ_FULL(q) ((q)->len >= (q)->maxlen)
|
||||
|
||||
#define NG_BT_MBUFQ_DROP(q) (q)->drops ++
|
||||
|
||||
@ -223,7 +224,6 @@ typedef struct ng_bt_itemq * ng_bt_itemq_p;
|
||||
|
||||
u_int32_t bluetooth_hci_command_timeout (void);
|
||||
u_int32_t bluetooth_hci_connect_timeout (void);
|
||||
u_int32_t bluetooth_hci_watchdog_timeout (void);
|
||||
u_int32_t bluetooth_hci_max_neighbor_age (void);
|
||||
u_int32_t bluetooth_l2cap_rtx_timeout (void);
|
||||
u_int32_t bluetooth_l2cap_ertx_timeout (void);
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_bt3c.h,v 1.2 2002/11/12 00:51:45 max Exp $
|
||||
* $Id: ng_bt3c.h,v 1.1 2002/11/24 19:47:05 max Exp $
|
||||
* $FreeBSD$
|
||||
*
|
||||
* XXX XXX XX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_btsocket.h,v 1.7 2002/11/12 22:31:39 max Exp $
|
||||
* $Id: ng_btsocket.h,v 1.8 2003/04/26 22:32:10 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -45,6 +45,7 @@
|
||||
|
||||
#define BLUETOOTH_PROTO_HCI 134 /* HCI protocol number */
|
||||
#define BLUETOOTH_PROTO_L2CAP 135 /* L2CAP protocol number */
|
||||
#define BLUETOOTH_PROTO_RFCOMM 136 /* RFCOMM protocol number */
|
||||
|
||||
/*
|
||||
* XXX FIXME: probably does not belong here
|
||||
@ -82,7 +83,6 @@ struct ng_btsocket_hci_raw_filter {
|
||||
|
||||
/* Get state */
|
||||
struct ng_btsocket_hci_raw_node_state {
|
||||
char hci_node[16];
|
||||
ng_hci_node_state_ep state;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_STATE \
|
||||
@ -90,16 +90,11 @@ struct ng_btsocket_hci_raw_node_state {
|
||||
struct ng_btsocket_hci_raw_node_state)
|
||||
|
||||
/* Initialize */
|
||||
struct ng_btsocket_hci_raw_node_init {
|
||||
char hci_node[16];
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_INIT \
|
||||
_IOWR('b', NGM_HCI_NODE_INIT, \
|
||||
struct ng_btsocket_hci_raw_node_init)
|
||||
_IO('b', NGM_HCI_NODE_INIT)
|
||||
|
||||
/* Get/Set debug level */
|
||||
struct ng_btsocket_hci_raw_node_debug {
|
||||
char hci_node[16];
|
||||
ng_hci_node_debug_ep debug;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_DEBUG \
|
||||
@ -111,7 +106,6 @@ struct ng_btsocket_hci_raw_node_debug {
|
||||
|
||||
/* Get buffer info */
|
||||
struct ng_btsocket_hci_raw_node_buffer {
|
||||
char hci_node[16];
|
||||
ng_hci_node_buffer_ep buffer;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_BUFFER \
|
||||
@ -120,7 +114,6 @@ struct ng_btsocket_hci_raw_node_buffer {
|
||||
|
||||
/* Get BD_ADDR */
|
||||
struct ng_btsocket_hci_raw_node_bdaddr {
|
||||
char hci_node[16];
|
||||
bdaddr_t bdaddr;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_BDADDR \
|
||||
@ -129,7 +122,6 @@ struct ng_btsocket_hci_raw_node_bdaddr {
|
||||
|
||||
/* Get features */
|
||||
struct ng_btsocket_hci_raw_node_features {
|
||||
char hci_node [16];
|
||||
u_int8_t features[NG_HCI_FEATURES_SIZE];
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_FEATURES \
|
||||
@ -138,7 +130,6 @@ struct ng_btsocket_hci_raw_node_features {
|
||||
|
||||
/* Get stat */
|
||||
struct ng_btsocket_hci_raw_node_stat {
|
||||
char hci_node[16];
|
||||
ng_hci_node_stat_ep stat;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_STAT \
|
||||
@ -146,24 +137,15 @@ struct ng_btsocket_hci_raw_node_stat {
|
||||
struct ng_btsocket_hci_raw_node_stat)
|
||||
|
||||
/* Reset stat */
|
||||
struct ng_btsocket_hci_raw_node_reset_stat {
|
||||
char hci_node[16];
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_RESET_STAT \
|
||||
_IOWR('b', NGM_HCI_NODE_RESET_STAT, \
|
||||
struct ng_btsocket_hci_raw_node_reset_stat)
|
||||
_IO('b', NGM_HCI_NODE_RESET_STAT)
|
||||
|
||||
/* Flush neighbor cache */
|
||||
struct ng_btsocket_hci_raw_node_flush_neighbor_cache {
|
||||
char hci_node[16];
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE \
|
||||
_IOWR('b', NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE, \
|
||||
struct ng_btsocket_hci_raw_node_flush_neighbor_cache)
|
||||
_IO('b', NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE)
|
||||
|
||||
/* Get neighbor cache */
|
||||
struct ng_btsocket_hci_raw_node_neighbor_cache {
|
||||
char hci_node[16];
|
||||
u_int32_t num_entries;
|
||||
ng_hci_node_neighbor_cache_entry_ep *entries;
|
||||
};
|
||||
@ -173,7 +155,6 @@ struct ng_btsocket_hci_raw_node_neighbor_cache {
|
||||
|
||||
/* Get connection list */
|
||||
struct ng_btsocket_hci_raw_con_list {
|
||||
char hci_node[16];
|
||||
u_int32_t num_connections;
|
||||
ng_hci_node_con_ep *connections;
|
||||
};
|
||||
@ -183,7 +164,6 @@ struct ng_btsocket_hci_raw_con_list {
|
||||
|
||||
/* Get/Set link policy settings mask */
|
||||
struct ng_btsocket_hci_raw_node_link_policy_mask {
|
||||
char hci_node[16];
|
||||
ng_hci_node_link_policy_mask_ep policy_mask;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK \
|
||||
@ -195,7 +175,6 @@ struct ng_btsocket_hci_raw_node_link_policy_mask {
|
||||
|
||||
/* Get/Set packet mask */
|
||||
struct ng_btsocket_hci_raw_node_packet_mask {
|
||||
char hci_node[16];
|
||||
ng_hci_node_packet_mask_ep packet_mask;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_PACKET_MASK \
|
||||
@ -205,6 +184,17 @@ struct ng_btsocket_hci_raw_node_packet_mask {
|
||||
_IOWR('b', NGM_HCI_NODE_SET_PACKET_MASK, \
|
||||
struct ng_btsocket_hci_raw_node_packet_mask)
|
||||
|
||||
/* Get/Set role switch */
|
||||
struct ng_btsocket_hci_raw_node_role_switch {
|
||||
ng_hci_node_role_switch_ep role_switch;
|
||||
};
|
||||
#define SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH \
|
||||
_IOWR('b', NGM_HCI_NODE_GET_ROLE_SWITCH, \
|
||||
struct ng_btsocket_hci_raw_node_role_switch)
|
||||
#define SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH \
|
||||
_IOWR('b', NGM_HCI_NODE_SET_ROLE_SWITCH, \
|
||||
struct ng_btsocket_hci_raw_node_role_switch)
|
||||
|
||||
/*
|
||||
* XXX FIXME: probably does not belong here
|
||||
* Bluetooth version of struct sockaddr for L2CAP sockets (RAW and SEQPACKET)
|
||||
@ -232,9 +222,6 @@ struct sockaddr_l2cap {
|
||||
|
||||
/* Ping */
|
||||
struct ng_btsocket_l2cap_raw_ping {
|
||||
bdaddr_t bdaddr[2];
|
||||
#define echo_src bdaddr[0]
|
||||
#define echo_dst bdaddr[1]
|
||||
u_int32_t result;
|
||||
u_int32_t echo_size;
|
||||
u_int8_t *echo_data;
|
||||
@ -245,9 +232,6 @@ struct ng_btsocket_l2cap_raw_ping {
|
||||
|
||||
/* Get info */
|
||||
struct ng_btsocket_l2cap_raw_get_info {
|
||||
bdaddr_t bdaddr[2];
|
||||
#define info_src bdaddr[0]
|
||||
#define info_dst bdaddr[1]
|
||||
u_int32_t result;
|
||||
u_int32_t info_type;
|
||||
u_int32_t info_size;
|
||||
@ -259,7 +243,6 @@ struct ng_btsocket_l2cap_raw_get_info {
|
||||
|
||||
/* Get flags */
|
||||
struct ng_btsocket_l2cap_raw_node_flags {
|
||||
bdaddr_t src;
|
||||
ng_l2cap_node_flags_ep flags;
|
||||
};
|
||||
#define SIOC_L2CAP_NODE_GET_FLAGS \
|
||||
@ -268,7 +251,6 @@ struct ng_btsocket_l2cap_raw_node_flags {
|
||||
|
||||
/* Get/Set debug level */
|
||||
struct ng_btsocket_l2cap_raw_node_debug {
|
||||
bdaddr_t src;
|
||||
ng_l2cap_node_debug_ep debug;
|
||||
};
|
||||
#define SIOC_L2CAP_NODE_GET_DEBUG \
|
||||
@ -280,7 +262,6 @@ struct ng_btsocket_l2cap_raw_node_debug {
|
||||
|
||||
/* Get connection list */
|
||||
struct ng_btsocket_l2cap_raw_con_list {
|
||||
bdaddr_t src;
|
||||
u_int32_t num_connections;
|
||||
ng_l2cap_node_con_ep *connections;
|
||||
};
|
||||
@ -290,7 +271,6 @@ struct ng_btsocket_l2cap_raw_con_list {
|
||||
|
||||
/* Get channel list */
|
||||
struct ng_btsocket_l2cap_raw_chan_list {
|
||||
bdaddr_t src;
|
||||
u_int32_t num_channels;
|
||||
ng_l2cap_node_chan_ep *channels;
|
||||
};
|
||||
@ -298,6 +278,46 @@ struct ng_btsocket_l2cap_raw_chan_list {
|
||||
_IOWR('b', NGM_L2CAP_NODE_GET_CHAN_LIST, \
|
||||
struct ng_btsocket_l2cap_raw_chan_list)
|
||||
|
||||
/* Get/Set auto disconnect timeout */
|
||||
struct ng_btsocket_l2cap_raw_auto_discon_timo
|
||||
{
|
||||
ng_l2cap_node_auto_discon_ep timeout;
|
||||
};
|
||||
#define SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO \
|
||||
_IOWR('b', NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO, \
|
||||
struct ng_btsocket_l2cap_raw_auto_discon_timo)
|
||||
#define SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO \
|
||||
_IOWR('b', NGM_L2CAP_NODE_SET_AUTO_DISCON_TIMO, \
|
||||
struct ng_btsocket_l2cap_raw_auto_discon_timo)
|
||||
|
||||
/*
|
||||
* XXX FIXME: probably does not belong here
|
||||
* Bluetooth version of struct sockaddr for RFCOMM sockets (STREAM)
|
||||
*/
|
||||
|
||||
struct sockaddr_rfcomm {
|
||||
u_char rfcomm_len; /* total length */
|
||||
u_char rfcomm_family; /* address family */
|
||||
bdaddr_t rfcomm_bdaddr; /* address */
|
||||
u_int8_t rfcomm_channel; /* channel */
|
||||
};
|
||||
|
||||
/* Flow control information */
|
||||
struct ng_btsocket_rfcomm_fc_info {
|
||||
u_int8_t lmodem; /* modem signals (local) */
|
||||
u_int8_t rmodem; /* modem signals (remote) */
|
||||
u_int8_t tx_cred; /* TX credits */
|
||||
u_int8_t rx_cred; /* RX credits */
|
||||
u_int8_t cfc; /* credit flow control */
|
||||
u_int8_t reserved;
|
||||
};
|
||||
|
||||
/* STREAM RFCOMM socket options */
|
||||
#define SOL_RFCOMM 0x0816 /* socket options level */
|
||||
|
||||
#define SO_RFCOMM_MTU 1 /* get channel MTU */
|
||||
#define SO_RFCOMM_FC_INFO 2 /* get flow control information */
|
||||
|
||||
/*
|
||||
* Netgraph node type name and cookie
|
||||
*/
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_btsocket_hci_raw.h,v 1.2 2002/09/16 19:46:02 max Exp $
|
||||
* $Id: ng_btsocket_hci_raw.h,v 1.3 2003/03/25 23:53:32 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -41,13 +41,15 @@
|
||||
|
||||
struct ng_btsocket_hci_raw_pcb {
|
||||
struct socket *so; /* socket */
|
||||
int flags; /* flags */
|
||||
u_int32_t flags; /* flags */
|
||||
#define NG_BTSOCKET_HCI_RAW_DIRECTION (1 << 0)
|
||||
#define NG_BTSOCKET_HCI_RAW_PRIVILEGED (1 << 1)
|
||||
struct sockaddr_hci addr; /* local address */
|
||||
struct ng_btsocket_hci_raw_filter filter; /* filter */
|
||||
u_int32_t token; /* message token */
|
||||
struct ng_mesg *msg; /* message */
|
||||
LIST_ENTRY(ng_btsocket_hci_raw_pcb) next; /* link to next */
|
||||
struct mtx pcb_mtx; /* pcb mutex */
|
||||
};
|
||||
typedef struct ng_btsocket_hci_raw_pcb ng_btsocket_hci_raw_pcb_t;
|
||||
typedef struct ng_btsocket_hci_raw_pcb * ng_btsocket_hci_raw_pcb_p;
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_btsocket_l2cap.h,v 1.3 2002/09/22 18:23:31 max Exp $
|
||||
* $Id: ng_btsocket_l2cap.h,v 1.4 2003/03/25 23:53:33 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -42,7 +42,7 @@ struct ng_message;
|
||||
struct ng_btsocket_l2cap_rtentry {
|
||||
bdaddr_t src; /* source BD_ADDR */
|
||||
struct ng_hook *hook; /* downstream hook */
|
||||
LIST_ENTRY(ng_btsocket_l2cap_rtentry) next; /* linkt to next */
|
||||
LIST_ENTRY(ng_btsocket_l2cap_rtentry) next; /* link to next */
|
||||
};
|
||||
typedef struct ng_btsocket_l2cap_rtentry ng_btsocket_l2cap_rtentry_t;
|
||||
typedef struct ng_btsocket_l2cap_rtentry * ng_btsocket_l2cap_rtentry_p;
|
||||
@ -63,12 +63,18 @@ typedef struct ng_btsocket_l2cap_rtentry * ng_btsocket_l2cap_rtentry_p;
|
||||
struct ng_btsocket_l2cap_raw_pcb {
|
||||
struct socket *so; /* socket */
|
||||
|
||||
u_int32_t flags; /* flags */
|
||||
#define NG_BTSOCKET_L2CAP_RAW_PRIVILEGED (1 << 0)
|
||||
|
||||
bdaddr_t src; /* source address */
|
||||
bdaddr_t dst; /* dest address */
|
||||
ng_btsocket_l2cap_rtentry_p rt; /* routing info */
|
||||
|
||||
u_int32_t token; /* message token */
|
||||
struct ng_mesg *msg; /* message */
|
||||
|
||||
struct mtx pcb_mtx; /* pcb mutex */
|
||||
|
||||
LIST_ENTRY(ng_btsocket_l2cap_raw_pcb) next; /* link to next PCB */
|
||||
};
|
||||
typedef struct ng_btsocket_l2cap_raw_pcb ng_btsocket_l2cap_raw_pcb_t;
|
||||
|
337
sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
Normal file
337
sys/netgraph/bluetooth/include/ng_btsocket_rfcomm.h
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
* ng_btsocket_rfcomm.h
|
||||
*
|
||||
* Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_btsocket_rfcomm.h,v 1.10 2003/03/29 22:27:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETGRAPH_BTSOCKET_RFCOMM_H_
|
||||
#define _NETGRAPH_BTSOCKET_RFCOMM_H_ 1
|
||||
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
** RFCOMM **
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
/* XXX FIXME this does not belong here */
|
||||
|
||||
#define RFCOMM_DEFAULT_MTU 127
|
||||
#define RFCOMM_MAX_MTU 1024
|
||||
|
||||
#define RFCOMM_DEFAULT_CREDITS 7
|
||||
#define RFCOMM_MAX_CREDITS 40
|
||||
|
||||
/* RFCOMM frame types */
|
||||
#define RFCOMM_FRAME_SABM 0x2f
|
||||
#define RFCOMM_FRAME_DISC 0x43
|
||||
#define RFCOMM_FRAME_UA 0x63
|
||||
#define RFCOMM_FRAME_DM 0x0f
|
||||
#define RFCOMM_FRAME_UIH 0xef
|
||||
|
||||
/* RFCOMM MCC commands */
|
||||
#define RFCOMM_MCC_TEST 0x08 /* Test */
|
||||
#define RFCOMM_MCC_FCON 0x28 /* Flow Control on */
|
||||
#define RFCOMM_MCC_FCOFF 0x18 /* Flow Control off */
|
||||
#define RFCOMM_MCC_MSC 0x38 /* Modem Status Command */
|
||||
#define RFCOMM_MCC_RPN 0x24 /* Remote Port Negotiation */
|
||||
#define RFCOMM_MCC_RLS 0x14 /* Remote Line Status */
|
||||
#define RFCOMM_MCC_PN 0x20 /* Port Negotiation */
|
||||
#define RFCOMM_MCC_NSC 0x04 /* Non Supported Command */
|
||||
|
||||
/* RFCOMM modem signals */
|
||||
#define RFCOMM_MODEM_FC 0x02 /* Flow Control asserted */
|
||||
#define RFCOMM_MODEM_RTC 0x04 /* Ready To Communicate */
|
||||
#define RFCOMM_MODEM_RTR 0x08 /* Ready To Receive */
|
||||
#define RFCOMM_MODEM_IC 0x40 /* Incomming Call */
|
||||
#define RFCOMM_MODEM_DV 0x80 /* Data Valid */
|
||||
|
||||
/* RPN parameters - baud rate */
|
||||
#define RFCOMM_RPN_BR_2400 0x0
|
||||
#define RFCOMM_RPN_BR_4800 0x1
|
||||
#define RFCOMM_RPN_BR_7200 0x2
|
||||
#define RFCOMM_RPN_BR_9600 0x3
|
||||
#define RFCOMM_RPN_BR_19200 0x4
|
||||
#define RFCOMM_RPN_BR_38400 0x5
|
||||
#define RFCOMM_RPN_BR_57600 0x6
|
||||
#define RFCOMM_RPN_BR_115200 0x7
|
||||
#define RFCOMM_RPN_BR_230400 0x8
|
||||
|
||||
/* RPN parameters - data bits */
|
||||
#define RFCOMM_RPN_DATA_5 0x0
|
||||
#define RFCOMM_RPN_DATA_6 0x1
|
||||
#define RFCOMM_RPN_DATA_7 0x2
|
||||
#define RFCOMM_RPN_DATA_8 0x3
|
||||
|
||||
/* RPN parameters - stop bit */
|
||||
#define RFCOMM_RPN_STOP_1 0
|
||||
#define RFCOMM_RPN_STOP_15 1
|
||||
|
||||
/* RPN parameters - parity */
|
||||
#define RFCOMM_RPN_PARITY_NONE 0x0
|
||||
#define RFCOMM_RPN_PARITY_ODD 0x4
|
||||
#define RFCOMM_RPN_PARITY_EVEN 0x5
|
||||
#define RFCOMM_RPN_PARITY_MARK 0x6
|
||||
#define RFCOMM_RPN_PARITY_SPACE 0x7
|
||||
|
||||
/* RPN parameters - flow control */
|
||||
#define RFCOMM_RPN_FLOW_NONE 0x00
|
||||
#define RFCOMM_RPN_XON_CHAR 0x11
|
||||
#define RFCOMM_RPN_XOFF_CHAR 0x13
|
||||
|
||||
/* RPN parameters - mask */
|
||||
#define RFCOMM_RPN_PM_BITRATE 0x0001
|
||||
#define RFCOMM_RPN_PM_DATA 0x0002
|
||||
#define RFCOMM_RPN_PM_STOP 0x0004
|
||||
#define RFCOMM_RPN_PM_PARITY 0x0008
|
||||
#define RFCOMM_RPN_PM_PARITY_TYPE 0x0010
|
||||
#define RFCOMM_RPN_PM_XON 0x0020
|
||||
#define RFCOMM_RPN_PM_XOFF 0x0040
|
||||
#define RFCOMM_RPN_PM_FLOW 0x3F00
|
||||
#define RFCOMM_RPN_PM_ALL 0x3F7F
|
||||
|
||||
/* RFCOMM frame header */
|
||||
struct rfcomm_frame_hdr
|
||||
{
|
||||
u_int8_t address;
|
||||
u_int8_t control;
|
||||
u_int8_t length; /* Actual size could be 2 bytes */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RFCOMM command frame header */
|
||||
struct rfcomm_cmd_hdr
|
||||
{
|
||||
u_int8_t address;
|
||||
u_int8_t control;
|
||||
u_int8_t length;
|
||||
u_int8_t fcs;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RFCOMM MCC command header */
|
||||
struct rfcomm_mcc_hdr
|
||||
{
|
||||
u_int8_t type;
|
||||
u_int8_t length; /* XXX FIXME Can actual size be 2 bytes?? */
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RFCOMM MSC command */
|
||||
struct rfcomm_mcc_msc
|
||||
{
|
||||
u_int8_t address;
|
||||
u_int8_t modem;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RFCOMM RPN command */
|
||||
struct rfcomm_mcc_rpn
|
||||
{
|
||||
u_int8_t dlci;
|
||||
u_int8_t bit_rate;
|
||||
u_int8_t line_settings;
|
||||
u_int8_t flow_control;
|
||||
u_int8_t xon_char;
|
||||
u_int8_t xoff_char;
|
||||
u_int16_t param_mask;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RFCOMM RLS command */
|
||||
struct rfcomm_mcc_rls
|
||||
{
|
||||
u_int8_t address;
|
||||
u_int8_t status;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RFCOMM PN command */
|
||||
struct rfcomm_mcc_pn
|
||||
{
|
||||
u_int8_t dlci;
|
||||
u_int8_t flow_control;
|
||||
u_int8_t priority;
|
||||
u_int8_t ack_timer;
|
||||
u_int16_t mtu;
|
||||
u_int8_t max_retrans;
|
||||
u_int8_t credits;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
/* RFCOMM frame parsing macros */
|
||||
#define RFCOMM_DLCI(b) (((b) & 0xfc) >> 2)
|
||||
#define RFCOMM_CHANNEL(b) (((b) & 0xf8) >> 3)
|
||||
#define RFCOMM_DIRECTION(b) (((b) & 0x04) >> 2)
|
||||
#define RFCOMM_TYPE(b) (((b) & 0xef))
|
||||
|
||||
#define RFCOMM_EA(b) (((b) & 0x01))
|
||||
#define RFCOMM_CR(b) (((b) & 0x02) >> 1)
|
||||
#define RFCOMM_PF(b) (((b) & 0x10) >> 4)
|
||||
|
||||
#define RFCOMM_SRVCHANNEL(dlci) ((dlci) >> 1)
|
||||
|
||||
#define RFCOMM_MKADDRESS(cr, dlci) \
|
||||
((((dlci) & 0x3f) << 2) | ((cr) << 1) | 0x01)
|
||||
|
||||
#define RFCOMM_MKCONTROL(type, pf) ((((type) & 0xef) | ((pf) << 4)))
|
||||
#define RFCOMM_MKDLCI(dir, channel) ((((channel) & 0x1f) << 1) | (dir))
|
||||
|
||||
#define RFCOMM_MKLEN8(len) (((len) << 1) | 1)
|
||||
#define RFCOMM_MKLEN16(len) ((len) << 1)
|
||||
|
||||
/* RFCOMM MCC macros */
|
||||
#define RFCOMM_MCC_TYPE(b) (((b) & 0xfc) >> 2)
|
||||
#define RFCOMM_MCC_LENGTH(b) (((b) & 0xfe) >> 1)
|
||||
#define RFCOMM_MKMCC_TYPE(cr, type) ((((type) << 2) | ((cr) << 1) | 0x01))
|
||||
|
||||
/* RPN macros */
|
||||
#define RFCOMM_RPN_DATA_BITS(line) ((line) & 0x3)
|
||||
#define RFCOMM_RPN_STOP_BITS(line) (((line) >> 2) & 0x1)
|
||||
#define RFCOMM_RPN_PARITY(line) (((line) >> 3) & 0x3)
|
||||
#define RFCOMM_MKRPN_LINE_SETTINGS(data, stop, parity) \
|
||||
(((data) & 0x3) | (((stop) & 0x1) << 2) | (((parity) & 0x3) << 3))
|
||||
|
||||
/*****************************************************************************
|
||||
*****************************************************************************
|
||||
** SOCK_STREAM RFCOMM sockets **
|
||||
*****************************************************************************
|
||||
*****************************************************************************/
|
||||
|
||||
#define NG_BTSOCKET_RFCOMM_SENDSPACE \
|
||||
(RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10)
|
||||
#define NG_BTSOCKET_RFCOMM_RECVSPACE \
|
||||
(RFCOMM_MAX_CREDITS * RFCOMM_DEFAULT_MTU * 10)
|
||||
|
||||
/*
|
||||
* Bluetooth RFCOMM session. One L2CAP connection == one RFCOMM session
|
||||
*/
|
||||
|
||||
struct ng_btsocket_rfcomm_pcb;
|
||||
struct ng_btsocket_rfcomm_session;
|
||||
|
||||
struct ng_btsocket_rfcomm_session {
|
||||
struct socket *l2so; /* L2CAP socket */
|
||||
|
||||
u_int16_t state; /* session state */
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_CLOSED 0
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_LISTENING 1
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_CONNECTING 2
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_CONNECTED 3
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_OPEN 4
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING 5
|
||||
|
||||
u_int16_t flags; /* session flags */
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_INITIATOR (1 << 0) /* initiator */
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_LFC (1 << 1) /* local flow */
|
||||
#define NG_BTSOCKET_RFCOMM_SESSION_RFC (1 << 2) /* remote flow */
|
||||
|
||||
#define INITIATOR(s) \
|
||||
(((s)->flags & NG_BTSOCKET_RFCOMM_SESSION_INITIATOR)? 1 : 0)
|
||||
|
||||
u_int16_t mtu; /* default MTU */
|
||||
struct ng_bt_mbufq outq; /* outgoing queue */
|
||||
|
||||
struct mtx session_mtx; /* session lock */
|
||||
LIST_HEAD(, ng_btsocket_rfcomm_pcb) dlcs; /* active DLC */
|
||||
|
||||
LIST_ENTRY(ng_btsocket_rfcomm_session) next; /* link to next */
|
||||
};
|
||||
typedef struct ng_btsocket_rfcomm_session ng_btsocket_rfcomm_session_t;
|
||||
typedef struct ng_btsocket_rfcomm_session * ng_btsocket_rfcomm_session_p;
|
||||
|
||||
/*
|
||||
* Bluetooth RFCOMM socket PCB (DLC)
|
||||
*/
|
||||
|
||||
struct ng_btsocket_rfcomm_pcb {
|
||||
struct socket *so; /* RFCOMM socket */
|
||||
struct ng_btsocket_rfcomm_session *session; /* RFCOMM session */
|
||||
|
||||
u_int16_t flags; /* DLC flags */
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_TIMO (1 << 0) /* timeout pending */
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_CFC (1 << 1) /* credit flow ctrl */
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_TIMEDOUT (1 << 2) /* timeout happend */
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_DETACHED (1 << 3) /* DLC detached */
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_SENDING (1 << 4) /* send pending */
|
||||
|
||||
u_int16_t state; /* DLC state */
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_CLOSED 0
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT 1
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_CONFIGURING 2
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_CONNECTING 3
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_CONNECTED 4
|
||||
#define NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING 5
|
||||
|
||||
bdaddr_t src; /* source address */
|
||||
bdaddr_t dst; /* dest. address */
|
||||
|
||||
u_int8_t channel; /* RFCOMM channel */
|
||||
u_int8_t dlci; /* RFCOMM DLCI */
|
||||
|
||||
u_int8_t lmodem; /* local mdm signls */
|
||||
u_int8_t rmodem; /* remote -/- */
|
||||
|
||||
u_int16_t mtu; /* MTU */
|
||||
int16_t rx_cred; /* RX credits */
|
||||
int16_t tx_cred; /* TX credits */
|
||||
|
||||
struct mtx pcb_mtx; /* PCB lock */
|
||||
struct callout_handle timo; /* timeout */
|
||||
|
||||
LIST_ENTRY(ng_btsocket_rfcomm_pcb) session_next;/* link to next */
|
||||
LIST_ENTRY(ng_btsocket_rfcomm_pcb) next; /* link to next */
|
||||
};
|
||||
typedef struct ng_btsocket_rfcomm_pcb ng_btsocket_rfcomm_pcb_t;
|
||||
typedef struct ng_btsocket_rfcomm_pcb * ng_btsocket_rfcomm_pcb_p;
|
||||
|
||||
#define so2rfcomm_pcb(so) \
|
||||
((struct ng_btsocket_rfcomm_pcb *)((so)->so_pcb))
|
||||
|
||||
/*
|
||||
* Bluetooth RFCOMM socket methods
|
||||
*/
|
||||
|
||||
#ifdef _KERNEL
|
||||
|
||||
void ng_btsocket_rfcomm_init (void);
|
||||
int ng_btsocket_rfcomm_abort (struct socket *);
|
||||
int ng_btsocket_rfcomm_accept (struct socket *, struct sockaddr **);
|
||||
int ng_btsocket_rfcomm_attach (struct socket *, int, struct thread *);
|
||||
int ng_btsocket_rfcomm_bind (struct socket *, struct sockaddr *,
|
||||
struct thread *);
|
||||
int ng_btsocket_rfcomm_connect (struct socket *, struct sockaddr *,
|
||||
struct thread *);
|
||||
int ng_btsocket_rfcomm_control (struct socket *, u_long, caddr_t,
|
||||
struct ifnet *, struct thread *);
|
||||
int ng_btsocket_rfcomm_ctloutput (struct socket *, struct sockopt *);
|
||||
int ng_btsocket_rfcomm_detach (struct socket *);
|
||||
int ng_btsocket_rfcomm_disconnect (struct socket *);
|
||||
int ng_btsocket_rfcomm_listen (struct socket *, struct thread *);
|
||||
int ng_btsocket_rfcomm_peeraddr (struct socket *, struct sockaddr **);
|
||||
int ng_btsocket_rfcomm_send (struct socket *, int, struct mbuf *,
|
||||
struct sockaddr *, struct mbuf *,
|
||||
struct thread *);
|
||||
int ng_btsocket_rfcomm_sockaddr (struct socket *, struct sockaddr **);
|
||||
|
||||
#endif /* _KERNEL */
|
||||
|
||||
#endif /* _NETGRAPH_BTSOCKET_RFCOMM_H_ */
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_h4.h,v 1.5 2002/06/27 09:50:18 max Exp $
|
||||
* $Id: ng_h4.h,v 1.1 2002/11/24 19:47:05 max Exp $
|
||||
* $FreeBSD$
|
||||
*
|
||||
* Based on:
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_hci.h,v 1.13 2002/11/12 22:35:39 max Exp $
|
||||
* $Id: ng_hci.h,v 1.2 2003/03/18 00:09:37 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -598,6 +598,10 @@ typedef u_int16_t ng_hci_node_link_policy_mask_ep;
|
||||
#define NGM_HCI_NODE_SET_PACKET_MASK 117 /* User -> HCI */
|
||||
typedef u_int16_t ng_hci_node_packet_mask_ep;
|
||||
|
||||
#define NGM_HCI_NODE_GET_ROLE_SWITCH 118 /* HCI -> User */
|
||||
#define NGM_HCI_NODE_SET_ROLE_SWITCH 119 /* User -> HCI */
|
||||
typedef u_int16_t ng_hci_node_role_switch_ep;
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
** Link control commands and return parameters
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap.h,v 1.13 2002/09/08 23:35:51 max Exp $
|
||||
* $Id: ng_l2cap.h,v 1.2 2003/04/27 00:52:26 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -610,14 +610,17 @@ typedef u_int16_t ng_l2cap_node_debug_ep;
|
||||
#define NGM_L2CAP_NODE_HOOK_INFO 0x409 /* L2CAP -> Upper */
|
||||
/* bdaddr_t bdaddr; -- local (source BDADDR) */
|
||||
|
||||
#define NGM_L2CAP_NODE_GET_CON_LIST 0x40a /* User -> L2CAP */
|
||||
#define NGM_L2CAP_NODE_GET_CON_LIST 0x40a /* L2CAP -> User */
|
||||
typedef struct {
|
||||
u_int32_t num_connections; /* number of connections */
|
||||
} ng_l2cap_node_con_list_ep;
|
||||
|
||||
/* Connection flags */
|
||||
#define NG_L2CAP_CON_TX (1 << 0) /* sending data */
|
||||
#define NG_L2CAP_CON_RX (1 << 1) /* receiving data */
|
||||
#define NG_L2CAP_CON_TX (1 << 0) /* sending data */
|
||||
#define NG_L2CAP_CON_RX (1 << 1) /* receiving data */
|
||||
#define NG_L2CAP_CON_OUTGOING (1 << 2) /* outgoing connection */
|
||||
#define NG_L2CAP_CON_LP_TIMO (1 << 3) /* LP timeout */
|
||||
#define NG_L2CAP_CON_AUTO_DISCON_TIMO (1 << 4) /* auto discon. timeout */
|
||||
|
||||
typedef struct {
|
||||
u_int8_t state; /* connection state */
|
||||
@ -630,7 +633,7 @@ typedef struct {
|
||||
#define NG_L2CAP_MAX_CON_NUM \
|
||||
((0xffff - sizeof(ng_l2cap_node_con_list_ep))/sizeof(ng_l2cap_node_con_ep))
|
||||
|
||||
#define NGM_L2CAP_NODE_GET_CHAN_LIST 0x40b /* User -> L2CAP */
|
||||
#define NGM_L2CAP_NODE_GET_CHAN_LIST 0x40b /* L2CAP -> User */
|
||||
typedef struct {
|
||||
u_int32_t num_channels; /* number of channels */
|
||||
} ng_l2cap_node_chan_list_ep;
|
||||
@ -651,5 +654,9 @@ typedef struct {
|
||||
#define NG_L2CAP_MAX_CHAN_NUM \
|
||||
((0xffff - sizeof(ng_l2cap_node_chan_list_ep))/sizeof(ng_l2cap_node_chan_ep))
|
||||
|
||||
#define NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO 0x40c /* L2CAP -> User */
|
||||
#define NGM_L2CAP_NODE_SET_AUTO_DISCON_TIMO 0x40d /* User -> L2CAP */
|
||||
typedef u_int16_t ng_l2cap_node_auto_discon_ep;
|
||||
|
||||
#endif /* ndef _NETGRAPH_L2CAP_H_ */
|
||||
|
||||
|
@ -25,29 +25,13 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_ubt.h,v 1.1 2002/11/09 19:09:02 max Exp $
|
||||
* $Id: ng_ubt.h,v 1.6 2003/04/13 21:34:42 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NG_UBT_H_
|
||||
#define _NG_UBT_H_
|
||||
|
||||
/* XXX FIXME Does not belong here. Move to usbdevs.h later */
|
||||
#define USB_VENDOR_MSI 0x0db0 /* MSI www.msi.com.tw */
|
||||
#define USB_VENDOR_EPOX 0x0a12 /* EPoX www.epox.com */
|
||||
|
||||
#define USB_PRODUCT_3COM_3CREB96 0x00a0 /* 3Com Bluetooth USB dongle */
|
||||
#define USB_PRODUCT_MITSUMI_BT_DONGLE 0x641f /* Mitsumi Bluetooth USB dongle*/
|
||||
#define USB_PRODUCT_TDK_BT_DONGLE 0x0309 /* TDK Bluetooth USB dongle */
|
||||
#define USB_PRODUCT_MSI_BT_DONGLE 0x1967 /* MSI Bluetooth USB dongle */
|
||||
#define USB_PRODUCT_DBW_120M_BT_DONGLE 0x2033 /* D-Link DBW-120M */
|
||||
#define USB_PRODUCT_BT_DG02_DONGLE 0x0001 /* EPoX BT-DG02 USB dongle */
|
||||
|
||||
/* XXX FIXME Does not belong here. Move to usb.h later */
|
||||
#define UICLASS_WIRELESS_CONTROLLER 0xe0 /* Wireless Controller */
|
||||
#define UISUBCLASS_RF_CONTROLLER 0x01 /* RF Controller */
|
||||
#define UIPROTO_BLUETOOTH 0x01 /* Bluetooth programming */
|
||||
|
||||
/**************************************************************************
|
||||
**************************************************************************
|
||||
** Netgraph node hook name, type name and type cookie and commands
|
||||
@ -79,10 +63,9 @@ typedef u_int16_t ng_ubt_node_debug_ep;
|
||||
#define NGM_UBT_NODE_GET_QLEN 4 /* get queue length */
|
||||
typedef struct {
|
||||
int32_t queue; /* queue index */
|
||||
#define NGM_UBT_NODE_QUEUE_IN 1 /* incoming queue */
|
||||
#define NGM_UBT_NODE_QUEUE_CMD 2 /* commands */
|
||||
#define NGM_UBT_NODE_QUEUE_ACL 3 /* ACL data */
|
||||
#define NGM_UBT_NODE_QUEUE_SCO 4 /* SCO data */
|
||||
#define NGM_UBT_NODE_QUEUE_CMD 1 /* commands */
|
||||
#define NGM_UBT_NODE_QUEUE_ACL 2 /* ACL data */
|
||||
#define NGM_UBT_NODE_QUEUE_SCO 3 /* SCO data */
|
||||
|
||||
int32_t qlen; /* queue length */
|
||||
} ng_ubt_node_qlen_ep;
|
||||
@ -99,5 +82,8 @@ typedef struct {
|
||||
|
||||
#define NGM_UBT_NODE_RESET_STAT 6 /* reset statistic */
|
||||
|
||||
#define NGM_UBT_NODE_DEV_NODES 7 /* on/off device interface */
|
||||
typedef u_int16_t ng_ubt_node_dev_nodes_ep;
|
||||
|
||||
#endif /* ndef _NG_UBT_H_ */
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
$Id: TODO,v 1.8 2002/09/06 21:03:58 max Exp $
|
||||
$Id: TODO,v 1.1 2002/11/24 19:47:06 max Exp $
|
||||
$FreeBSD$
|
||||
|
||||
FIXME/TODO list
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_cmds.c,v 1.14 2002/09/04 21:38:38 max Exp $
|
||||
* $Id: ng_l2cap_cmds.c,v 1.1 2002/11/24 19:47:06 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_cmds.h,v 1.9 2002/04/16 00:43:56 max Exp $
|
||||
* $Id: ng_l2cap_cmds.h,v 1.4 2003/04/01 18:15:26 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -152,9 +152,11 @@ do { \
|
||||
c->param.dcid = htole16((_dcid)); \
|
||||
c->param.flags = htole16((_flags)); \
|
||||
if ((_data) != NULL) { \
|
||||
int l = (_data)->m_pkthdr.len; \
|
||||
\
|
||||
m_cat((_m), (_data)); \
|
||||
c->hdr.length += (_data)->m_pkthdr.len; \
|
||||
(_m)->m_pkthdr.len += (_data)->m_pkthdr.len; \
|
||||
c->hdr.length += l; \
|
||||
(_m)->m_pkthdr.len += l; \
|
||||
} \
|
||||
\
|
||||
c->hdr.length = htole16(c->hdr.length); \
|
||||
@ -185,9 +187,11 @@ do { \
|
||||
c->param.flags = htole16((_flags)); \
|
||||
c->param.result = htole16((_result)); \
|
||||
if ((_data) != NULL) { \
|
||||
int l = (_data)->m_pkthdr.len; \
|
||||
\
|
||||
m_cat((_m), (_data)); \
|
||||
c->hdr.length += (_data)->m_pkthdr.len; \
|
||||
(_m)->m_pkthdr.len += (_data)->m_pkthdr.len; \
|
||||
c->hdr.length += l; \
|
||||
(_m)->m_pkthdr.len += l; \
|
||||
} \
|
||||
\
|
||||
c->hdr.length = htole16(c->hdr.length); \
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_evnt.c,v 1.18 2002/09/04 21:38:38 max Exp $
|
||||
* $Id: ng_l2cap_evnt.c,v 1.4 2003/04/01 18:15:26 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -844,7 +844,8 @@ ng_l2cap_process_discon_req(ng_l2cap_con_p con, u_int8_t ident)
|
||||
}
|
||||
|
||||
/* XXX Verify channel state and reject if invalid -- is that true? */
|
||||
if (ch->state != NG_L2CAP_OPEN && ch->state != NG_L2CAP_CONFIG) {
|
||||
if (ch->state != NG_L2CAP_OPEN && ch->state != NG_L2CAP_CONFIG &&
|
||||
ch->state != NG_L2CAP_W4_L2CAP_DISCON_RSP) {
|
||||
NG_L2CAP_ERR(
|
||||
"%s: %s - unexpected L2CAP_DisconnectReq. " \
|
||||
"Invalid channel state, cid=%d, state=%d\n",
|
||||
@ -869,8 +870,10 @@ ng_l2cap_process_discon_req(ng_l2cap_con_p con, u_int8_t ident)
|
||||
* with L2CAP_DisconnectRsp.
|
||||
*/
|
||||
|
||||
ng_l2cap_l2ca_discon_ind(ch); /* do not care about result */
|
||||
ng_l2cap_free_chan(ch);
|
||||
if (ch->state != NG_L2CAP_W4_L2CAP_DISCON_RSP) {
|
||||
ng_l2cap_l2ca_discon_ind(ch); /* do not care about result */
|
||||
ng_l2cap_free_chan(ch);
|
||||
}
|
||||
|
||||
/* Send L2CAP_DisconnectRsp */
|
||||
cmd = ng_l2cap_new_cmd(con, NULL, ident, NG_L2CAP_DISCON_RSP, 0);
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_evnt.h,v 1.2 2002/04/16 00:43:56 max Exp $
|
||||
* $Id: ng_l2cap_evnt.h,v 1.1 2002/11/24 19:47:06 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_llpi.c,v 1.16 2002/09/04 21:38:38 max Exp $
|
||||
* $Id: ng_l2cap_llpi.c,v 1.4 2003/04/28 21:44:59 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -108,12 +108,15 @@ ng_l2cap_lp_con_req(ng_l2cap_p l2cap, bdaddr_p bdaddr)
|
||||
bcopy(bdaddr, &ep->bdaddr, sizeof(ep->bdaddr));
|
||||
ep->link_type = NG_HCI_LINK_ACL;
|
||||
|
||||
con->flags |= NG_L2CAP_CON_OUTGOING;
|
||||
con->state = NG_L2CAP_W4_LP_CON_CFM;
|
||||
ng_l2cap_lp_timeout(con);
|
||||
|
||||
NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, NULL);
|
||||
if (error != 0)
|
||||
ng_l2cap_free_con(con); /* will remove timeout */
|
||||
if (error != 0) {
|
||||
ng_l2cap_lp_untimeout(con);
|
||||
ng_l2cap_free_con(con);
|
||||
}
|
||||
|
||||
return (error);
|
||||
} /* ng_l2cap_lp_con_req */
|
||||
@ -174,11 +177,8 @@ ng_l2cap_lp_con_cfm(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
||||
con->state = NG_L2CAP_CON_OPEN;
|
||||
con->con_handle = ep->con_handle;
|
||||
ng_l2cap_lp_deliver(con);
|
||||
} else {
|
||||
/* Negative confirmation - remove connection descriptor */
|
||||
con->state = NG_L2CAP_CON_CLOSED;
|
||||
} else /* Negative confirmation - remove connection descriptor */
|
||||
ng_l2cap_con_fail(con, ep->status);
|
||||
}
|
||||
out:
|
||||
return (error);
|
||||
} /* ng_l2cap_lp_con_cfm */
|
||||
@ -258,8 +258,10 @@ ng_l2cap_lp_con_ind(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
||||
ng_l2cap_lp_timeout(con);
|
||||
|
||||
NG_SEND_MSG_HOOK(error, l2cap->node, rsp, l2cap->hci, NULL);
|
||||
if (error != 0)
|
||||
ng_l2cap_free_con(con); /* will remove timeout */
|
||||
if (error != 0) {
|
||||
ng_l2cap_lp_untimeout(con);
|
||||
ng_l2cap_free_con(con);
|
||||
}
|
||||
out:
|
||||
return (error);
|
||||
} /* ng_hci_lp_con_ind */
|
||||
@ -310,7 +312,9 @@ ng_l2cap_lp_discon_ind(ng_l2cap_p l2cap, struct ng_mesg *msg)
|
||||
}
|
||||
|
||||
/* Notify upper layer and remove connection */
|
||||
con->state = NG_L2CAP_CON_CLOSED;
|
||||
if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
|
||||
ng_l2cap_discon_untimeout(con);
|
||||
|
||||
ng_l2cap_con_fail(con, ep->reason);
|
||||
out:
|
||||
return (error);
|
||||
@ -800,7 +804,45 @@ ng_l2cap_process_lp_timeout(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
* connection, channels and pending commands.
|
||||
*/
|
||||
|
||||
con->state = NG_L2CAP_CON_CLOSED;
|
||||
con->flags &= ~NG_L2CAP_CON_LP_TIMO;
|
||||
ng_l2cap_con_fail(con, NG_L2CAP_TIMEOUT);
|
||||
} /* ng_l2cap_process_lp_timeout */
|
||||
|
||||
/*
|
||||
* Process auto disconnect timeout and send LP_DisconReq event to the
|
||||
* lower layer protocol
|
||||
*/
|
||||
|
||||
void
|
||||
ng_l2cap_process_discon_timeout(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
{
|
||||
ng_l2cap_con_p con = (ng_l2cap_con_p) arg1;
|
||||
ng_l2cap_p l2cap = con->l2cap;
|
||||
struct ng_mesg *msg = NULL;
|
||||
ng_hci_lp_discon_req_ep *ep = NULL;
|
||||
int error;
|
||||
|
||||
con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
|
||||
|
||||
/* Check if lower layer protocol is still connected */
|
||||
if (l2cap->hci == NULL || NG_HOOK_NOT_VALID(l2cap->hci)) {
|
||||
NG_L2CAP_ERR(
|
||||
"%s: %s - hook \"%s\" is not connected or valid\n",
|
||||
__func__, NG_NODE_NAME(l2cap->node), NG_L2CAP_HOOK_HCI);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create and send LP_DisconReq event */
|
||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_LP_DISCON_REQ,
|
||||
sizeof(*ep), M_NOWAIT);
|
||||
if (msg == NULL)
|
||||
return;
|
||||
|
||||
ep = (ng_hci_lp_discon_req_ep *) (msg->data);
|
||||
ep->con_handle = con->con_handle;
|
||||
ep->reason = 0x13; /* User Ended Connection */
|
||||
|
||||
NG_SEND_MSG_HOOK(error, l2cap->node, msg, l2cap->hci, NULL);
|
||||
} /* ng_l2cap_process_discon_timeout */
|
||||
|
||||
|
@ -25,24 +25,25 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_llpi.h,v 1.6 2002/04/16 00:43:57 max Exp $
|
||||
* $Id: ng_l2cap_llpi.h,v 1.2 2003/04/28 21:44:59 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#ifndef _NETGRAPH_L2CAP_LLPI_H_
|
||||
#define _NETGRAPH_L2CAP_LLPI_H_
|
||||
|
||||
int ng_l2cap_lp_con_req (ng_l2cap_p, bdaddr_p);
|
||||
int ng_l2cap_lp_con_cfm (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_con_ind (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_discon_ind (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_qos_req (ng_l2cap_p, u_int16_t, ng_l2cap_flow_p);
|
||||
int ng_l2cap_lp_qos_cfm (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_qos_ind (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_send (ng_l2cap_con_p, u_int16_t,struct mbuf *);
|
||||
int ng_l2cap_lp_receive (ng_l2cap_p, struct mbuf *);
|
||||
void ng_l2cap_lp_deliver (ng_l2cap_con_p);
|
||||
void ng_l2cap_process_lp_timeout (node_p, hook_p, void *, int);
|
||||
int ng_l2cap_lp_con_req (ng_l2cap_p, bdaddr_p);
|
||||
int ng_l2cap_lp_con_cfm (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_con_ind (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_discon_ind (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_qos_req (ng_l2cap_p, u_int16_t, ng_l2cap_flow_p);
|
||||
int ng_l2cap_lp_qos_cfm (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_qos_ind (ng_l2cap_p, struct ng_mesg *);
|
||||
int ng_l2cap_lp_send (ng_l2cap_con_p, u_int16_t,struct mbuf *);
|
||||
int ng_l2cap_lp_receive (ng_l2cap_p, struct mbuf *);
|
||||
void ng_l2cap_lp_deliver (ng_l2cap_con_p);
|
||||
void ng_l2cap_process_lp_timeout (node_p, hook_p, void *, int);
|
||||
void ng_l2cap_process_discon_timeout (node_p, hook_p, void *, int);
|
||||
|
||||
#endif /* ndef _NETGRAPH_L2CAP_LLPI_H_ */
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_main.c,v 1.24 2002/09/04 21:38:38 max Exp $
|
||||
* $Id: ng_l2cap_main.c,v 1.2 2003/04/28 21:44:59 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -120,6 +120,7 @@ ng_l2cap_constructor(node_p node)
|
||||
|
||||
l2cap->node = node;
|
||||
l2cap->debug = NG_L2CAP_WARN_LEVEL;
|
||||
l2cap->discon_timo = 5; /* sec */
|
||||
|
||||
LIST_INIT(&l2cap->con_list);
|
||||
LIST_INIT(&l2cap->chan_list);
|
||||
@ -574,6 +575,7 @@ ng_l2cap_default_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
LIST_FOREACH(con, &l2cap->con_list, next) {
|
||||
e2->state = con->state;
|
||||
|
||||
e2->flags = con->flags;
|
||||
if (con->tx_pkt != NULL)
|
||||
e2->flags |= NG_L2CAP_CON_TX;
|
||||
if (con->rx_pkt != NULL)
|
||||
@ -637,6 +639,26 @@ ng_l2cap_default_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
}
|
||||
} break;
|
||||
|
||||
case NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO:
|
||||
NG_MKRESPONSE(rsp, msg,
|
||||
sizeof(ng_l2cap_node_auto_discon_ep), M_NOWAIT);
|
||||
if (rsp == NULL)
|
||||
error = ENOMEM;
|
||||
else
|
||||
*((ng_l2cap_node_auto_discon_ep *)(rsp->data)) =
|
||||
l2cap->discon_timo;
|
||||
break;
|
||||
|
||||
case NGM_L2CAP_NODE_SET_AUTO_DISCON_TIMO:
|
||||
if (msg->header.arglen !=
|
||||
sizeof(ng_l2cap_node_auto_discon_ep))
|
||||
error = EMSGSIZE;
|
||||
else
|
||||
l2cap->discon_timo =
|
||||
*((ng_l2cap_node_auto_discon_ep *)
|
||||
(msg->data));
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
break;
|
||||
@ -714,12 +736,13 @@ ng_l2cap_cleanup(ng_l2cap_p l2cap)
|
||||
while (!LIST_EMPTY(&l2cap->con_list)) {
|
||||
con = LIST_FIRST(&l2cap->con_list);
|
||||
|
||||
if (con->state == NG_L2CAP_W4_LP_CON_CFM)
|
||||
if (con->flags & NG_L2CAP_CON_LP_TIMO)
|
||||
ng_l2cap_lp_untimeout(con);
|
||||
else if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
|
||||
ng_l2cap_discon_untimeout(con);
|
||||
|
||||
con->state = NG_L2CAP_CON_CLOSED;
|
||||
/* Connection terminated by local host */
|
||||
ng_l2cap_con_fail(con, 0x16);
|
||||
/* Connection terminated by local host */
|
||||
}
|
||||
} /* ng_l2cap_cleanup */
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_misc.c,v 1.16 2002/09/04 21:38:38 max Exp $
|
||||
* $Id: ng_l2cap_misc.c,v 1.4 2003/04/28 21:44:59 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -48,6 +48,7 @@
|
||||
#include "ng_l2cap_misc.h"
|
||||
|
||||
static u_int16_t ng_l2cap_get_cid (ng_l2cap_p);
|
||||
static void ng_l2cap_queue_discon_timeout (void *);
|
||||
static void ng_l2cap_queue_lp_timeout (void *);
|
||||
static void ng_l2cap_queue_command_timeout (void *);
|
||||
|
||||
@ -93,9 +94,8 @@ ng_l2cap_send_hook_info(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
} /* ng_l2cap_send_hook_info */
|
||||
|
||||
/*
|
||||
* Create new connection descriptor for the "remote" unit. Will create new
|
||||
* connection descriptor and signal channel. Will link both connection and
|
||||
* channel to the l2cap node.
|
||||
* Create new connection descriptor for the "remote" unit.
|
||||
* Will link connection descriptor to the l2cap node.
|
||||
*/
|
||||
|
||||
ng_l2cap_con_p
|
||||
@ -124,6 +124,104 @@ ng_l2cap_new_con(ng_l2cap_p l2cap, bdaddr_p bdaddr)
|
||||
return (con);
|
||||
} /* ng_l2cap_new_con */
|
||||
|
||||
/*
|
||||
* Add reference to the connection descriptor
|
||||
*/
|
||||
|
||||
void
|
||||
ng_l2cap_con_ref(ng_l2cap_con_p con)
|
||||
{
|
||||
con->refcnt ++;
|
||||
|
||||
if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO) {
|
||||
if ((con->state != NG_L2CAP_CON_OPEN) ||
|
||||
(con->flags & NG_L2CAP_CON_OUTGOING) == 0)
|
||||
panic("%s: %s - bad auto disconnect timeout\n",
|
||||
__func__, NG_NODE_NAME(con->l2cap->node));
|
||||
|
||||
ng_l2cap_discon_untimeout(con);
|
||||
}
|
||||
} /* ng_l2cap_con_ref */
|
||||
|
||||
/*
|
||||
* Remove reference from the connection descriptor
|
||||
*/
|
||||
|
||||
void
|
||||
ng_l2cap_con_unref(ng_l2cap_con_p con)
|
||||
{
|
||||
con->refcnt --;
|
||||
|
||||
if (con->refcnt < 0)
|
||||
panic("%s: %s - con->refcnt < 0\n",
|
||||
__func__, NG_NODE_NAME(con->l2cap->node));
|
||||
|
||||
/*
|
||||
* Set auto disconnect timer only if the following conditions are met:
|
||||
* 1) we have no reference on the connection
|
||||
* 2) connection is in OPEN state
|
||||
* 3) it is an outgoing connection
|
||||
* 4) disconnect timeout > 0
|
||||
*/
|
||||
|
||||
if ((con->refcnt == 0) &&
|
||||
(con->state == NG_L2CAP_CON_OPEN) &&
|
||||
(con->flags & NG_L2CAP_CON_OUTGOING) &&
|
||||
(con->l2cap->discon_timo > 0)) {
|
||||
if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
|
||||
panic("%s: %s - duplicated auto disconnect timeout\n",
|
||||
__func__, NG_NODE_NAME(con->l2cap->node));
|
||||
|
||||
ng_l2cap_discon_timeout(con);
|
||||
}
|
||||
} /* ng_l2cap_con_unref */
|
||||
|
||||
/*
|
||||
* Set auto disconnect timeout
|
||||
*/
|
||||
|
||||
void
|
||||
ng_l2cap_discon_timeout(ng_l2cap_con_p con)
|
||||
{
|
||||
if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
|
||||
panic("%s: %s - invalid timeout, state=%d, flags=%#x\n",
|
||||
__func__, NG_NODE_NAME(con->l2cap->node),
|
||||
con->state, con->flags);
|
||||
|
||||
NG_NODE_REF(con->l2cap->node);
|
||||
con->flags |= NG_L2CAP_CON_AUTO_DISCON_TIMO;
|
||||
con->con_timo = timeout(ng_l2cap_queue_discon_timeout, con,
|
||||
con->l2cap->discon_timo * hz);
|
||||
} /* ng_l2cap_discon_timeout */
|
||||
|
||||
/*
|
||||
* Unset auto disconnect timeout
|
||||
*/
|
||||
|
||||
void
|
||||
ng_l2cap_discon_untimeout(ng_l2cap_con_p con)
|
||||
{
|
||||
untimeout(ng_l2cap_queue_discon_timeout, con, con->con_timo);
|
||||
con->flags &= ~NG_L2CAP_CON_AUTO_DISCON_TIMO;
|
||||
NG_NODE_UNREF(con->l2cap->node);
|
||||
} /* ng_l2cap_discon_untimeout */
|
||||
|
||||
/*
|
||||
* Queue auto disconnect timeout
|
||||
*/
|
||||
|
||||
static void
|
||||
ng_l2cap_queue_discon_timeout(void *context)
|
||||
{
|
||||
ng_l2cap_con_p con = (ng_l2cap_con_p) context;
|
||||
node_p node = con->l2cap->node;
|
||||
|
||||
if (NG_NODE_IS_VALID(node))
|
||||
ng_send_fn(node,NULL,&ng_l2cap_process_discon_timeout,con,0);
|
||||
|
||||
NG_NODE_UNREF(node);
|
||||
} /* ng_l2cap_queue_discon_timeout */
|
||||
|
||||
/*
|
||||
* Free connection descriptor. Will unlink connection and free everything.
|
||||
*/
|
||||
@ -133,8 +231,12 @@ ng_l2cap_free_con(ng_l2cap_con_p con)
|
||||
{
|
||||
ng_l2cap_chan_p f = NULL, n = NULL;
|
||||
|
||||
if (con->state == NG_L2CAP_W4_LP_CON_CFM)
|
||||
if (con->flags & NG_L2CAP_CON_LP_TIMO)
|
||||
ng_l2cap_lp_untimeout(con);
|
||||
else if (con->flags & NG_L2CAP_CON_AUTO_DISCON_TIMO)
|
||||
ng_l2cap_discon_untimeout(con);
|
||||
|
||||
con->state = NG_L2CAP_CON_CLOSED;
|
||||
|
||||
if (con->tx_pkt != NULL) {
|
||||
while (con->tx_pkt != NULL) {
|
||||
@ -234,6 +336,8 @@ ng_l2cap_new_chan(ng_l2cap_p l2cap, ng_l2cap_con_p con, u_int16_t psm)
|
||||
ch->link_timo = NG_L2CAP_LINK_TIMO_DEFAULT;
|
||||
|
||||
LIST_INSERT_HEAD(&l2cap->chan_list, ch, next);
|
||||
|
||||
ng_l2cap_con_ref(con);
|
||||
} else {
|
||||
bzero(ch, sizeof(*ch));
|
||||
FREE(ch, M_NETGRAPH_L2CAP);
|
||||
@ -281,6 +385,9 @@ ng_l2cap_free_chan(ng_l2cap_chan_p ch)
|
||||
}
|
||||
|
||||
LIST_REMOVE(ch, next);
|
||||
|
||||
ng_l2cap_con_unref(ch->con);
|
||||
|
||||
bzero(ch, sizeof(*ch));
|
||||
FREE(ch, M_NETGRAPH_L2CAP);
|
||||
} /* ng_l2cap_free_chan */
|
||||
@ -337,7 +444,13 @@ ng_l2cap_cmd_by_ident(ng_l2cap_con_p con, u_int8_t ident)
|
||||
void
|
||||
ng_l2cap_lp_timeout(ng_l2cap_con_p con)
|
||||
{
|
||||
if (con->flags & (NG_L2CAP_CON_LP_TIMO|NG_L2CAP_CON_AUTO_DISCON_TIMO))
|
||||
panic("%s: %s - invalid timeout, state=%d, flags=%#x\n",
|
||||
__func__, NG_NODE_NAME(con->l2cap->node),
|
||||
con->state, con->flags);
|
||||
|
||||
NG_NODE_REF(con->l2cap->node);
|
||||
con->flags |= NG_L2CAP_CON_LP_TIMO;
|
||||
con->con_timo = timeout(ng_l2cap_queue_lp_timeout, con,
|
||||
bluetooth_hci_connect_timeout());
|
||||
} /* ng_l2cap_lp_timeout */
|
||||
@ -350,6 +463,7 @@ void
|
||||
ng_l2cap_lp_untimeout(ng_l2cap_con_p con)
|
||||
{
|
||||
untimeout(ng_l2cap_queue_lp_timeout, con, con->con_timo);
|
||||
con->flags &= ~NG_L2CAP_CON_LP_TIMO;
|
||||
NG_NODE_UNREF(con->l2cap->node);
|
||||
} /* ng_l2cap_lp_untimeout */
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_misc.h,v 1.6 2002/04/16 00:43:57 max Exp $
|
||||
* $Id: ng_l2cap_misc.h,v 1.2 2003/04/28 21:44:59 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -39,6 +39,8 @@ void ng_l2cap_send_hook_info (node_p, hook_p, void *, int);
|
||||
*/
|
||||
|
||||
ng_l2cap_con_p ng_l2cap_new_con (ng_l2cap_p, bdaddr_p);
|
||||
void ng_l2cap_con_ref (ng_l2cap_con_p);
|
||||
void ng_l2cap_con_unref (ng_l2cap_con_p);
|
||||
ng_l2cap_con_p ng_l2cap_con_by_addr (ng_l2cap_p, bdaddr_p);
|
||||
ng_l2cap_con_p ng_l2cap_con_by_handle (ng_l2cap_p, u_int16_t);
|
||||
void ng_l2cap_free_con (ng_l2cap_con_p);
|
||||
@ -58,11 +60,13 @@ void ng_l2cap_free_chan (ng_l2cap_chan_p);
|
||||
#define ng_l2cap_link_cmd(con, cmd) \
|
||||
do { \
|
||||
TAILQ_INSERT_TAIL(&(con)->cmd_list, (cmd), next); \
|
||||
ng_l2cap_con_ref((con)); \
|
||||
} while (0)
|
||||
|
||||
#define ng_l2cap_unlink_cmd(cmd) \
|
||||
do { \
|
||||
TAILQ_REMOVE(&((cmd)->con->cmd_list), (cmd), next); \
|
||||
ng_l2cap_con_unref((cmd)->con); \
|
||||
} while (0)
|
||||
|
||||
#define ng_l2cap_free_cmd(cmd) \
|
||||
@ -84,6 +88,8 @@ u_int8_t ng_l2cap_get_ident (ng_l2cap_con_p);
|
||||
* Timeout
|
||||
*/
|
||||
|
||||
void ng_l2cap_discon_timeout (ng_l2cap_con_p);
|
||||
void ng_l2cap_discon_untimeout (ng_l2cap_con_p);
|
||||
void ng_l2cap_lp_timeout (ng_l2cap_con_p);
|
||||
void ng_l2cap_lp_untimeout (ng_l2cap_con_p);
|
||||
void ng_l2cap_command_timeout (ng_l2cap_cmd_p, int);
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_prse.h,v 1.2 2002/09/04 21:38:38 max Exp $
|
||||
* $Id: ng_l2cap_prse.h,v 1.2 2003/04/28 21:44:59 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -64,6 +64,20 @@ static const struct ng_cmdlist ng_l2cap_cmdlist[] = {
|
||||
&ng_parse_uint16_type,
|
||||
NULL
|
||||
},
|
||||
{
|
||||
NGM_L2CAP_COOKIE,
|
||||
NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO,
|
||||
"get_disc_timo",
|
||||
NULL,
|
||||
&ng_parse_uint16_type
|
||||
},
|
||||
{
|
||||
NGM_L2CAP_COOKIE,
|
||||
NGM_L2CAP_NODE_SET_AUTO_DISCON_TIMO,
|
||||
"set_disc_timo",
|
||||
&ng_parse_uint16_type,
|
||||
NULL
|
||||
},
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_ulpi.c,v 1.22 2002/09/08 23:35:51 max Exp $
|
||||
* $Id: ng_l2cap_ulpi.c,v 1.1 2002/11/24 19:47:06 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_ulpi.h,v 1.5 2002/07/04 21:48:53 max Exp $
|
||||
* $Id: ng_l2cap_ulpi.h,v 1.1 2002/11/24 19:47:06 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_l2cap_var.h,v 1.13 2002/09/04 21:38:38 max Exp $
|
||||
* $Id: ng_l2cap_var.h,v 1.2 2003/04/28 21:44:59 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -78,10 +78,11 @@ typedef struct ng_l2cap {
|
||||
|
||||
ng_l2cap_node_debug_ep debug; /* debug level */
|
||||
ng_l2cap_node_flags_ep flags; /* L2CAP node flags */
|
||||
ng_l2cap_node_auto_discon_ep discon_timo; /* auto discon. timeout */
|
||||
|
||||
bdaddr_t bdaddr; /* unit BDADDR */
|
||||
u_int16_t pkt_size; /* max. ACL packet size */
|
||||
u_int16_t num_pkts; /* out queue size */
|
||||
bdaddr_t bdaddr; /* unit BDADDR */
|
||||
|
||||
hook_p hci; /* HCI downstream hook */
|
||||
hook_p l2c; /* L2CAP upstream hook */
|
||||
@ -104,6 +105,9 @@ typedef struct ng_l2cap_con {
|
||||
ng_l2cap_p l2cap; /* pointer to L2CAP */
|
||||
|
||||
u_int16_t state; /* ACL connection state */
|
||||
u_int16_t flags; /* ACL connection flags */
|
||||
|
||||
int32_t refcnt; /* reference count */
|
||||
|
||||
bdaddr_t remote; /* remote unit address */
|
||||
u_int16_t con_handle; /* ACL connection handle */
|
||||
|
@ -1,4 +1,4 @@
|
||||
$Id: TODO,v 1.4 2002/09/06 21:03:56 max Exp $
|
||||
$Id: TODO,v 1.1 2002/11/24 19:47:07 max Exp $
|
||||
$FreeBSD$
|
||||
|
||||
FIXME/TODO list
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_btsocket.c,v 1.20 2002/09/13 17:56:58 max Exp $
|
||||
* $Id: ng_btsocket.c,v 1.3 2003/01/19 00:19:04 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/taskqueue.h>
|
||||
#include <bitstring.h>
|
||||
#include <netgraph/ng_message.h>
|
||||
#include <netgraph/netgraph.h>
|
||||
@ -49,6 +50,7 @@
|
||||
#include "ng_btsocket.h"
|
||||
#include "ng_btsocket_hci_raw.h"
|
||||
#include "ng_btsocket_l2cap.h"
|
||||
#include "ng_btsocket_rfcomm.h"
|
||||
|
||||
static int ng_btsocket_modevent (module_t, int, void *);
|
||||
extern struct domain ng_btsocket_domain;
|
||||
@ -134,6 +136,33 @@ static struct pr_usrreqs ng_btsocket_l2cap_usrreqs = {
|
||||
sopoll
|
||||
};
|
||||
|
||||
/*
|
||||
* Bluetooth STREAM RFCOMM sockets
|
||||
*/
|
||||
|
||||
static struct pr_usrreqs ng_btsocket_rfcomm_usrreqs = {
|
||||
ng_btsocket_rfcomm_abort, /* abort */
|
||||
ng_btsocket_rfcomm_accept, /* accept */
|
||||
ng_btsocket_rfcomm_attach, /* attach */
|
||||
ng_btsocket_rfcomm_bind, /* bind */
|
||||
ng_btsocket_rfcomm_connect, /* connect */
|
||||
pru_connect2_notsupp, /* connect2 */
|
||||
ng_btsocket_rfcomm_control, /* control */
|
||||
ng_btsocket_rfcomm_detach, /* detach */
|
||||
ng_btsocket_rfcomm_disconnect, /* disconnect */
|
||||
ng_btsocket_rfcomm_listen, /* listen */
|
||||
ng_btsocket_rfcomm_peeraddr, /* peeraddr */
|
||||
pru_rcvd_notsupp, /* rcvd */
|
||||
pru_rcvoob_notsupp, /* rcvoob */
|
||||
ng_btsocket_rfcomm_send, /* send */
|
||||
pru_sense_null, /* send */
|
||||
NULL, /* shutdown */
|
||||
ng_btsocket_rfcomm_sockaddr, /* sockaddr */
|
||||
sosend,
|
||||
soreceive,
|
||||
sopoll
|
||||
};
|
||||
|
||||
/*
|
||||
* Definitions of protocols supported in the BLUETOOTH domain
|
||||
*/
|
||||
@ -177,6 +206,19 @@ static struct protosw ng_btsocket_protosw[] = {
|
||||
NULL, NULL, NULL, /* fasttimeo, slowtimo, drain */
|
||||
&ng_btsocket_l2cap_usrreqs, /* usrreq table (above) */
|
||||
/* { NULL } */ /* pfh (protocol filter head?) */
|
||||
},
|
||||
{
|
||||
SOCK_STREAM, /* protocol type */
|
||||
&ng_btsocket_domain, /* backpointer to domain */
|
||||
BLUETOOTH_PROTO_RFCOMM, /* protocol */
|
||||
PR_ATOMIC | PR_CONNREQUIRED, /* flags */
|
||||
NULL, NULL, NULL, /* input, output, ctlinput */
|
||||
ng_btsocket_rfcomm_ctloutput, /* ctloutput */
|
||||
NULL, /* ousrreq() */
|
||||
ng_btsocket_rfcomm_init, /* init */
|
||||
NULL, NULL, NULL, /* fasttimeo, slowtimo, drain */
|
||||
&ng_btsocket_rfcomm_usrreqs, /* usrreq table (above) */
|
||||
/* { NULL } */ /* pfh (protocol filter head?) */
|
||||
}
|
||||
};
|
||||
#define ng_btsocket_protosw_size \
|
||||
@ -210,6 +252,8 @@ SYSCTL_NODE(_net_bluetooth_hci, OID_AUTO, sockets, CTLFLAG_RW,
|
||||
0, "Bluetooth HCI sockets family");
|
||||
SYSCTL_NODE(_net_bluetooth_l2cap, OID_AUTO, sockets, CTLFLAG_RW,
|
||||
0, "Bluetooth L2CAP sockets family");
|
||||
SYSCTL_NODE(_net_bluetooth_rfcomm, OID_AUTO, sockets, CTLFLAG_RW,
|
||||
0, "Bluetooth RFCOMM sockets family");
|
||||
|
||||
/*
|
||||
* Module
|
||||
|
@ -25,13 +25,14 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_btsocket_hci_raw.c,v 1.3 2002/11/12 22:31:39 max Exp $
|
||||
* $Id: ng_btsocket_hci_raw.c,v 1.13 2003/04/01 18:15:27 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/domain.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/errno.h>
|
||||
#include <sys/filedesc.h>
|
||||
#include <sys/ioccom.h>
|
||||
@ -77,6 +78,17 @@ static void ng_btsocket_hci_raw_output(node_p, hook_p, void *, int);
|
||||
static void ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p,
|
||||
struct mbuf **,
|
||||
struct mbuf *);
|
||||
static int ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p,
|
||||
struct mbuf *, int);
|
||||
|
||||
#define ng_btsocket_hci_raw_wakeup_input_task() \
|
||||
taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_hci_raw_task)
|
||||
|
||||
/* Security filter */
|
||||
struct ng_btsocket_hci_raw_sec_filter {
|
||||
bitstr_t bit_decl(events, 0xff);
|
||||
bitstr_t bit_decl(commands[0x3f], 0x3ff);
|
||||
};
|
||||
|
||||
/* Netgraph type descriptor */
|
||||
static struct ng_type typestruct = {
|
||||
@ -106,7 +118,8 @@ static LIST_HEAD(, ng_btsocket_hci_raw_pcb) ng_btsocket_hci_raw_sockets;
|
||||
static struct mtx ng_btsocket_hci_raw_sockets_mtx;
|
||||
static u_int32_t ng_btsocket_hci_raw_token;
|
||||
static struct mtx ng_btsocket_hci_raw_token_mtx;
|
||||
|
||||
static struct ng_btsocket_hci_raw_sec_filter *ng_btsocket_hci_raw_sec_filter;
|
||||
|
||||
/* Sysctl tree */
|
||||
SYSCTL_DECL(_net_bluetooth_hci_sockets);
|
||||
SYSCTL_NODE(_net_bluetooth_hci_sockets, OID_AUTO, raw, CTLFLAG_RW,
|
||||
@ -236,11 +249,25 @@ static int
|
||||
ng_btsocket_hci_raw_node_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
{
|
||||
struct ng_mesg *msg = NGI_MSG(item); /* item still has message */
|
||||
int error = 0;
|
||||
int empty, error = 0;
|
||||
|
||||
mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
empty = LIST_EMPTY(&ng_btsocket_hci_raw_sockets);
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
|
||||
if (empty) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (msg != NULL &&
|
||||
msg->header.typecookie == NGM_HCI_COOKIE &&
|
||||
msg->header.flags & NGF_RESP) {
|
||||
if (msg->header.token == 0) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (0);
|
||||
}
|
||||
|
||||
mtx_lock(&ng_btsocket_hci_raw_queue_mtx);
|
||||
if (NG_BT_ITEMQ_FULL(&ng_btsocket_hci_raw_queue)) {
|
||||
NG_BTSOCKET_HCI_RAW_ERR(
|
||||
@ -251,8 +278,7 @@ ng_btsocket_hci_raw_node_rcvmsg(node_p node, item_p item, hook_p lasthook)
|
||||
error = ENOBUFS;
|
||||
} else {
|
||||
NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item);
|
||||
error = taskqueue_enqueue(taskqueue_swi_giant,
|
||||
&ng_btsocket_hci_raw_task);
|
||||
error = ng_btsocket_hci_raw_wakeup_input_task();
|
||||
}
|
||||
mtx_unlock(&ng_btsocket_hci_raw_queue_mtx);
|
||||
} else {
|
||||
@ -273,7 +299,16 @@ static int
|
||||
ng_btsocket_hci_raw_node_rcvdata(hook_p hook, item_p item)
|
||||
{
|
||||
struct mbuf *nam = NULL;
|
||||
int error;
|
||||
int empty, error;
|
||||
|
||||
mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
empty = LIST_EMPTY(&ng_btsocket_hci_raw_sockets);
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
|
||||
if (empty) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (0);
|
||||
}
|
||||
|
||||
MGET(nam, M_DONTWAIT, MT_SONAME);
|
||||
if (nam != NULL) {
|
||||
@ -283,9 +318,8 @@ ng_btsocket_hci_raw_node_rcvdata(hook_p hook, item_p item)
|
||||
|
||||
sa->hci_len = sizeof(*sa);
|
||||
sa->hci_family = AF_BLUETOOTH;
|
||||
strncpy(sa->hci_node, NG_PEER_NODE_NAME(hook),
|
||||
strlcpy(sa->hci_node, NG_PEER_NODE_NAME(hook),
|
||||
sizeof(sa->hci_node));
|
||||
sa->hci_node[sizeof(sa->hci_node) - 1] = 0; /* sanity */
|
||||
|
||||
NGI_GET_M(item, nam->m_next);
|
||||
NGI_M(item) = nam;
|
||||
@ -300,8 +334,7 @@ ng_btsocket_hci_raw_node_rcvdata(hook_p hook, item_p item)
|
||||
error = ENOBUFS;
|
||||
} else {
|
||||
NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_hci_raw_queue, item);
|
||||
error = taskqueue_enqueue(taskqueue_swi_giant,
|
||||
&ng_btsocket_hci_raw_task);
|
||||
error = ng_btsocket_hci_raw_wakeup_input_task();
|
||||
}
|
||||
mtx_unlock(&ng_btsocket_hci_raw_queue_mtx);
|
||||
} else {
|
||||
@ -322,33 +355,35 @@ ng_btsocket_hci_raw_node_rcvdata(hook_p hook, item_p item)
|
||||
****************************************************************************/
|
||||
|
||||
/*
|
||||
* Get next token
|
||||
* Get next token. We need token to avoid theoretical race where process
|
||||
* submits ioctl() message then interrupts ioctl() and re-submits another
|
||||
* ioctl() on the same socket *before* first ioctl() complete.
|
||||
*/
|
||||
|
||||
|
||||
static void
|
||||
ng_btsocket_hci_raw_get_token(u_int32_t *token)
|
||||
{
|
||||
mtx_lock(&ng_btsocket_hci_raw_token_mtx);
|
||||
|
||||
|
||||
if (++ ng_btsocket_hci_raw_token == 0)
|
||||
ng_btsocket_hci_raw_token = 1;
|
||||
|
||||
|
||||
*token = ng_btsocket_hci_raw_token;
|
||||
|
||||
|
||||
mtx_unlock(&ng_btsocket_hci_raw_token_mtx);
|
||||
} /* ng_btsocket_hci_raw_token */
|
||||
} /* ng_btsocket_hci_raw_get_token */
|
||||
|
||||
/*
|
||||
* Send Netgraph message to the node - do not expect reply
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_btsocket_raw_send_ngmsg(char *path, int cmd, void *arg, int arglen)
|
||||
ng_btsocket_hci_raw_send_ngmsg(char *path, int cmd, void *arg, int arglen)
|
||||
{
|
||||
struct ng_mesg *msg = NULL;
|
||||
int error = 0;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, M_WAITOK);
|
||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, arglen, M_NOWAIT);
|
||||
if (msg == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
@ -358,28 +393,28 @@ ng_btsocket_raw_send_ngmsg(char *path, int cmd, void *arg, int arglen)
|
||||
NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, NULL);
|
||||
|
||||
return (error);
|
||||
} /* ng_btsocket_raw_send_ngmsg */
|
||||
} /* ng_btsocket_hci_raw_send_ngmsg */
|
||||
|
||||
/*
|
||||
* Send Netgraph message to the node (no data) and wait for reply
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_btsocket_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path,
|
||||
ng_btsocket_hci_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path,
|
||||
int cmd, void *rsp, int rsplen)
|
||||
{
|
||||
struct ng_mesg *msg = NULL;
|
||||
int error = 0;
|
||||
|
||||
ng_btsocket_hci_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
mtx_assert(&pcb->pcb_mtx, MA_OWNED);
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, M_WAITOK);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, cmd, 0, M_NOWAIT);
|
||||
if (msg == NULL)
|
||||
return (ENOMEM);
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
|
||||
ng_btsocket_hci_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_SEND_MSG_PATH(error, ng_btsocket_hci_raw_node, msg, path, NULL);
|
||||
if (error != 0) {
|
||||
@ -387,12 +422,12 @@ ng_btsocket_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path,
|
||||
return (error);
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "hcictl",
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "hcictl",
|
||||
ng_btsocket_hci_raw_ioctl_timeout * hz);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL && pcb->msg->header.cmd == cmd)
|
||||
bcopy(pcb->msg->data, rsp, rsplen);
|
||||
@ -400,10 +435,9 @@ ng_btsocket_raw_send_sync_ngmsg(ng_btsocket_hci_raw_pcb_p pcb, char *path,
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
|
||||
return (0);
|
||||
} /* ng_btsocket_raw_send_sync_ngmsg */
|
||||
} /* ng_btsocket_hci_raw_send_sync_ngmsg */
|
||||
|
||||
/*
|
||||
* Create control information for the packet
|
||||
@ -416,6 +450,8 @@ ng_btsocket_hci_raw_savctl(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf **ctl,
|
||||
int dir;
|
||||
struct timeval tv;
|
||||
|
||||
mtx_assert(&pcb->pcb_mtx, MA_OWNED);
|
||||
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_DIRECTION) {
|
||||
dir = (m->m_flags & M_PROTO1)? 1 : 0;
|
||||
*ctl = sbcreatecontrol((caddr_t) &dir, sizeof(dir),
|
||||
@ -443,21 +479,23 @@ ng_btsocket_hci_raw_data_input(struct mbuf *nam)
|
||||
ng_btsocket_hci_raw_pcb_p pcb = NULL;
|
||||
struct mbuf *m0 = NULL, *m = NULL;
|
||||
struct sockaddr_hci *sa = NULL;
|
||||
bitstr_t *mask = NULL;
|
||||
int bit;
|
||||
|
||||
m0 = nam->m_next;
|
||||
nam->m_next = NULL;
|
||||
|
||||
KASSERT((nam->m_type == MT_SONAME),
|
||||
("%s: m_type=%d\n", __func__, nam->m_type));
|
||||
M_ASSERTPKTHDR(m0);
|
||||
KASSERT((m0->m_flags & M_PKTHDR),
|
||||
("%s: m_flags=%#x\n", __func__, m0->m_flags));
|
||||
|
||||
sa = mtod(nam, struct sockaddr_hci *);
|
||||
|
||||
mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
|
||||
LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) {
|
||||
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
/*
|
||||
* If socket was bound then check address and
|
||||
* make sure it matches.
|
||||
@ -465,37 +503,15 @@ ng_btsocket_hci_raw_data_input(struct mbuf *nam)
|
||||
|
||||
if (pcb->addr.hci_node[0] != 0 &&
|
||||
strcmp(sa->hci_node, pcb->addr.hci_node) != 0)
|
||||
continue;
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* Check packet agains socket filter
|
||||
* Check packet against filters
|
||||
* XXX do we have to call m_pullup() here?
|
||||
*/
|
||||
|
||||
switch (*mtod(m0, u_int8_t *)) {
|
||||
case NG_HCI_CMD_PKT:
|
||||
case NG_HCI_ACL_DATA_PKT:
|
||||
case NG_HCI_SCO_DATA_PKT:
|
||||
mask = pcb->filter.packet_mask;
|
||||
bit = *mtod(m0, u_int8_t *) - 1;
|
||||
break;
|
||||
|
||||
case NG_HCI_EVENT_PKT:
|
||||
mask = pcb->filter.event_mask;
|
||||
bit = mtod(m0, ng_hci_event_pkt_t *)->event - 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
KASSERT(0,
|
||||
("%s: invalid packet type=%#x\n", __func__, *mtod(m0, u_int8_t *)));
|
||||
|
||||
mask = NULL;
|
||||
bit = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (mask == NULL || !bit_test(mask, bit))
|
||||
continue;
|
||||
if (ng_btsocket_hci_raw_filter(pcb, m0, 1) != 0)
|
||||
goto next;
|
||||
|
||||
/*
|
||||
* Make a copy of the packet, append to the socket's
|
||||
@ -513,13 +529,15 @@ ng_btsocket_hci_raw_data_input(struct mbuf *nam)
|
||||
(struct sockaddr *) sa, m, ctl))
|
||||
sorwakeup(pcb->so);
|
||||
else {
|
||||
NG_BTSOCKET_HCI_RAW_WARN(
|
||||
"%s: sbappendadd() failed\n", __func__);
|
||||
NG_BTSOCKET_HCI_RAW_INFO(
|
||||
"%s: sbappendaddr() failed\n", __func__);
|
||||
|
||||
NG_FREE_M(m);
|
||||
NG_FREE_M(ctl);
|
||||
}
|
||||
}
|
||||
next:
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
}
|
||||
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
@ -537,21 +555,26 @@ ng_btsocket_hci_raw_msg_input(struct ng_mesg *msg)
|
||||
{
|
||||
ng_btsocket_hci_raw_pcb_p pcb = NULL;
|
||||
|
||||
if (msg->header.token != 0) {
|
||||
mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
|
||||
LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) {
|
||||
if (msg->header.token == pcb->token) {
|
||||
pcb->msg = msg;
|
||||
msg = NULL;
|
||||
wakeup(&pcb->msg);
|
||||
break;
|
||||
}
|
||||
LIST_FOREACH(pcb, &ng_btsocket_hci_raw_sockets, next) {
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
if (msg->header.token == pcb->token) {
|
||||
pcb->msg = msg;
|
||||
wakeup(&pcb->msg);
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
}
|
||||
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
|
||||
NG_FREE_MSG(msg); /* checks for != NULL */
|
||||
} /* ng_btsocket_hci_raw_msg_input */
|
||||
|
||||
@ -613,7 +636,8 @@ ng_btsocket_hci_raw_output(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
|
||||
KASSERT((nam->m_type == MT_SONAME),
|
||||
("%s: m_type=%d\n", __func__, nam->m_type));
|
||||
M_ASSERTPKTHDR(m);
|
||||
KASSERT((m->m_flags & M_PKTHDR),
|
||||
("%s: m_flags=%#x\n", __func__, m->m_flags));
|
||||
|
||||
sa = mtod(nam, struct sockaddr_hci *);
|
||||
|
||||
@ -638,6 +662,62 @@ ng_btsocket_hci_raw_output(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
NG_FREE_M(m);
|
||||
} /* ng_btsocket_hci_raw_output */
|
||||
|
||||
/*
|
||||
* Check frame against security and socket filters.
|
||||
* d (direction bit) == 1 means incoming frame.
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_btsocket_hci_raw_filter(ng_btsocket_hci_raw_pcb_p pcb, struct mbuf *m, int d)
|
||||
{
|
||||
int type, event, opcode;
|
||||
|
||||
mtx_assert(&pcb->pcb_mtx, MA_OWNED);
|
||||
|
||||
switch ((type = *mtod(m, u_int8_t *))) {
|
||||
case NG_HCI_CMD_PKT:
|
||||
if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)) {
|
||||
opcode = le16toh(mtod(m, ng_hci_cmd_pkt_t *)->opcode);
|
||||
|
||||
if (!bit_test(
|
||||
ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF(opcode) - 1],
|
||||
NG_HCI_OCF(opcode) - 1))
|
||||
return (EPERM);
|
||||
}
|
||||
|
||||
if (d && !bit_test(pcb->filter.packet_mask, NG_HCI_CMD_PKT - 1))
|
||||
return (EPERM);
|
||||
break;
|
||||
|
||||
case NG_HCI_ACL_DATA_PKT:
|
||||
case NG_HCI_SCO_DATA_PKT:
|
||||
if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED) ||
|
||||
!bit_test(pcb->filter.packet_mask, type - 1) ||
|
||||
!d)
|
||||
return (EPERM);
|
||||
break;
|
||||
|
||||
case NG_HCI_EVENT_PKT:
|
||||
if (!d)
|
||||
return (EINVAL);
|
||||
|
||||
event = mtod(m, ng_hci_event_pkt_t *)->event - 1;
|
||||
|
||||
if (!(pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED))
|
||||
if (!bit_test(ng_btsocket_hci_raw_sec_filter->events, event))
|
||||
return (EPERM);
|
||||
|
||||
if (!bit_test(pcb->filter.event_mask, event))
|
||||
return (EPERM);
|
||||
break;
|
||||
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
return (0);
|
||||
} /* ng_btsocket_hci_raw_filter */
|
||||
|
||||
/*
|
||||
* Initialize everything
|
||||
*/
|
||||
@ -645,7 +725,8 @@ ng_btsocket_hci_raw_output(node_p node, hook_p hook, void *arg1, int arg2)
|
||||
void
|
||||
ng_btsocket_hci_raw_init(void)
|
||||
{
|
||||
int error = 0;
|
||||
bitstr_t *f = NULL;
|
||||
int error = 0;
|
||||
|
||||
ng_btsocket_hci_raw_node = NULL;
|
||||
ng_btsocket_hci_raw_debug_level = NG_BTSOCKET_WARN_LEVEL;
|
||||
@ -699,6 +780,99 @@ ng_btsocket_hci_raw_init(void)
|
||||
ng_btsocket_hci_raw_token = 0;
|
||||
mtx_init(&ng_btsocket_hci_raw_token_mtx,
|
||||
"btsocks_hci_raw_token_mtx", NULL, MTX_DEF);
|
||||
|
||||
/*
|
||||
* Security filter
|
||||
* XXX never FREE()ed
|
||||
*/
|
||||
|
||||
ng_btsocket_hci_raw_sec_filter = NULL;
|
||||
|
||||
MALLOC(ng_btsocket_hci_raw_sec_filter,
|
||||
struct ng_btsocket_hci_raw_sec_filter *,
|
||||
sizeof(struct ng_btsocket_hci_raw_sec_filter),
|
||||
M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO);
|
||||
if (ng_btsocket_hci_raw_sec_filter == NULL) {
|
||||
printf("%s: Could not allocate security filter!\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXX How paranoid can we get?
|
||||
*
|
||||
* Initialize security filter. If bit is set in the mask then
|
||||
* unprivileged socket is allowed to send (receive) this command
|
||||
* (event).
|
||||
*/
|
||||
|
||||
/* Enable all events */
|
||||
memset(&ng_btsocket_hci_raw_sec_filter->events, 0xff,
|
||||
sizeof(ng_btsocket_hci_raw_sec_filter->events)/
|
||||
sizeof(ng_btsocket_hci_raw_sec_filter->events[0]));
|
||||
|
||||
/* Disable some critical events */
|
||||
f = ng_btsocket_hci_raw_sec_filter->events;
|
||||
bit_clear(f, NG_HCI_EVENT_RETURN_LINK_KEYS - 1);
|
||||
bit_clear(f, NG_HCI_EVENT_LINK_KEY_NOTIFICATION - 1);
|
||||
bit_clear(f, NG_HCI_EVENT_VENDOR - 1);
|
||||
|
||||
/* Commands - Link control */
|
||||
f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_CONTROL-1];
|
||||
bit_set(f, NG_HCI_OCF_INQUIRY - 1);
|
||||
bit_set(f, NG_HCI_OCF_INQUIRY_CANCEL - 1);
|
||||
bit_set(f, NG_HCI_OCF_PERIODIC_INQUIRY - 1);
|
||||
bit_set(f, NG_HCI_OCF_EXIT_PERIODIC_INQUIRY - 1);
|
||||
bit_set(f, NG_HCI_OCF_REMOTE_NAME_REQ - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_REMOTE_FEATURES - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_REMOTE_VER_INFO - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_CLOCK_OFFSET - 1);
|
||||
|
||||
/* Commands - Link policy */
|
||||
f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_LINK_POLICY-1];
|
||||
bit_set(f, NG_HCI_OCF_ROLE_DISCOVERY - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_LINK_POLICY_SETTINGS - 1);
|
||||
|
||||
/* Commands - Host controller and baseband */
|
||||
f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_HC_BASEBAND-1];
|
||||
bit_set(f, NG_HCI_OCF_READ_PIN_TYPE - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_LOCAL_NAME - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_CON_ACCEPT_TIMO - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_PAGE_TIMO - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_SCAN_ENABLE - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_ACTIVITY - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_INQUIRY_SCAN_ACTIVITY - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_AUTH_ENABLE - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_ENCRYPTION_MODE - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_UNIT_CLASS - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_VOICE_SETTINGS - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_AUTO_FLUSH_TIMO - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_NUM_BROADCAST_RETRANS - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_HOLD_MODE_ACTIVITY - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_XMIT_LEVEL - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_SCO_FLOW_CONTROL - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_LINK_SUPERVISION_TIMO - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_SUPPORTED_IAC_NUM - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_IAC_LAP - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN_PERIOD - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_PAGE_SCAN - 1);
|
||||
|
||||
/* Commands - Informational */
|
||||
f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_INFO - 1];
|
||||
bit_set(f, NG_HCI_OCF_READ_LOCAL_VER - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_LOCAL_FEATURES - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_BUFFER_SIZE - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_COUNTRY_CODE - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_BDADDR - 1);
|
||||
|
||||
/* Commands - Status */
|
||||
f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_STATUS - 1];
|
||||
bit_set(f, NG_HCI_OCF_READ_FAILED_CONTACT_CNTR - 1);
|
||||
bit_set(f, NG_HCI_OCF_GET_LINK_QUALITY - 1);
|
||||
bit_set(f, NG_HCI_OCF_READ_RSSI - 1);
|
||||
|
||||
/* Commands - Testing */
|
||||
f = ng_btsocket_hci_raw_sec_filter->commands[NG_HCI_OGF_TESTING - 1];
|
||||
bit_set(f, NG_HCI_OCF_READ_LOOPBACK_MODE - 1);
|
||||
} /* ng_btsocket_hci_raw_init */
|
||||
|
||||
/*
|
||||
@ -708,8 +882,6 @@ ng_btsocket_hci_raw_init(void)
|
||||
int
|
||||
ng_btsocket_hci_raw_abort(struct socket *so)
|
||||
{
|
||||
soisdisconnected(so);
|
||||
|
||||
return (ng_btsocket_hci_raw_detach(so));
|
||||
} /* ng_btsocket_hci_raw_abort */
|
||||
|
||||
@ -732,8 +904,6 @@ ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td)
|
||||
return (EPROTONOSUPPORT);
|
||||
if (so->so_type != SOCK_RAW)
|
||||
return (ESOCKTNOSUPPORT);
|
||||
if ((error = suser(td)) != 0)
|
||||
return (error);
|
||||
|
||||
error = soreserve(so, NG_BTSOCKET_HCI_RAW_SENDSPACE,
|
||||
NG_BTSOCKET_HCI_RAW_RECVSPACE);
|
||||
@ -741,13 +911,16 @@ ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td)
|
||||
return (error);
|
||||
|
||||
MALLOC(pcb, ng_btsocket_hci_raw_pcb_p, sizeof(*pcb),
|
||||
M_NETGRAPH_BTSOCKET_HCI_RAW, M_WAITOK | M_ZERO);
|
||||
M_NETGRAPH_BTSOCKET_HCI_RAW, M_NOWAIT|M_ZERO);
|
||||
if (pcb == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
so->so_pcb = (caddr_t) pcb;
|
||||
pcb->so = so;
|
||||
|
||||
if (suser(td) == 0)
|
||||
pcb->flags |= NG_BTSOCKET_HCI_RAW_PRIVILEGED;
|
||||
|
||||
/*
|
||||
* Set default socket filter. By default socket only accepts HCI
|
||||
* Command_Complete and Command_Status event packets.
|
||||
@ -756,6 +929,8 @@ ng_btsocket_hci_raw_attach(struct socket *so, int proto, struct thread *td)
|
||||
bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_COMPL - 1);
|
||||
bit_set(pcb->filter.event_mask, NG_HCI_EVENT_COMMAND_STATUS - 1);
|
||||
|
||||
mtx_init(&pcb->pcb_mtx, "btsocks_hci_raw_pcb_mtx", NULL, MTX_DEF);
|
||||
|
||||
mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
LIST_INSERT_HEAD(&ng_btsocket_hci_raw_sockets, pcb, next);
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
@ -834,8 +1009,7 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ifnet *ifp, struct thread *td)
|
||||
{
|
||||
ng_btsocket_hci_raw_pcb_p pcb = so2hci_raw_pcb(so);
|
||||
char path[NG_NODELEN + 2],
|
||||
*hci_node = (char *) data;
|
||||
char path[NG_NODELEN + 2];
|
||||
struct ng_mesg *msg = NULL;
|
||||
int error = 0;
|
||||
|
||||
@ -844,41 +1018,45 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
if (ng_btsocket_hci_raw_node == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
/*
|
||||
* Make sure caller has provided HCI node name, if not try to
|
||||
* use addr from socket (if socket was bound)
|
||||
*/
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
if (hci_node[0] == 0) {
|
||||
if (pcb->addr.hci_node[0] == 0)
|
||||
return (EINVAL);
|
||||
|
||||
bzero(hci_node, sizeof(pcb->addr.hci_node));
|
||||
strncpy(hci_node,pcb->addr.hci_node,sizeof(pcb->addr.hci_node));
|
||||
/* Check if we have device name */
|
||||
if (pcb->addr.hci_node[0] == 0) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
return (EHOSTUNREACH);
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "%s:", hci_node);
|
||||
/* Check if we have pending ioctl() */
|
||||
if (pcb->token != 0) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
snprintf(path, sizeof(path), "%s:", pcb->addr.hci_node);
|
||||
|
||||
switch (cmd) {
|
||||
case SIOC_HCI_RAW_NODE_GET_STATE: {
|
||||
struct ng_btsocket_hci_raw_node_state *p =
|
||||
(struct ng_btsocket_hci_raw_node_state *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_STATE,
|
||||
&p->state, sizeof(p->state));
|
||||
} break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_INIT:
|
||||
error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_INIT,
|
||||
NULL, 0);
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_hci_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_INIT, NULL, 0);
|
||||
else
|
||||
error = EPERM;
|
||||
break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_GET_DEBUG: {
|
||||
struct ng_btsocket_hci_raw_node_debug *p =
|
||||
(struct ng_btsocket_hci_raw_node_debug *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_DEBUG,
|
||||
&p->debug, sizeof(p->debug));
|
||||
} break;
|
||||
@ -887,15 +1065,19 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ng_btsocket_hci_raw_node_debug *p =
|
||||
(struct ng_btsocket_hci_raw_node_debug *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_ngmsg(path, NGM_HCI_NODE_SET_DEBUG,
|
||||
&p->debug, sizeof(p->debug));
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_hci_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_SET_DEBUG, &p->debug,
|
||||
sizeof(p->debug));
|
||||
else
|
||||
error = EPERM;
|
||||
} break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_GET_BUFFER: {
|
||||
struct ng_btsocket_hci_raw_node_buffer *p =
|
||||
(struct ng_btsocket_hci_raw_node_buffer *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_BUFFER,
|
||||
&p->buffer, sizeof(p->buffer));
|
||||
} break;
|
||||
@ -904,7 +1086,7 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ng_btsocket_hci_raw_node_bdaddr *p =
|
||||
(struct ng_btsocket_hci_raw_node_bdaddr *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_BDADDR,
|
||||
&p->bdaddr, sizeof(p->bdaddr));
|
||||
} break;
|
||||
@ -913,7 +1095,7 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ng_btsocket_hci_raw_node_features *p =
|
||||
(struct ng_btsocket_hci_raw_node_features *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_FEATURES,
|
||||
&p->features, sizeof(p->features));
|
||||
} break;
|
||||
@ -922,19 +1104,26 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ng_btsocket_hci_raw_node_stat *p =
|
||||
(struct ng_btsocket_hci_raw_node_stat *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_STAT,
|
||||
&p->stat, sizeof(p->stat));
|
||||
} break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_RESET_STAT:
|
||||
error = ng_btsocket_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_RESET_STAT, NULL, 0);
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_hci_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_RESET_STAT, NULL, 0);
|
||||
else
|
||||
error = EPERM;
|
||||
break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_FLUSH_NEIGHBOR_CACHE:
|
||||
error = ng_btsocket_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE, NULL, 0);
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_hci_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_FLUSH_NEIGHBOR_CACHE,
|
||||
NULL, 0);
|
||||
else
|
||||
error = EPERM;
|
||||
break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_GET_NEIGHBOR_CACHE: {
|
||||
@ -950,17 +1139,15 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
break;
|
||||
}
|
||||
|
||||
ng_btsocket_hci_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE,
|
||||
NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_WAITOK);
|
||||
NGM_HCI_NODE_GET_NEIGHBOR_CACHE, 0, M_NOWAIT);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
ng_btsocket_hci_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_SEND_MSG_PATH(error,ng_btsocket_hci_raw_node,msg,path,NULL);
|
||||
if (error != 0) {
|
||||
@ -968,12 +1155,13 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "hcictl",
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx,
|
||||
PZERO|PCATCH, "hcictl",
|
||||
ng_btsocket_hci_raw_ioctl_timeout * hz);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_HCI_NODE_GET_NEIGHBOR_CACHE) {
|
||||
@ -992,7 +1180,6 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
}break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_GET_CON_LIST: {
|
||||
@ -1008,17 +1195,15 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
break;
|
||||
}
|
||||
|
||||
ng_btsocket_hci_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_HCI_COOKIE, NGM_HCI_NODE_GET_CON_LIST,
|
||||
0, M_WAITOK);
|
||||
0, M_NOWAIT);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
ng_btsocket_hci_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_SEND_MSG_PATH(error,ng_btsocket_hci_raw_node,msg,path,NULL);
|
||||
if (error != 0) {
|
||||
@ -1026,12 +1211,13 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "hcictl",
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx,
|
||||
PZERO|PCATCH, "hcictl",
|
||||
ng_btsocket_hci_raw_ioctl_timeout * hz);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_HCI_NODE_GET_CON_LIST) {
|
||||
@ -1049,7 +1235,6 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
} break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_GET_LINK_POLICY_MASK: {
|
||||
@ -1057,7 +1242,7 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
(struct ng_btsocket_hci_raw_node_link_policy_mask *)
|
||||
data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_LINK_POLICY_SETTINGS_MASK,
|
||||
&p->policy_mask, sizeof(p->policy_mask));
|
||||
} break;
|
||||
@ -1067,16 +1252,20 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
(struct ng_btsocket_hci_raw_node_link_policy_mask *)
|
||||
data;
|
||||
|
||||
error = ng_btsocket_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK,
|
||||
&p->policy_mask, sizeof(p->policy_mask));
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_hci_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_SET_LINK_POLICY_SETTINGS_MASK,
|
||||
&p->policy_mask,
|
||||
sizeof(p->policy_mask));
|
||||
else
|
||||
error = EPERM;
|
||||
} break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_GET_PACKET_MASK: {
|
||||
struct ng_btsocket_hci_raw_node_packet_mask *p =
|
||||
(struct ng_btsocket_hci_raw_node_packet_mask *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_sync_ngmsg(pcb, path,
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_PACKET_MASK,
|
||||
&p->packet_mask, sizeof(p->packet_mask));
|
||||
} break;
|
||||
@ -1085,10 +1274,35 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ng_btsocket_hci_raw_node_packet_mask *p =
|
||||
(struct ng_btsocket_hci_raw_node_packet_mask *) data;
|
||||
|
||||
error = ng_btsocket_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_SET_PACKET_MASK,
|
||||
&p->packet_mask, sizeof(p->packet_mask));
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_hci_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_SET_PACKET_MASK,
|
||||
&p->packet_mask,
|
||||
sizeof(p->packet_mask));
|
||||
else
|
||||
error = EPERM;
|
||||
} break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_GET_ROLE_SWITCH: {
|
||||
struct ng_btsocket_hci_raw_node_role_switch *p =
|
||||
(struct ng_btsocket_hci_raw_node_role_switch *) data;
|
||||
|
||||
error = ng_btsocket_hci_raw_send_sync_ngmsg(pcb, path,
|
||||
NGM_HCI_NODE_GET_ROLE_SWITCH,
|
||||
&p->role_switch, sizeof(p->role_switch));
|
||||
} break;
|
||||
|
||||
case SIOC_HCI_RAW_NODE_SET_ROLE_SWITCH: {
|
||||
struct ng_btsocket_hci_raw_node_role_switch *p =
|
||||
(struct ng_btsocket_hci_raw_node_role_switch *) data;
|
||||
|
||||
if (pcb->flags & NG_BTSOCKET_HCI_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_hci_raw_send_ngmsg(path,
|
||||
NGM_HCI_NODE_SET_ROLE_SWITCH,
|
||||
&p->role_switch,
|
||||
sizeof(p->role_switch));
|
||||
else
|
||||
error = EPERM;
|
||||
} break;
|
||||
|
||||
default:
|
||||
@ -1096,6 +1310,8 @@ ng_btsocket_hci_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
|
||||
return (error);
|
||||
} /* ng_btsocket_hci_raw_control */
|
||||
|
||||
@ -1118,6 +1334,8 @@ ng_btsocket_hci_raw_ctloutput(struct socket *so, struct sockopt *sopt)
|
||||
if (sopt->sopt_level != SOL_HCI_RAW)
|
||||
return (0);
|
||||
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
switch (sopt->sopt_dir) {
|
||||
case SOPT_GET:
|
||||
switch (sopt->sopt_name) {
|
||||
@ -1169,6 +1387,8 @@ ng_btsocket_hci_raw_ctloutput(struct socket *so, struct sockopt *sopt)
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
|
||||
return (error);
|
||||
} /* ng_btsocket_hci_raw_ctloutput */
|
||||
@ -1187,16 +1407,22 @@ ng_btsocket_hci_raw_detach(struct socket *so)
|
||||
if (ng_btsocket_hci_raw_node == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
so->so_pcb = NULL;
|
||||
sotryfree(so);
|
||||
|
||||
mtx_lock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
LIST_REMOVE(pcb, next);
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_hci_raw_sockets_mtx);
|
||||
|
||||
mtx_destroy(&pcb->pcb_mtx);
|
||||
|
||||
bzero(pcb, sizeof(*pcb));
|
||||
FREE(pcb, M_NETGRAPH_BTSOCKET_HCI_RAW);
|
||||
|
||||
so->so_pcb = NULL;
|
||||
sotryfree(so);
|
||||
|
||||
return (0);
|
||||
} /* ng_btsocket_hci_raw_detach */
|
||||
|
||||
@ -1226,7 +1452,7 @@ ng_btsocket_hci_raw_disconnect(struct socket *so)
|
||||
int
|
||||
ng_btsocket_hci_raw_peeraddr(struct socket *so, struct sockaddr **nam)
|
||||
{
|
||||
return (EOPNOTSUPP);
|
||||
return (ng_btsocket_hci_raw_sockaddr(so, nam));
|
||||
} /* ng_btsocket_hci_raw_peeraddr */
|
||||
|
||||
/*
|
||||
@ -1260,8 +1486,28 @@ ng_btsocket_hci_raw_send(struct socket *so, int flags, struct mbuf *m,
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (m->m_len < sizeof(ng_hci_cmd_pkt_t)) {
|
||||
if ((m = m_pullup(m, sizeof(ng_hci_cmd_pkt_t))) == NULL) {
|
||||
error = ENOBUFS;
|
||||
goto drop;
|
||||
}
|
||||
}
|
||||
if (*mtod(m, u_int8_t *) != NG_HCI_CMD_PKT) {
|
||||
error = ENOTSUP;
|
||||
goto drop;
|
||||
}
|
||||
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
error = ng_btsocket_hci_raw_filter(pcb, m, 0);
|
||||
if (error != 0) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
goto drop;
|
||||
}
|
||||
|
||||
if (sa == NULL) {
|
||||
if (pcb->addr.hci_node[0] == 0) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
error = EDESTADDRREQ;
|
||||
goto drop;
|
||||
}
|
||||
@ -1269,8 +1515,9 @@ ng_btsocket_hci_raw_send(struct socket *so, int flags, struct mbuf *m,
|
||||
sa = (struct sockaddr *) &pcb->addr;
|
||||
}
|
||||
|
||||
MGET(nam, M_TRYWAIT, MT_SONAME);
|
||||
MGET(nam, M_DONTWAIT, MT_SONAME);
|
||||
if (nam == NULL) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
error = ENOBUFS;
|
||||
goto drop;
|
||||
}
|
||||
@ -1281,6 +1528,8 @@ ng_btsocket_hci_raw_send(struct socket *so, int flags, struct mbuf *m,
|
||||
nam->m_next = m;
|
||||
m = NULL;
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
|
||||
return (ng_send_fn(ng_btsocket_hci_raw_node, NULL,
|
||||
ng_btsocket_hci_raw_output, nam, 0));
|
||||
drop:
|
||||
@ -1309,7 +1558,7 @@ ng_btsocket_hci_raw_sockaddr(struct socket *so, struct sockaddr **nam)
|
||||
bzero(&sa, sizeof(sa));
|
||||
sa.hci_len = sizeof(sa);
|
||||
sa.hci_family = AF_BLUETOOTH;
|
||||
strncpy(sa.hci_node, pcb->addr.hci_node, sizeof(sa.hci_node));
|
||||
strlcpy(sa.hci_node, pcb->addr.hci_node, sizeof(sa.hci_node));
|
||||
|
||||
*nam = dup_sockaddr((struct sockaddr *) &sa, 0);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: ng_btsocket_l2cap_raw.c,v 1.1 2002/09/04 21:44:00 max Exp $
|
||||
* $Id: ng_btsocket_l2cap_raw.c,v 1.11 2003/04/27 19:52:14 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -76,6 +76,17 @@ static void ng_btsocket_l2cap_raw_input (void *, int);
|
||||
static void ng_btsocket_l2cap_raw_rtclean (void *, int);
|
||||
static void ng_btsocket_l2cap_raw_get_token (u_int32_t *);
|
||||
|
||||
static int ng_btsocket_l2cap_raw_send_ngmsg
|
||||
(hook_p, int, void *, int);
|
||||
static int ng_btsocket_l2cap_raw_send_sync_ngmsg
|
||||
(ng_btsocket_l2cap_raw_pcb_p, int, void *, int);
|
||||
|
||||
#define ng_btsocket_l2cap_raw_wakeup_input_task() \
|
||||
taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_raw_queue_task)
|
||||
|
||||
#define ng_btsocket_l2cap_raw_wakeup_route_task() \
|
||||
taskqueue_enqueue(taskqueue_swi_giant, &ng_btsocket_l2cap_raw_rt_task)
|
||||
|
||||
/* Netgraph type descriptor */
|
||||
static struct ng_type typestruct = {
|
||||
NG_ABI_VERSION,
|
||||
@ -242,8 +253,7 @@ ng_btsocket_l2cap_raw_node_disconnect(hook_p hook)
|
||||
*/
|
||||
|
||||
if (NG_HOOK_PRIVATE(hook) != NULL)
|
||||
return (taskqueue_enqueue(taskqueue_swi_giant,
|
||||
&ng_btsocket_l2cap_raw_rt_task));
|
||||
return (ng_btsocket_l2cap_raw_wakeup_route_task());
|
||||
|
||||
NG_HOOK_UNREF(hook); /* Remove extra reference */
|
||||
|
||||
@ -261,6 +271,21 @@ ng_btsocket_l2cap_raw_node_rcvmsg(node_p node, item_p item, hook_p hook)
|
||||
int error = 0;
|
||||
|
||||
if (msg != NULL && msg->header.typecookie == NGM_L2CAP_COOKIE) {
|
||||
|
||||
/*
|
||||
* NGM_L2CAP_NODE_HOOK_INFO is special message initiated by
|
||||
* L2CAP layer. Ignore all other messages if they are not
|
||||
* replies or token is zero
|
||||
*/
|
||||
|
||||
if (msg->header.cmd != NGM_L2CAP_NODE_HOOK_INFO) {
|
||||
if (msg->header.token == 0 ||
|
||||
!(msg->header.flags & NGF_RESP)) {
|
||||
NG_FREE_ITEM(item);
|
||||
return (0);
|
||||
}
|
||||
}
|
||||
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_queue_mtx);
|
||||
if (NG_BT_ITEMQ_FULL(&ng_btsocket_l2cap_raw_queue)) {
|
||||
NG_BTSOCKET_L2CAP_RAW_ERR(
|
||||
@ -276,8 +301,7 @@ ng_btsocket_l2cap_raw_node_rcvmsg(node_p node, item_p item, hook_p hook)
|
||||
}
|
||||
|
||||
NG_BT_ITEMQ_ENQUEUE(&ng_btsocket_l2cap_raw_queue, item);
|
||||
error = taskqueue_enqueue(taskqueue_swi_giant,
|
||||
&ng_btsocket_l2cap_raw_queue_task);
|
||||
error = ng_btsocket_l2cap_raw_wakeup_input_task();
|
||||
}
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_queue_mtx);
|
||||
} else {
|
||||
@ -344,6 +368,8 @@ ng_btsocket_l2cap_raw_input(void *context, int pending)
|
||||
sizeof(bdaddr_t)) == 0)
|
||||
break;
|
||||
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
rt = (ng_btsocket_l2cap_rtentry_t *)
|
||||
NG_HOOK_PRIVATE(hook);
|
||||
if (rt == NULL) {
|
||||
@ -351,13 +377,13 @@ ng_btsocket_l2cap_raw_input(void *context, int pending)
|
||||
sizeof(*rt),
|
||||
M_NETGRAPH_BTSOCKET_L2CAP_RAW,
|
||||
M_NOWAIT|M_ZERO);
|
||||
if (rt == NULL)
|
||||
if (rt == NULL) {
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
LIST_INSERT_HEAD(&ng_btsocket_l2cap_raw_rt,
|
||||
rt, next);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
NG_HOOK_SET_PRIVATE(hook, rt);
|
||||
}
|
||||
@ -365,6 +391,8 @@ ng_btsocket_l2cap_raw_input(void *context, int pending)
|
||||
bcopy(msg->data, &rt->src, sizeof(rt->src));
|
||||
rt->hook = hook;
|
||||
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
NG_BTSOCKET_L2CAP_RAW_INFO(
|
||||
"%s: Updating hook \"%s\", src bdaddr=%x:%x:%x:%x:%x:%x\n",
|
||||
__func__, NG_HOOK_NAME(hook),
|
||||
@ -376,24 +404,27 @@ ng_btsocket_l2cap_raw_input(void *context, int pending)
|
||||
case NGM_L2CAP_NODE_GET_DEBUG:
|
||||
case NGM_L2CAP_NODE_GET_CON_LIST:
|
||||
case NGM_L2CAP_NODE_GET_CHAN_LIST:
|
||||
case NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO:
|
||||
case NGM_L2CAP_L2CA_PING:
|
||||
case NGM_L2CAP_L2CA_GET_INFO: {
|
||||
ng_btsocket_l2cap_raw_pcb_p pcb = NULL;
|
||||
|
||||
if (msg->header.token == 0 ||
|
||||
!(msg->header.flags & NGF_RESP))
|
||||
break;
|
||||
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
|
||||
LIST_FOREACH(pcb, &ng_btsocket_l2cap_raw_sockets, next)
|
||||
LIST_FOREACH(pcb,&ng_btsocket_l2cap_raw_sockets,next) {
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
if (pcb->token == msg->header.token) {
|
||||
pcb->msg = msg;
|
||||
msg = NULL;
|
||||
wakeup(&pcb->msg);
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
}
|
||||
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
} break;
|
||||
|
||||
@ -408,7 +439,7 @@ ng_btsocket_l2cap_raw_input(void *context, int pending)
|
||||
|
||||
NG_FREE_MSG(msg); /* Checks for msg != NULL */
|
||||
}
|
||||
} /* ng_btsocket_l2cap_raw_default_msg_input */
|
||||
} /* ng_btsocket_l2cap_raw_input */
|
||||
|
||||
/*
|
||||
* Route cleanup task. Gets scheduled when hook is disconnected. Here we
|
||||
@ -428,7 +459,9 @@ ng_btsocket_l2cap_raw_rtclean(void *context, int pending)
|
||||
* First disconnect all sockets that use "invalid" hook
|
||||
*/
|
||||
|
||||
LIST_FOREACH(pcb, &ng_btsocket_l2cap_raw_sockets, next)
|
||||
LIST_FOREACH(pcb, &ng_btsocket_l2cap_raw_sockets, next) {
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
if (pcb->rt != NULL &&
|
||||
pcb->rt->hook != NULL && NG_HOOK_NOT_VALID(pcb->rt->hook)) {
|
||||
if (pcb->so != NULL &&
|
||||
@ -438,12 +471,14 @@ ng_btsocket_l2cap_raw_rtclean(void *context, int pending)
|
||||
pcb->rt = NULL;
|
||||
}
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now cleanup routing table
|
||||
*/
|
||||
|
||||
rt = LIST_FIRST(&ng_btsocket_l2cap_raw_rt);
|
||||
while (rt != NULL) {
|
||||
for (rt = LIST_FIRST(&ng_btsocket_l2cap_raw_rt); rt != NULL; ) {
|
||||
ng_btsocket_l2cap_rtentry_p rt_next = LIST_NEXT(rt, next);
|
||||
|
||||
if (rt->hook != NULL && NG_HOOK_NOT_VALID(rt->hook)) {
|
||||
@ -560,8 +595,6 @@ ng_btsocket_l2cap_raw_attach(struct socket *so, int proto, struct thread *td)
|
||||
return (EPROTONOSUPPORT);
|
||||
if (so->so_type != SOCK_RAW)
|
||||
return (ESOCKTNOSUPPORT);
|
||||
if ((error = suser(td)) != 0)
|
||||
return (error);
|
||||
|
||||
/* Reserve send and receive space if it is not reserved yet */
|
||||
error = soreserve(so, NG_BTSOCKET_L2CAP_RAW_SENDSPACE,
|
||||
@ -571,7 +604,7 @@ ng_btsocket_l2cap_raw_attach(struct socket *so, int proto, struct thread *td)
|
||||
|
||||
/* Allocate the PCB */
|
||||
MALLOC(pcb, ng_btsocket_l2cap_raw_pcb_p, sizeof(*pcb),
|
||||
M_NETGRAPH_BTSOCKET_L2CAP_RAW, M_WAITOK | M_ZERO);
|
||||
M_NETGRAPH_BTSOCKET_L2CAP_RAW, M_NOWAIT|M_ZERO);
|
||||
if (pcb == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
@ -579,6 +612,11 @@ ng_btsocket_l2cap_raw_attach(struct socket *so, int proto, struct thread *td)
|
||||
so->so_pcb = (caddr_t) pcb;
|
||||
pcb->so = so;
|
||||
|
||||
if (suser(td) == 0)
|
||||
pcb->flags |= NG_BTSOCKET_L2CAP_RAW_PRIVILEGED;
|
||||
|
||||
mtx_init(&pcb->pcb_mtx, "btsocks_l2cap_raw_pcb_mtx", NULL, MTX_DEF);
|
||||
|
||||
/* Add the PCB to the list */
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
LIST_INSERT_HEAD(&ng_btsocket_l2cap_raw_sockets, pcb, next);
|
||||
@ -597,6 +635,8 @@ ng_btsocket_l2cap_raw_bind(struct socket *so, struct sockaddr *nam,
|
||||
{
|
||||
ng_btsocket_l2cap_raw_pcb_t *pcb = so2l2cap_raw_pcb(so);
|
||||
struct sockaddr_l2cap *sa = (struct sockaddr_l2cap *) nam;
|
||||
ng_btsocket_l2cap_rtentry_t *rt = NULL;
|
||||
int error;
|
||||
|
||||
if (pcb == NULL)
|
||||
return (EINVAL);
|
||||
@ -609,12 +649,41 @@ ng_btsocket_l2cap_raw_bind(struct socket *so, struct sockaddr *nam,
|
||||
return (EAFNOSUPPORT);
|
||||
if (sa->l2cap_len != sizeof(*sa))
|
||||
return (EINVAL);
|
||||
if (bcmp(&sa->l2cap_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
|
||||
return (EINVAL);
|
||||
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
pcb->rt = NULL;
|
||||
bcopy(&sa->l2cap_bdaddr, &pcb->src, sizeof(pcb->src));
|
||||
|
||||
return (0);
|
||||
if (bcmp(&pcb->src, NG_HCI_BDADDR_ANY, sizeof(pcb->src)) == 0) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
LIST_FOREACH(rt, &ng_btsocket_l2cap_raw_rt, next) {
|
||||
if (rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook))
|
||||
continue;
|
||||
|
||||
if (bcmp(&pcb->src, &rt->src, sizeof(rt->src)) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rt != NULL) {
|
||||
pcb->rt = rt;
|
||||
error = 0;
|
||||
} else
|
||||
error = ENETDOWN;
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
return (error);
|
||||
} /* ng_btsocket_l2cap_raw_bind */
|
||||
|
||||
/*
|
||||
@ -628,6 +697,7 @@ ng_btsocket_l2cap_raw_connect(struct socket *so, struct sockaddr *nam,
|
||||
ng_btsocket_l2cap_raw_pcb_t *pcb = so2l2cap_raw_pcb(so);
|
||||
struct sockaddr_l2cap *sa = (struct sockaddr_l2cap *) nam;
|
||||
ng_btsocket_l2cap_rtentry_t *rt = NULL;
|
||||
int error;
|
||||
|
||||
if (pcb == NULL)
|
||||
return (EINVAL);
|
||||
@ -642,81 +712,64 @@ ng_btsocket_l2cap_raw_connect(struct socket *so, struct sockaddr *nam,
|
||||
return (EINVAL);
|
||||
if (bcmp(&sa->l2cap_bdaddr, NG_HCI_BDADDR_ANY, sizeof(bdaddr_t)) == 0)
|
||||
return (EINVAL);
|
||||
if (bcmp(&sa->l2cap_bdaddr, &pcb->src, sizeof(pcb->src)) != 0)
|
||||
return (EADDRNOTAVAIL);
|
||||
|
||||
/*
|
||||
* Find hook with specified source address
|
||||
*/
|
||||
|
||||
pcb->rt = NULL;
|
||||
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
bcopy(&sa->l2cap_bdaddr, &pcb->dst, sizeof(pcb->dst));
|
||||
|
||||
if (bcmp(&pcb->src, &pcb->dst, sizeof(pcb->src)) == 0) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
return (EADDRNOTAVAIL);
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is route already - use it
|
||||
*/
|
||||
|
||||
if (pcb->rt != NULL) {
|
||||
soisconnected(so);
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the first hook that does not match specified destination address
|
||||
*/
|
||||
|
||||
LIST_FOREACH(rt, &ng_btsocket_l2cap_raw_rt, next) {
|
||||
if (rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook))
|
||||
continue;
|
||||
|
||||
if (bcmp(&pcb->src, &rt->src, sizeof(rt->src)) == 0)
|
||||
if (bcmp(&pcb->dst, &rt->src, sizeof(rt->src)) != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (rt != NULL) {
|
||||
pcb->rt = rt;
|
||||
soisconnected(so);
|
||||
}
|
||||
|
||||
pcb->rt = rt;
|
||||
bcopy(&rt->src, &pcb->src, sizeof(pcb->src));
|
||||
|
||||
error = 0;
|
||||
} else
|
||||
error = ENETDOWN;
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
return ((pcb->rt != NULL)? 0 : ENETDOWN);
|
||||
return (error);
|
||||
} /* ng_btsocket_l2cap_raw_connect */
|
||||
|
||||
/*
|
||||
* Find hook that matches source address
|
||||
*/
|
||||
|
||||
static ng_btsocket_l2cap_rtentry_p
|
||||
ng_btsocket_l2cap_raw_find_src_route(bdaddr_p src)
|
||||
{
|
||||
ng_btsocket_l2cap_rtentry_p rt = NULL;
|
||||
|
||||
if (bcmp(src, NG_HCI_BDADDR_ANY, sizeof(*src)) != 0) {
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
LIST_FOREACH(rt, &ng_btsocket_l2cap_raw_rt, next)
|
||||
if (rt->hook != NULL && NG_HOOK_IS_VALID(rt->hook) &&
|
||||
bcmp(src, &rt->src, sizeof(*src)) == 0)
|
||||
break;
|
||||
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
}
|
||||
|
||||
return (rt);
|
||||
} /* ng_btsocket_l2cap_raw_find_src_route */
|
||||
|
||||
/*
|
||||
* Find first hook does does not match destination address
|
||||
*/
|
||||
|
||||
static ng_btsocket_l2cap_rtentry_p
|
||||
ng_btsocket_l2cap_raw_find_dst_route(bdaddr_p dst)
|
||||
{
|
||||
ng_btsocket_l2cap_rtentry_p rt = NULL;
|
||||
|
||||
if (bcmp(dst, NG_HCI_BDADDR_ANY, sizeof(*dst)) != 0) {
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
|
||||
LIST_FOREACH(rt, &ng_btsocket_l2cap_raw_rt, next)
|
||||
if (rt->hook != NULL && NG_HOOK_IS_VALID(rt->hook) &&
|
||||
bcmp(dst, &rt->src, sizeof(*dst)) != 0)
|
||||
break;
|
||||
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_rt_mtx);
|
||||
}
|
||||
|
||||
return (rt);
|
||||
} /* ng_btsocket_l2cap_raw_find_dst_route */
|
||||
|
||||
/*
|
||||
* Process ioctl's calls on socket
|
||||
*/
|
||||
@ -726,8 +779,6 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
struct ifnet *ifp, struct thread *td)
|
||||
{
|
||||
ng_btsocket_l2cap_raw_pcb_p pcb = so2l2cap_raw_pcb(so);
|
||||
bdaddr_t *src = (bdaddr_t *) data;
|
||||
ng_btsocket_l2cap_rtentry_p rt = pcb->rt;
|
||||
struct ng_mesg *msg = NULL;
|
||||
int error = 0;
|
||||
|
||||
@ -736,116 +787,49 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
if (ng_btsocket_l2cap_raw_node == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
if (rt == NULL || rt->hook == NULL || NG_HOOK_NOT_VALID(rt->hook)) {
|
||||
if (cmd == SIOC_L2CAP_L2CA_PING ||
|
||||
cmd == SIOC_L2CAP_L2CA_GET_INFO)
|
||||
rt = ng_btsocket_l2cap_raw_find_dst_route(src + 1);
|
||||
else
|
||||
rt = ng_btsocket_l2cap_raw_find_src_route(src);
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
if (rt == NULL)
|
||||
return (EHOSTUNREACH);
|
||||
/* Check if we route info */
|
||||
if (pcb->rt == NULL) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
return (EHOSTUNREACH);
|
||||
}
|
||||
|
||||
bcopy(&rt->src, src, sizeof(*src));
|
||||
/* Check if we have pending ioctl() */
|
||||
if (pcb->token != 0) {
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
return (EBUSY);
|
||||
}
|
||||
|
||||
switch (cmd) {
|
||||
case SIOC_L2CAP_NODE_GET_FLAGS: {
|
||||
struct ng_btsocket_l2cap_raw_node_flags *p =
|
||||
(struct ng_btsocket_l2cap_raw_node_flags *) data;
|
||||
|
||||
ng_btsocket_l2cap_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_NODE_GET_FLAGS,
|
||||
0, M_WAITOK);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg,
|
||||
rt->hook, NULL);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "l2ctl",
|
||||
ng_btsocket_l2cap_raw_ioctl_timeout * hz);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_L2CAP_NODE_GET_FLAGS)
|
||||
p->flags = *((ng_l2cap_node_flags_ep *)
|
||||
(pcb->msg->data));
|
||||
else
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
error = ng_btsocket_l2cap_raw_send_sync_ngmsg(pcb,
|
||||
NGM_L2CAP_NODE_GET_FLAGS,
|
||||
&p->flags, sizeof(p->flags));
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_NODE_GET_DEBUG: {
|
||||
struct ng_btsocket_l2cap_raw_node_debug *p =
|
||||
(struct ng_btsocket_l2cap_raw_node_debug *) data;
|
||||
|
||||
ng_btsocket_l2cap_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_NODE_GET_DEBUG,
|
||||
0, M_WAITOK);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg,
|
||||
rt->hook, NULL);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "l2ctl",
|
||||
ng_btsocket_l2cap_raw_ioctl_timeout * hz);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_L2CAP_NODE_GET_DEBUG)
|
||||
p->debug = *((ng_l2cap_node_debug_ep *)
|
||||
(pcb->msg->data));
|
||||
else
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
error = ng_btsocket_l2cap_raw_send_sync_ngmsg(pcb,
|
||||
NGM_L2CAP_NODE_GET_DEBUG,
|
||||
&p->debug, sizeof(p->debug));
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_NODE_SET_DEBUG: {
|
||||
struct ng_btsocket_l2cap_raw_node_debug *p =
|
||||
(struct ng_btsocket_l2cap_raw_node_debug *) data;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_NODE_SET_DEBUG,
|
||||
sizeof(ng_l2cap_node_debug_ep), M_WAITOK);
|
||||
if (msg == NULL) {
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
*((ng_l2cap_node_debug_ep *)(msg->data)) = p->debug;
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node,
|
||||
msg, rt->hook, NULL);
|
||||
if (pcb->flags & NG_BTSOCKET_L2CAP_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_l2cap_raw_send_ngmsg(pcb->rt->hook,
|
||||
NGM_L2CAP_NODE_SET_DEBUG,
|
||||
&p->debug, sizeof(p->debug));
|
||||
else
|
||||
error = EPERM;
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_NODE_GET_CON_LIST: {
|
||||
@ -860,32 +844,30 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ng_btsocket_l2cap_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, NGM_L2CAP_NODE_GET_CON_LIST,
|
||||
0, M_WAITOK);
|
||||
0, M_NOWAIT);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
ng_btsocket_l2cap_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg,
|
||||
rt->hook, NULL);
|
||||
pcb->rt->hook, NULL);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "l2ctl",
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "l2ctl",
|
||||
ng_btsocket_l2cap_raw_ioctl_timeout * hz);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_L2CAP_NODE_GET_CON_LIST) {
|
||||
@ -903,7 +885,6 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_NODE_GET_CHAN_LIST: {
|
||||
@ -919,31 +900,29 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
break;
|
||||
}
|
||||
|
||||
ng_btsocket_l2cap_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE,
|
||||
NGM_L2CAP_NODE_GET_CHAN_LIST, 0, M_WAITOK);
|
||||
NGM_L2CAP_NODE_GET_CHAN_LIST, 0, M_NOWAIT);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
ng_btsocket_l2cap_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg,
|
||||
rt->hook, NULL);
|
||||
pcb->rt->hook, NULL);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "l2ctl",
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "l2ctl",
|
||||
ng_btsocket_l2cap_raw_ioctl_timeout * hz);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_L2CAP_NODE_GET_CHAN_LIST) {
|
||||
@ -961,7 +940,6 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_L2CA_PING: {
|
||||
@ -970,33 +948,30 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
ng_l2cap_l2ca_ping_ip *ip = NULL;
|
||||
ng_l2cap_l2ca_ping_op *op = NULL;
|
||||
|
||||
if (!(pcb->flags & NG_BTSOCKET_L2CAP_RAW_PRIVILEGED)) {
|
||||
error = EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((p->echo_size != 0 && p->echo_data == NULL) ||
|
||||
p->echo_size > NG_L2CAP_MAX_ECHO_SIZE) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Loop back local ping */
|
||||
if (bcmp(&p->echo_dst, &rt->src, sizeof(rt->src)) == 0) {
|
||||
p->result = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
ng_btsocket_l2cap_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE,
|
||||
NGM_L2CAP_L2CA_PING, sizeof(*ip) + p->echo_size,
|
||||
M_WAITOK);
|
||||
M_NOWAIT);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
ng_btsocket_l2cap_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
ip = (ng_l2cap_l2ca_ping_ip *)(msg->data);
|
||||
bcopy(&p->echo_dst, &ip->bdaddr, sizeof(ip->bdaddr));
|
||||
bcopy(&pcb->dst, &ip->bdaddr, sizeof(ip->bdaddr));
|
||||
ip->echo_size = p->echo_size;
|
||||
|
||||
if (ip->echo_size > 0) {
|
||||
@ -1009,18 +984,18 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
}
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg,
|
||||
rt->hook, NULL);
|
||||
pcb->rt->hook, NULL);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "l2ctl",
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "l2ctl",
|
||||
bluetooth_l2cap_rtx_timeout());
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_L2CAP_L2CA_PING) {
|
||||
@ -1036,7 +1011,6 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_L2CA_GET_INFO: {
|
||||
@ -1045,42 +1019,44 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
ng_l2cap_l2ca_get_info_ip *ip = NULL;
|
||||
ng_l2cap_l2ca_get_info_op *op = NULL;
|
||||
|
||||
if ((p->info_size != 0 && p->info_data == NULL) ||
|
||||
bcmp(&p->info_dst, &rt->src, sizeof(rt->src)) == 0) {
|
||||
if (!(pcb->flags & NG_BTSOCKET_L2CAP_RAW_PRIVILEGED)) {
|
||||
error = EPERM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (p->info_size != 0 && p->info_data == NULL) {
|
||||
error = EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
ng_btsocket_l2cap_raw_get_token(&pcb->token);
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE,
|
||||
NGM_L2CAP_L2CA_GET_INFO, sizeof(*ip) + p->info_size,
|
||||
M_WAITOK);
|
||||
M_NOWAIT);
|
||||
if (msg == NULL) {
|
||||
pcb->token = 0;
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
msg->header.token = pcb->token;
|
||||
ng_btsocket_l2cap_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
ip = (ng_l2cap_l2ca_get_info_ip *)(msg->data);
|
||||
bcopy(&p->info_dst, &ip->bdaddr, sizeof(ip->bdaddr));
|
||||
bcopy(&pcb->dst, &ip->bdaddr, sizeof(ip->bdaddr));
|
||||
ip->info_type = p->info_type;
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg,
|
||||
rt->hook, NULL);
|
||||
pcb->rt->hook, NULL);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
error = tsleep(&pcb->msg, PZERO|PCATCH, "l2ctl",
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "l2ctl",
|
||||
bluetooth_l2cap_rtx_timeout());
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (pcb->msg != NULL &&
|
||||
pcb->msg->header.cmd == NGM_L2CAP_L2CA_GET_INFO) {
|
||||
@ -1096,7 +1072,27 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
pcb->token = 0;
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_NODE_GET_AUTO_DISCON_TIMO: {
|
||||
struct ng_btsocket_l2cap_raw_auto_discon_timo *p =
|
||||
(struct ng_btsocket_l2cap_raw_auto_discon_timo *) data;
|
||||
|
||||
error = ng_btsocket_l2cap_raw_send_sync_ngmsg(pcb,
|
||||
NGM_L2CAP_NODE_GET_AUTO_DISCON_TIMO,
|
||||
&p->timeout, sizeof(p->timeout));
|
||||
} break;
|
||||
|
||||
case SIOC_L2CAP_NODE_SET_AUTO_DISCON_TIMO: {
|
||||
struct ng_btsocket_l2cap_raw_auto_discon_timo *p =
|
||||
(struct ng_btsocket_l2cap_raw_auto_discon_timo *) data;
|
||||
|
||||
if (pcb->flags & NG_BTSOCKET_L2CAP_RAW_PRIVILEGED)
|
||||
error = ng_btsocket_l2cap_raw_send_ngmsg(pcb->rt->hook,
|
||||
NGM_L2CAP_NODE_SET_AUTO_DISCON_TIMO,
|
||||
&p->timeout, sizeof(p->timeout));
|
||||
else
|
||||
error = EPERM;
|
||||
} break;
|
||||
|
||||
default:
|
||||
@ -1104,6 +1100,8 @@ ng_btsocket_l2cap_raw_control(struct socket *so, u_long cmd, caddr_t data,
|
||||
break;
|
||||
}
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
|
||||
return (error);
|
||||
} /* ng_btsocket_l2cap_raw_control */
|
||||
|
||||
@ -1121,16 +1119,22 @@ ng_btsocket_l2cap_raw_detach(struct socket *so)
|
||||
if (ng_btsocket_l2cap_raw_node == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
so->so_pcb = NULL;
|
||||
sotryfree(so);
|
||||
|
||||
mtx_lock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
|
||||
LIST_REMOVE(pcb, next);
|
||||
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_sockets_mtx);
|
||||
|
||||
mtx_destroy(&pcb->pcb_mtx);
|
||||
|
||||
bzero(pcb, sizeof(*pcb));
|
||||
FREE(pcb, M_NETGRAPH_BTSOCKET_L2CAP_RAW);
|
||||
|
||||
so->so_pcb = NULL;
|
||||
sotryfree(so);
|
||||
|
||||
return (0);
|
||||
} /* ng_btsocket_l2cap_raw_detach */
|
||||
|
||||
@ -1148,8 +1152,10 @@ ng_btsocket_l2cap_raw_disconnect(struct socket *so)
|
||||
if (ng_btsocket_l2cap_raw_node == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
mtx_lock(&pcb->pcb_mtx);
|
||||
pcb->rt = NULL;
|
||||
soisdisconnected(so);
|
||||
mtx_unlock(&pcb->pcb_mtx);
|
||||
|
||||
return (0);
|
||||
} /* ng_btsocket_l2cap_raw_disconnect */
|
||||
@ -1161,7 +1167,22 @@ ng_btsocket_l2cap_raw_disconnect(struct socket *so)
|
||||
int
|
||||
ng_btsocket_l2cap_raw_peeraddr(struct socket *so, struct sockaddr **nam)
|
||||
{
|
||||
return (EOPNOTSUPP);
|
||||
ng_btsocket_l2cap_raw_pcb_p pcb = so2l2cap_raw_pcb(so);
|
||||
struct sockaddr_l2cap sa;
|
||||
|
||||
if (pcb == NULL)
|
||||
return (EINVAL);
|
||||
if (ng_btsocket_l2cap_raw_node == NULL)
|
||||
return (EINVAL);
|
||||
|
||||
bcopy(&pcb->dst, &sa.l2cap_bdaddr, sizeof(sa.l2cap_bdaddr));
|
||||
sa.l2cap_psm = 0;
|
||||
sa.l2cap_len = sizeof(sa);
|
||||
sa.l2cap_family = AF_BLUETOOTH;
|
||||
|
||||
*nam = dup_sockaddr((struct sockaddr *) &sa, 0);
|
||||
|
||||
return ((*nam == NULL)? ENOMEM : 0);
|
||||
} /* ng_btsocket_l2cap_raw_peeraddr */
|
||||
|
||||
/*
|
||||
@ -1220,3 +1241,70 @@ ng_btsocket_l2cap_raw_get_token(u_int32_t *token)
|
||||
mtx_unlock(&ng_btsocket_l2cap_raw_token_mtx);
|
||||
} /* ng_btsocket_l2cap_raw_get_token */
|
||||
|
||||
/*
|
||||
* Send Netgraph message to the node - do not expect reply
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_btsocket_l2cap_raw_send_ngmsg(hook_p hook, int cmd, void *arg, int arglen)
|
||||
{
|
||||
struct ng_mesg *msg = NULL;
|
||||
int error = 0;
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, cmd, arglen, M_NOWAIT);
|
||||
if (msg == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
if (arg != NULL && arglen > 0)
|
||||
bcopy(arg, msg->data, arglen);
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg, hook, NULL);
|
||||
|
||||
return (error);
|
||||
} /* ng_btsocket_l2cap_raw_send_ngmsg */
|
||||
|
||||
/*
|
||||
* Send Netgraph message to the node (no data) and wait for reply
|
||||
*/
|
||||
|
||||
static int
|
||||
ng_btsocket_l2cap_raw_send_sync_ngmsg(ng_btsocket_l2cap_raw_pcb_p pcb,
|
||||
int cmd, void *rsp, int rsplen)
|
||||
{
|
||||
struct ng_mesg *msg = NULL;
|
||||
int error = 0;
|
||||
|
||||
mtx_assert(&pcb->pcb_mtx, MA_OWNED);
|
||||
|
||||
NG_MKMESSAGE(msg, NGM_L2CAP_COOKIE, cmd, 0, M_NOWAIT);
|
||||
if (msg == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
ng_btsocket_l2cap_raw_get_token(&msg->header.token);
|
||||
pcb->token = msg->header.token;
|
||||
pcb->msg = NULL;
|
||||
|
||||
NG_SEND_MSG_HOOK(error, ng_btsocket_l2cap_raw_node, msg,
|
||||
pcb->rt->hook, NULL);
|
||||
if (error != 0) {
|
||||
pcb->token = 0;
|
||||
return (error);
|
||||
}
|
||||
|
||||
error = msleep(&pcb->msg, &pcb->pcb_mtx, PZERO|PCATCH, "l2ctl",
|
||||
ng_btsocket_l2cap_raw_ioctl_timeout * hz);
|
||||
pcb->token = 0;
|
||||
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
if (pcb->msg != NULL && pcb->msg->header.cmd == cmd)
|
||||
bcopy(pcb->msg->data, rsp, rsplen);
|
||||
else
|
||||
error = EINVAL;
|
||||
|
||||
NG_FREE_MSG(pcb->msg); /* checks for != NULL */
|
||||
|
||||
return (0);
|
||||
} /* ng_btsocket_l2cap_raw_send_sync_ngmsg */
|
||||
|
||||
|
3570
sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
Normal file
3570
sys/netgraph/bluetooth/socket/ng_btsocket_rfcomm.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,8 @@
|
||||
# $Id $
|
||||
# $FreeBSD$
|
||||
SUBDIR= btsockstat
|
||||
|
||||
SUBDIR= btsockstat \
|
||||
rfcomm_sppd
|
||||
|
||||
.include <bsd.subdir.mk>
|
||||
|
||||
|
@ -1,14 +1,16 @@
|
||||
# $Id: Makefile,v 1.1.1.1 2002/09/09 16:12:49 max Exp $
|
||||
# $Id: Makefile,v 1.3 2003/03/24 23:59:49 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= btsockstat
|
||||
BINGRP= kmem
|
||||
BINMODE= 2555
|
||||
MAN1= btsockstat.1
|
||||
|
||||
DESTDIR= /usr/bin/
|
||||
MANDIR= ../share/man/man
|
||||
|
||||
WARNS?= 2
|
||||
CFLAGS+= -g -I../../../sys/netgraph/bluetooth/include/
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include/
|
||||
|
||||
SRCS= btsockstat.c
|
||||
DPADD= ${LIBKVM}
|
||||
|
@ -1,3 +1,5 @@
|
||||
.\" btsockstat.1
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2002 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
@ -22,8 +24,8 @@
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id: btsockstat.1,v 1.4 2003/04/27 19:25:15 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd August 31, 2002
|
||||
.Dt BTSOCKSTAT 1
|
||||
.Os
|
||||
@ -33,43 +35,42 @@
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl p Ar protocol
|
||||
.Op Fl r
|
||||
.Op Fl r
|
||||
.Op Fl M Ar core
|
||||
.Op Fl h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
utility symbolically displays the contents of various Bluetooth sockets
|
||||
related data structures.
|
||||
There are few output formats, depending on the
|
||||
.Nm
|
||||
command symbolically displays the contents of various Bluetooth sockets
|
||||
related data structures. There are few output formats, depending on the
|
||||
options for the information presented.
|
||||
The
|
||||
.Nm
|
||||
utility
|
||||
will print results to the standard output and error messages to the
|
||||
will print results to the standard output and error messages to the
|
||||
standard error.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl p Ar protocol
|
||||
Display a list of active sockets (protocol control blocks) for each
|
||||
specified protocol.
|
||||
Supported protocols are:
|
||||
.Cm hci_raw , l2cap_raw
|
||||
Display a list of active sockets (protocol control blocks) for each
|
||||
specified protocol. Supported protocols are:
|
||||
.Cm hci_raw , l2cap_raw , l2cap, rfcomm
|
||||
and
|
||||
.Cm l2cap .
|
||||
.Cm rfcomm_s .
|
||||
.It Fl r
|
||||
Display a list of active routing entries (if any) for specified protocol.
|
||||
.It Fl M Ar core
|
||||
Extract values associated with the name list from the specified core
|
||||
Extract values associated with the name list from the specified core
|
||||
instead of the default
|
||||
.Pa /dev/kmem .
|
||||
.It Fl h
|
||||
Display usage message and exit.
|
||||
.El
|
||||
.Sh BUGS
|
||||
Most likely.
|
||||
Please report if found.
|
||||
Most likely. Please report if found.
|
||||
.Sh DIAGNOSTICS
|
||||
.Ex -std
|
||||
.Sh SEE ALSO
|
||||
.Xr ng_btsocket 4
|
||||
.Sh AUTHORS
|
||||
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
|
||||
|
||||
|
@ -25,7 +25,7 @@
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: btsockstat.c,v 1.2 2002/09/16 19:40:14 max Exp $
|
||||
* $Id: btsockstat.c,v 1.4 2003/03/29 22:28:18 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
@ -45,11 +45,13 @@
|
||||
#include <kvm.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <ng_bluetooth.h>
|
||||
#include <ng_hci.h>
|
||||
#include <ng_l2cap.h>
|
||||
#include <ng_btsocket.h>
|
||||
#include <ng_btsocket_hci_raw.h>
|
||||
#include <ng_btsocket_l2cap.h>
|
||||
#include <ng_btsocket_rfcomm.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -60,6 +62,8 @@ static void hcirawpr (kvm_t *kvmd, u_long addr);
|
||||
static void l2caprawpr (kvm_t *kvmd, u_long addr);
|
||||
static void l2cappr (kvm_t *kvmd, u_long addr);
|
||||
static void l2caprtpr (kvm_t *kvmd, u_long addr);
|
||||
static void rfcommpr (kvm_t *kvmd, u_long addr);
|
||||
static void rfcommpr_s (kvm_t *kvmd, u_long addr);
|
||||
|
||||
static kvm_t * kopen (char const *memf);
|
||||
static int kread (kvm_t *kvmd, u_long addr, char *buffer, int size);
|
||||
@ -81,9 +85,16 @@ static struct nlist nl[] = {
|
||||
{ "_ng_btsocket_l2cap_raw_rt" },
|
||||
#define N_L2CAP_RT 4
|
||||
{ "_ng_btsocket_l2cap_rt" },
|
||||
#define N_RFCOMM 5
|
||||
{ "_ng_btsocket_rfcomm_sockets" },
|
||||
#define N_RFCOMM_S 6
|
||||
{ "_ng_btsocket_rfcomm_sessions" },
|
||||
{ "" },
|
||||
};
|
||||
|
||||
#define state2str(x) \
|
||||
(((x) >= sizeof(states)/sizeof(states[0]))? "UNKNOWN" : states[(x)])
|
||||
|
||||
/*
|
||||
* Main
|
||||
*/
|
||||
@ -108,6 +119,10 @@ main(int argc, char *argv[])
|
||||
proto = N_L2CAP_RAW;
|
||||
else if (strcasecmp(optarg, "l2cap") == 0)
|
||||
proto = N_L2CAP;
|
||||
else if (strcasecmp(optarg, "rfcomm") == 0)
|
||||
proto = N_RFCOMM;
|
||||
else if (strcasecmp(optarg, "rfcomm_s") == 0)
|
||||
proto = N_RFCOMM_S;
|
||||
else
|
||||
usage();
|
||||
/* NOT REACHED */
|
||||
@ -124,10 +139,18 @@ main(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
|
||||
if (proto == N_HCI_RAW && route)
|
||||
if ((proto == N_HCI_RAW || proto == N_RFCOMM || proto == N_RFCOMM_S) && route)
|
||||
usage();
|
||||
/* NOT REACHED */
|
||||
|
||||
/*
|
||||
* Discard setgid privileges if not the running kernel so that
|
||||
* bad guys can't print interesting stuff from kernel memory.
|
||||
*/
|
||||
|
||||
if (memf != NULL)
|
||||
setgid(getgid());
|
||||
|
||||
kvmd = kopen(memf);
|
||||
if (kvmd == NULL)
|
||||
return (1);
|
||||
@ -151,6 +174,14 @@ main(int argc, char *argv[])
|
||||
l2cappr(kvmd, nl[N_L2CAP].n_value);
|
||||
break;
|
||||
|
||||
case N_RFCOMM:
|
||||
rfcommpr(kvmd, nl[N_RFCOMM].n_value);
|
||||
break;
|
||||
|
||||
case N_RFCOMM_S:
|
||||
rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value);
|
||||
break;
|
||||
|
||||
default:
|
||||
if (route) {
|
||||
l2caprtpr(kvmd, nl[N_L2CAP_RAW_RT].n_value);
|
||||
@ -159,6 +190,8 @@ main(int argc, char *argv[])
|
||||
hcirawpr(kvmd, nl[N_HCI_RAW].n_value);
|
||||
l2caprawpr(kvmd, nl[N_L2CAP_RAW].n_value);
|
||||
l2cappr(kvmd, nl[N_L2CAP].n_value);
|
||||
rfcommpr_s(kvmd, nl[N_RFCOMM_S].n_value);
|
||||
rfcommpr(kvmd, nl[N_RFCOMM].n_value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -252,7 +285,7 @@ l2caprawpr(kvm_t *kvmd, u_long addr)
|
||||
first = 0;
|
||||
fprintf(stdout,
|
||||
"Active raw L2CAP sockets\n" \
|
||||
"%-8.8s %-8.8s %-6.6s %-6.6s %-18.18s\n",
|
||||
"%-8.8s %-8.8s %-6.6s %-6.6s %-17.17s\n",
|
||||
"Socket",
|
||||
"PCB",
|
||||
"Recv-Q",
|
||||
@ -270,7 +303,7 @@ l2caprawpr(kvm_t *kvmd, u_long addr)
|
||||
pcb.src.b[2], pcb.src.b[1], pcb.src.b[0]);
|
||||
|
||||
fprintf(stdout,
|
||||
"%-8.8x %-8.8x %6d %6d %-18.18s\n",
|
||||
"%-8.8x %-8.8x %6d %6d %-17.17s\n",
|
||||
(int) pcb.so,
|
||||
(int) this,
|
||||
so.so_rcv.sb_cc,
|
||||
@ -293,8 +326,6 @@ l2cappr(kvm_t *kvmd, u_long addr)
|
||||
/* NG_BTSOCKET_L2CAP_OPEN */ "OPEN",
|
||||
/* NG_BTSOCKET_L2CAP_DISCONNECTING */ "DISCON"
|
||||
};
|
||||
#define state2str(x) \
|
||||
(((x) >= sizeof(states)/sizeof(states[0]))? "UNKNOWN" : states[(x)])
|
||||
|
||||
ng_btsocket_l2cap_pcb_p this = NULL, next = NULL;
|
||||
ng_btsocket_l2cap_pcb_t pcb;
|
||||
@ -302,7 +333,6 @@ l2cappr(kvm_t *kvmd, u_long addr)
|
||||
int first = 1;
|
||||
char local[32], remote[32];
|
||||
|
||||
|
||||
if (addr == 0)
|
||||
return;
|
||||
|
||||
@ -321,7 +351,7 @@ l2cappr(kvm_t *kvmd, u_long addr)
|
||||
first = 0;
|
||||
fprintf(stdout,
|
||||
"Active L2CAP sockets\n" \
|
||||
"%-8.8s %-6.6s %-6.6s %-24.24s %-18.18s %-5.5s %s\n",
|
||||
"%-8.8s %-6.6s %-6.6s %-23.23s %-17.17s %-5.5s %s\n",
|
||||
"PCB",
|
||||
"Recv-Q",
|
||||
"Send-Q",
|
||||
@ -350,7 +380,7 @@ l2cappr(kvm_t *kvmd, u_long addr)
|
||||
pcb.dst.b[2], pcb.dst.b[1], pcb.dst.b[0]);
|
||||
|
||||
fprintf(stdout,
|
||||
"%-8.8x %6d %6d %-24.24s %-18.18s %-5d %s\n",
|
||||
"%-8.8x %6d %6d %-23.23s %-17.17s %-5d %s\n",
|
||||
(int) this,
|
||||
so.so_rcv.sb_cc,
|
||||
so.so_snd.sb_cc,
|
||||
@ -391,7 +421,7 @@ l2caprtpr(kvm_t *kvmd, u_long addr)
|
||||
fprintf(stdout,
|
||||
"Known %sL2CAP routes\n", (addr == nl[N_L2CAP_RAW_RT].n_value)? "raw " : "");
|
||||
fprintf(stdout,
|
||||
"%-8.8s %-8.8s %-18.18s\n", "RTentry",
|
||||
"%-8.8s %-8.8s %-17.17s\n", "RTentry",
|
||||
"Hook",
|
||||
"BD_ADDR");
|
||||
}
|
||||
@ -405,13 +435,157 @@ l2caprtpr(kvm_t *kvmd, u_long addr)
|
||||
rt.src.b[2], rt.src.b[1], rt.src.b[0]);
|
||||
|
||||
fprintf(stdout,
|
||||
"%-8.8x %-8.8x %-18.18s\n",
|
||||
"%-8.8x %-8.8x %-17.17s\n",
|
||||
(int) this,
|
||||
(int) rt.hook,
|
||||
bdaddr);
|
||||
}
|
||||
} /* l2caprtpr */
|
||||
|
||||
/*
|
||||
* Print RFCOMM sockets
|
||||
*/
|
||||
|
||||
static void
|
||||
rfcommpr(kvm_t *kvmd, u_long addr)
|
||||
{
|
||||
static char const * const states[] = {
|
||||
/* NG_BTSOCKET_RFCOMM_DLC_CLOSED */ "CLOSED",
|
||||
/* NG_BTSOCKET_RFCOMM_DLC_W4_CONNECT */ "W4CON",
|
||||
/* NG_BTSOCKET_RFCOMM_DLC_CONFIGURING */ "CONFIG",
|
||||
/* NG_BTSOCKET_RFCOMM_DLC_CONNECTING */ "CONN",
|
||||
/* NG_BTSOCKET_RFCOMM_DLC_CONNECTED */ "OPEN",
|
||||
/* NG_BTSOCKET_RFCOMM_DLC_DISCONNECTING */ "DISCON"
|
||||
};
|
||||
|
||||
ng_btsocket_rfcomm_pcb_p this = NULL, next = NULL;
|
||||
ng_btsocket_rfcomm_pcb_t pcb;
|
||||
struct socket so;
|
||||
int first = 1;
|
||||
char local[32], remote[32];
|
||||
|
||||
if (addr == 0)
|
||||
return;
|
||||
|
||||
if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
|
||||
return;
|
||||
|
||||
for ( ; this != NULL; this = next) {
|
||||
if (kread(kvmd, (u_long) this, (char *) &pcb, sizeof(pcb)) < 0)
|
||||
return;
|
||||
if (kread(kvmd, (u_long) pcb.so, (char *) &so, sizeof(so)) < 0)
|
||||
return;
|
||||
|
||||
next = LIST_NEXT(&pcb, next);
|
||||
|
||||
if (first) {
|
||||
first = 0;
|
||||
fprintf(stdout,
|
||||
"Active RFCOMM sockets\n" \
|
||||
"%-8.8s %-6.6s %-6.6s %-17.17s %-17.17s %-4.4s %-4.4s %s\n",
|
||||
"PCB",
|
||||
"Recv-Q",
|
||||
"Send-Q",
|
||||
"Local address",
|
||||
"Foreign address",
|
||||
"Chan",
|
||||
"DLCI",
|
||||
"State");
|
||||
}
|
||||
|
||||
if (memcmp(&pcb.src, NG_HCI_BDADDR_ANY, sizeof(pcb.src)) == 0) {
|
||||
local[0] = '*';
|
||||
local[1] = 0;
|
||||
} else
|
||||
snprintf(local, sizeof(local),
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
pcb.src.b[5], pcb.src.b[4], pcb.src.b[3],
|
||||
pcb.src.b[2], pcb.src.b[1], pcb.src.b[0]);
|
||||
|
||||
if (memcmp(&pcb.dst, NG_HCI_BDADDR_ANY, sizeof(pcb.dst)) == 0) {
|
||||
remote[0] = '*';
|
||||
remote[1] = 0;
|
||||
} else
|
||||
snprintf(remote, sizeof(remote),
|
||||
"%02x:%02x:%02x:%02x:%02x:%02x",
|
||||
pcb.dst.b[5], pcb.dst.b[4], pcb.dst.b[3],
|
||||
pcb.dst.b[2], pcb.dst.b[1], pcb.dst.b[0]);
|
||||
|
||||
fprintf(stdout,
|
||||
"%-8.8x %6d %6d %-17.17s %-17.17s %-4d %-4d %s\n",
|
||||
(int) this,
|
||||
so.so_rcv.sb_cc,
|
||||
so.so_snd.sb_cc,
|
||||
local,
|
||||
remote,
|
||||
pcb.channel,
|
||||
pcb.dlci,
|
||||
(so.so_options & SO_ACCEPTCONN)?
|
||||
"LISTEN" : state2str(pcb.state));
|
||||
}
|
||||
} /* rfcommpr */
|
||||
|
||||
/*
|
||||
* Print RFCOMM sessions
|
||||
*/
|
||||
|
||||
static void
|
||||
rfcommpr_s(kvm_t *kvmd, u_long addr)
|
||||
{
|
||||
static char const * const states[] = {
|
||||
/* NG_BTSOCKET_RFCOMM_SESSION_CLOSED */ "CLOSED",
|
||||
/* NG_BTSOCKET_RFCOMM_SESSION_LISTENING */ "LISTEN",
|
||||
/* NG_BTSOCKET_RFCOMM_SESSION_CONNECTING */ "CONNECTING",
|
||||
/* NG_BTSOCKET_RFCOMM_SESSION_CONNECTED */ "CONNECTED",
|
||||
/* NG_BTSOCKET_RFCOMM_SESSION_OPEN */ "OPEN",
|
||||
/* NG_BTSOCKET_RFCOMM_SESSION_DISCONNECTING */ "DISCONNECTING"
|
||||
};
|
||||
|
||||
ng_btsocket_rfcomm_session_p this = NULL, next = NULL;
|
||||
ng_btsocket_rfcomm_session_t s;
|
||||
struct socket so;
|
||||
int first = 1;
|
||||
|
||||
if (addr == 0)
|
||||
return;
|
||||
|
||||
if (kread(kvmd, addr, (char *) &this, sizeof(this)) < 0)
|
||||
return;
|
||||
|
||||
for ( ; this != NULL; this = next) {
|
||||
if (kread(kvmd, (u_long) this, (char *) &s, sizeof(s)) < 0)
|
||||
return;
|
||||
if (kread(kvmd, (u_long) s.l2so, (char *) &so, sizeof(so)) < 0)
|
||||
return;
|
||||
|
||||
next = LIST_NEXT(&s, next);
|
||||
|
||||
if (first) {
|
||||
first = 0;
|
||||
fprintf(stdout,
|
||||
"Active RFCOMM sessions\n" \
|
||||
"%-8.8s %-8.8s %-4.4s %-5.5s %-5.5s %-4.4s %s\n",
|
||||
"L2PCB",
|
||||
"PCB",
|
||||
"Flags",
|
||||
"MTU",
|
||||
"Out-Q",
|
||||
"DLCs",
|
||||
"State");
|
||||
}
|
||||
|
||||
fprintf(stdout,
|
||||
"%-8.8x %-8.8x %-4x %-5d %-5d %-4s %s\n",
|
||||
(int) so.so_pcb,
|
||||
(int) this,
|
||||
s.flags,
|
||||
s.mtu,
|
||||
s.outq.len,
|
||||
LIST_EMPTY(&s.dlcs)? "No" : "Yes",
|
||||
state2str(s.state));
|
||||
}
|
||||
} /* rfcommpr_s */
|
||||
|
||||
/*
|
||||
* Open kvm
|
||||
*/
|
||||
|
15
usr.bin/bluetooth/rfcomm_sppd/Makefile
Normal file
15
usr.bin/bluetooth/rfcomm_sppd/Makefile
Normal file
@ -0,0 +1,15 @@
|
||||
# $Id: Makefile,v 1.2 2003/04/26 23:55:34 max Exp $
|
||||
# $FreeBSD$
|
||||
|
||||
PROG= rfcomm_sppd
|
||||
MAN1= rfcomm_sppd.1
|
||||
|
||||
DESTDIR= /usr/bin/
|
||||
MANDIR= ../share/man/man
|
||||
|
||||
WARNS?= 2
|
||||
CFLAGS+= -g -I${.CURDIR}/../../../sys/netgraph/bluetooth/include/
|
||||
|
||||
SRCS= rfcomm_sppd.c
|
||||
|
||||
.include <bsd.prog.mk>
|
107
usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
Normal file
107
usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.1
Normal file
@ -0,0 +1,107 @@
|
||||
.\" rfcomm_pppd.1
|
||||
.\"
|
||||
.\" Copyright (c) 2001-2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
.\" All rights reserved.
|
||||
.\"
|
||||
.\" Redistribution and use in source and binary forms, with or without
|
||||
.\" modification, are permitted provided that the following conditions
|
||||
.\" are met:
|
||||
.\" 1. Redistributions of source code must retain the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer.
|
||||
.\" 2. Redistributions in binary form must reproduce the above copyright
|
||||
.\" notice, this list of conditions and the following disclaimer in the
|
||||
.\" documentation and/or other materials provided with the distribution.
|
||||
.\"
|
||||
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
.\" SUCH DAMAGE.
|
||||
.\"
|
||||
.\" $Id: rfcomm_sppd.1,v 1.1 2003/04/26 23:55:34 max Exp $
|
||||
.\" $FreeBSD$
|
||||
.Dd April 26, 2003
|
||||
.Dt RFCOMM_SPPD 1
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rfcomm_sppd
|
||||
.Nd RFCOMM Serial Port Profile daemon
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl a Ar BD_ADDR
|
||||
.Op Fl b
|
||||
.Op Fl c Ar channel
|
||||
.Op Fl t Ar tty
|
||||
.Op Fl h
|
||||
.Sh DESCRIPTION
|
||||
The
|
||||
.Nm
|
||||
is a Serial Port Profile daemon. It opens RFCOMM connection to the
|
||||
specified server's BD_ADDR and channel. Once connection is established
|
||||
.Nm
|
||||
provides access to the server's remote serial port via
|
||||
.Xr pty 4
|
||||
interface.
|
||||
.Pp
|
||||
.Nm
|
||||
opens both master and slave pseudo terminals. This is done to ensure that
|
||||
RFCOMM connection stays open until
|
||||
.Nm
|
||||
is terminated. The data received from the master pseudo terminal are sent over
|
||||
the RFCOMM connection. The data received from the RFCOMM connection are written
|
||||
into master pseudo terminal. The application in its turn opens slave pseudo
|
||||
terminal and operates on it just like it would operate over the standard serial
|
||||
port.
|
||||
.Pp
|
||||
The options are as follows:
|
||||
.Bl -tag -width indent
|
||||
.It Fl a Ar BD_ADDR
|
||||
This requied option specifies the remote BD_ADDR of the RFCOMM server.
|
||||
.It Fl b
|
||||
Detach from the controlling terminal, i.e. run in background.
|
||||
.It Fl c Ar channel
|
||||
This required option specifies RFCOMM channel to connect to. This channel
|
||||
must provide Serial Port service.
|
||||
.It Fl t Ar tty
|
||||
Slave pseudo tty name.
|
||||
.It Fl h
|
||||
Display usage message and exit.
|
||||
.El
|
||||
.Sh EXAMPLES
|
||||
.Bl -tag -width indent
|
||||
.It rfcomm_sppd -a 00:01:02:03:04:05 -c 1 -t /dev/ttyp1
|
||||
.Pp
|
||||
Will start
|
||||
.Nm
|
||||
and open RFCOMM connection to the server at
|
||||
.Em 00:01:02:03:04:05
|
||||
and channel
|
||||
.Em 1 .
|
||||
Once connection has been established
|
||||
.Pa /dev/ttyp1
|
||||
can be used to talk to the remote serial port on the server.
|
||||
.El
|
||||
.Sh FILES
|
||||
.Bl -tag -width /dev/tty[p-sP-S][0-9a-v]x -compact
|
||||
.It Pa /dev/pty[p-sP-S][0-9a-v]
|
||||
master pseudo terminals
|
||||
.It Pa /dev/tty[p-sP-S][0-9a-v]
|
||||
slave pseudo terminals
|
||||
.El
|
||||
.Sh DIAGNOSTICS
|
||||
.Ex -std
|
||||
.Sh BUGS
|
||||
.Nm
|
||||
currently is not integrated with SDP (Service Discovery Protocol).
|
||||
.Sh SEE ALSO
|
||||
.Xr pty 4 ,
|
||||
.Xr ng_btsocket 4 ,
|
||||
.Xr rfcomm_pppd 8
|
||||
.Sh AUTHORS
|
||||
.An Maksim Yevmenkin Aq m_evmenkin@yahoo.com
|
383
usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
Normal file
383
usr.bin/bluetooth/rfcomm_sppd/rfcomm_sppd.c
Normal file
@ -0,0 +1,383 @@
|
||||
/*
|
||||
* rfcomm_sppd.c
|
||||
*
|
||||
* Copyright (c) 2003 Maksim Yevmenkin <m_evmenkin@yahoo.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $Id: rfcomm_sppd.c,v 1.2 2003/04/27 19:22:30 max Exp $
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <bitstring.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <grp.h>
|
||||
#include <limits.h>
|
||||
#include <ng_hci.h>
|
||||
#include <ng_l2cap.h>
|
||||
#include <ng_btsocket.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define SPPD_IDENT "rfcomm_sppd"
|
||||
#define SPPD_BUFFER_SIZE 1024
|
||||
#define max(a, b) (((a) > (b))? (a) : (b))
|
||||
|
||||
static int sppd_ttys_open (char const *tty, int *amaster, int *aslave);
|
||||
static int sppd_read (int fd, char *buffer, int size);
|
||||
static int sppd_write (int fd, char *buffer, int size);
|
||||
static void sppd_sighandler (int s);
|
||||
static void usage (void);
|
||||
|
||||
static int done; /* are we done? */
|
||||
|
||||
/* Main */
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct sigaction sa;
|
||||
struct sockaddr_rfcomm ra;
|
||||
bdaddr_t addr;
|
||||
int n, background, channel, s, amaster, aslave;
|
||||
fd_set rfd;
|
||||
char *tty = NULL, buf[SPPD_BUFFER_SIZE];
|
||||
|
||||
memcpy(&addr, NG_HCI_BDADDR_ANY, sizeof(addr));
|
||||
background = channel = 0;
|
||||
|
||||
/* Parse command line options */
|
||||
while ((n = getopt(argc, argv, "a:bc:t:h")) != -1) {
|
||||
switch (n) {
|
||||
case 'a': { /* BDADDR */
|
||||
int a0, a1, a2, a3, a4, a5;
|
||||
|
||||
if (sscanf(optarg, "%x:%x:%x:%x:%x:%x",
|
||||
&a5, &a4, &a3, &a2, &a1, &a0) != 6)
|
||||
usage();
|
||||
/* NOT REACHED */
|
||||
|
||||
addr.b[0] = a0 & 0xff;
|
||||
addr.b[1] = a1 & 0xff;
|
||||
addr.b[2] = a2 & 0xff;
|
||||
addr.b[3] = a3 & 0xff;
|
||||
addr.b[4] = a4 & 0xff;
|
||||
addr.b[5] = a5 & 0xff;
|
||||
} break;
|
||||
|
||||
case 'c': /* RFCOMM channel */
|
||||
channel = atoi(optarg);
|
||||
break;
|
||||
|
||||
case 'b': /* Run in background */
|
||||
background = 1;
|
||||
break;
|
||||
|
||||
case 't': /* Slave TTY name */
|
||||
tty = optarg;
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
default:
|
||||
usage();
|
||||
/* NOT REACHED */
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if we have everything we need */
|
||||
if (channel == 0 || tty == NULL ||
|
||||
memcmp(&addr, NG_HCI_BDADDR_ANY, sizeof(addr)) == 0)
|
||||
usage();
|
||||
/* NOT REACHED */
|
||||
|
||||
/* Set signal handlers */
|
||||
memset(&sa, 0, sizeof(sa));
|
||||
sa.sa_handler = sppd_sighandler;
|
||||
|
||||
if (sigaction(SIGTERM, &sa, NULL) < 0)
|
||||
err(1, "Could not sigaction(SIGTERM)");
|
||||
|
||||
if (sigaction(SIGHUP, &sa, NULL) < 0)
|
||||
err(1, "Could not sigaction(SIGHUP)");
|
||||
|
||||
if (sigaction(SIGINT, &sa, NULL) < 0)
|
||||
err(1, "Could not sigaction(SIGINT)");
|
||||
|
||||
sa.sa_handler = SIG_IGN;
|
||||
sa.sa_flags = SA_NOCLDWAIT;
|
||||
|
||||
if (sigaction(SIGCHLD, &sa, NULL) < 0)
|
||||
err(1, "Could not sigaction(SIGCHLD)");
|
||||
|
||||
/* Open TTYs */
|
||||
if (sppd_ttys_open(tty, &amaster, &aslave) < 0)
|
||||
exit(1);
|
||||
|
||||
/* Open RFCOMM connection */
|
||||
memset(&ra, 0, sizeof(ra));
|
||||
ra.rfcomm_len = sizeof(ra);
|
||||
ra.rfcomm_family = AF_BLUETOOTH;
|
||||
|
||||
s = socket(PF_BLUETOOTH, SOCK_STREAM, BLUETOOTH_PROTO_RFCOMM);
|
||||
if (s < 0)
|
||||
err(1, "Could not create socket");
|
||||
|
||||
if (bind(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
|
||||
err(1, "Could not bind socket");
|
||||
|
||||
memcpy(&ra.rfcomm_bdaddr, &addr, sizeof(ra.rfcomm_bdaddr));
|
||||
ra.rfcomm_channel = channel;
|
||||
|
||||
if (connect(s, (struct sockaddr *) &ra, sizeof(ra)) < 0)
|
||||
err(1, "Could not connect socket");
|
||||
|
||||
/* Became daemon if required */
|
||||
if (background) {
|
||||
switch (fork()) {
|
||||
case -1:
|
||||
err(1, "Could not fork()");
|
||||
/* NOT REACHED */
|
||||
|
||||
case 0:
|
||||
exit(0);
|
||||
/* NOT REACHED */
|
||||
|
||||
default:
|
||||
if (daemon(0, 0) < 0)
|
||||
err(1, "Could not daemon()");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
openlog(SPPD_IDENT, LOG_NDELAY|LOG_PERROR|LOG_PID, LOG_DAEMON);
|
||||
syslog(LOG_INFO, "Starting on %s...", tty);
|
||||
|
||||
for (done = 0; !done; ) {
|
||||
FD_ZERO(&rfd);
|
||||
FD_SET(amaster, &rfd);
|
||||
FD_SET(s, &rfd);
|
||||
|
||||
n = select(max(amaster, s) + 1, &rfd, NULL, NULL, NULL);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
syslog(LOG_ERR, "Could not select(). %s",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
continue;
|
||||
|
||||
if (FD_ISSET(amaster, &rfd)) {
|
||||
n = sppd_read(amaster, buf, sizeof(buf));
|
||||
if (n < 0) {
|
||||
syslog(LOG_ERR, "Could not read master pty, " \
|
||||
"fd=%d. %s", amaster, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
break; /* XXX */
|
||||
|
||||
if (sppd_write(s, buf, n) < 0) {
|
||||
syslog(LOG_ERR, "Could not write to socket, " \
|
||||
"fd=%d, size=%d. %s",
|
||||
s, n, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (FD_ISSET(s, &rfd)) {
|
||||
n = sppd_read(s, buf, sizeof(buf));
|
||||
if (n < 0) {
|
||||
syslog(LOG_ERR, "Could not read socket, " \
|
||||
"fd=%d. %s", s, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (n == 0)
|
||||
break;
|
||||
|
||||
if (sppd_write(amaster, buf, n) < 0) {
|
||||
syslog(LOG_ERR, "Could not write to master " \
|
||||
"pty, fd=%d, size=%d. %s",
|
||||
amaster, n, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
syslog(LOG_INFO, "Completed on %s", tty);
|
||||
closelog();
|
||||
|
||||
close(s);
|
||||
close(aslave);
|
||||
close(amaster);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Open TTYs */
|
||||
static int
|
||||
sppd_ttys_open(char const *tty, int *amaster, int *aslave)
|
||||
{
|
||||
char pty[PATH_MAX];
|
||||
struct group *gr = NULL;
|
||||
gid_t ttygid;
|
||||
struct termios tio;
|
||||
|
||||
/*
|
||||
* Master PTY
|
||||
*/
|
||||
|
||||
strlcpy(pty, tty, sizeof(pty));
|
||||
pty[5] = 'p';
|
||||
|
||||
if (strcmp(pty, tty) == 0) {
|
||||
syslog(LOG_ERR, "Master and slave tty are the same (%s)", tty);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if ((*amaster = open(pty, O_RDWR, 0)) < 0) {
|
||||
syslog(LOG_ERR, "Could not open(%s). %s", pty, strerror(errno));
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Slave TTY
|
||||
*/
|
||||
|
||||
if ((gr = getgrnam("tty")) != NULL)
|
||||
ttygid = gr->gr_gid;
|
||||
else
|
||||
ttygid = -1;
|
||||
|
||||
(void) chown(tty, getuid(), ttygid);
|
||||
(void) chmod(tty, S_IRUSR|S_IWUSR|S_IWGRP);
|
||||
(void) revoke(tty);
|
||||
|
||||
if ((*aslave = open(tty, O_RDWR, 0)) < 0) {
|
||||
syslog(LOG_ERR, "Could not open(%s). %s", tty, strerror(errno));
|
||||
close(*amaster);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make slave TTY raw
|
||||
*/
|
||||
|
||||
cfmakeraw(&tio);
|
||||
|
||||
if (tcsetattr(*aslave, TCSANOW, &tio) < 0) {
|
||||
syslog(LOG_ERR, "Could not tcsetattr(). %s", strerror(errno));
|
||||
close(*aslave);
|
||||
close(*amaster);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
} /* sppd_ttys_open */
|
||||
|
||||
/* Read data */
|
||||
static int
|
||||
sppd_read(int fd, char *buffer, int size)
|
||||
{
|
||||
int n;
|
||||
|
||||
again:
|
||||
n = read(fd, buffer, size);
|
||||
if (n < 0) {
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (n);
|
||||
} /* sppd_read */
|
||||
|
||||
/* Write data */
|
||||
static int
|
||||
sppd_write(int fd, char *buffer, int size)
|
||||
{
|
||||
int n, wrote;
|
||||
|
||||
for (wrote = 0; size > 0; ) {
|
||||
n = write(fd, buffer, size);
|
||||
switch (n) {
|
||||
case -1:
|
||||
if (errno != EINTR)
|
||||
return (-1);
|
||||
break;
|
||||
|
||||
case 0:
|
||||
/* XXX can happen? */
|
||||
break;
|
||||
|
||||
default:
|
||||
wrote += n;
|
||||
buffer += n;
|
||||
size -= n;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (wrote);
|
||||
} /* sppd_write */
|
||||
|
||||
/* Signal handler */
|
||||
static void
|
||||
sppd_sighandler(int s)
|
||||
{
|
||||
syslog(LOG_INFO, "Signal %d received. Total %d signals received\n",
|
||||
s, ++ done);
|
||||
} /* sppd_sighandler */
|
||||
|
||||
/* Display usage and exit */
|
||||
static void
|
||||
usage(void)
|
||||
{
|
||||
fprintf(stdout,
|
||||
"Usage: %s options\n" \
|
||||
"Where options are:\n" \
|
||||
"\t-a bdaddr BDADDR to connect to (required)\n" \
|
||||
"\t-b Run in background\n" \
|
||||
"\t-c channel RFCOMM channel to connect to (required)\n" \
|
||||
"\t-t tty TTY name\n" \
|
||||
"\t-h Display this message\n", SPPD_IDENT);
|
||||
|
||||
exit(255);
|
||||
} /* usage */
|
||||
|
Loading…
Reference in New Issue
Block a user