btsocket: support L2CAP, RFCOMM & SCO sockets

Python's socket module doesn't consistently provide these (depending
whether it saw bluetooth.h during build or not), and provides old
versions - so support bind() on them too.

BUG=chromium:256771
TEST=import btsocket, socket
  s1 = btsocket.socket(btsocket.AF_BLUETOOTH, socket.SOCK_SEQPACKET, btsocket.BTPROTO_L2CAP)
  s1.bind((btsocket.BDADDR_ANY, 0))

  s2 = btsocket.socket(btsocket.AF_BLUETOOTH, socket.SOCK_STREAM, btsocket.BTPROTO_RFCOMM)
  s2.bind((btsocket.BDADDR_ANY, 1))

  s3 = btsocket.socket(btsocket.AF_BLUETOOTH, socket.SOCK_RAW, btsocket.BTPROTO_HCI)
  s3.bind((0, btsocket.HCI_CHANNEL_RAW))

  s4 = btsocket.socket(btsocket.AF_BLUETOOTH, socket.SOCK_RAW, btsocket.BTPROTO_HCI)
  s4.bind((btsocket.HCI_DEV_NONE, btsocket.HCI_CHANNEL_CONTROL))

  s5 = btsocket.socket(btsocket.AF_BLUETOOTH, socket.SOCK_RAW, btsocket.BTPROTO_HCI)
  s5.bind((btsocket.HCI_DEV_NONE, btsocket.HCI_CHANNEL_MONITOR))

  s6 = btsocket.socket(btsocket.AF_BLUETOOTH, socket.SOCK_STREAM, btsocket.BTPROTO_SCO)
  s6.bind((btsocket.BDADDR_ANY))

Change-Id: I6d44a11b667e96d7fa3334df80e383911d658405
diff --git a/PRESUBMIT.cfg b/PRESUBMIT.cfg
new file mode 100644
index 0000000..76b4df1
--- /dev/null
+++ b/PRESUBMIT.cfg
@@ -0,0 +1,9 @@
+# This sample config file disables all of the ChromiumOS source style checks.
+# Comment out the disable-flags for any checks you want to leave enabled.
+
+[Hook Overrides]
+#stray_whitespace_check: false
+#long_line_check: false
+cros_license_check: false
+tab_check: false
+
diff --git a/btsocket/btsocket.py b/btsocket/btsocket.py
index 4473830..0b38a77 100644
--- a/btsocket/btsocket.py
+++ b/btsocket/btsocket.py
@@ -6,6 +6,7 @@
 import socket
 
 import _btsocket
+import constants
 
 class BluetoothSocket(socket._socketobject):
     """Socket wrapper class for Bluetooth sockets.
@@ -16,11 +17,11 @@
 
     """
 
-    def __init__(self):
-        # TODO(keybuk): do we want to support other BTPROTO_* ?
-        super(BluetoothSocket, self).__init__(family=socket.AF_BLUETOOTH,
-                                              type=socket.SOCK_RAW,
-                                              proto=socket.BTPROTO_HCI)
+    def __init__(self,
+                 family=constants.AF_BLUETOOTH,
+                 type=socket.SOCK_RAW,
+                 proto=constants.BTPROTO_HCI):
+        super(BluetoothSocket, self).__init__(family, type, proto)
 
     def bind(self, *args):
         """Bind the socket.
@@ -31,10 +32,8 @@
         @param channel channel to bind to, e.g. HCI_CHANNEL_RAW.
 
         """
-        if (self.family == socket.AF_BLUETOOTH and
-            self.type == socket.SOCK_RAW and
-            self.proto == socket.BTPROTO_HCI):
-            return _btsocket.bind(self, *args)
+        if self.family == constants.AF_BLUETOOTH:
+            return _btsocket.bind(self, self.proto, *args)
         else:
             return super(BluetoothSocket, self).bind(*args)
 
diff --git a/btsocket/constants.py b/btsocket/constants.py
index 31b8e2b..e1408e3 100644
--- a/btsocket/constants.py
+++ b/btsocket/constants.py
@@ -54,6 +54,121 @@
 BDADDR_LE_PUBLIC = 0x01
 BDADDR_LE_RANDOM = 0x02
 
+BDADDR_ANY   = "00:00:00:00:00:00"
+BDADDR_ALL   = "FF:FF:FF:FF:FF:FF"
+BDADDR_LOCAL = "00:00:00:FF:FF:FF"
+
+# Constants from src/l2cap.h
+L2CAP_DEFAULT_MTU   = 672
+L2CAP_DEFAULT_FLUSH_TO  = 0xFFFF
+L2CAP_OPTIONS   = 0x01
+L2CAP_CONNINFO  = 0x02
+L2CAP_LM    = 0x03
+L2CAP_LM_MASTER =   0x0001
+L2CAP_LM_AUTH   =   0x0002
+L2CAP_LM_ENCRYPT    = 0x0004
+L2CAP_LM_TRUSTED    = 0x0008
+L2CAP_LM_RELIABLE   = 0x0010
+L2CAP_LM_SECURE =   0x0020
+L2CAP_COMMAND_REJ   = 0x01
+L2CAP_CONN_REQ  =   0x02
+L2CAP_CONN_RSP  =   0x03
+L2CAP_CONF_REQ  =   0x04
+L2CAP_CONF_RSP  =   0x05
+L2CAP_DISCONN_REQ   = 0x06
+L2CAP_DISCONN_RSP   = 0x07
+L2CAP_ECHO_REQ  =   0x08
+L2CAP_ECHO_RSP  =   0x09
+L2CAP_INFO_REQ  =   0x0a
+L2CAP_INFO_RSP  =   0x0b
+L2CAP_CREATE_REQ    = 0x0c
+L2CAP_CREATE_RSP    = 0x0d
+L2CAP_MOVE_REQ  =   0x0e
+L2CAP_MOVE_RSP  =   0x0f
+L2CAP_MOVE_CFM  =   0x10
+L2CAP_MOVE_CFM_RSP  = 0x11
+L2CAP_FEAT_FLOWCTL  = 0x00000001
+L2CAP_FEAT_RETRANS  = 0x00000002
+L2CAP_FEAT_BIDIR_QOS    = 0x00000004
+L2CAP_FEAT_ERTM =   0x00000008
+L2CAP_FEAT_STREAMING    = 0x00000010
+L2CAP_FEAT_FCS  =   0x00000020
+L2CAP_FEAT_EXT_FLOW = 0x00000040
+L2CAP_FEAT_FIXED_CHAN   = 0x00000080
+L2CAP_FEAT_EXT_WINDOW   = 0x00000100
+L2CAP_FEAT_UCD  =   0x00000200
+L2CAP_FC_L2CAP  =   0x02
+L2CAP_FC_CONNLESS   = 0x04
+L2CAP_FC_A2MP   =   0x08
+L2CAP_HDR_SIZE = 4
+L2CAP_CMD_HDR_SIZE = 4
+L2CAP_CMD_REJ_SIZE = 2
+L2CAP_CONN_REQ_SIZE = 4
+L2CAP_CONN_RSP_SIZE = 8
+L2CAP_CR_SUCCESS    = 0x0000
+L2CAP_CR_PEND   =   0x0001
+L2CAP_CR_BAD_PSM    = 0x0002
+L2CAP_CR_SEC_BLOCK  = 0x0003
+L2CAP_CR_NO_MEM =   0x0004
+L2CAP_CS_NO_INFO    = 0x0000
+L2CAP_CS_AUTHEN_PEND    = 0x0001
+L2CAP_CS_AUTHOR_PEND    = 0x0002
+L2CAP_CONF_REQ_SIZE = 4
+L2CAP_CONF_RSP_SIZE = 6
+L2CAP_CONF_SUCCESS  = 0x0000
+L2CAP_CONF_UNACCEPT = 0x0001
+L2CAP_CONF_REJECT   = 0x0002
+L2CAP_CONF_UNKNOWN  = 0x0003
+L2CAP_CONF_PENDING  = 0x0004
+L2CAP_CONF_EFS_REJECT   = 0x0005
+L2CAP_CONF_OPT_SIZE = 2
+L2CAP_CONF_MTU  =   0x01
+L2CAP_CONF_FLUSH_TO = 0x02
+L2CAP_CONF_QOS  =   0x03
+L2CAP_CONF_RFC  =   0x04
+L2CAP_CONF_FCS  =   0x05
+L2CAP_CONF_EFS  =   0x06
+L2CAP_CONF_EWS  =   0x07
+L2CAP_CONF_MAX_SIZE = 22
+L2CAP_MODE_BASIC    = 0x00
+L2CAP_MODE_RETRANS  = 0x01
+L2CAP_MODE_FLOWCTL  = 0x02
+L2CAP_MODE_ERTM =   0x03
+L2CAP_MODE_STREAMING    = 0x04
+L2CAP_SERVTYPE_NOTRAFFIC    = 0x00
+L2CAP_SERVTYPE_BESTEFFORT   = 0x01
+L2CAP_SERVTYPE_GUARANTEED   = 0x02
+L2CAP_DISCONN_REQ_SIZE = 4
+L2CAP_DISCONN_RSP_SIZE = 4
+L2CAP_INFO_REQ_SIZE = 2
+L2CAP_INFO_RSP_SIZE = 4
+L2CAP_IT_CL_MTU =   0x0001
+L2CAP_IT_FEAT_MASK  = 0x0002
+L2CAP_IR_SUCCESS    = 0x0000
+L2CAP_IR_NOTSUPP    = 0x0001
+L2CAP_CREATE_REQ_SIZE = 5
+L2CAP_CREATE_RSP_SIZE = 8
+L2CAP_MOVE_REQ_SIZE = 3
+L2CAP_MOVE_RSP_SIZE = 4
+L2CAP_MOVE_CFM_SIZE = 4
+L2CAP_MOVE_CFM_RSP_SIZE = 2
+
+# Constants from src/rfcomm.h
+RFCOMM_DEFAULT_MTU  = 127
+RFCOMM_PSM = 3
+RFCOMM_CONNINFO = 0x02
+RFCOMM_LM   = 0x03
+RFCOMM_LM_MASTER    = 0x0001
+RFCOMM_LM_AUTH  =   0x0002
+RFCOMM_LM_ENCRYPT   = 0x0004
+RFCOMM_LM_TRUSTED   = 0x0008
+RFCOMM_LM_RELIABLE  = 0x0010
+RFCOMM_LM_SECURE    = 0x0020
+RFCOMM_MAX_DEV  = 256
+RFCOMM_REUSE_DLC    = 0
+RFCOMM_RELEASE_ONHUP    = 1
+RFCOMM_HANGUP_NOW   = 2
+RFCOMM_TTY_ATTACHED = 3
 
 # Constants from src/hci.h
 HCI_MAX_DEV	= 16
@@ -798,3 +913,9 @@
 HCI_FLT_OGF_BITS	= 63
 HCI_FLT_OCF_BITS	= 127
 IREQ_CACHE_FLUSH = 0x0001
+
+# Constants from src/sco.h
+SCO_DEFAULT_MTU =   500
+SCO_DEFAULT_FLUSH_TO    = 0xFFFF
+SCO_OPTIONS = 0x01
+SCO_CONNINFO    = 0x02
diff --git a/src/btsocket.c b/src/btsocket.c
index 020c2ad..a4e4b62 100644
--- a/src/btsocket.c
+++ b/src/btsocket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013 The Chromium Authors. All rights reserved.
+/* Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
  * Use of this source code is governed by a BSD-style license that can be
  * found in the LICENSE file.
  */
@@ -10,7 +10,10 @@
 #include <poll.h>
 
 #include "bluetooth.h"
+#include "l2cap.h"
+#include "rfcomm.h"
 #include "hci.h"
+#include "sco.h"
 
 static PyObject *_btsocket_error;
 static PyObject *_btsocket_timeout;
@@ -47,23 +50,106 @@
   return 1;
 }
 
+static int _setbdaddr(const char *straddr, bdaddr_t *bdaddr) {
+  unsigned int b0, b1, b2, b3, b4, b5;
+  int n;
+
+  n = sscanf(straddr, "%X:%X:%X:%X:%X:%X", &b5, &b4, &b3, &b2, &b1, &b0);
+  if (n == 6) {
+    bdaddr->b[0] = b0;
+    bdaddr->b[1] = b1;
+    bdaddr->b[2] = b2;
+    bdaddr->b[3] = b3;
+    bdaddr->b[4] = b4;
+    bdaddr->b[5] = b5;
+    return 1;
+  } else {
+    PyErr_SetString(_btsocket_error, "bad bluetooth address for bind()");
+    return 0;
+  }
+}
+
 static PyObject *_btsocket_bind(PyObject *self, PyObject *args) {
-  PyObject *socket_object;
-  struct sockaddr_hci addr;
-  int fd, result;
+  PyObject *socket_object, *tuple;
+  union {
+    struct sockaddr_l2 l2;
+    struct sockaddr_rc rc;
+    struct sockaddr_hci hci;
+    struct sockaddr_sco sco;
+  } addr;
+  size_t addrlen;
+  int proto, fd, result;
 
-  addr.hci_family = AF_BLUETOOTH;
-
-  if (!PyArg_ParseTuple(args, "O(HH):_btsocket.bind",
-                        &socket_object, &addr.hci_dev, &addr.hci_channel))
+  if (!PyArg_ParseTuple(args, "OiO:_btsocket.bind",
+                        &socket_object, &proto, &tuple))
     return NULL;
 
   fd = _get_fileno(socket_object);
   if (fd < 0)
     return NULL;
 
+  memset(&addr, 0, sizeof addr);
+
+  switch (proto) {
+    case BTPROTO_L2CAP: {
+      char *straddr;
+
+      addr.l2.l2_family = AF_BLUETOOTH;
+
+      if (!PyArg_ParseTuple(tuple, "si:_btsocket.bind",
+                            &straddr, &addr.l2.l2_psm))
+        return NULL;
+      if (!_setbdaddr(straddr, &addr.l2.l2_bdaddr))
+        return NULL;
+
+      addrlen = sizeof (struct sockaddr_l2);
+      break;
+    }
+    case BTPROTO_RFCOMM: {
+      char *straddr;
+
+      addr.rc.rc_family = AF_BLUETOOTH;
+
+      if (!PyArg_ParseTuple(tuple, "si:_btsocket.bind",
+                            &straddr, &addr.rc.rc_channel))
+        return NULL;
+      if (!_setbdaddr(straddr, &addr.rc.rc_bdaddr))
+        return NULL;
+
+      addrlen = sizeof (struct sockaddr_rc);
+      break;
+    }
+    case BTPROTO_HCI: {
+      addr.hci.hci_family = AF_BLUETOOTH;
+
+      if (!PyArg_ParseTuple(tuple, "HH:_btsocket.bind",
+                            &addr.hci.hci_dev, &addr.hci.hci_channel))
+        return NULL;
+
+      addrlen = sizeof (struct sockaddr_hci);
+      break;
+    }
+    case BTPROTO_SCO: {
+      char *straddr;
+
+      addr.sco.sco_family = AF_BLUETOOTH;
+
+      if (!PyArg_ParseTuple(tuple, "s:_btsocket.bind",
+                            &straddr))
+        return NULL;
+      if (!_setbdaddr(straddr, &addr.sco.sco_bdaddr))
+        return NULL;
+
+      addrlen = sizeof (struct sockaddr_sco);
+      break;
+    }
+    default:
+      PyErr_SetString(_btsocket_error, "unknown protocol for bind()");
+      return NULL;
+  }
+
   Py_BEGIN_ALLOW_THREADS;
-  result = bind(fd, (struct sockaddr *)&addr, sizeof addr);
+  result = bind(fd, (struct sockaddr *)&addr, addrlen);
   Py_END_ALLOW_THREADS;
 
   if (result < 0)
diff --git a/src/l2cap.h b/src/l2cap.h
new file mode 100644
index 0000000..5ce94c4
--- /dev/null
+++ b/src/l2cap.h
@@ -0,0 +1,279 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2000-2001  Qualcomm Incorporated
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
+ *  Copyright (c) 2012       Code Aurora Forum. All rights reserved.
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __L2CAP_H
+#define __L2CAP_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/socket.h>
+
+/* L2CAP defaults */
+#define L2CAP_DEFAULT_MTU	672
+#define L2CAP_DEFAULT_FLUSH_TO	0xFFFF
+
+/* L2CAP socket address */
+struct sockaddr_l2 {
+	sa_family_t	l2_family;
+	unsigned short	l2_psm;
+	bdaddr_t	l2_bdaddr;
+	unsigned short	l2_cid;
+	uint8_t		l2_bdaddr_type;
+};
+
+/* L2CAP socket options */
+#define L2CAP_OPTIONS	0x01
+struct l2cap_options {
+	uint16_t	omtu;
+	uint16_t	imtu;
+	uint16_t	flush_to;
+	uint8_t		mode;
+	uint8_t		fcs;
+	uint8_t		max_tx;
+	uint16_t	txwin_size;
+};
+
+#define L2CAP_CONNINFO	0x02
+struct l2cap_conninfo {
+	uint16_t	hci_handle;
+	uint8_t		dev_class[3];
+};
+
+#define L2CAP_LM	0x03
+#define L2CAP_LM_MASTER		0x0001
+#define L2CAP_LM_AUTH		0x0002
+#define L2CAP_LM_ENCRYPT	0x0004
+#define L2CAP_LM_TRUSTED	0x0008
+#define L2CAP_LM_RELIABLE	0x0010
+#define L2CAP_LM_SECURE		0x0020
+
+/* L2CAP command codes */
+#define L2CAP_COMMAND_REJ	0x01
+#define L2CAP_CONN_REQ		0x02
+#define L2CAP_CONN_RSP		0x03
+#define L2CAP_CONF_REQ		0x04
+#define L2CAP_CONF_RSP		0x05
+#define L2CAP_DISCONN_REQ	0x06
+#define L2CAP_DISCONN_RSP	0x07
+#define L2CAP_ECHO_REQ		0x08
+#define L2CAP_ECHO_RSP		0x09
+#define L2CAP_INFO_REQ		0x0a
+#define L2CAP_INFO_RSP		0x0b
+#define L2CAP_CREATE_REQ	0x0c
+#define L2CAP_CREATE_RSP	0x0d
+#define L2CAP_MOVE_REQ		0x0e
+#define L2CAP_MOVE_RSP		0x0f
+#define L2CAP_MOVE_CFM		0x10
+#define L2CAP_MOVE_CFM_RSP	0x11
+
+/* L2CAP extended feature mask */
+#define L2CAP_FEAT_FLOWCTL	0x00000001
+#define L2CAP_FEAT_RETRANS	0x00000002
+#define L2CAP_FEAT_BIDIR_QOS	0x00000004
+#define L2CAP_FEAT_ERTM		0x00000008
+#define L2CAP_FEAT_STREAMING	0x00000010
+#define L2CAP_FEAT_FCS		0x00000020
+#define L2CAP_FEAT_EXT_FLOW	0x00000040
+#define L2CAP_FEAT_FIXED_CHAN	0x00000080
+#define L2CAP_FEAT_EXT_WINDOW	0x00000100
+#define L2CAP_FEAT_UCD		0x00000200
+
+/* L2CAP fixed channels */
+#define L2CAP_FC_L2CAP		0x02
+#define L2CAP_FC_CONNLESS	0x04
+#define L2CAP_FC_A2MP		0x08
+
+/* L2CAP structures */
+typedef struct {
+	uint16_t	len;
+	uint16_t	cid;
+} __attribute__ ((packed)) l2cap_hdr;
+#define L2CAP_HDR_SIZE 4
+
+typedef struct {
+	uint8_t		code;
+	uint8_t		ident;
+	uint16_t	len;
+} __attribute__ ((packed)) l2cap_cmd_hdr;
+#define L2CAP_CMD_HDR_SIZE 4
+
+typedef struct {
+	uint16_t	reason;
+} __attribute__ ((packed)) l2cap_cmd_rej;
+#define L2CAP_CMD_REJ_SIZE 2
+
+typedef struct {
+	uint16_t	psm;
+	uint16_t	scid;
+} __attribute__ ((packed)) l2cap_conn_req;
+#define L2CAP_CONN_REQ_SIZE 4
+
+typedef struct {
+	uint16_t	dcid;
+	uint16_t	scid;
+	uint16_t	result;
+	uint16_t	status;
+} __attribute__ ((packed)) l2cap_conn_rsp;
+#define L2CAP_CONN_RSP_SIZE 8
+
+/* connect result */
+#define L2CAP_CR_SUCCESS	0x0000
+#define L2CAP_CR_PEND		0x0001
+#define L2CAP_CR_BAD_PSM	0x0002
+#define L2CAP_CR_SEC_BLOCK	0x0003
+#define L2CAP_CR_NO_MEM		0x0004
+
+/* connect status */
+#define L2CAP_CS_NO_INFO	0x0000
+#define L2CAP_CS_AUTHEN_PEND	0x0001
+#define L2CAP_CS_AUTHOR_PEND	0x0002
+
+typedef struct {
+	uint16_t	dcid;
+	uint16_t	flags;
+	uint8_t		data[0];
+} __attribute__ ((packed)) l2cap_conf_req;
+#define L2CAP_CONF_REQ_SIZE 4
+
+typedef struct {
+	uint16_t	scid;
+	uint16_t	flags;
+	uint16_t	result;
+	uint8_t		data[0];
+} __attribute__ ((packed)) l2cap_conf_rsp;
+#define L2CAP_CONF_RSP_SIZE 6
+
+#define L2CAP_CONF_SUCCESS	0x0000
+#define L2CAP_CONF_UNACCEPT	0x0001
+#define L2CAP_CONF_REJECT	0x0002
+#define L2CAP_CONF_UNKNOWN	0x0003
+#define L2CAP_CONF_PENDING	0x0004
+#define L2CAP_CONF_EFS_REJECT	0x0005
+
+typedef struct {
+	uint8_t		type;
+	uint8_t		len;
+	uint8_t		val[0];
+} __attribute__ ((packed)) l2cap_conf_opt;
+#define L2CAP_CONF_OPT_SIZE 2
+
+#define L2CAP_CONF_MTU		0x01
+#define L2CAP_CONF_FLUSH_TO	0x02
+#define L2CAP_CONF_QOS		0x03
+#define L2CAP_CONF_RFC		0x04
+#define L2CAP_CONF_FCS		0x05
+#define L2CAP_CONF_EFS		0x06
+#define L2CAP_CONF_EWS		0x07
+
+#define L2CAP_CONF_MAX_SIZE	22
+
+#define L2CAP_MODE_BASIC	0x00
+#define L2CAP_MODE_RETRANS	0x01
+#define L2CAP_MODE_FLOWCTL	0x02
+#define L2CAP_MODE_ERTM		0x03
+#define L2CAP_MODE_STREAMING	0x04
+
+#define L2CAP_SERVTYPE_NOTRAFFIC	0x00
+#define L2CAP_SERVTYPE_BESTEFFORT	0x01
+#define L2CAP_SERVTYPE_GUARANTEED	0x02
+
+typedef struct {
+	uint16_t	dcid;
+	uint16_t	scid;
+} __attribute__ ((packed)) l2cap_disconn_req;
+#define L2CAP_DISCONN_REQ_SIZE 4
+
+typedef struct {
+	uint16_t	dcid;
+	uint16_t	scid;
+} __attribute__ ((packed)) l2cap_disconn_rsp;
+#define L2CAP_DISCONN_RSP_SIZE 4
+
+typedef struct {
+	uint16_t	type;
+} __attribute__ ((packed)) l2cap_info_req;
+#define L2CAP_INFO_REQ_SIZE 2
+
+typedef struct {
+	uint16_t	type;
+	uint16_t	result;
+	uint8_t		data[0];
+} __attribute__ ((packed)) l2cap_info_rsp;
+#define L2CAP_INFO_RSP_SIZE 4
+
+/* info type */
+#define L2CAP_IT_CL_MTU		0x0001
+#define L2CAP_IT_FEAT_MASK	0x0002
+
+/* info result */
+#define L2CAP_IR_SUCCESS	0x0000
+#define L2CAP_IR_NOTSUPP	0x0001
+
+typedef struct {
+	uint16_t	psm;
+	uint16_t	scid;
+	uint8_t		id;
+} __attribute__ ((packed)) l2cap_create_req;
+#define L2CAP_CREATE_REQ_SIZE 5
+
+typedef struct {
+	uint16_t	dcid;
+	uint16_t	scid;
+	uint16_t	result;
+	uint16_t	status;
+} __attribute__ ((packed)) l2cap_create_rsp;
+#define L2CAP_CREATE_RSP_SIZE 8
+
+typedef struct {
+	uint16_t	icid;
+	uint8_t		id;
+} __attribute__ ((packed)) l2cap_move_req;
+#define L2CAP_MOVE_REQ_SIZE 3
+
+typedef struct {
+	uint16_t	icid;
+	uint16_t	result;
+} __attribute__ ((packed)) l2cap_move_rsp;
+#define L2CAP_MOVE_RSP_SIZE 4
+
+typedef struct {
+	uint16_t	icid;
+	uint16_t	result;
+} __attribute__ ((packed)) l2cap_move_cfm;
+#define L2CAP_MOVE_CFM_SIZE 4
+
+typedef struct {
+	uint16_t	icid;
+} __attribute__ ((packed)) l2cap_move_cfm_rsp;
+#define L2CAP_MOVE_CFM_RSP_SIZE 2
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __L2CAP_H */
diff --git a/src/rfcomm.h b/src/rfcomm.h
new file mode 100644
index 0000000..ad6c0e1
--- /dev/null
+++ b/src/rfcomm.h
@@ -0,0 +1,99 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __RFCOMM_H
+#define __RFCOMM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/socket.h>
+
+/* RFCOMM defaults */
+#define RFCOMM_DEFAULT_MTU	127
+
+#define RFCOMM_PSM 3
+
+/* RFCOMM socket address */
+struct sockaddr_rc {
+	sa_family_t	rc_family;
+	bdaddr_t	rc_bdaddr;
+	uint8_t		rc_channel;
+};
+
+/* RFCOMM socket options */
+#define RFCOMM_CONNINFO	0x02
+struct rfcomm_conninfo {
+	uint16_t	hci_handle;
+	uint8_t		dev_class[3];
+};
+
+#define RFCOMM_LM	0x03
+#define RFCOMM_LM_MASTER	0x0001
+#define RFCOMM_LM_AUTH		0x0002
+#define RFCOMM_LM_ENCRYPT	0x0004
+#define RFCOMM_LM_TRUSTED	0x0008
+#define RFCOMM_LM_RELIABLE	0x0010
+#define RFCOMM_LM_SECURE	0x0020
+
+/* RFCOMM TTY support */
+#define RFCOMM_MAX_DEV	256
+
+#define RFCOMMCREATEDEV		_IOW('R', 200, int)
+#define RFCOMMRELEASEDEV	_IOW('R', 201, int)
+#define RFCOMMGETDEVLIST	_IOR('R', 210, int)
+#define RFCOMMGETDEVINFO	_IOR('R', 211, int)
+
+struct rfcomm_dev_req {
+	int16_t		dev_id;
+	uint32_t	flags;
+	bdaddr_t	src;
+	bdaddr_t	dst;
+	uint8_t	channel;
+};
+#define RFCOMM_REUSE_DLC	0
+#define RFCOMM_RELEASE_ONHUP	1
+#define RFCOMM_HANGUP_NOW	2
+#define RFCOMM_TTY_ATTACHED	3
+
+struct rfcomm_dev_info {
+	int16_t		id;
+	uint32_t	flags;
+	uint16_t	state;
+	bdaddr_t	src;
+	bdaddr_t	dst;
+	uint8_t		channel;
+};
+
+struct rfcomm_dev_list_req {
+	uint16_t	dev_num;
+	struct rfcomm_dev_info dev_info[0];
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __RFCOMM_H */
diff --git a/src/sco.h b/src/sco.h
new file mode 100644
index 0000000..75336a5
--- /dev/null
+++ b/src/sco.h
@@ -0,0 +1,62 @@
+/*
+ *
+ *  BlueZ - Bluetooth protocol stack for Linux
+ *
+ *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
+ *  Copyright (C) 2002-2010  Marcel Holtmann <marcel@holtmann.org>
+ *
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#ifndef __SCO_H
+#define __SCO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* SCO defaults */
+#define SCO_DEFAULT_MTU		500
+#define SCO_DEFAULT_FLUSH_TO	0xFFFF
+
+#define SCO_CONN_TIMEOUT	(HZ * 40)
+#define SCO_DISCONN_TIMEOUT	(HZ * 2)
+#define SCO_CONN_IDLE_TIMEOUT	(HZ * 60)
+
+/* SCO socket address */
+struct sockaddr_sco {
+	sa_family_t	sco_family;
+	bdaddr_t	sco_bdaddr;
+};
+
+/* set/get sockopt defines */
+#define SCO_OPTIONS	0x01
+struct sco_options {
+	uint16_t	mtu;
+};
+
+#define SCO_CONNINFO	0x02
+struct sco_conninfo {
+	uint16_t	hci_handle;
+	uint8_t		dev_class[3];
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __SCO_H */