diff --git a/headers/os/bluetooth/HCI/btHCI_command.h b/headers/os/bluetooth/HCI/btHCI_command.h index f324378b2f..3e140e3390 100644 --- a/headers/os/bluetooth/HCI/btHCI_command.h +++ b/headers/os/bluetooth/HCI/btHCI_command.h @@ -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 diff --git a/headers/os/bluetooth/bluetooth.h b/headers/os/bluetooth/bluetooth.h index 3de6e8a314..33e26f10a5 100644 --- a/headers/os/bluetooth/bluetooth.h +++ b/headers/os/bluetooth/bluetooth.h @@ -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 diff --git a/src/add-ons/kernel/network/protocols/l2cap/Jamfile b/src/add-ons/kernel/network/protocols/l2cap/Jamfile index da58ac0940..12ffa498be 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/Jamfile +++ b/src/add-ons/kernel/network/protocols/l2cap/Jamfile @@ -15,6 +15,7 @@ UsePrivateHeaders kernel net bluetooth ; KernelAddon l2cap : l2cap.cpp l2cap_address.cpp + l2cap_command.cpp ; # Installation diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp b/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp index 096632aeb9..7a6ec93685 100644 --- a/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap.cpp @@ -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 + * 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 #include #include diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap.h b/src/add-ons/kernel/network/protocols/l2cap/l2cap.h new file mode 100644 index 0000000000..3321f45802 --- /dev/null +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap.h @@ -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 + * 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 + +// 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 + diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap_command.cpp b/src/add-ons/kernel/network/protocols/l2cap/l2cap_command.cpp new file mode 100644 index 0000000000..049ef74fcf --- /dev/null +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap_command.cpp @@ -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 + * 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 + +#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 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 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 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 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 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 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 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 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 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 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; +} +*/ diff --git a/src/add-ons/kernel/network/protocols/l2cap/l2cap_command.h b/src/add-ons/kernel/network/protocols/l2cap/l2cap_command.h new file mode 100644 index 0000000000..82a0f6531e --- /dev/null +++ b/src/add-ons/kernel/network/protocols/l2cap/l2cap_command.h @@ -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 + +//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_ */ +