- 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:
parent
350458a6ba
commit
c15ecd98ca
@ -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
|
||||
|
@ -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
|
||||
|
@ -15,6 +15,7 @@ UsePrivateHeaders kernel net bluetooth ;
|
||||
KernelAddon l2cap :
|
||||
l2cap.cpp
|
||||
l2cap_address.cpp
|
||||
l2cap_command.cpp
|
||||
;
|
||||
|
||||
# Installation
|
||||
|
@ -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>
|
||||
|
295
src/add-ons/kernel/network/protocols/l2cap/l2cap.h
Normal file
295
src/add-ons/kernel/network/protocols/l2cap/l2cap.h
Normal 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
|
||||
|
487
src/add-ons/kernel/network/protocols/l2cap/l2cap_command.cpp
Normal file
487
src/add-ons/kernel/network/protocols/l2cap/l2cap_command.cpp
Normal 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;
|
||||
}
|
||||
*/
|
50
src/add-ons/kernel/network/protocols/l2cap/l2cap_command.h
Normal file
50
src/add-ons/kernel/network/protocols/l2cap/l2cap_command.h
Normal 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_ */
|
||||
|
Loading…
Reference in New Issue
Block a user