- Add some core code for the L2CAP layer (l2cap commands)

- Tailor a bit the main module
- Fix definitions in the main header




git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@25943 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Oliver Ruiz Dorantes 2008-06-12 19:31:29 +00:00
parent 350458a6ba
commit c15ecd98ca
7 changed files with 867 additions and 1 deletions

View File

@ -240,7 +240,7 @@ struct hci_command_header {
struct hci_cp_pin_code_reply {
bdaddr_t bdaddr;
uint8 pin_len;
uint8 pin_code[16];
uint8 pin_code[HCI_PIN_SIZE];
} __attribute__ ((packed));
#define OCF_PIN_CODE_NEG_REPLY 0x000E

View File

@ -26,6 +26,12 @@ typedef struct {
uint8 b[6];
} __attribute__((packed)) bdaddr_t;
#define BDADDR_NULL (&(bdaddr_t) {{0, 0, 0, 0, 0, 0}})
#define BDADDR_LOCAL (&(bdaddr_t) {{0, 0, 0, 0xff, 0xff, 0xff}})
#define BDADDR_BROADCAST (&(bdaddr_t) {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}})
#define BDADDR_ANY BDADDR_BROADCAST
/* 128 integer type needed for SDP */
struct int128 {
int8 b[16];
@ -33,5 +39,12 @@ struct int128 {
typedef struct int128 int128;
typedef struct int128 uint128;
/* Protocol definitions - add to as required... */
#define BLUETOOTH_PROTO_HCI 134 /* HCI protocol number */
#define BLUETOOTH_PROTO_L2CAP 135 /* L2CAP protocol number */
#define BLUETOOTH_PROTO_RFCOMM 136 /* RFCOMM protocol number */
#define BLUETOOTH_PROTO_MAX 256
#endif

View File

@ -15,6 +15,7 @@ UsePrivateHeaders kernel net bluetooth ;
KernelAddon l2cap :
l2cap.cpp
l2cap_address.cpp
l2cap_command.cpp
;
# Installation

View File

@ -1,3 +1,23 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
/*-
* Copyright (c) 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.
*/
#include <net_datalink.h>
#include <net_protocol.h>
#include <net_stack.h>

View File

@ -0,0 +1,295 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
/*-
* Copyright (c) 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.
*/
/**************************************************************************
**************************************************************************
** Common defines and types (L2CAP)
**************************************************************************
**************************************************************************/
#ifndef _L2CAP_
#define _L2CAP_
#include <bluetooth/bluetooth.h>
// TODO: from BSD compatibility layer
#define htole16(x) (x)
/*
* Channel IDs are assigned relative to the instance of L2CAP node, i.e.
* relative to the unit. So the total number of channels that unit can have
* open at the same time is 0xffff - 0x0040 = 0xffbf (65471). This number
* does not depend on number of connections.
*/
#define L2CAP_NULL_CID 0x0000 /* DO NOT USE THIS CID */
#define L2CAP_SIGNAL_CID 0x0001 /* signaling channel ID */
#define L2CAP_CLT_CID 0x0002 /* connectionless channel ID */
/* 0x0003 - 0x003f Reserved */
#define L2CAP_FIRST_CID 0x0040 /* dynamically alloc. (start) */
#define L2CAP_LAST_CID 0xffff /* dynamically alloc. (end) */
/*
* L2CAP signaling command ident's are assigned relative to the connection,
* because there is only one signaling channel (cid == 0x01) for every
* connection. So up to 254 (0xff - 0x01) L2CAP commands can be pending at the
* same time for the same connection.
*/
#define L2CAP_NULL_IDENT 0x00 /* DO NOT USE THIS IDENT */
#define L2CAP_FIRST_IDENT 0x01 /* dynamically alloc. (start) */
#define L2CAP_LAST_IDENT 0xff /* dynamically alloc. (end) */
/* L2CAP MTU */
#define L2CAP_MTU_MINIMUM 48
#define L2CAP_MTU_DEFAULT 672
#define L2CAP_MTU_MAXIMUM 0xffff
/* L2CAP flush and link timeouts */
#define L2CAP_FLUSH_TIMO_DEFAULT 0xffff /* always retransmit */
#define L2CAP_LINK_TIMO_DEFAULT 0xffff
/* L2CAP Command Reject reasons */
#define L2CAP_REJ_NOT_UNDERSTOOD 0x0000
#define L2CAP_REJ_MTU_EXCEEDED 0x0001
#define L2CAP_REJ_INVALID_CID 0x0002
/* 0x0003 - 0xffff - reserved for future use */
/* Protocol/Service Multioplexor (PSM) values */
#define L2CAP_PSM_ANY 0x0000 /* Any/Invalid PSM */
#define L2CAP_PSM_SDP 0x0001 /* Service Discovery Protocol */
#define L2CAP_PSM_RFCOMM 0x0003 /* RFCOMM protocol */
#define L2CAP_PSM_TCP 0x0005 /* Telephony Control Protocol */
#define L2CAP_PSM_TCS 0x0007 /* TCS cordless */
#define L2CAP_PSM_BNEP 0x000F /* BNEP */
#define L2CAP_PSM_HID_CTRL 0x0011 /* HID Control */
#define L2CAP_PSM_HID_INT 0x0013 /* HID Interrupt */
#define L2CAP_PSM_UPnP 0x0015 /* UPnP (ESDP) */
#define L2CAP_PSM_AVCTP 0x0017 /* AVCTP */
#define L2CAP_PSM_AVDTP 0x0019 /* AVDTP */
/* < 0x1000 - reserved for future use */
/* 0x1001 < x < 0xFFFF dinamically assigned */
/* L2CAP Connection response command result codes */
#define L2CAP_SUCCESS 0x0000
#define L2CAP_PENDING 0x0001
#define L2CAP_PSM_NOT_SUPPORTED 0x0002
#define L2CAP_SEQUIRY_BLOCK 0x0003
#define L2CAP_NO_RESOURCES 0x0004
#define L2CAP_TIMEOUT 0xeeee
#define L2CAP_UNKNOWN 0xffff
/* 0x0005 - 0xffff - reserved for future use */
/* L2CAP Connection response status codes */
#define L2CAP_NO_INFO 0x0000
#define L2CAP_AUTH_PENDING 0x0001
#define L2CAP_AUTZ_PENDING 0x0002
/* 0x0003 - 0xffff - reserved for future use */
/* L2CAP Configuration response result codes */
#define L2CAP_UNACCEPTABLE_PARAMS 0x0001
#define L2CAP_REJECT 0x0002
#define L2CAP_UNKNOWN_OPTION 0x0003
/* 0x0003 - 0xffff - reserved for future use */
/* L2CAP Configuration options */
#define L2CAP_OPT_CFLAG_BIT 0x0001
#define L2CAP_OPT_CFLAG(flags) ((flags) & L2CAP_OPT_CFLAG_BIT)
#define L2CAP_OPT_HINT_BIT 0x80
#define L2CAP_OPT_HINT(type) ((type) & L2CAP_OPT_HINT_BIT)
#define L2CAP_OPT_HINT_MASK 0x7f
#define L2CAP_OPT_MTU 0x01
#define L2CAP_OPT_MTU_SIZE sizeof(uint16)
#define L2CAP_OPT_FLUSH_TIMO 0x02
#define L2CAP_OPT_FLUSH_TIMO_SIZE sizeof(uint16)
#define L2CAP_OPT_QOS 0x03
#define L2CAP_OPT_QOS_SIZE sizeof(l2cap_qos)
/* 0x4 - 0xff - reserved for future use */
/* L2CAP Information request type codes */
#define L2CAP_CONNLESS_MTU 0x0001
#define L2CAP_EXTENDED_MASK 0x0002
/* 0x0003 - 0xffff - reserved for future use */
/* L2CAP Information response codes */
#define L2CAP_NOT_SUPPORTED 0x0001
/* 0x0002 - 0xffff - reserved for future use */
/* L2CAP flow (QoS) */
typedef struct {
uint8 flags; /* reserved for future use */
uint8 service_type; /* service type */
uint32 token_rate; /* bytes per second */
uint32 token_bucket_size; /* bytes */
uint32 peak_bandwidth; /* bytes per second */
uint32 latency; /* microseconds */
uint32 delay_variation; /* microseconds */
} __attribute__ ((packed)) l2cap_flow_t;
/**************************************************************************
**************************************************************************
** Link level defines, headers and types
**************************************************************************
**************************************************************************/
/* L2CAP header */
typedef struct {
uint16 length; /* payload size */
uint16 dcid; /* destination channel ID */
} __attribute__ ((packed)) l2cap_hdr_t;
/* L2CAP ConnectionLess Traffic (CLT) (if destination cid == 0x2) */
typedef struct {
uint16 psm; /* Protocol/Service Multiplexor */
} __attribute__ ((packed)) l2cap_clt_hdr_t;
#define L2CAP_CLT_MTU_MAXIMUM (L2CAP_MTU_MAXIMUM - sizeof(l2cap_clt_hdr_t))
/* L2CAP command header */
typedef struct {
uint8 code; /* command OpCode */
uint8 ident; /* identifier to match request and response */
uint16 length; /* command parameters length */
} __attribute__ ((packed)) l2cap_cmd_hdr_t;
/* L2CAP Command Reject */
#define L2CAP_CMD_REJ 0x01
typedef struct {
uint16 reason; /* reason to reject command */
/* u_int8_t data[]; -- optional data (depends on reason) */
} __attribute__ ((packed)) l2cap_cmd_rej_cp;
/* CommandReject data */
typedef union {
/* L2CAP_REJ_MTU_EXCEEDED */
struct {
uint16 mtu; /* actual signaling MTU */
} __attribute__ ((packed)) mtu;
/* L2CAP_REJ_INVALID_CID */
struct {
uint16 scid; /* local CID */
uint16 dcid; /* remote CID */
} __attribute__ ((packed)) cid;
} l2cap_cmd_rej_data_t;
typedef l2cap_cmd_rej_data_t * l2cap_cmd_rej_data_p;
/* L2CAP Connection Request */
#define L2CAP_CON_REQ 0x02
typedef struct {
uint16 psm; /* Protocol/Service Multiplexor (PSM) */
uint16 scid; /* source channel ID */
} __attribute__ ((packed)) l2cap_con_req_cp;
/* L2CAP Connection Response */
#define L2CAP_CON_RSP 0x03
typedef struct {
uint16 dcid; /* destination channel ID */
uint16 scid; /* source channel ID */
uint16 result; /* 0x00 - success */
uint16 status; /* more info if result != 0x00 */
} __attribute__ ((packed)) l2cap_con_rsp_cp;
/* L2CAP Configuration Request */
#define L2CAP_CFG_REQ 0x04
typedef struct {
uint16 dcid; /* destination channel ID */
uint16 flags; /* flags */
/* u_int8_t options[] -- options */
} __attribute__ ((packed)) l2cap_cfg_req_cp;
/* L2CAP Configuration Response */
#define L2CAP_CFG_RSP 0x05
typedef struct {
uint16 scid; /* source channel ID */
uint16 flags; /* flags */
uint16 result; /* 0x00 - success */
/* u_int8_t options[] -- options */
} __attribute__ ((packed)) l2cap_cfg_rsp_cp;
/* L2CAP configuration option */
typedef struct {
u_int8_t type;
u_int8_t length;
/* u_int8_t value[] -- option value (depends on type) */
} __attribute__ ((packed)) l2cap_cfg_opt_t;
typedef l2cap_cfg_opt_t * l2cap_cfg_opt_p;
/* L2CAP configuration option value */
typedef union {
uint16 mtu; /* L2CAP_OPT_MTU */
uint16 flush_timo; /* L2CAP_OPT_FLUSH_TIMO */
l2cap_flow_t flow; /* L2CAP_OPT_QOS */
} l2cap_cfg_opt_val_t;
typedef l2cap_cfg_opt_val_t * l2cap_cfg_opt_val_p;
/* L2CAP Disconnect Request */
#define L2CAP_DISCON_REQ 0x06
typedef struct {
uint16 dcid; /* destination channel ID */
uint16 scid; /* source channel ID */
} __attribute__ ((packed)) l2cap_discon_req_cp;
/* L2CAP Disconnect Response */
#define L2CAP_DISCON_RSP 0x07
typedef l2cap_discon_req_cp l2cap_discon_rsp_cp;
/* L2CAP Echo Request */
#define L2CAP_ECHO_REQ 0x08
/* No command parameters, only optional data */
/* L2CAP Echo Response */
#define L2CAP_ECHO_RSP 0x09
#define L2CAP_MAX_ECHO_SIZE \
(L2CAP_MTU_MAXIMUM - sizeof(l2cap_cmd_hdr_t))
/* No command parameters, only optional data */
/* L2CAP Information Request */
#define L2CAP_INFO_REQ 0x0a
typedef struct {
uint16 type; /* requested information type */
} __attribute__ ((packed)) l2cap_info_req_cp;
/* L2CAP Information Response */
#define L2CAP_INFO_RSP 0x0b
typedef struct {
uint16 type; /* requested information type */
uint16 result; /* 0x00 - success */
/* u_int8_t info[] -- info data (depends on type)
*
* L2CAP_CONNLESS_MTU - 2 bytes connectionless MTU
*/
} __attribute__ ((packed)) l2cap_info_rsp_cp;
typedef union {
/* L2CAP_CONNLESS_MTU */
struct {
uint16 mtu;
} __attribute__ ((packed)) mtu;
} l2cap_info_rsp_data_t;
typedef l2cap_info_rsp_data_t * l2cap_info_rsp_data_p;
#endif

View File

@ -0,0 +1,487 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
/*-
* Copyright (c) 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.
*/
#include <NetBufferUtilities.h>
#include "l2cap_command.h"
/*
* Note: All L2CAP implementations are required to support minimal signaling
* MTU of 48 bytes. In order to simplify things we will send one command
* per one L2CAP packet. Given evrything above we can assume that one
* signaling packet will fit into single mbuf.
*/
/* Private types */
struct _cmd_rej {
l2cap_cmd_hdr_t hdr;
l2cap_cmd_rej_cp param;
l2cap_cmd_rej_data_t data;
} __attribute__ ((packed)) ;
struct _con_req {
l2cap_cmd_hdr_t hdr;
l2cap_con_req_cp param;
} __attribute__ ((packed));
struct _con_rsp {
l2cap_cmd_hdr_t hdr;
l2cap_con_rsp_cp param;
} __attribute__ ((packed));
struct _cfg_req {
l2cap_cmd_hdr_t hdr;
l2cap_cfg_req_cp param;
} __attribute__ ((packed));
struct _cfg_rsp {
l2cap_cmd_hdr_t hdr;
l2cap_cfg_rsp_cp param;
} __attribute__ ((packed));
struct _discon_req {
l2cap_cmd_hdr_t hdr;
l2cap_discon_req_cp param;
} __attribute__ ((packed));
struct _discon_rsp {
l2cap_cmd_hdr_t hdr;
l2cap_discon_rsp_cp param;
} __attribute__ ((packed));
struct _info_req {
l2cap_cmd_hdr_t hdr;
l2cap_info_req_cp param;
} __attribute__ ((packed));
struct _info_rsp {
l2cap_cmd_hdr_t hdr;
l2cap_info_rsp_cp param;
l2cap_info_rsp_data_t data;
} __attribute__ ((packed));
/* L2CAP_CommandRej */
static inline net_buffer*
l2cap_cmd_rej(uint8 _ident, uint16 _reason, uint16 _mtu, uint16 _scid, uint16 _dcid)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _cmd_rej));
if ((_m) == NULL)
return NULL;
NetBufferPrepend<struct _cmd_rej> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
// free the buffer
return NULL;
}
bufferHeader->hdr.code = L2CAP_CMD_REJ;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = sizeof(bufferHeader->param);
bufferHeader->param.reason = htole16((_reason));
if ((_reason) == L2CAP_REJ_MTU_EXCEEDED) {
bufferHeader->data.mtu.mtu = htole16((_mtu));
bufferHeader->hdr.length += sizeof(bufferHeader->data.mtu);
} else if ((_reason) == L2CAP_REJ_INVALID_CID) {
bufferHeader->data.cid.scid = htole16((_scid));
bufferHeader->data.cid.dcid = htole16((_dcid));
bufferHeader->hdr.length += sizeof(bufferHeader->data.cid);
}
_m->size = sizeof(bufferHeader->hdr) + bufferHeader->hdr.length; /* TODO: needed ?*/
bufferHeader->hdr.length = htole16(bufferHeader->hdr.length);
bufferHeader.Sync();
return _m;
}
/* L2CAP_ConnectReq */
static inline net_buffer*
l2cap_con_req(uint8 _ident, uint16 _psm, uint16 _scid)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _con_req));
if ((_m) == NULL)
return NULL;
NetBufferPrepend<struct _con_req> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_CON_REQ;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = htole16(sizeof(bufferHeader->param));
bufferHeader->param.psm = htole16((_psm));
bufferHeader->param.scid = htole16((_scid));
bufferHeader.Sync();
return _m;
}
/* L2CAP_ConnectRsp */
static inline net_buffer*
l2cap_con_rsp(uint8 _ident, uint16 _dcid, uint16 _scid, uint16 _result, uint16 _status)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _con_rsp));
if ((_m) == NULL)
return NULL;
NetBufferPrepend<struct _con_rsp> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_CON_RSP;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = htole16(sizeof(bufferHeader->param));
bufferHeader->param.dcid = htole16((_dcid));
bufferHeader->param.scid = htole16((_scid));
bufferHeader->param.result = htole16((_result));
bufferHeader->param.status = htole16((_status)); /* reason */
bufferHeader.Sync();
return _m;
}
/* L2CAP_ConfigReq */
static inline net_buffer*
l2cap_cfg_req(uint8 _ident, uint16 _dcid, uint16 _flags, net_buffer* _data)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _cfg_req));
if ((_m) == NULL){
/* TODO free the _data buffer? */
return NULL;
}
(_m)->size = sizeof(struct _cfg_req); /* check if needed */
NetBufferPrepend<struct _cfg_req> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_CFG_REQ;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = htole16(sizeof(bufferHeader->param));
bufferHeader->param.dcid = htole16((_dcid));
bufferHeader->param.flags = htole16((_flags));
bufferHeader.Sync();
/* Add the given data */
gBufferModule->merge(_m, _data, true);
return _m;
}
/* L2CAP_ConfigRsp */
static inline net_buffer*
l2cap_cfg_rsp(uint8 _ident, uint16 _scid, uint16 _flags, uint16 _result, net_buffer* _data)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _cfg_rsp));
if ((_m) == NULL){
/* TODO free the _data buffer */
return NULL;
}
NetBufferPrepend<struct _cfg_rsp> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_CFG_RSP;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = htole16(sizeof(bufferHeader->param));
bufferHeader->param.scid = htole16((_scid));
bufferHeader->param.flags = htole16((_flags));
bufferHeader->param.result = htole16((_result));
bufferHeader.Sync();
gBufferModule->merge(_m, _data, true);
return _m;
}
/* L2CAP_DisconnectReq */
static inline net_buffer*
l2cap_discon_req(uint8 _ident, uint16 _dcid, uint16 _scid)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _discon_req));
if ((_m) == NULL){
return NULL;
}
NetBufferPrepend<struct _discon_req> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_DISCON_REQ;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = htole16(sizeof(bufferHeader->param));
bufferHeader->param.dcid = htole16((_dcid));
bufferHeader->param.scid = htole16((_scid));
bufferHeader.Sync();
return _m;
}
/* L2CA_DisconnectRsp */
static inline net_buffer*
l2cap_discon_rsp(uint8 _ident, uint16 _dcid, uint16 _scid)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _discon_rsp));
if ((_m) == NULL){
return NULL;
}
NetBufferPrepend<struct _discon_rsp> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_DISCON_RSP;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = htole16(sizeof(bufferHeader->param));
bufferHeader->param.dcid = htole16((_dcid));
bufferHeader->param.scid = htole16((_scid));
bufferHeader.Sync();
return _m;
}
/* L2CAP_EchoReq */
static inline net_buffer*
l2cap_echo_req(uint8 _ident, void* _data, size_t _size)
{
net_buffer* _m = gBufferModule->create(sizeof(l2cap_cmd_hdr_t));
if ((_m) == NULL){
/* TODO free the _data buffer */
return NULL;
}
NetBufferPrepend<l2cap_cmd_hdr_t> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->code = L2CAP_ECHO_REQ;
bufferHeader->ident = (_ident);
bufferHeader->length = htole16(0);
bufferHeader.Sync();
if ((_data) != NULL) {
gBufferModule->append(_m, _data, _size);
}
return _m;
}
/* L2CAP_InfoReq */
static inline net_buffer*
l2cap_info_req(uint8 _ident, uint16 _type)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _info_req));
if ((_m) == NULL){
return NULL;
}
NetBufferPrepend<struct _info_req> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_INFO_REQ;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = htole16(sizeof(bufferHeader->param));
bufferHeader->param.type = htole16((_type));
bufferHeader.Sync();
return _m;
}
/* L2CAP_InfoRsp */
static inline net_buffer*
l2cap_info_rsp(uint8 _ident, uint16 _type, uint16 _result, uint16 _mtu)
{
net_buffer* _m = gBufferModule->create(sizeof(struct _info_rsp));
if ((_m) == NULL){
return NULL;
}
NetBufferPrepend<struct _info_rsp> bufferHeader(_m);
status_t status = bufferHeader.Status();
if (status < B_OK) {
/* TODO free the buffer */
return NULL;
}
bufferHeader->hdr.code = L2CAP_INFO_REQ;
bufferHeader->hdr.ident = (_ident);
bufferHeader->hdr.length = sizeof(bufferHeader->param);
bufferHeader->param.type = htole16((_type));
bufferHeader->param.result = htole16((_result));
if ((_result) == L2CAP_SUCCESS) {
switch ((_type)) {
case L2CAP_CONNLESS_MTU:
bufferHeader->data.mtu.mtu = htole16((_mtu));
bufferHeader->hdr.length += sizeof((bufferHeader->data.mtu.mtu));
break;
}
}
(_m)->size = sizeof(bufferHeader->hdr) + bufferHeader->hdr.length;
bufferHeader->hdr.length = htole16(bufferHeader->hdr.length);
bufferHeader.Sync();
return _m;
}
#if 0
#pragma mark -
#endif
/* Build configuration options
static inline net_buffer*
l2cap_build_cfg_options(_m, * _mtu, * _flush_timo, _flow)
{
u_int8_t *p = NULL;
MGETHDR((_m), M_DONTWAIT, MT_DATA);
if ((_m) == NULL)
break;
(_m)->m_pkthdr.len = (_m)->m_len = 0;
p = mtod((_m), u_int8_t *);
if ((_mtu) != NULL) {
struct _cfg_opt_mtu {
l2cap_cfg_opt_t hdr;
u_int16_t val;
} __attribute__ ((packed)) *o = NULL;
o = (struct _cfg_opt_mtu *) p;
o->hdr.type = L2CAP_OPT_MTU;
o->hdr.length = sizeof(o->val);
o->val = htole16(*(u_int16_t *)(_mtu));
(_m)->m_pkthdr.len += sizeof(*o);
p += sizeof(*o);
}
if ((_flush_timo) != NULL) {
struct _cfg_opt_flush {
l2cap_cfg_opt_t hdr;
u_int16_t val;
} __attribute__ ((packed)) *o = NULL;
o = (struct _cfg_opt_flush *) p;
o->hdr.type = L2CAP_OPT_FLUSH_TIMO;
o->hdr.length = sizeof(o->val);
o->val = htole16(*(u_int16_t *)(_flush_timo));
(_m)->m_pkthdr.len += sizeof(*o);
p += sizeof(*o);
}
if ((_flow) != NULL) {
struct _cfg_opt_flow {
l2cap_cfg_opt_t hdr;
l2cap_flow_t val;
} __attribute__ ((packed)) *o = NULL;
o = (struct _cfg_opt_flow *) p;
o->hdr.type = L2CAP_OPT_QOS;
o->hdr.length = sizeof(o->val);
o->val.flags = ((l2cap_flow_p)(_flow))->flags;
o->val.service_type = ((l2cap_flow_p) (_flow))->service_type;
o->val.token_rate = htole32(((l2cap_flow_p)(_flow))->token_rate);
o->val.token_bucket_size = htole32(((l2cap_flow_p) (_flow))->token_bucket_size);
o->val.peak_bandwidth = htole32(((l2cap_flow_p) (_flow))->peak_bandwidth);
o->val.latency = htole32(((l2cap_flow_p) (_flow))->latency);
o->val.delay_variation = htole32(((l2cap_flow_p) (_flow))->delay_variation);
(_m)->m_pkthdr.len += sizeof(*o);
}
(_m)->m_len = (_m)->m_pkthdr.len;
}
*/

View File

@ -0,0 +1,50 @@
/*
* Copyright 2007 Oliver Ruiz Dorantes, oliver.ruiz.dorantes_at_gmail.com
* All rights reserved. Distributed under the terms of the MIT License.
*
*/
#ifndef _L2CAP_CMDS_H_
#define _L2CAP_CMDS_H_
//net
#include <net_buffer.h>
//bt
#include "l2cap.h"
extern net_buffer_module_info *gBufferModule;
static inline net_buffer*
l2cap_cmd_rej(uint8 _ident, uint16 _reason, uint16 _mtu, uint16 _scid, uint16 _dcid);
static inline net_buffer*
l2cap_con_req(uint8 _ident, uint16 _psm, uint16 _scid);
static inline net_buffer*
l2cap_con_rsp(uint8 _ident, uint16 _dcid, uint16 _scid, uint16 _result, uint16 _status);
static inline net_buffer*
l2cap_cfg_req(uint8 _ident, uint16 _dcid, uint16 _flags, net_buffer* _data);
static inline net_buffer*
l2cap_cfg_rsp(uint8 _ident, uint16 _scid, uint16 _flags, uint16 _result, net_buffer* _data);
static inline net_buffer*
l2cap_discon_req(uint8 _ident, uint16 _dcid, uint16 _scid);
static inline net_buffer*
l2cap_discon_rsp(uint8 _ident, uint16 _dcid, uint16 _scid);
static inline net_buffer*
l2cap_echo_req(uint8 _ident, void* _data, size_t _size);
static inline net_buffer*
l2cap_info_req(uint8 _ident, uint16 _type);
static inline net_buffer*
l2cap_info_rsp(uint8 _ident, uint16 _type, uint16 _result, uint16 _mtu);
#endif /* L2CAP_CMDS_H_ */