* Re: Help hcitool cmd (hci to connect)
From: haijun liu @ 2011-02-24 1:23 UTC (permalink / raw)
To: Thibaut L; +Cc: linux-bluetooth
In-Reply-To: <AANLkTin7W9jtfAmV4vo9E+YOrkUfrWpO0-B_jzkXZChm@mail.gmail.com>
Thibaut,
I remember there is a monitor for hci connection, if nobody reference
it for a while, then it will issue a disconnect request, so you'd
better make a l2cap connection on it to keep it alive.
Haijun.Liu
skype: liu.haijun
On 2/22/11, Thibaut L <thibaut.dvr@gmail.com> wrote:
> Dear all,
>
> Please, could anyone tell me how to connect to a bluetooth device
> through hcitool (BlueZ) hci command. Like this: "hcitool cmd 0x01
> 0x0005 [parameters]". How can I input this cmd? Is the [parameters] a
> bt device MAC adress like XX:XX:XX:XX:XX:XX?
>
> I've tryed to use "hcitool cc <MAC>", but it doesn't work for me cause
> it disconnects the device a second later.
>
> I just wanna measure RSSI.
>
> Thanks in advance.
>
> Best
>
> Thibaut
> --
> To unsubscribe from this list: send the line "unsubscribe linux-bluetooth"
> in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Haijun Liu
^ permalink raw reply
* [PATCH 2/2] Use attribute data list memory allocation function on attrib server
From: Claudio Takahasi @ 2011-02-23 22:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
In-Reply-To: <1298500393-4894-1-git-send-email-claudio.takahasi@openbossa.org>
---
src/attrib-server.c | 33 ++++++++++++++++++---------------
1 files changed, 18 insertions(+), 15 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 7ec0f56..21868b3 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -260,17 +260,17 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
length = g_slist_length(groups);
- adl = g_new0(struct att_data_list, 1);
- adl->len = last_size + 4; /* Length of each element */
- adl->num = length; /* Number of primary or secondary services */
- adl->data = g_malloc(length * sizeof(uint8_t *));
+ adl = att_data_list_alloc(length, last_size + 4);
+ if (adl == NULL) {
+ length = 0;
+ goto failed;
+ }
for (i = 0, l = groups; l; l = l->next, i++) {
uint8_t *value;
cur = l->data;
- adl->data[i] = g_malloc(adl->len);
value = (void *) adl->data[i];
att_put_u16(cur->handle, value);
@@ -281,6 +281,7 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
length = enc_read_by_grp_resp(adl, pdu, len);
+failed:
att_data_list_free(adl);
g_slist_foreach(groups, (GFunc) g_free, NULL);
g_slist_free(groups);
@@ -341,16 +342,16 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
/* Handle length plus attribute value length */
length += 2;
- adl = g_new0(struct att_data_list, 1);
- adl->len = length; /* Length of each element */
- adl->num = num; /* Number of primary or secondary services */
- adl->data = g_malloc(num * sizeof(uint8_t *));
+ adl = att_data_list_alloc(num, length);
+ if (adl == NULL) {
+ length = 0;
+ goto failed;
+ }
for (i = 0, l = types; l; i++, l = l->next) {
uint8_t *value;
a = l->data;
- adl->data[i] = g_malloc(length);
value = (void *) adl->data[i];
@@ -362,6 +363,7 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
length = enc_read_by_type_resp(adl, pdu, len);
+failed:
att_data_list_free(adl);
g_slist_free(types);
@@ -414,16 +416,16 @@ static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
format = 0x02;
}
- adl = g_new0(struct att_data_list, 1);
- adl->len = length + 2; /* Length of each element */
- adl->num = num; /* Number of primary or secondary services */
- adl->data = g_malloc(num * sizeof(uint8_t *));
+ adl = att_data_list_alloc(num, length + 2);
+ if (adl == NULL) {
+ length = 0;
+ goto failed;
+ }
for (i = 0, l = info; l; i++, l = l->next) {
uint8_t *value;
a = l->data;
- adl->data[i] = g_malloc(adl->len);
value = (void *) adl->data[i];
@@ -435,6 +437,7 @@ static int find_info(uint16_t start, uint16_t end, uint8_t *pdu, int len)
length = enc_find_info_resp(format, adl, pdu, len);
+failed:
att_data_list_free(adl);
g_slist_free(info);
--
1.7.4.1
^ permalink raw reply related
* [PATCH 1/2] Coding standard change replacing malloc by glib functions
From: Claudio Takahasi @ 2011-02-23 22:33 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
Use glib memory allocation functions instead of malloc for attribute
data list in ATT protocol utility functions.
---
attrib/att.c | 101 ++++++++++++++++++++++++++++++++++++++++++----------------
attrib/att.h | 1 +
2 files changed, 74 insertions(+), 28 deletions(-)
diff --git a/attrib/att.c b/attrib/att.c
index 3259fca..1de93c4 100644
--- a/attrib/att.c
+++ b/attrib/att.c
@@ -80,13 +80,47 @@ const char *att_ecode2str(uint8_t status)
void att_data_list_free(struct att_data_list *list)
{
+ if (list == NULL)
+ return;
+
+ if (list->data) {
+ int i;
+ for (i = 0; i < list->num; i++)
+ g_free(list->data[i]);
+ }
+
+ g_free(list->data);
+ g_free(list);
+}
+
+struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len)
+{
+ struct att_data_list *list;
int i;
- for (i = 0; i < list->num; i++)
- free(list->data[i]);
+ list = g_try_new0(struct att_data_list, 1);
+ if (list == NULL)
+ return NULL;
+
+ list->len = len;
+ list->num = num;
+
+ list->data = g_try_malloc0(sizeof(uint8_t *) * num);
+ if (list->data == NULL)
+ goto enomem;
- free(list->data);
- free(list);
+ for (i = 0; i < num; i++) {
+ list->data[i] = g_try_malloc0(sizeof(uint8_t) * len);
+ if (list->data[i] == NULL)
+ goto enomem;
+ }
+
+ return list;
+
+enomem:
+ att_data_list_free(list);
+
+ return NULL;
}
uint16_t enc_read_by_grp_req(uint16_t start, uint16_t end, uuid_t *uuid,
@@ -178,20 +212,21 @@ struct att_data_list *dec_read_by_grp_resp(const uint8_t *pdu, int len)
{
struct att_data_list *list;
const uint8_t *ptr;
+ uint16_t elen, num;
int i;
if (pdu[0] != ATT_OP_READ_BY_GROUP_RESP)
return NULL;
- list = malloc(sizeof(struct att_data_list));
- list->len = pdu[1];
- list->num = (len - 2) / list->len;
+ elen = pdu[1];
+ num = (len - 2) / elen;
+ list = att_data_list_alloc(num, elen);
+ if (list == NULL)
+ return NULL;
- list->data = malloc(sizeof(uint8_t *) * list->num);
ptr = &pdu[2];
- for (i = 0; i < list->num; i++) {
- list->data[i] = malloc(sizeof(uint8_t) * list->len);
+ for (i = 0; i < num; i++) {
memcpy(list->data[i], ptr, list->len);
ptr += list->len;
}
@@ -307,7 +342,10 @@ GSList *dec_find_by_type_resp(const uint8_t *pdu, int len)
return NULL;
for (offset = 1, matches = NULL; len >= (offset + 4); offset += 4) {
- range = malloc(sizeof(struct att_range));
+ range = g_try_new0(struct att_range, 1);
+ if (range == NULL)
+ goto enomem;
+
range->start = att_get_u16(&pdu[offset]);
range->end = att_get_u16(&pdu[offset + 2]);
@@ -315,6 +353,12 @@ GSList *dec_find_by_type_resp(const uint8_t *pdu, int len)
}
return matches;
+
+enomem:
+ g_slist_foreach(matches, (GFunc) g_free, NULL);
+ g_slist_free(matches);
+
+ return NULL;
}
uint16_t enc_read_by_type_req(uint16_t start, uint16_t end, uuid_t *uuid,
@@ -406,20 +450,21 @@ struct att_data_list *dec_read_by_type_resp(const uint8_t *pdu, int len)
{
struct att_data_list *list;
const uint8_t *ptr;
+ uint16_t elen, num;
int i;
if (pdu[0] != ATT_OP_READ_BY_TYPE_RESP)
return NULL;
- list = malloc(sizeof(struct att_data_list));
- list->len = pdu[1];
- list->num = (len - 2) / list->len;
+ elen = pdu[1];
+ num = (len - 2) / elen;
+ list = att_data_list_alloc(num, elen);
+ if (list == NULL)
+ return NULL;
- list->data = malloc(sizeof(uint8_t *) * list->num);
ptr = &pdu[2];
- for (i = 0; i < list->num; i++) {
- list->data[i] = malloc(sizeof(uint8_t) * list->len);
+ for (i = 0; i < num; i++) {
memcpy(list->data[i], ptr, list->len);
ptr += list->len;
}
@@ -775,6 +820,7 @@ struct att_data_list *dec_find_info_resp(const uint8_t *pdu, int len,
{
struct att_data_list *list;
uint8_t *ptr;
+ uint16_t elen, num;
int i;
if (pdu == NULL)
@@ -787,22 +833,21 @@ struct att_data_list *dec_find_info_resp(const uint8_t *pdu, int len,
return 0;
*format = pdu[1];
-
- list = malloc(sizeof(struct att_data_list));
-
- list->len = sizeof(pdu[0]) + sizeof(*format);
+ elen = sizeof(pdu[0]) + sizeof(*format);
if (*format == 0x01)
- list->len += 2;
+ elen += 2;
else if (*format == 0x02)
- list->len += 16;
+ elen += 16;
- list->num = (len - 2) / list->len;
- list->data = malloc(sizeof(uint8_t *) * list->num);
+ num = (len - 2) / elen;
ptr = (void *) &pdu[2];
- for (i = 0; i < list->num; i++) {
- list->data[i] = malloc(list->len);
+ list = att_data_list_alloc(num, elen);
+ if (list == NULL)
+ return NULL;
+
+ for (i = 0; i < num; i++) {
memcpy(list->data[i], ptr, list->len);
ptr += list->len;
}
@@ -859,7 +904,7 @@ struct attribute *dec_indication(const uint8_t *pdu, int len)
if (len < min_len)
return NULL;
- a = malloc(sizeof(struct attribute) + len - min_len);
+ a = g_try_malloc0(sizeof(struct attribute) + len - min_len);
if (a == NULL)
return NULL;
diff --git a/attrib/att.h b/attrib/att.h
index 7d9afeb..76072c0 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -185,6 +185,7 @@ static inline void att_put_u32(uint32_t src, void *dst)
bt_put_unaligned(htobl(src), (uint32_t *) dst);
}
+struct att_data_list *att_data_list_alloc(uint16_t num, uint16_t len);
void att_data_list_free(struct att_data_list *list);
const char *att_ecode2str(uint8_t status);
--
1.7.4.1
^ permalink raw reply related
* [PATCH] Add sec-level option to interactive gattool
From: Sheldon Demario @ 2011-02-23 21:30 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
---
attrib/interactive.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 46 insertions(+), 0 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 05d94af..ec77f27 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -537,6 +537,50 @@ static void cmd_char_write_req(int argcp, char **argvp)
g_free(value);
}
+static void cmd_sec_level(int argcp, char **argvp)
+{
+ GError *gerr = NULL;
+ BtIOSecLevel sec_level;
+
+ if (argcp < 2) {
+ printf("sec-level: %s\n", opt_sec_level);
+ return;
+ }
+
+ if (strcasecmp(argvp[1], "medium") == 0)
+ sec_level = BT_IO_SEC_MEDIUM;
+ else if (strcasecmp(argvp[1], "high") == 0)
+ sec_level = BT_IO_SEC_HIGH;
+ else if (strcasecmp(argvp[1], "low") == 0)
+ sec_level = BT_IO_SEC_LOW;
+ else {
+ printf("Allowed values: low | medium | high\n");
+ return;
+ }
+
+ g_free(opt_sec_level);
+ opt_sec_level = strdup(argvp[1]);
+
+ if (conn_state == STATE_CONNECTED) {
+ if (opt_psm) {
+ printf("It must be reconnected to this "
+ "change take effect\n");
+ return;
+ }
+
+ bt_io_set(iochannel, BT_IO_L2CAP, &gerr,
+ BT_IO_OPT_SEC_LEVEL, sec_level,
+ BT_IO_OPT_INVALID);
+
+ if (gerr) {
+ printf("Error: %s\n", gerr->message);
+ g_error_free(gerr);
+ }
+ }
+
+ return;
+}
+
static struct {
const char *cmd;
void (*func)(int argcp, char **argvp);
@@ -563,6 +607,8 @@ static struct {
"Characteristics Value/Descriptor Read by UUID" },
{ "char-write-req", cmd_char_write_req, "<handle> <new value>",
"Characteristic Value Write (Write Request)" },
+ { "sec-level", cmd_sec_level, "[low | medium | high]",
+ "Set security level. Default: low" },
{ NULL, NULL, NULL}
};
--
1.7.1
^ permalink raw reply related
* [PATCH] hcitool: add discovery procedure to lescan command
From: Andre Guedes @ 2011-02-23 21:16 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andre Guedes
This patch adds the option [--discovery=g|l] to lescan command. Use
this option to enable the general or limited discovery procedure.
If discovery option is not given scanning will display all results
ignoring the AD flags.
---
tools/hcitool.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++---
1 files changed, 77 insertions(+), 5 deletions(-)
diff --git a/tools/hcitool.c b/tools/hcitool.c
index d7a82cc..cb7d181 100644
--- a/tools/hcitool.c
+++ b/tools/hcitool.c
@@ -49,6 +49,10 @@
/* Unofficial value, might still change */
#define LE_LINK 0x03
+#define FLAGS_AD_TYPE 0x01
+#define FLAGS_LIMITED_MODE_BIT 0x01
+#define FLAGS_GENERAL_MODE_BIT 0x02
+
#define for_each_opt(opt, long, short) while ((opt=getopt_long(argc, argv, short ? short:"+", long, NULL)) != -1)
static void usage(void);
@@ -2287,7 +2291,62 @@ static void cmd_clock(int dev_id, int argc, char **argv)
hci_close_dev(dd);
}
-static int print_advertising_devices(int dd)
+static int read_flags(uint8_t *flags, const uint8_t *data, size_t size)
+{
+ unsigned int offset;
+
+ if (!flags || !data)
+ return -EINVAL;
+
+ offset = 0;
+ while (offset < size) {
+ uint8_t len = data[offset];
+ uint8_t type = data[offset + 1];
+
+ /* Check if it is the end of the significant part */
+ if (len == 0)
+ break;
+
+ if (type == FLAGS_AD_TYPE) {
+ *flags = data[offset + 2];
+ return 0;
+ }
+
+ offset += 1 + len;
+ }
+
+ return -ENOENT;
+}
+
+static int check_report_filter(uint8_t procedure, le_advertising_info *info)
+{
+ uint8_t flags;
+
+ /* If no discovery procedure is set, all reports are treat as valid */
+ if (procedure == 0)
+ return 1;
+
+ /* Read flags AD type value from the advertising report if it exists */
+ if (read_flags(&flags, info->data, info->length))
+ return 0;
+
+ switch (procedure) {
+ case 'l': /* Limited Discovery Procedure */
+ if (flags & FLAGS_LIMITED_MODE_BIT)
+ return 1;
+ break;
+ case 'g': /* General Discovery Procedure */
+ if (flags & (FLAGS_LIMITED_MODE_BIT | FLAGS_GENERAL_MODE_BIT))
+ return 1;
+ break;
+ default:
+ fprintf(stderr, "Unknown discovery procedure\n");
+ }
+
+ return 0;
+}
+
+static int print_advertising_devices(int dd, uint8_t filter_type)
{
unsigned char buf[HCI_MAX_EVENT_SIZE], *ptr;
struct hci_filter nf, of;
@@ -2334,8 +2393,10 @@ static int print_advertising_devices(int dd)
/* Ignoring multiple reports */
info = (le_advertising_info *) (meta->data + 1);
- ba2str(&info->bdaddr, addr);
- printf("%s\n", addr);
+ if (check_report_filter(filter_type, info)) {
+ ba2str(&info->bdaddr, addr);
+ printf("%s\n", addr);
+ }
}
done:
@@ -2351,19 +2412,23 @@ static struct option lescan_options[] = {
{ "help", 0, 0, 'h' },
{ "privacy", 0, 0, 'p' },
{ "passive", 0, 0, 'P' },
+ { "discovery", 1, 0, 'd' },
{ 0, 0, 0, 0 }
};
static const char *lescan_help =
"Usage:\n"
"\tlescan [--privacy] enable privacy\n"
- "\tlescan [--passive] set scan type passive (default active)\n";
+ "\tlescan [--passive] set scan type passive (default active)\n"
+ "\tlescan [--discovery=g|l] enable general or limited discovery"
+ "procedure\n";
static void cmd_lescan(int dev_id, int argc, char **argv)
{
int err, opt, dd;
uint8_t own_type = 0x00;
uint8_t scan_type = 0x01;
+ uint8_t filter_type = 0;
for_each_opt(opt, lescan_options, NULL) {
switch (opt) {
@@ -2373,6 +2438,13 @@ static void cmd_lescan(int dev_id, int argc, char **argv)
case 'P':
scan_type = 0x00; /* Passive */
break;
+ case 'd':
+ filter_type = optarg[0];
+ if (filter_type != 'g' && filter_type != 'l') {
+ fprintf(stderr, "Unknown discovery procedure\n");
+ exit(1);
+ }
+ break;
default:
printf("%s", lescan_help);
return;
@@ -2404,7 +2476,7 @@ static void cmd_lescan(int dev_id, int argc, char **argv)
printf("LE Scan ...\n");
- err = print_advertising_devices(dd);
+ err = print_advertising_devices(dd, filter_type);
if (err < 0) {
perror("Could not receive advertising events");
exit(1);
--
1.7.1
^ permalink raw reply related
* can't pair the phone
From: sergio @ 2011-02-23 21:12 UTC (permalink / raw)
To: linux-bluetooth
Hello.
I can't pair my Ericsson T39 with my linux box.
I can pair any another phone (for example Nokia 6310) with linux.
I can pair Ericsson with any other device (for example with adroid phone, or
with windows). So it's bluez problem.
% bluez-test-discovery
[ 00:01:EC:0C:D2:00 ]
Name = totoro
Paired = 0
LegacyPairing = 1
Alias = totoro
Address = 00:01:EC:0C:D2:00
RSSI = 0
Class = 0x520204
Icon = phone
[ 00:01:EC:0C:D2:00 ]
Name = totoro
Paired = 0
LegacyPairing = 1
Alias = totoro
Address = 00:01:EC:0C:D2:00
RSSI = 0
Class = 0x520204
Icon = phone
I don't know why it shows it twice.
bluetoothd -n -d shows:
bluetoothd[8071]: plugins/hciops.c:hciops_start_inquiry() hci0 length 8
periodic 1
bluetoothd[8071]: Discovery session 0xf77741c8 with :1.64 activated
bluetoothd[8071]: src/adapter.c:session_ref() 0xf77741c8: ref=1
bluetoothd[8071]: plugins/hciops.c:hciops_resolve_name() hci0 dba
00:01:EC:0C:D2:00
bluetoothd[8071]: plugins/hciops.c:remote_name_information() hci0 status 0
bluetoothd[8071]: src/adapter.c:session_remove() Discovery session
0xf77741c8 with :1.64 deactivated
bluetoothd[8071]: src/adapter.c:session_remove() Stopping discovery
bluetoothd[8071]: plugins/hciops.c:hciops_stop_inquiry() hci0
% bluez-simple-agent hci0 00:01:EC:0C:D2:00
RequestPinCode (/org/bluez/8071/hci0/dev_00_01_EC_0C_D2_00)
Enter PIN Code: 1234
Creating device failed: org.bluez.Error.AuthenticationRejected:
Authentication Rejected
Phone doesn't ask to enter pin.
bluetoothd -n -d shows:
before pin enter:
bluetoothd[8071]: src/adapter.c:adapter_create_device() 00:01:EC:0C:D2:00
bluetoothd[8071]: src/device.c:device_create() Creating device
/org/bluez/8071/hci0/dev_00_01_EC_0C_D2_00
bluetoothd[8071]: src/device.c:btd_device_ref() 0xf7786b88: ref=1
bluetoothd[8071]: src/device.c:bonding_request_new() Requesting bonding
for 00:01:EC:0C:D2:00
bluetoothd[8071]: src/device.c:bonding_request_new() Temporary agent
registered for 00:01:EC:0C:D2:00 at :1.65:/test/agent
bluetoothd[8071]: src/adapter.c:adapter_get_device() 00:01:EC:0C:D2:00
bluetoothd[8071]: plugins/hciops.c:remote_features_information() hci0
status 0
bluetoothd[8071]: plugins/hciops.c:link_key_request() hci0 dba
00:01:EC:0C:D2:00
bluetoothd[8071]: plugins/hciops.c:link_key_request() kernel auth
requirements = 0x03
bluetoothd[8071]: plugins/hciops.c:link_key_request() Matching key not found
bluetoothd[8071]: plugins/hciops.c:pin_code_request() hci0 PIN request
for 00:01:EC:0C:D2:00
bluetoothd[8071]: src/adapter.c:adapter_get_device() 00:01:EC:0C:D2:00
bluetoothd[8071]: src/device.c:device_request_authentication()
Requesting agent authentication for 00:01:EC:0C:D2:00
after pin enter:
bluetoothd[8071]: plugins/hciops.c:hciops_pincode_reply() hci0 dba
00:01:EC:0C:D2:00
bluetoothd[8071]: plugins/hciops.c:auth_complete() hci0 status 24
bluetoothd[8071]: src/event.c:btd_event_bonding_process_complete() status=18
bluetoothd[8071]: src/device.c:device_cancel_authentication() Canceling
authentication request for 00:01:EC:0C:D2:00
bluetoothd[8071]: src/device.c:device_cancel_bonding() Canceling bonding
request for 00:01:EC:0C:D2:00
bluetoothd[8071]: src/agent.c:agent_release() Releasing agent :1.65,
/test/agent
bluetoothd[8071]: src/adapter.c:adapter_get_device() 00:01:EC:0C:D2:00
bluetoothd[8071]: src/adapter.c:adapter_remove_connection() Removing
temporary device /org/bluez/8071/hci0/dev_00_01_EC_0C_D2_00
bluetoothd[8071]: src/device.c:device_remove() Removing device
/org/bluez/8071/hci0/dev_00_01_EC_0C_D2_00
bluetoothd[8071]: src/device.c:btd_device_unref() 0xf7786b88: ref=0
bluetoothd[8071]: src/device.c:device_free() 0xf7786b88
When I try to iniate pairing from phone I get, after enter pin on phone:
bluetoothd[8071]: src/adapter.c:adapter_get_device() 00:01:EC:0C:D2:00
bluetoothd[8071]: src/adapter.c:adapter_create_device() 00:01:EC:0C:D2:00
bluetoothd[8071]: src/device.c:device_create() Creating device
/org/bluez/8071/hci0/dev_00_01_EC_0C_D2_00
bluetoothd[8071]: src/device.c:btd_device_ref() 0xf7786b88: ref=1
bluetoothd[8071]: src/device.c:device_remove() Removing device
/org/bluez/8071/hci0/dev_00_01_EC_0C_D2_00
bluetoothd[8071]: src/device.c:btd_device_unref() 0xf7786b88: ref=0
bluetoothd[8071]: src/device.c:device_free() 0xf7786b88
bluez-simple-agent shows nothing.
--
sergio.
^ permalink raw reply
* Re: [Bug 26182] btusb hangs after resetting USB device
From: Rafael J. Wysocki @ 2011-02-23 19:36 UTC (permalink / raw)
To: Alan Stern; +Cc: Marcel Holtmann, Gustavo F. Padovan, linux-bluetooth
In-Reply-To: <201102231604.p1NG4UEf006117@demeter1.kernel.org>
On Wednesday, February 23, 2011, bugzilla-daemon@bugzilla.kernel.org wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=26182
>
>
> Alan Stern <stern@rowland.harvard.edu> changed:
>
> What |Removed |Added
> ----------------------------------------------------------------------------
> CC| |mjg59-kernel@srcf.ucam.org
>
>
>
>
> --- Comment #7 from Alan Stern <stern@rowland.harvard.edu> 2011-02-23 16:04:19 ---
> Matthew, it looks like your 556ea928f78a390fe16ae584e6433dff304d3014 commit
> (Bluetooth: Enable USB autosuspend by default on btusb) needs to be reverted,
> at least until somebody adds reset-resume support to the btusb driver.
>
> Florian or Rafael, can one of you let the Bluetooth maintainers know about this
> bug? There has been at least one other bug report for this same problem on
> LKML:
>
> http://marc.info/?l=linux-kernel&m=129845423017429&w=2
Sure, CCed.
Thanks,
Rafael
^ permalink raw reply
* [PATCH] Don't register GATT related SDP records if attrib server is disabled
From: Claudio Takahasi @ 2011-02-23 18:15 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Claudio Takahasi
GATT related SDP records should not be added if "AttributeServer" option
is false in the configuration file. Problem happens only when attribute
plugin is enabled.
---
attrib/manager.c | 14 ++++++++------
1 files changed, 8 insertions(+), 6 deletions(-)
diff --git a/attrib/manager.c b/attrib/manager.c
index f991f8e..a5a7de4 100644
--- a/attrib/manager.c
+++ b/attrib/manager.c
@@ -32,6 +32,7 @@
#include "../src/adapter.h"
#include "../src/device.h"
+#include "hcid.h"
#include "manager.h"
#include "client.h"
@@ -84,19 +85,20 @@ int attrib_manager_init(DBusConnection *conn)
btd_register_device_driver(&client_driver);
- /*
- * FIXME: Add config file option to allow
- * enable/disable the GATT server and client.
- */
- return server_example_init();
+ if (main_opts.attrib_server)
+ return server_example_init();
+
+ return 0;
}
void attrib_manager_exit(void)
{
btd_unregister_device_driver(&client_driver);
- server_example_exit();
+ if (main_opts.attrib_server)
+ server_example_exit();
+
attrib_client_exit();
dbus_connection_unref(connection);
--
1.7.4.1
^ permalink raw reply related
* Re: [PATCH] Drop trailing newline from DBG() calls
From: Anderson Lizardo @ 2011-02-23 18:12 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1298467707-11121-1-git-send-email-anderson.lizardo@openbossa.org>
Hi Johan,
On Wed, Feb 23, 2011 at 10:28 AM, Anderson Lizardo
<anderson.lizardo@openbossa.org> wrote:
> ---
> audio/telephony-ofono.c | 2 +-
> plugins/service.c | 4 ++--
> 2 files changed, 3 insertions(+), 3 deletions(-)
Please ignore this patch, it was superseded by the one titled "Fix
DBG() calls with bogus messages".
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* [PATCH] Fix DBG() calls with bogus messages
From: Anderson Lizardo @ 2011-02-23 18:11 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1298467707-11121-1-git-send-email-anderson.lizardo@openbossa.org>
Remove unnecessary trailing newlines (already added by DBG()) and
rewrite debug messages to become more useful.
---
audio/telephony-ofono.c | 2 +-
plugins/service.c | 5 +++--
2 files changed, 4 insertions(+), 3 deletions(-)
diff --git a/audio/telephony-ofono.c b/audio/telephony-ofono.c
index 0a7f0bd..ef4ede7 100644
--- a/audio/telephony-ofono.c
+++ b/audio/telephony-ofono.c
@@ -1116,7 +1116,7 @@ static void get_modems_reply(DBusPendingCall *call, void *user_data)
DBusMessage *reply;
DBusMessageIter iter, entry;
- DBG("list_modem_reply is called\n");
+ DBG("");
reply = dbus_pending_call_steal_reply(call);
dbus_error_init(&err);
diff --git a/plugins/service.c b/plugins/service.c
index f44aa92..d73cdea 100644
--- a/plugins/service.c
+++ b/plugins/service.c
@@ -172,13 +172,14 @@ static void element_end(GMarkupParseContext *context,
int ret = sdp_attr_add(ctx_data->record, ctx_data->attr_id,
ctx_data->stack_head->data);
if (ret == -1)
- DBG("Trouble adding attribute\n");
+ DBG("Could not add attribute 0x%04x",
+ ctx_data->attr_id);
ctx_data->stack_head->data = NULL;
sdp_xml_data_free(ctx_data->stack_head);
ctx_data->stack_head = NULL;
} else {
- DBG("No data for attribute 0x%04x\n", ctx_data->attr_id);
+ DBG("No data for attribute 0x%04x", ctx_data->attr_id);
}
return;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH] Update mgmt-api.txt with controller index moved to mgmt packet header
From: Szymon Janc @ 2011-02-23 17:39 UTC (permalink / raw)
To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
---
doc/mgmt-api.txt | 214 ++++++++++++++++++++++++++++--------------------------
1 files changed, 110 insertions(+), 104 deletions(-)
diff --git a/doc/mgmt-api.txt b/doc/mgmt-api.txt
index 2add44f..63fa9a7 100644
--- a/doc/mgmt-api.txt
+++ b/doc/mgmt-api.txt
@@ -9,25 +9,31 @@ Packet Structures
Commands:
- 0 4 8 12 16 202 24 28 31
- +-------------------------------+-----------------------------+
- | Command Code | Parameter Total Length |
- +-------------------------------+-----------------------------+
- | |
+ 0 4 8 12 16 22 24 28 31 35 39 43 47
+ +-------------------+-------------------+-------------------+
+ | Command Code | Controller Index | Parameter Length |
+ +-------------------+-------------------+-------------------+
+ | |
Events:
- 0 4 8 12 16 202 24 28 31
- +-------------------------------+-----------------------------+
- | Event Code | Parameter Total Length |
- +-------------------------------+-----------------------------+
- | |
+ 0 4 8 12 16 22 24 28 31 35 39 43 47
+ +-------------------+-------------------+-------------------+
+ | Event Code | Controller Index | Parameter Length |
+ +-------------------+-------------------+-------------------+
+ | |
+
+Controller Index can have a special value <non-controller> to indicate that
+command or event is not related to any controller. Possible values:
+ <controller id> 0x0000 to 0xFFFE
+ <non-controller> 0xFFFF
Read Management Version Information Command
===========================================
Command Code: 0x0001
+ Controller Index: <non-controller>
Command Parameters:
Return Parameters: Version (1 Octets)
Revision (2 Octets)
@@ -37,6 +43,7 @@ Read Management Supported Features Command
==========================================
Command Code: 0x0002
+ Controller Index: <non-controller>
Command Parameters:
Return Parameters: Features (8 Octets)
@@ -48,6 +55,7 @@ Read Controller Index List Command
==================================
Command Code: 0x0003
+ Controller Index: <non-controller>
Command Parameters:
Return Paramters: Num_Controllers (2 Octets)
Controller_Index[i] (2 Octets)
@@ -57,9 +65,9 @@ Read Controller Information Command
===================================
Command Code: 0x0004
- Command Parameters: Controller_Index (2 Octets)
- Return Parameters: Controller_Index (2 Octets)
- Controller_Type (1 Octet)
+ Controller Index: <controller id>
+ Command Parameters:
+ Return Parameters: Controller_Type (1 Octet)
Powered (1 octet)
Connectable (1 octet)
Discoverable (1 octet)
@@ -81,85 +89,81 @@ Set Powered Command
===================
Command Code: 0x0005
- Command Parameters: Controller_Index (2 Octets)
- Powered (1 Octet)
- Return Paramters: Controller_Index (2 Octets)
- Powered (1 Octet)
+ Controller Index: <controller id>
+ Command Parameters: Powered (1 Octet)
+ Return Paramters: Powered (1 Octet)
Set Discoverable Command
========================
Command Code: 0x0006
- Command Parameters: Controller_Index (2 Octets)
- Discoverable (1 Octet)
- Return Paramters: Controller_Index (2 Octets)
- Discoverable (1 Octet)
+ Controller Index: <controller id>
+ Command Parameters: Discoverable (1 Octet)
+ Return Paramters: Discoverable (1 Octet)
Set Connectable Command
=======================
Command Code: 0x0007
- Command Parameters: Controller_Index (2 Octets)
- Connectable (1 Octet)
- Return Paramters: Controller_Index (2 Octets)
- Connectable (1 Octet)
+ Controller Index: <controller id>
+ Command Parameters: Connectable (1 Octet)
+ Return Paramters: Connectable (1 Octet)
Set Pairable Command
====================
Command Code: 0x0008
- Command Parameters: Controller_Index (2 Octets)
- Pairable (1 Octet)
- Return Paramters: Controller_Index (2 Octets)
- Pairable (1 Octet)
+ Controller Index: <controller id>
+ Command Parameters: Pairable (1 Octet)
+ Return Paramters: Pairable (1 Octet)
Add UUID Command
================
Command Code: 0x0009
- Command Parameters: Controller_Index (2 Octets)
- UUID (16 Octets)
+ Controller Index: <controller id>
+ Command Parameters: UUID (16 Octets)
SVC_Hint (1 octet)
- Return Paramters: Controller_Index (2 Octets)
+ Return Paramters:
Remove UUID Command
===================
Command Code: 0x000A
- Command Parameters: Controller_Index (2 Octets)
- UUID (16 Octets)
- Return Paramters: Controller_Index (2 Octets)
+ Controller Index: <controller id>
+ Command Parameters: UUID (16 Octets)
+ Return Paramters:
Set Device Class
================
Command Code: 0x000B
- Command Parameters: Controller_Index (2 Octets)
- Major_Class (1 octet)
+ Controller Index: <controller id>
+ Command Parameters: Major_Class (1 octet)
Minor_Class (1 octed)
- Return Paramters: Controller_Index (2 Octets)
+ Return Paramters:
Set Service Cache Command
=========================
Command Code: 0x000C
- Command Parameters: Controller_Index (2 Octets)
- Enable (1 octet)
- Return Paramters: Controller_Index (2 Octets)
+ Controller Index: <controller id>
+ Command Parameters: Enable (1 octet)
+ Return Paramters:
Load Keys Command
=================
Command Code: 0x000D
- Command Parameters: Controller_Index (2 Octets)
- Debug_Keys (1 Octet)
+ Controller Index: <controller id>
+ Command Parameters: Debug_Keys (1 Octet)
Key_Count (2 Octets)
Key1 {
Address (6 Octets)
@@ -169,35 +173,34 @@ Load Keys Command
}
Key2 { }
...
- Return Paramters: Controller_Index (2 Octets)
+ Return Paramters:
Remove Key Command
==================
Command Code: 0x000E
- Command Parameters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Controller Index: <controller id>
+ Command Parameters: Address (6 Octets)
Disconnect (1 Octet)
- Return Paramters: Controller_Index (2 Octets)
+ Return Paramters:
Disconnect Command
==================
Command Code: 0x000F
- Command Parameters: Controller_Index (2 Octets)
- Address (6 Octets)
- Return Paramters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Controller Index: <controller id>
+ Command Parameters: Address (6 Octets)
+ Return Paramters: Address (6 Octets)
Get Connections Command
=======================
Command Code: 0x0010
- Command Parameters: Controller_Index (2 Octets)
- Return Paramters: Controller_Index (2 Octets)
- Connection_Count (2 Octets)
+ Controller Index: <controller id>
+ Command Parameters:
+ Return Paramters: Connection_Count (2 Octets)
Address1 (6 Octets)
Address2 (6 Octets)
...
@@ -206,9 +209,9 @@ PIN Code Reply Command
=======================
Command Code: 0x0011
- Command Parameters: Controller_Index (2 Octets)
- Return Paramters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Controller Index: <controller id>
+ Command Parameters:
+ Return Paramters: Address (6 Octets)
PIN_Length (1 Octet)
PIN_Code (16 Octets)
@@ -217,29 +220,28 @@ PIN Code Negative Reply Command
===============================
Command Code: 0x0012
- Command Parameters: Controller_Index (2 Octets)
- Return Paramters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Controller Index: <controller id>
+ Command Parameters:
+ Return Paramters: Address (6 Octets)
Set IO Capability Command
=========================
Command Code: 0x0013
- Command Parameters: Controller_Index (2 Octets)
- IO_Capability (1 Octet)
- Return Paramters: Controller_Index (2 Octets)
+ Controller Index: <controller id>
+ Command Parameters: IO_Capability (1 Octet)
+ Return Paramters:
Pair Device Command
===================
Command Code: 0x0014
- Command Parameters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Controller Index: <controller id>
+ Command Parameters: Address (6 Octets)
IO_Capability (1 Octet)
- Return Paramters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Return Paramters: Address (6 Octets)
Status (1 Octet)
@@ -247,10 +249,9 @@ User Confirmation Reply Command
===============================
Command Code: 0x0015
- Command Parameters: Controller_Index (2 Octets)
- Address (6 Octets)
- Return Paramters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Controller Index: <controller id>
+ Command Parameters: Address (6 Octets)
+ Return Paramters: Address (6 Octets)
Status (1 Octet)
@@ -258,10 +259,9 @@ User Confirmation Negative Reply Command
========================================
Command Code: 0x0016
- Command Parameters: Controller_Index (2 Octets)
- Address (6 Octets)
- Return Paramters: Controller_Index (2 Octets)
- Address (6 Octets)
+ Controller Index: <controller id>
+ Command Parameters: Address (6 Octets)
+ Return Paramters: Address (6 Octets)
Status (1 Octet)
@@ -269,6 +269,7 @@ Read Tracing Buffer Size Command
================================
Command Code: <not yet assigned>
+ Controller Index: <non-controller>
Command Parameters:
Return Parameters: Status (1 Octet)
Buffer_Size (2 Octets)
@@ -280,6 +281,7 @@ Write Tracing Buffer Size Command
=================================
Command Code: <not yet assigned>
+ Controller Index: <non-controller>
Command Parameters: Buffer_Size (2 Octets)
Return Parameters: Status (1 Octet)
@@ -290,9 +292,9 @@ Read Controller Tracing Filter Command
=======================================
Command Code: <not yet assigned>
- Command Parameters: Controller_Index (2 Octects)
+ Controller Index: <controller id>
+ Command Parameters:
Return Parameters: Status (1 Octet)
- Controller_Index (2 Octets)
Tracing_Enable (1 Octect)
Num_Filters (2 Octect)
Protocol_UUID[i] (16 Octets)
@@ -308,19 +310,19 @@ Write Controller Tracing Filter Command
=======================================
Command Code: <not yet assigned>
- Command Parameters: Controller_Index (2 Octects)
- Tracing_Enable (1 Octect)
+ Controller Index: <controller id>
+ Command Parameters: Tracing_Enable (1 Octect)
Num_Filters (2 Octect)
Protocol_UUID[i] (16 Octets)
Protocol_Identifier[i] (16 Octets)
Return Paramters: Status (1 Octet)
- Controller_Index (2 Octets)
Command Complete Event
======================
Event Code 0x0001
+Controller Index: <controller id> or <non-controller>
Event Parameters Command_Opcode (2 Octets)
Return_Parameters
@@ -329,6 +331,7 @@ Command Status Event
====================
Event Code 0x0002
+Controller Index: <controller id> or <non-controller>
Event Parameters Status (1 Octet)
Command_Opcode (2 Octets)
@@ -337,6 +340,7 @@ Controller Error Event
======================
Event Code 0x0003
+Controller Index: <controller id>
Event Parameters Error_Code (1 Octet)
@@ -344,49 +348,51 @@ Index Added Event
=================
Event Code 0x0004
-Event Parameters Controller_Index (2 Octets)
+Controller Index: <controller id>
+Event Parameters
Index Removed Event
===================
Event Code 0x0005
-Event Parameters Controller_Index (2 Octets)
+Controller Index: <controller id>
+Event Parameters
Controller Powered Event
========================
Event Code 0x0006
-Event Parameters Controller_Index (2 Octets)
- Powered (1 Octet)
+Controller Index: <controller id>
+Event Parameters Powered (1 Octet)
Controller Discoverable Event
=============================
Event Code 0x0007
-Event Parameters Controller_Index (2 Octets)
- Discoverable (1 Octet)
+Controller Index: <controller id>
+Event Parameters Discoverable (1 Octet)
Controller Connectable Event
============================
Event Code 0x0008
-Event Parameters Controller_Index (2 Octets)
- Connectable (1 Octet)
+Controller Index: <controller id>
+Event Parameters Connectable (1 Octet)
Controller Pairable Event
=========================
Event Code 0x0009
-Event Parameters Controller_Index (2 Octets)
- Pairable (1 Octet)
+Controller Index: <controller id>
+Event Parameters Pairable (1 Octet)
New Key Event
=============
Event Code 0x000A
-Event Parameters Controller_Index (2 Octets)
- Key {
+Controller Index: <controller id>
+Event Parameters Key {
Address (6 Octets)
Type (1 Octet)
Value (16 Octets)
@@ -398,38 +404,38 @@ Device Connected Event
======================
Event Code 0x000B
-Event Parameters Controller_Index (2 Octets)
- Address (6 Octets)
+Controller Index: <controller id>
+Event Parameters Address (6 Octets)
Device Disconnected Event
=========================
Event Code 0x000C
-Event Parameters Controller_Index (2 Octets)
- Address (6 Octets)
+Controller Index: <controller id>
+Event Parameters Address (6 Octets)
Connect Failed Event
====================
Event Code 0x000D
-Event Parameters Controller_Index (2 Octets)
- Address (6 Octets)
+Controller Index: <controller id>
+Event Parameters Address (6 Octets)
Status (1 Octet)
PIN Code Request Event
======================
Event Code 0x000E
-Event Parameters Controller_Index (2 Octets)
- Address (6 Octets)
+Controller Index: <controller id>
+Event Parameters Address (6 Octets)
User Confirmation Request Event
===============================
Event Code 0x000F
-Event Parameters Controller_Index (2 Octets)
- Address (6 Octets)
+Controller Index: <controller id>
+Event Parameters Address (6 Octets)
Value (4 Octets)
@@ -437,6 +443,6 @@ Authentication Failed Event
===========================
Event Code 0x0010
-Event Parameters Controller_Index (2 Octets)
- Address (6 Octets)
+Controller Index: <controller id>
+Event Parameters Address (6 Octets)
Status (1 Octet)
--
1.7.0.4
^ permalink raw reply related
* [PATCH v2 3/3] Bluetooth: Validate data size before accessing mgmt commands
From: Szymon Janc @ 2011-02-23 15:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1298476240-18124-1-git-send-email-szymon.janc@tieto.com>
Crafted (too small) data buffer could result in reading data outside of buffer.
Validate buffer size and return EINVAL if size is wrong..
Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
---
net/bluetooth/mgmt.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 53 insertions(+), 0 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 98c92ae..64d6927 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -302,6 +302,9 @@ static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_POWERED, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
@@ -351,6 +354,9 @@ static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
@@ -409,6 +415,9 @@ static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
@@ -499,6 +508,9 @@ static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
@@ -569,6 +581,9 @@ static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_ADD_UUID, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
@@ -611,6 +626,9 @@ static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
@@ -663,6 +681,9 @@ static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("request for hci%u", index);
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
@@ -692,6 +713,10 @@ static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE,
+ EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
@@ -726,6 +751,10 @@ static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
int i;
cp = (void *) data;
+
+ if (len < sizeof(*cp))
+ return -EINVAL;
+
key_count = get_unaligned_le16(&cp->key_count);
expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
@@ -775,6 +804,9 @@ static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
@@ -821,6 +853,9 @@ static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_DISCONNECT, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
@@ -931,6 +966,9 @@ static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
@@ -975,6 +1013,10 @@ static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+ EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
@@ -1017,6 +1059,10 @@ static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY,
+ EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
@@ -1107,6 +1153,9 @@ static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
cp = (void *) data;
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EINVAL);
+
hdev = hci_dev_get(index);
if (!hdev)
return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
@@ -1170,6 +1219,10 @@ static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
BT_DBG("");
+ if (len != sizeof(*cp))
+ return cmd_status(sk, index, MGMT_OP_USER_CONFIRM_REPLY,
+ EINVAL);
+
if (success) {
mgmt_op = MGMT_OP_USER_CONFIRM_REPLY;
hci_op = HCI_OP_USER_CONFIRM_REPLY;
--
1.7.0.4
on behalf of ST-Ericsson
^ permalink raw reply related
* [PATCH v2 2/3] Bluetooth: Move index to common header in management interface
From: Szymon Janc @ 2011-02-23 15:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
In-Reply-To: <1298476240-18124-1-git-send-email-szymon.janc@tieto.com>
Most mgmt commands and event are related to hci adapter. Moving index to
common header allow to easily use it in command status while reporting errors.
For those not related to adapter use MGMT_INDEX_NONE (0xFFFF) as index.
Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
---
include/net/bluetooth/mgmt.h | 43 +----
net/bluetooth/mgmt.c | 407 +++++++++++++++++++-----------------------
2 files changed, 183 insertions(+), 267 deletions(-)
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index 1e63c31..5fabfa8 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -21,11 +21,13 @@
SOFTWARE IS DISCLAIMED.
*/
+#define MGMT_INDEX_NONE 0xFFFF
+
struct mgmt_hdr {
__le16 opcode;
+ __le16 index;
__le16 len;
} __packed;
-#define MGMT_HDR_SIZE 4
#define MGMT_OP_READ_VERSION 0x0001
struct mgmt_rp_read_version {
@@ -40,11 +42,7 @@ struct mgmt_rp_read_index_list {
} __packed;
#define MGMT_OP_READ_INFO 0x0004
-struct mgmt_cp_read_info {
- __le16 index;
-} __packed;
struct mgmt_rp_read_info {
- __le16 index;
__u8 type;
__u8 powered;
__u8 connectable;
@@ -60,7 +58,6 @@ struct mgmt_rp_read_info {
} __packed;
struct mgmt_mode {
- __le16 index;
__u8 val;
} __packed;
@@ -74,27 +71,23 @@ struct mgmt_mode {
#define MGMT_OP_ADD_UUID 0x0009
struct mgmt_cp_add_uuid {
- __le16 index;
__u8 uuid[16];
__u8 svc_hint;
} __packed;
#define MGMT_OP_REMOVE_UUID 0x000A
struct mgmt_cp_remove_uuid {
- __le16 index;
__u8 uuid[16];
} __packed;
#define MGMT_OP_SET_DEV_CLASS 0x000B
struct mgmt_cp_set_dev_class {
- __le16 index;
__u8 major;
__u8 minor;
} __packed;
#define MGMT_OP_SET_SERVICE_CACHE 0x000C
struct mgmt_cp_set_service_cache {
- __le16 index;
__u8 enable;
} __packed;
@@ -107,7 +100,6 @@ struct mgmt_key_info {
#define MGMT_OP_LOAD_KEYS 0x000D
struct mgmt_cp_load_keys {
- __le16 index;
__u8 debug_keys;
__le16 key_count;
struct mgmt_key_info keys[0];
@@ -115,75 +107,60 @@ struct mgmt_cp_load_keys {
#define MGMT_OP_REMOVE_KEY 0x000E
struct mgmt_cp_remove_key {
- __le16 index;
bdaddr_t bdaddr;
__u8 disconnect;
} __packed;
#define MGMT_OP_DISCONNECT 0x000F
struct mgmt_cp_disconnect {
- __le16 index;
bdaddr_t bdaddr;
} __packed;
struct mgmt_rp_disconnect {
- __le16 index;
bdaddr_t bdaddr;
} __packed;
#define MGMT_OP_GET_CONNECTIONS 0x0010
-struct mgmt_cp_get_connections {
- __le16 index;
-} __packed;
struct mgmt_rp_get_connections {
- __le16 index;
__le16 conn_count;
bdaddr_t conn[0];
} __packed;
#define MGMT_OP_PIN_CODE_REPLY 0x0011
struct mgmt_cp_pin_code_reply {
- __le16 index;
bdaddr_t bdaddr;
__u8 pin_len;
__u8 pin_code[16];
} __packed;
struct mgmt_rp_pin_code_reply {
- __le16 index;
bdaddr_t bdaddr;
uint8_t status;
} __packed;
#define MGMT_OP_PIN_CODE_NEG_REPLY 0x0012
struct mgmt_cp_pin_code_neg_reply {
- __le16 index;
bdaddr_t bdaddr;
} __packed;
#define MGMT_OP_SET_IO_CAPABILITY 0x0013
struct mgmt_cp_set_io_capability {
- __le16 index;
__u8 io_capability;
} __packed;
#define MGMT_OP_PAIR_DEVICE 0x0014
struct mgmt_cp_pair_device {
- __le16 index;
bdaddr_t bdaddr;
__u8 io_cap;
} __packed;
struct mgmt_rp_pair_device {
- __le16 index;
bdaddr_t bdaddr;
__u8 status;
} __packed;
#define MGMT_OP_USER_CONFIRM_REPLY 0x0015
struct mgmt_cp_user_confirm_reply {
- __le16 index;
bdaddr_t bdaddr;
} __packed;
struct mgmt_rp_user_confirm_reply {
- __le16 index;
bdaddr_t bdaddr;
__u8 status;
} __packed;
@@ -204,19 +181,12 @@ struct mgmt_ev_cmd_status {
#define MGMT_EV_CONTROLLER_ERROR 0x0003
struct mgmt_ev_controller_error {
- __le16 index;
__u8 error_code;
} __packed;
#define MGMT_EV_INDEX_ADDED 0x0004
-struct mgmt_ev_index_added {
- __le16 index;
-} __packed;
#define MGMT_EV_INDEX_REMOVED 0x0005
-struct mgmt_ev_index_removed {
- __le16 index;
-} __packed;
#define MGMT_EV_POWERED 0x0006
@@ -228,46 +198,39 @@ struct mgmt_ev_index_removed {
#define MGMT_EV_NEW_KEY 0x000A
struct mgmt_ev_new_key {
- __le16 index;
struct mgmt_key_info key;
__u8 old_key_type;
} __packed;
#define MGMT_EV_CONNECTED 0x000B
struct mgmt_ev_connected {
- __le16 index;
bdaddr_t bdaddr;
} __packed;
#define MGMT_EV_DISCONNECTED 0x000C
struct mgmt_ev_disconnected {
- __le16 index;
bdaddr_t bdaddr;
} __packed;
#define MGMT_EV_CONNECT_FAILED 0x000D
struct mgmt_ev_connect_failed {
- __le16 index;
bdaddr_t bdaddr;
__u8 status;
} __packed;
#define MGMT_EV_PIN_CODE_REQUEST 0x000E
struct mgmt_ev_pin_code_request {
- __le16 index;
bdaddr_t bdaddr;
} __packed;
#define MGMT_EV_USER_CONFIRM_REQUEST 0x000F
struct mgmt_ev_user_confirm_request {
- __le16 index;
bdaddr_t bdaddr;
__le32 value;
} __packed;
#define MGMT_EV_AUTH_FAILED 0x0010
struct mgmt_ev_auth_failed {
- __le16 index;
bdaddr_t bdaddr;
__u8 status;
} __packed;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 4543ede..98c92ae 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -43,7 +43,7 @@ struct pending_cmd {
LIST_HEAD(cmd_list);
-static int cmd_status(struct sock *sk, u16 cmd, u8 status)
+static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status)
{
struct sk_buff *skb;
struct mgmt_hdr *hdr;
@@ -58,6 +58,7 @@ static int cmd_status(struct sock *sk, u16 cmd, u8 status)
hdr = (void *) skb_put(skb, sizeof(*hdr));
hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS);
+ hdr->index = cpu_to_le16(index);
hdr->len = cpu_to_le16(sizeof(*ev));
ev = (void *) skb_put(skb, sizeof(*ev));
@@ -70,7 +71,8 @@ static int cmd_status(struct sock *sk, u16 cmd, u8 status)
return 0;
}
-static int cmd_complete(struct sock *sk, u16 cmd, void *rp, size_t rp_len)
+static int cmd_complete(struct sock *sk, u16 index, u16 cmd, void *rp,
+ size_t rp_len)
{
struct sk_buff *skb;
struct mgmt_hdr *hdr;
@@ -85,6 +87,7 @@ static int cmd_complete(struct sock *sk, u16 cmd, void *rp, size_t rp_len)
hdr = (void *) skb_put(skb, sizeof(*hdr));
hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE);
+ hdr->index = cpu_to_le16(index);
hdr->len = cpu_to_le16(sizeof(*ev) + rp_len);
ev = (void *) skb_put(skb, sizeof(*ev) + rp_len);
@@ -106,7 +109,8 @@ static int read_version(struct sock *sk)
rp.version = MGMT_VERSION;
put_unaligned_le16(MGMT_REVISION, &rp.revision);
- return cmd_complete(sk, MGMT_OP_READ_VERSION, &rp, sizeof(rp));
+ return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, &rp,
+ sizeof(rp));
}
static int read_index_list(struct sock *sk)
@@ -152,32 +156,24 @@ static int read_index_list(struct sock *sk)
read_unlock(&hci_dev_list_lock);
- err = cmd_complete(sk, MGMT_OP_READ_INDEX_LIST, rp, rp_len);
+ err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_INDEX_LIST, rp,
+ rp_len);
kfree(rp);
return err;
}
-static int read_controller_info(struct sock *sk, unsigned char *data, u16 len)
+static int read_controller_info(struct sock *sk, u16 index)
{
struct mgmt_rp_read_info rp;
- struct mgmt_cp_read_info *cp = (void *) data;
struct hci_dev *hdev;
- u16 dev_id;
- BT_DBG("sock %p", sk);
-
- if (len != 2)
- return cmd_status(sk, MGMT_OP_READ_INFO, EINVAL);
-
- dev_id = get_unaligned_le16(&cp->index);
+ BT_DBG("sock %p hci%u", sk, index);
- BT_DBG("request for hci%u", dev_id);
-
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_READ_INFO, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_READ_INFO, ENODEV);
hci_del_off_timer(hdev);
@@ -185,7 +181,6 @@ static int read_controller_info(struct sock *sk, unsigned char *data, u16 len)
set_bit(HCI_MGMT, &hdev->flags);
- put_unaligned_le16(hdev->id, &rp.index);
rp.type = hdev->dev_type;
rp.powered = test_bit(HCI_UP, &hdev->flags);
@@ -210,7 +205,7 @@ static int read_controller_info(struct sock *sk, unsigned char *data, u16 len)
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
- return cmd_complete(sk, MGMT_OP_READ_INFO, &rp, sizeof(rp));
+ return cmd_complete(sk, index, MGMT_OP_READ_INFO, &rp, sizeof(rp));
}
static void mgmt_pending_free(struct pending_cmd *cmd)
@@ -296,37 +291,35 @@ static void mgmt_pending_remove(struct pending_cmd *cmd)
mgmt_pending_free(cmd);
}
-static int set_powered(struct sock *sk, unsigned char *data, u16 len)
+static int set_powered(struct sock *sk, u16 index, unsigned char *data, u16 len)
{
struct mgmt_mode *cp;
struct hci_dev *hdev;
struct pending_cmd *cmd;
- u16 dev_id;
int err, up;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- BT_DBG("request for hci%u", dev_id);
+ BT_DBG("request for hci%u", index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_SET_POWERED, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_SET_POWERED, ENODEV);
hci_dev_lock_bh(hdev);
up = test_bit(HCI_UP, &hdev->flags);
if ((cp->val && up) || (!cp->val && !up)) {
- err = cmd_status(sk, MGMT_OP_SET_POWERED, EALREADY);
+ err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EALREADY);
goto failed;
}
- if (mgmt_pending_find(MGMT_OP_SET_POWERED, dev_id)) {
- err = cmd_status(sk, MGMT_OP_SET_POWERED, EBUSY);
+ if (mgmt_pending_find(MGMT_OP_SET_POWERED, index)) {
+ err = cmd_status(sk, index, MGMT_OP_SET_POWERED, EBUSY);
goto failed;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, dev_id, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_POWERED, index, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -345,44 +338,43 @@ failed:
return err;
}
-static int set_discoverable(struct sock *sk, unsigned char *data, u16 len)
+static int set_discoverable(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct mgmt_mode *cp;
struct hci_dev *hdev;
struct pending_cmd *cmd;
- u16 dev_id;
u8 scan;
int err;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- BT_DBG("request for hci%u", dev_id);
+ BT_DBG("request for hci%u", index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENODEV);
hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
- err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
+ err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, ENETDOWN);
goto failed;
}
- if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, dev_id) ||
- mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, dev_id)) {
- err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EBUSY);
+ if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
+ mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
+ err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EBUSY);
goto failed;
}
if (cp->val == test_bit(HCI_ISCAN, &hdev->flags) &&
test_bit(HCI_PSCAN, &hdev->flags)) {
- err = cmd_status(sk, MGMT_OP_SET_DISCOVERABLE, EALREADY);
+ err = cmd_status(sk, index, MGMT_OP_SET_DISCOVERABLE, EALREADY);
goto failed;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, dev_id, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_DISCOVERABLE, index, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -404,43 +396,42 @@ failed:
return err;
}
-static int set_connectable(struct sock *sk, unsigned char *data, u16 len)
+static int set_connectable(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct mgmt_mode *cp;
struct hci_dev *hdev;
struct pending_cmd *cmd;
- u16 dev_id;
u8 scan;
int err;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- BT_DBG("request for hci%u", dev_id);
+ BT_DBG("request for hci%u", index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_SET_CONNECTABLE, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENODEV);
hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
- err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
+ err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, ENETDOWN);
goto failed;
}
- if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, dev_id) ||
- mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, dev_id)) {
- err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EBUSY);
+ if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, index) ||
+ mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, index)) {
+ err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EBUSY);
goto failed;
}
if (cp->val == test_bit(HCI_PSCAN, &hdev->flags)) {
- err = cmd_status(sk, MGMT_OP_SET_CONNECTABLE, EALREADY);
+ err = cmd_status(sk, index, MGMT_OP_SET_CONNECTABLE, EALREADY);
goto failed;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, dev_id, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_SET_CONNECTABLE, index, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -462,7 +453,8 @@ failed:
return err;
}
-static int mgmt_event(u16 event, void *data, u16 data_len, struct sock *skip_sk)
+static int mgmt_event(u16 event, u16 index, void *data, u16 data_len,
+ struct sock *skip_sk)
{
struct sk_buff *skb;
struct mgmt_hdr *hdr;
@@ -475,9 +467,11 @@ static int mgmt_event(u16 event, void *data, u16 data_len, struct sock *skip_sk)
hdr = (void *) skb_put(skb, sizeof(*hdr));
hdr->opcode = cpu_to_le16(event);
+ hdr->index = cpu_to_le16(index);
hdr->len = cpu_to_le16(data_len);
- memcpy(skb_put(skb, data_len), data, data_len);
+ if (data)
+ memcpy(skb_put(skb, data_len), data, data_len);
hci_send_to_sock(NULL, skb, skip_sk);
kfree_skb(skb);
@@ -489,27 +483,25 @@ static int send_mode_rsp(struct sock *sk, u16 opcode, u16 index, u8 val)
{
struct mgmt_mode rp;
- put_unaligned_le16(index, &rp.index);
rp.val = val;
- return cmd_complete(sk, opcode, &rp, sizeof(rp));
+ return cmd_complete(sk, index, opcode, &rp, sizeof(rp));
}
-static int set_pairable(struct sock *sk, unsigned char *data, u16 len)
+static int set_pairable(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct mgmt_mode *cp, ev;
struct hci_dev *hdev;
- u16 dev_id;
int err;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- BT_DBG("request for hci%u", dev_id);
+ BT_DBG("request for hci%u", index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_SET_PAIRABLE, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_SET_PAIRABLE, ENODEV);
hci_dev_lock_bh(hdev);
@@ -518,14 +510,13 @@ static int set_pairable(struct sock *sk, unsigned char *data, u16 len)
else
clear_bit(HCI_PAIRABLE, &hdev->flags);
- err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, dev_id, cp->val);
+ err = send_mode_rsp(sk, MGMT_OP_SET_PAIRABLE, index, cp->val);
if (err < 0)
goto failed;
- put_unaligned_le16(dev_id, &ev.index);
ev.val = cp->val;
- err = mgmt_event(MGMT_EV_PAIRABLE, &ev, sizeof(ev), sk);
+ err = mgmt_event(MGMT_EV_PAIRABLE, index, &ev, sizeof(ev), sk);
failed:
hci_dev_unlock_bh(hdev);
@@ -567,22 +558,20 @@ static int update_class(struct hci_dev *hdev)
return hci_send_cmd(hdev, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod);
}
-static int add_uuid(struct sock *sk, unsigned char *data, u16 len)
+static int add_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
{
struct mgmt_cp_add_uuid *cp;
struct hci_dev *hdev;
struct bt_uuid *uuid;
- u16 dev_id;
int err;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- BT_DBG("request for hci%u", dev_id);
+ BT_DBG("request for hci%u", index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_ADD_UUID, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_ADD_UUID, ENODEV);
hci_dev_lock_bh(hdev);
@@ -601,7 +590,7 @@ static int add_uuid(struct sock *sk, unsigned char *data, u16 len)
if (err < 0)
goto failed;
- err = cmd_complete(sk, MGMT_OP_ADD_UUID, &dev_id, sizeof(dev_id));
+ err = cmd_complete(sk, index, MGMT_OP_ADD_UUID, NULL, 0);
failed:
hci_dev_unlock_bh(hdev);
@@ -610,23 +599,21 @@ failed:
return err;
}
-static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
+static int remove_uuid(struct sock *sk, u16 index, unsigned char *data, u16 len)
{
struct list_head *p, *n;
struct mgmt_cp_remove_uuid *cp;
struct hci_dev *hdev;
u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
- u16 dev_id;
int err, found;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- BT_DBG("request for hci%u", dev_id);
+ BT_DBG("request for hci%u", index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_REMOVE_UUID, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENODEV);
hci_dev_lock_bh(hdev);
@@ -648,7 +635,7 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
}
if (found == 0) {
- err = cmd_status(sk, MGMT_OP_REMOVE_UUID, ENOENT);
+ err = cmd_status(sk, index, MGMT_OP_REMOVE_UUID, ENOENT);
goto unlock;
}
@@ -656,7 +643,7 @@ static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
if (err < 0)
goto unlock;
- err = cmd_complete(sk, MGMT_OP_REMOVE_UUID, &dev_id, sizeof(dev_id));
+ err = cmd_complete(sk, index, MGMT_OP_REMOVE_UUID, NULL, 0);
unlock:
hci_dev_unlock_bh(hdev);
@@ -665,21 +652,20 @@ unlock:
return err;
}
-static int set_dev_class(struct sock *sk, unsigned char *data, u16 len)
+static int set_dev_class(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_set_dev_class *cp;
- u16 dev_id;
int err;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- BT_DBG("request for hci%u", dev_id);
+ BT_DBG("request for hci%u", index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_SET_DEV_CLASS, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_SET_DEV_CLASS, ENODEV);
hci_dev_lock_bh(hdev);
@@ -689,8 +675,7 @@ static int set_dev_class(struct sock *sk, unsigned char *data, u16 len)
err = update_class(hdev);
if (err == 0)
- err = cmd_complete(sk, MGMT_OP_SET_DEV_CLASS, &dev_id,
- sizeof(dev_id));
+ err = cmd_complete(sk, index, MGMT_OP_SET_DEV_CLASS, NULL, 0);
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
@@ -698,23 +683,22 @@ static int set_dev_class(struct sock *sk, unsigned char *data, u16 len)
return err;
}
-static int set_service_cache(struct sock *sk, unsigned char *data, u16 len)
+static int set_service_cache(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_set_service_cache *cp;
- u16 dev_id;
int err;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_SET_SERVICE_CACHE, ENODEV);
hci_dev_lock_bh(hdev);
- BT_DBG("hci%u enable %d", dev_id, cp->enable);
+ BT_DBG("hci%u enable %d", index, cp->enable);
if (cp->enable) {
set_bit(HCI_SERVICE_CACHE, &hdev->flags);
@@ -725,8 +709,8 @@ static int set_service_cache(struct sock *sk, unsigned char *data, u16 len)
}
if (err == 0)
- err = cmd_complete(sk, MGMT_OP_SET_SERVICE_CACHE, &dev_id,
- sizeof(dev_id));
+ err = cmd_complete(sk, index, MGMT_OP_SET_SERVICE_CACHE, NULL,
+ 0);
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
@@ -734,15 +718,14 @@ static int set_service_cache(struct sock *sk, unsigned char *data, u16 len)
return err;
}
-static int load_keys(struct sock *sk, unsigned char *data, u16 len)
+static int load_keys(struct sock *sk, u16 index, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_load_keys *cp;
- u16 dev_id, key_count, expected_len;
+ u16 key_count, expected_len;
int i;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
key_count = get_unaligned_le16(&cp->key_count);
expected_len = sizeof(*cp) + key_count * sizeof(struct mgmt_key_info);
@@ -752,11 +735,11 @@ static int load_keys(struct sock *sk, unsigned char *data, u16 len)
return -EINVAL;
}
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_LOAD_KEYS, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_LOAD_KEYS, ENODEV);
- BT_DBG("hci%u debug_keys %u key_count %u", dev_id, cp->debug_keys,
+ BT_DBG("hci%u debug_keys %u key_count %u", index, cp->debug_keys,
key_count);
hci_dev_lock_bh(hdev);
@@ -783,26 +766,24 @@ static int load_keys(struct sock *sk, unsigned char *data, u16 len)
return 0;
}
-static int remove_key(struct sock *sk, unsigned char *data, u16 len)
+static int remove_key(struct sock *sk, u16 index, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_remove_key *cp;
struct hci_conn *conn;
- u16 dev_id;
int err;
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_REMOVE_KEY, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_REMOVE_KEY, ENODEV);
hci_dev_lock_bh(hdev);
err = hci_remove_link_key(hdev, &cp->bdaddr);
if (err < 0) {
- err = cmd_status(sk, MGMT_OP_REMOVE_KEY, -err);
+ err = cmd_status(sk, index, MGMT_OP_REMOVE_KEY, -err);
goto unlock;
}
@@ -827,44 +808,42 @@ unlock:
return err;
}
-static int disconnect(struct sock *sk, unsigned char *data, u16 len)
+static int disconnect(struct sock *sk, u16 index, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_disconnect *cp;
struct hci_cp_disconnect dc;
struct pending_cmd *cmd;
struct hci_conn *conn;
- u16 dev_id;
int err;
BT_DBG("");
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_DISCONNECT, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_DISCONNECT, ENODEV);
hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
- err = cmd_status(sk, MGMT_OP_DISCONNECT, ENETDOWN);
+ err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENETDOWN);
goto failed;
}
- if (mgmt_pending_find(MGMT_OP_DISCONNECT, dev_id)) {
- err = cmd_status(sk, MGMT_OP_DISCONNECT, EBUSY);
+ if (mgmt_pending_find(MGMT_OP_DISCONNECT, index)) {
+ err = cmd_status(sk, index, MGMT_OP_DISCONNECT, EBUSY);
goto failed;
}
conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr);
if (!conn) {
- err = cmd_status(sk, MGMT_OP_DISCONNECT, ENOTCONN);
+ err = cmd_status(sk, index, MGMT_OP_DISCONNECT, ENOTCONN);
goto failed;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, dev_id, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_DISCONNECT, index, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -884,24 +863,24 @@ failed:
return err;
}
-static int get_connections(struct sock *sk, unsigned char *data, u16 len)
+static int get_connections(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct mgmt_cp_get_connections *cp;
struct mgmt_rp_get_connections *rp;
struct hci_dev *hdev;
struct list_head *p;
size_t rp_len;
- u16 dev_id, count;
+ u16 count;
int i, err;
BT_DBG("");
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_GET_CONNECTIONS, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_GET_CONNECTIONS, ENODEV);
hci_dev_lock_bh(hdev);
@@ -917,7 +896,6 @@ static int get_connections(struct sock *sk, unsigned char *data, u16 len)
goto unlock;
}
- put_unaligned_le16(dev_id, &rp->index);
put_unaligned_le16(count, &rp->conn_count);
read_lock(&hci_dev_list_lock);
@@ -931,7 +909,7 @@ static int get_connections(struct sock *sk, unsigned char *data, u16 len)
read_unlock(&hci_dev_list_lock);
- err = cmd_complete(sk, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
+ err = cmd_complete(sk, index, MGMT_OP_GET_CONNECTIONS, rp, rp_len);
unlock:
kfree(rp);
@@ -940,32 +918,31 @@ unlock:
return err;
}
-static int pin_code_reply(struct sock *sk, unsigned char *data, u16 len)
+static int pin_code_reply(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_pin_code_reply *cp;
struct hci_cp_pin_code_reply reply;
struct pending_cmd *cmd;
- u16 dev_id;
int err;
BT_DBG("");
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_PIN_CODE_REPLY, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENODEV);
hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
- err = cmd_status(sk, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
+ err = cmd_status(sk, index, MGMT_OP_PIN_CODE_REPLY, ENETDOWN);
goto failed;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, dev_id, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_REPLY, index, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -986,31 +963,32 @@ failed:
return err;
}
-static int pin_code_neg_reply(struct sock *sk, unsigned char *data, u16 len)
+static int pin_code_neg_reply(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_pin_code_neg_reply *cp;
struct pending_cmd *cmd;
- u16 dev_id;
int err;
BT_DBG("");
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+ ENODEV);
hci_dev_lock_bh(hdev);
if (!test_bit(HCI_UP, &hdev->flags)) {
- err = cmd_status(sk, MGMT_OP_PIN_CODE_NEG_REPLY, ENETDOWN);
+ err = cmd_status(sk, index, MGMT_OP_PIN_CODE_NEG_REPLY,
+ ENETDOWN);
goto failed;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, dev_id,
+ cmd = mgmt_pending_add(sk, MGMT_OP_PIN_CODE_NEG_REPLY, index,
data, len);
if (!cmd) {
err = -ENOMEM;
@@ -1029,20 +1007,19 @@ failed:
return err;
}
-static int set_io_capability(struct sock *sk, unsigned char *data, u16 len)
+static int set_io_capability(struct sock *sk, u16 index, unsigned char *data,
+ u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_set_io_capability *cp;
- u16 dev_id;
BT_DBG("");
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_SET_IO_CAPABILITY, ENODEV);
hci_dev_lock_bh(hdev);
@@ -1054,8 +1031,7 @@ static int set_io_capability(struct sock *sk, unsigned char *data, u16 len)
hci_dev_unlock_bh(hdev);
hci_dev_put(hdev);
- return cmd_complete(sk, MGMT_OP_SET_IO_CAPABILITY,
- &dev_id, sizeof(dev_id));
+ return cmd_complete(sk, index, MGMT_OP_SET_IO_CAPABILITY, NULL, 0);
}
static inline struct pending_cmd *find_pairing(struct hci_conn *conn)
@@ -1088,11 +1064,10 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status)
struct mgmt_rp_pair_device rp;
struct hci_conn *conn = cmd->user_data;
- rp.index = cmd->index;
bacpy(&rp.bdaddr, &conn->dst);
rp.status = status;
- cmd_complete(cmd->sk, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
+ cmd_complete(cmd->sk, cmd->index, MGMT_OP_PAIR_DEVICE, &rp, sizeof(rp));
/* So we don't get further callbacks for this connection */
conn->connect_cfm_cb = NULL;
@@ -1119,24 +1094,22 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status)
pairing_complete(cmd, status);
}
-static int pair_device(struct sock *sk, unsigned char *data, u16 len)
+static int pair_device(struct sock *sk, u16 index, unsigned char *data, u16 len)
{
struct hci_dev *hdev;
struct mgmt_cp_pair_device *cp;
struct pending_cmd *cmd;
u8 sec_level, auth_type;
struct hci_conn *conn;
- u16 dev_id;
int err;
BT_DBG("");
cp = (void *) data;
- dev_id = get_unaligned_le16(&cp->index);
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, MGMT_OP_PAIR_DEVICE, ENODEV);
+ return cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, ENODEV);
hci_dev_lock_bh(hdev);
@@ -1156,11 +1129,11 @@ static int pair_device(struct sock *sk, unsigned char *data, u16 len)
if (conn->connect_cfm_cb) {
hci_conn_put(conn);
- err = cmd_status(sk, MGMT_OP_PAIR_DEVICE, EBUSY);
+ err = cmd_status(sk, index, MGMT_OP_PAIR_DEVICE, EBUSY);
goto unlock;
}
- cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, dev_id, data, len);
+ cmd = mgmt_pending_add(sk, MGMT_OP_PAIR_DEVICE, index, data, len);
if (!cmd) {
err = -ENOMEM;
hci_conn_put(conn);
@@ -1186,19 +1159,17 @@ unlock:
return err;
}
-static int user_confirm_reply(struct sock *sk, unsigned char *data, u16 len,
- int success)
+static int user_confirm_reply(struct sock *sk, u16 index, unsigned char *data,
+ u16 len, int success)
{
struct mgmt_cp_user_confirm_reply *cp = (void *) data;
- u16 dev_id, mgmt_op, hci_op;
+ u16 mgmt_op, hci_op;
struct pending_cmd *cmd;
struct hci_dev *hdev;
int err;
BT_DBG("");
- dev_id = get_unaligned_le16(&cp->index);
-
if (success) {
mgmt_op = MGMT_OP_USER_CONFIRM_REPLY;
hci_op = HCI_OP_USER_CONFIRM_REPLY;
@@ -1207,16 +1178,16 @@ static int user_confirm_reply(struct sock *sk, unsigned char *data, u16 len,
hci_op = HCI_OP_USER_CONFIRM_NEG_REPLY;
}
- hdev = hci_dev_get(dev_id);
+ hdev = hci_dev_get(index);
if (!hdev)
- return cmd_status(sk, mgmt_op, ENODEV);
+ return cmd_status(sk, index, mgmt_op, ENODEV);
if (!test_bit(HCI_UP, &hdev->flags)) {
- err = cmd_status(sk, mgmt_op, ENETDOWN);
+ err = cmd_status(sk, index, mgmt_op, ENETDOWN);
goto failed;
}
- cmd = mgmt_pending_add(sk, mgmt_op, dev_id, data, len);
+ cmd = mgmt_pending_add(sk, mgmt_op, index, data, len);
if (!cmd) {
err = -ENOMEM;
goto failed;
@@ -1237,7 +1208,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
{
unsigned char *buf;
struct mgmt_hdr *hdr;
- u16 opcode, len;
+ u16 opcode, index, len;
int err;
BT_DBG("got %zu bytes", msglen);
@@ -1256,6 +1227,7 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
hdr = (struct mgmt_hdr *) buf;
opcode = get_unaligned_le16(&hdr->opcode);
+ index = get_unaligned_le16(&hdr->index);
len = get_unaligned_le16(&hdr->len);
if (len != msglen - sizeof(*hdr)) {
@@ -1271,65 +1243,65 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen)
err = read_index_list(sk);
break;
case MGMT_OP_READ_INFO:
- err = read_controller_info(sk, buf + sizeof(*hdr), len);
+ err = read_controller_info(sk, index);
break;
case MGMT_OP_SET_POWERED:
- err = set_powered(sk, buf + sizeof(*hdr), len);
+ err = set_powered(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_DISCOVERABLE:
- err = set_discoverable(sk, buf + sizeof(*hdr), len);
+ err = set_discoverable(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_CONNECTABLE:
- err = set_connectable(sk, buf + sizeof(*hdr), len);
+ err = set_connectable(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_PAIRABLE:
- err = set_pairable(sk, buf + sizeof(*hdr), len);
+ err = set_pairable(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_ADD_UUID:
- err = add_uuid(sk, buf + sizeof(*hdr), len);
+ err = add_uuid(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_REMOVE_UUID:
- err = remove_uuid(sk, buf + sizeof(*hdr), len);
+ err = remove_uuid(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_DEV_CLASS:
- err = set_dev_class(sk, buf + sizeof(*hdr), len);
+ err = set_dev_class(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_SERVICE_CACHE:
- err = set_service_cache(sk, buf + sizeof(*hdr), len);
+ err = set_service_cache(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_LOAD_KEYS:
- err = load_keys(sk, buf + sizeof(*hdr), len);
+ err = load_keys(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_REMOVE_KEY:
- err = remove_key(sk, buf + sizeof(*hdr), len);
+ err = remove_key(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_DISCONNECT:
- err = disconnect(sk, buf + sizeof(*hdr), len);
+ err = disconnect(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_GET_CONNECTIONS:
- err = get_connections(sk, buf + sizeof(*hdr), len);
+ err = get_connections(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_PIN_CODE_REPLY:
- err = pin_code_reply(sk, buf + sizeof(*hdr), len);
+ err = pin_code_reply(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_PIN_CODE_NEG_REPLY:
- err = pin_code_neg_reply(sk, buf + sizeof(*hdr), len);
+ err = pin_code_neg_reply(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_SET_IO_CAPABILITY:
- err = set_io_capability(sk, buf + sizeof(*hdr), len);
+ err = set_io_capability(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_PAIR_DEVICE:
- err = pair_device(sk, buf + sizeof(*hdr), len);
+ err = pair_device(sk, index, buf + sizeof(*hdr), len);
break;
case MGMT_OP_USER_CONFIRM_REPLY:
- err = user_confirm_reply(sk, buf + sizeof(*hdr), len, 1);
+ err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 1);
break;
case MGMT_OP_USER_CONFIRM_NEG_REPLY:
- err = user_confirm_reply(sk, buf + sizeof(*hdr), len, 0);
+ err = user_confirm_reply(sk, index, buf + sizeof(*hdr), len, 0);
break;
default:
BT_DBG("Unknown op %u", opcode);
- err = cmd_status(sk, opcode, 0x01);
+ err = cmd_status(sk, index, opcode, 0x01);
break;
}
@@ -1345,20 +1317,12 @@ done:
int mgmt_index_added(u16 index)
{
- struct mgmt_ev_index_added ev;
-
- put_unaligned_le16(index, &ev.index);
-
- return mgmt_event(MGMT_EV_INDEX_ADDED, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_INDEX_ADDED, index, NULL, 0, NULL);
}
int mgmt_index_removed(u16 index)
{
- struct mgmt_ev_index_added ev;
-
- put_unaligned_le16(index, &ev.index);
-
- return mgmt_event(MGMT_EV_INDEX_REMOVED, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_INDEX_REMOVED, index, NULL, 0, NULL);
}
struct cmd_lookup {
@@ -1394,10 +1358,9 @@ int mgmt_powered(u16 index, u8 powered)
mgmt_pending_foreach(MGMT_OP_SET_POWERED, index, mode_rsp, &match);
- put_unaligned_le16(index, &ev.index);
ev.val = powered;
- ret = mgmt_event(MGMT_EV_POWERED, &ev, sizeof(ev), match.sk);
+ ret = mgmt_event(MGMT_EV_POWERED, index, &ev, sizeof(ev), match.sk);
if (match.sk)
sock_put(match.sk);
@@ -1414,10 +1377,10 @@ int mgmt_discoverable(u16 index, u8 discoverable)
mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, index,
mode_rsp, &match);
- put_unaligned_le16(index, &ev.index);
ev.val = discoverable;
- ret = mgmt_event(MGMT_EV_DISCOVERABLE, &ev, sizeof(ev), match.sk);
+ ret = mgmt_event(MGMT_EV_DISCOVERABLE, index, &ev, sizeof(ev),
+ match.sk);
if (match.sk)
sock_put(match.sk);
@@ -1433,10 +1396,9 @@ int mgmt_connectable(u16 index, u8 connectable)
mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, index, mode_rsp, &match);
- put_unaligned_le16(index, &ev.index);
ev.val = connectable;
- ret = mgmt_event(MGMT_EV_CONNECTABLE, &ev, sizeof(ev), match.sk);
+ ret = mgmt_event(MGMT_EV_CONNECTABLE, index, &ev, sizeof(ev), match.sk);
if (match.sk)
sock_put(match.sk);
@@ -1450,25 +1412,22 @@ int mgmt_new_key(u16 index, struct link_key *key, u8 old_key_type)
memset(&ev, 0, sizeof(ev));
- put_unaligned_le16(index, &ev.index);
-
bacpy(&ev.key.bdaddr, &key->bdaddr);
ev.key.type = key->type;
memcpy(ev.key.val, key->val, 16);
ev.key.pin_len = key->pin_len;
ev.old_key_type = old_key_type;
- return mgmt_event(MGMT_EV_NEW_KEY, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_NEW_KEY, index, &ev, sizeof(ev), NULL);
}
int mgmt_connected(u16 index, bdaddr_t *bdaddr)
{
struct mgmt_ev_connected ev;
- put_unaligned_le16(index, &ev.index);
bacpy(&ev.bdaddr, bdaddr);
- return mgmt_event(MGMT_EV_CONNECTED, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
}
static void disconnect_rsp(struct pending_cmd *cmd, void *data)
@@ -1477,10 +1436,9 @@ static void disconnect_rsp(struct pending_cmd *cmd, void *data)
struct sock **sk = data;
struct mgmt_rp_disconnect rp;
- put_unaligned_le16(cmd->index, &rp.index);
bacpy(&rp.bdaddr, &cp->bdaddr);
- cmd_complete(cmd->sk, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
+ cmd_complete(cmd->sk, cmd->index, MGMT_OP_DISCONNECT, &rp, sizeof(rp));
*sk = cmd->sk;
sock_hold(*sk);
@@ -1496,10 +1454,9 @@ int mgmt_disconnected(u16 index, bdaddr_t *bdaddr)
mgmt_pending_foreach(MGMT_OP_DISCONNECT, index, disconnect_rsp, &sk);
- put_unaligned_le16(index, &ev.index);
bacpy(&ev.bdaddr, bdaddr);
- err = mgmt_event(MGMT_EV_DISCONNECTED, &ev, sizeof(ev), sk);
+ err = mgmt_event(MGMT_EV_DISCONNECTED, index, &ev, sizeof(ev), sk);
if (sk)
sock_put(sk);
@@ -1516,7 +1473,7 @@ int mgmt_disconnect_failed(u16 index)
if (!cmd)
return -ENOENT;
- err = cmd_status(cmd->sk, MGMT_OP_DISCONNECT, EIO);
+ err = cmd_status(cmd->sk, index, MGMT_OP_DISCONNECT, EIO);
mgmt_pending_remove(cmd);
@@ -1527,21 +1484,20 @@ int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status)
{
struct mgmt_ev_connect_failed ev;
- put_unaligned_le16(index, &ev.index);
bacpy(&ev.bdaddr, bdaddr);
ev.status = status;
- return mgmt_event(MGMT_EV_CONNECT_FAILED, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_CONNECT_FAILED, index, &ev, sizeof(ev), NULL);
}
int mgmt_pin_code_request(u16 index, bdaddr_t *bdaddr)
{
struct mgmt_ev_pin_code_request ev;
- put_unaligned_le16(index, &ev.index);
bacpy(&ev.bdaddr, bdaddr);
- return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_PIN_CODE_REQUEST, index, &ev, sizeof(ev),
+ NULL);
}
int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
@@ -1554,11 +1510,11 @@ int mgmt_pin_code_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
if (!cmd)
return -ENOENT;
- put_unaligned_le16(index, &rp.index);
bacpy(&rp.bdaddr, bdaddr);
rp.status = status;
- err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_REPLY, &rp, sizeof(rp));
+ err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_REPLY, &rp,
+ sizeof(rp));
mgmt_pending_remove(cmd);
@@ -1575,12 +1531,11 @@ int mgmt_pin_code_neg_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status)
if (!cmd)
return -ENOENT;
- put_unaligned_le16(index, &rp.index);
bacpy(&rp.bdaddr, bdaddr);
rp.status = status;
- err = cmd_complete(cmd->sk, MGMT_OP_PIN_CODE_NEG_REPLY,
- &rp, sizeof(rp));
+ err = cmd_complete(cmd->sk, index, MGMT_OP_PIN_CODE_NEG_REPLY, &rp,
+ sizeof(rp));
mgmt_pending_remove(cmd);
@@ -1593,11 +1548,11 @@ int mgmt_user_confirm_request(u16 index, bdaddr_t *bdaddr, __le32 value)
BT_DBG("hci%u", index);
- put_unaligned_le16(index, &ev.index);
bacpy(&ev.bdaddr, bdaddr);
put_unaligned_le32(value, &ev.value);
- return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, index, &ev, sizeof(ev),
+ NULL);
}
static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
@@ -1611,10 +1566,9 @@ static int confirm_reply_complete(u16 index, bdaddr_t *bdaddr, u8 status,
if (!cmd)
return -ENOENT;
- put_unaligned_le16(index, &rp.index);
bacpy(&rp.bdaddr, bdaddr);
rp.status = status;
- err = cmd_complete(cmd->sk, opcode, &rp, sizeof(rp));
+ err = cmd_complete(cmd->sk, index, opcode, &rp, sizeof(rp));
mgmt_pending_remove(cmd);
@@ -1638,9 +1592,8 @@ int mgmt_auth_failed(u16 index, bdaddr_t *bdaddr, u8 status)
{
struct mgmt_ev_auth_failed ev;
- put_unaligned_le16(index, &ev.index);
bacpy(&ev.bdaddr, bdaddr);
ev.status = status;
- return mgmt_event(MGMT_EV_AUTH_FAILED, &ev, sizeof(ev), NULL);
+ return mgmt_event(MGMT_EV_AUTH_FAILED, index, &ev, sizeof(ev), NULL);
}
--
1.7.0.4
on behalf of ST-Ericsson
^ permalink raw reply related
* [PATCH v2 1/3] Bluetooth: Use proper command structure in remove_uuid
From: Szymon Janc @ 2011-02-23 15:50 UTC (permalink / raw)
To: linux-bluetooth; +Cc: par-gunnar.p.hjalmdahl, henrik.possung, Szymon Janc
The structure used for command was wrong (probably copy-paste mistake).
Signed-off-by: Szymon Janc <szymon.janc@tieto.com>
---
net/bluetooth/mgmt.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index 982becd..4543ede 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -613,7 +613,7 @@ failed:
static int remove_uuid(struct sock *sk, unsigned char *data, u16 len)
{
struct list_head *p, *n;
- struct mgmt_cp_add_uuid *cp;
+ struct mgmt_cp_remove_uuid *cp;
struct hci_dev *hdev;
u8 bt_uuid_any[] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
u16 dev_id;
--
1.7.0.4
on behalf of ST-Ericsson
^ permalink raw reply related
* [PATCH v3 5/5] Implement ATT handle indication
From: Anderson Lizardo @ 2011-02-23 15:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Elvis Pfützenreuter
In-Reply-To: <1298408491-11154-1-git-send-email-anderson.lizardo@openbossa.org>
From: Elvis Pfützenreuter <epx@signove.com>
---
src/attrib-server.c | 40 ++++++++++++++++++++++++++++++++++++++++
1 files changed, 40 insertions(+), 0 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 62c10f4..a0c30b5 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -61,6 +61,8 @@ struct gatt_channel {
guint mtu;
guint id;
gboolean encrypted;
+ guint outstanding_indications;
+ time_t oldest_indication;
};
struct group_elem {
@@ -889,6 +891,10 @@ static void channel_handler(const uint8_t *ipdu, uint16_t len,
length = find_by_type(start, end, &uuid, value, vlen,
opdu, channel->mtu);
break;
+ case ATT_OP_HANDLE_CNF:
+ if (channel->outstanding_indications)
+ channel->outstanding_indications -= 1;
+ return;
case ATT_OP_READ_MULTI_REQ:
case ATT_OP_PREP_WRITE_REQ:
case ATT_OP_EXEC_WRITE_REQ:
@@ -968,8 +974,11 @@ static void confirm_event(GIOChannel *io, void *user_data)
static void attrib_notify_clients(struct attribute *attr)
{
guint handle = attr->handle;
+ time_t now;
GSList *l;
+ time(&now);
+
for (l = clients; l; l = l->next) {
struct gatt_channel *channel = l->data;
@@ -986,6 +995,37 @@ static void attrib_notify_clients(struct attribute *attr)
g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
NULL, NULL, NULL);
}
+
+ /* The outstanding_indications variable counts how many
+ * unconfirmed indications have been sent. The oldest_indication
+ * variable gives a small time frame to accomodate
+ * almost-concomitant indications, sending both without forcing
+ * a serialization.
+ *
+ * Indications are withheld once oldest_indication is older than
+ * at least 1 second and there are pending confirmations. */
+
+ if (channel->outstanding_indications &&
+ (now - channel->oldest_indication) > 1)
+ continue;
+
+ /* Indication */
+ if (g_slist_find_custom(channel->indicate,
+ GUINT_TO_POINTER(handle), handle_cmp) != NULL) {
+ uint8_t pdu[ATT_MAX_MTU];
+ uint16_t len;
+
+ len = enc_indication(attr, pdu, channel->mtu);
+ if (len == 0)
+ continue;
+
+ g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
+ NULL, NULL, NULL);
+
+ channel->outstanding_indications += 1;
+ if (channel->outstanding_indications == 1)
+ channel->oldest_indication = now;
+ }
}
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 4/5] Implement server-side ATT handle notification
From: Anderson Lizardo @ 2011-02-23 15:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andre Dieb Martins
In-Reply-To: <1298408491-11154-1-git-send-email-anderson.lizardo@openbossa.org>
From: Andre Dieb Martins <andre.dieb@signove.com>
Adds an initial version of ATT handle notification. Notifications are sent to
interested clients (based on the Client Characteristic Configuration) always
when the attribute is updated.
This enables services to call db_attrib_update() and send notifications on their
own terms.
---
src/attrib-server.c | 26 ++++++++++++++++++++++++++
1 files changed, 26 insertions(+), 0 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 21da17e..62c10f4 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -965,6 +965,30 @@ static void confirm_event(GIOChannel *io, void *user_data)
return;
}
+static void attrib_notify_clients(struct attribute *attr)
+{
+ guint handle = attr->handle;
+ GSList *l;
+
+ for (l = clients; l; l = l->next) {
+ struct gatt_channel *channel = l->data;
+
+ /* Notification */
+ if (g_slist_find_custom(channel->notify,
+ GUINT_TO_POINTER(handle), handle_cmp)) {
+ uint8_t pdu[ATT_MAX_MTU];
+ uint16_t len;
+
+ len = enc_notification(attr, pdu, channel->mtu);
+ if (len == 0)
+ continue;
+
+ g_attrib_send(channel->attrib, 0, pdu[0], pdu, len,
+ NULL, NULL, NULL);
+ }
+ }
+}
+
static gboolean register_core_services(void)
{
uint8_t atval[256];
@@ -1209,6 +1233,8 @@ int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
a->len = len;
memcpy(a->data, value, len);
+ attrib_notify_clients(a);
+
return 0;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 3/5] Check properties before setting client configs
From: Anderson Lizardo @ 2011-02-23 15:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Andre Dieb Martins
In-Reply-To: <1298408491-11154-1-git-send-email-anderson.lizardo@openbossa.org>
From: Andre Dieb Martins <andre.dieb@signove.com>
Only enable notification/indication if the descriptor allows it.
---
src/attrib-server.c | 11 ++++++++---
1 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 47ca5d9..21da17e 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -199,13 +199,14 @@ static uint8_t client_set_notifications(struct attribute *attr,
struct gatt_channel *channel = user_data;
struct attribute *last_chr_val = NULL;
uint16_t cfg_val;
+ uint8_t props;
uuid_t uuid;
GSList *l;
cfg_val = att_get_u16(attr->data);
sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
- for (l = database; l != NULL; l = l->next) {
+ for (l = database, props = 0; l != NULL; l = l->next) {
struct attribute *a = l->data;
static uint16_t handle = 0;
@@ -213,6 +214,7 @@ static uint8_t client_set_notifications(struct attribute *attr,
break;
if (sdp_uuid_cmp(&a->uuid, &uuid) == 0) {
+ props = att_get_u8(&a->data[0]);
handle = att_get_u16(&a->data[1]);
continue;
}
@@ -224,8 +226,11 @@ static uint8_t client_set_notifications(struct attribute *attr,
if (last_chr_val == NULL)
return 0;
- /* FIXME: Characteristic properties shall be checked for
- * Notification/Indication permissions. */
+ if ((cfg_val & 0x0001) && !(props & ATT_CHAR_PROPER_NOTIFY))
+ return ATT_ECODE_WRITE_NOT_PERM;
+
+ if ((cfg_val & 0x0002) && !(props & ATT_CHAR_PROPER_INDICATE))
+ return ATT_ECODE_WRITE_NOT_PERM;
if (cfg_val & 0x0001)
channel->notify = g_slist_append(channel->notify, last_chr_val);
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 2/5] Initial Client Characteristic Configuration implementation
From: Anderson Lizardo @ 2011-02-23 15:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1298408491-11154-1-git-send-email-anderson.lizardo@openbossa.org>
This initial version creates a private copy of the Client Configuration
attribute for each client on the first write to that attribute. Further
reads/writes should use the client's private copy.
Two list of attributes are created: one for values to be indicated and
another for values to be notified. The actual notification/indication
sending is implemented in a separate commit.
This initial version also does not check for the characteristic
properties, which is implemented in a separate commit as well.
---
src/attrib-server.c | 181 ++++++++++++++++++++++++++++++++++++++++++---------
1 files changed, 150 insertions(+), 31 deletions(-)
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 28649f1..47ca5d9 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -54,6 +54,9 @@ static GSList *database = NULL;
struct gatt_channel {
bdaddr_t src;
bdaddr_t dst;
+ GSList *configs;
+ GSList *notify;
+ GSList *indicate;
GAttrib *attrib;
guint mtu;
guint id;
@@ -143,6 +146,22 @@ static sdp_record_t *server_record_new(uuid_t *uuid, uint16_t start, uint16_t en
return record;
}
+static int handle_cmp(gconstpointer a, gconstpointer b)
+{
+ const struct attribute *attrib = a;
+ uint16_t handle = GPOINTER_TO_UINT(b);
+
+ return attrib->handle - handle;
+}
+
+static int attribute_cmp(gconstpointer a1, gconstpointer a2)
+{
+ const struct attribute *attrib1 = a1;
+ const struct attribute *attrib2 = a2;
+
+ return attrib1->handle - attrib2->handle;
+}
+
static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
int reqs)
{
@@ -174,6 +193,93 @@ static uint8_t att_check_reqs(struct gatt_channel *channel, uint8_t opcode,
return 0;
}
+static uint8_t client_set_notifications(struct attribute *attr,
+ gpointer user_data)
+{
+ struct gatt_channel *channel = user_data;
+ struct attribute *last_chr_val = NULL;
+ uint16_t cfg_val;
+ uuid_t uuid;
+ GSList *l;
+
+ cfg_val = att_get_u16(attr->data);
+
+ sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
+ for (l = database; l != NULL; l = l->next) {
+ struct attribute *a = l->data;
+ static uint16_t handle = 0;
+
+ if (a->handle >= attr->handle)
+ break;
+
+ if (sdp_uuid_cmp(&a->uuid, &uuid) == 0) {
+ handle = att_get_u16(&a->data[1]);
+ continue;
+ }
+
+ if (handle && a->handle == handle)
+ last_chr_val = a;
+ }
+
+ if (last_chr_val == NULL)
+ return 0;
+
+ /* FIXME: Characteristic properties shall be checked for
+ * Notification/Indication permissions. */
+
+ if (cfg_val & 0x0001)
+ channel->notify = g_slist_append(channel->notify, last_chr_val);
+ else
+ channel->notify = g_slist_remove(channel->notify, last_chr_val);
+
+ if (cfg_val & 0x0002)
+ channel->indicate = g_slist_append(channel->indicate,
+ last_chr_val);
+ else
+ channel->indicate = g_slist_remove(channel->indicate,
+ last_chr_val);
+
+ return 0;
+}
+
+static struct attribute *client_cfg_attribute(struct gatt_channel *channel,
+ struct attribute *orig_attr,
+ const uint8_t *value, int vlen)
+{
+ guint handle = orig_attr->handle;
+ uuid_t uuid;
+ GSList *l;
+
+ sdp_uuid16_create(&uuid, GATT_CLIENT_CHARAC_CFG_UUID);
+ if (sdp_uuid_cmp(&orig_attr->uuid, &uuid) != 0)
+ return NULL;
+
+ /* Value is unchanged, not need to create a private copy yet */
+ if (vlen == orig_attr->len && memcmp(orig_attr->data, value, vlen) == 0)
+ return orig_attr;
+
+ l = g_slist_find_custom(channel->configs, GUINT_TO_POINTER(handle),
+ handle_cmp);
+ if (!l) {
+ struct attribute *a;
+
+ /* Create a private copy of the Client Characteristic
+ * Configuration attribute */
+ a = g_malloc0(sizeof(*a) + vlen);
+ memcpy(a, orig_attr, sizeof(*a));
+ memcpy(a->data, value, vlen);
+ a->write_cb = client_set_notifications;
+ a->cb_user_data = channel;
+
+ channel->configs = g_slist_insert_sorted(channel->configs, a,
+ attribute_cmp);
+
+ return a;
+ }
+
+ return l->data;
+}
+
static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
uint16_t end, uuid_t *uuid,
uint8_t *pdu, int len)
@@ -202,6 +308,8 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
last_handle = end;
for (l = database, groups = NULL; l; l = l->next) {
+ struct attribute *client_attr;
+
a = l->data;
if (a->handle < start)
@@ -230,6 +338,10 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -308,6 +420,8 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
ATT_ECODE_INVALID_HANDLE, pdu, len);
for (l = database, length = 0, types = NULL; l; l = l->next) {
+ struct attribute *client_attr;
+
a = l->data;
if (a->handle < start)
@@ -322,6 +436,10 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -506,22 +624,6 @@ static int find_by_type(uint16_t start, uint16_t end, uuid_t *uuid,
return len;
}
-static int handle_cmp(gconstpointer a, gconstpointer b)
-{
- const struct attribute *attrib = a;
- uint16_t handle = GPOINTER_TO_UINT(b);
-
- return attrib->handle - handle;
-}
-
-static int attribute_cmp(gconstpointer a1, gconstpointer a2)
-{
- const struct attribute *attrib1 = a1;
- const struct attribute *attrib2 = a2;
-
- return attrib1->handle - attrib2->handle;
-}
-
static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
{
struct attribute *attrib;
@@ -559,7 +661,7 @@ static struct attribute *find_primary_range(uint16_t start, uint16_t *end)
static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
uint8_t *pdu, int len)
{
- struct attribute *a;
+ struct attribute *a, *client_attr;
uint8_t status;
GSList *l;
guint h = handle;
@@ -573,6 +675,10 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -586,7 +692,7 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
uint16_t offset, uint8_t *pdu, int len)
{
- struct attribute *a;
+ struct attribute *a, *client_attr;
uint8_t status;
GSList *l;
guint h = handle;
@@ -604,6 +710,10 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
+ client_attr = client_cfg_attribute(channel, a, a->data, a->len);
+ if (client_attr)
+ a = client_attr;
+
if (status == 0x00 && a->read_cb)
status = a->read_cb(a, a->cb_user_data);
@@ -618,11 +728,10 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
const uint8_t *value, int vlen,
uint8_t *pdu, int len)
{
- struct attribute *a;
+ struct attribute *a, *client_attr;
uint8_t status;
GSList *l;
guint h = handle;
- uuid_t uuid;
l = g_slist_find_custom(database, GUINT_TO_POINTER(h), handle_cmp);
if (!l)
@@ -636,8 +745,11 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
return enc_error_resp(ATT_OP_WRITE_REQ, handle, status, pdu,
len);
- memcpy(&uuid, &a->uuid, sizeof(uuid_t));
- attrib_db_update(handle, &uuid, value, vlen);
+ client_attr = client_cfg_attribute(channel, a, value, vlen);
+ if (client_attr)
+ a = client_attr;
+ else
+ attrib_db_update(a->handle, &a->uuid, value, vlen);
if (a->write_cb) {
status = a->write_cb(a, a->cb_user_data);
@@ -646,6 +758,10 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
pdu, len);
}
+ DBG("Notifications: %d, indications: %d",
+ g_slist_length(channel->notify),
+ g_slist_length(channel->indicate));
+
return enc_write_resp(pdu, len);
}
@@ -664,6 +780,11 @@ static void channel_disconnect(void *user_data)
g_attrib_unref(channel->attrib);
clients = g_slist_remove(clients, channel);
+ g_slist_free(channel->notify);
+ g_slist_free(channel->indicate);
+ g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
+ g_slist_free(channel->configs);
+
g_free(channel);
}
@@ -976,6 +1097,11 @@ void attrib_server_exit(void)
for (l = clients; l; l = l->next) {
struct gatt_channel *channel = l->data;
+ g_slist_free(channel->notify);
+ g_slist_free(channel->indicate);
+ g_slist_foreach(channel->configs, (GFunc) g_free, NULL);
+ g_slist_free(channel->configs);
+
g_attrib_unref(channel->attrib);
g_free(channel);
}
@@ -1073,18 +1199,11 @@ int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
l->data = a;
a->handle = handle;
- memcpy(&a->uuid, uuid, sizeof(uuid_t));
+ if (uuid != &a->uuid)
+ memcpy(&a->uuid, uuid, sizeof(uuid_t));
a->len = len;
memcpy(a->data, value, len);
- /*
- * <<Client/Server Characteristic Configuration>> descriptors are
- * not supported yet. If a given attribute changes, the attribute
- * server shall report the new values using the mechanism selected
- * by the client. Notification/Indication shall not be automatically
- * sent if the client didn't request them.
- */
-
return 0;
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH v3 1/5] Add read/write callbacks to attribute server
From: Anderson Lizardo @ 2011-02-23 15:14 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Anderson Lizardo
In-Reply-To: <1298408491-11154-1-git-send-email-anderson.lizardo@openbossa.org>
These callbacks will allow profiles to act before an attribute is read
and after it is written, to e.g. update the attribute value to/from an
external source.
Note that by the time the callback is called, the necessary security
checks (attribute permissions, authentication and encryption) were
already performed by the core attribute server.
The callback can optionally return an ATT status code, which will be
sent to the client using an Error Response PDU.
---
attrib/att.h | 3 +++
src/attrib-server.c | 29 ++++++++++++++++++++++++++---
src/attrib-server.h | 4 ++--
3 files changed, 31 insertions(+), 5 deletions(-)
diff --git a/attrib/att.h b/attrib/att.h
index 7d9afeb..9b0b538 100644
--- a/attrib/att.h
+++ b/attrib/att.h
@@ -123,6 +123,9 @@ struct attribute {
uuid_t uuid;
int read_reqs;
int write_reqs;
+ uint8_t (*read_cb)(struct attribute *a, gpointer user_data);
+ uint8_t (*write_cb)(struct attribute *a, gpointer user_data);
+ gpointer cb_user_data;
int len;
uint8_t data[0];
};
diff --git a/src/attrib-server.c b/src/attrib-server.c
index 7ec0f56..28649f1 100644
--- a/src/attrib-server.c
+++ b/src/attrib-server.c
@@ -229,6 +229,10 @@ static uint16_t read_by_group(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_GROUP_REQ,
a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status) {
g_slist_foreach(groups, (GFunc) g_free, NULL);
g_slist_free(groups);
@@ -317,6 +321,10 @@ static uint16_t read_by_type(struct gatt_channel *channel, uint16_t start,
status = att_check_reqs(channel, ATT_OP_READ_BY_TYPE_REQ,
a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status) {
g_slist_free(types);
return enc_error_resp(ATT_OP_READ_BY_TYPE_REQ,
@@ -564,6 +572,10 @@ static uint16_t read_value(struct gatt_channel *channel, uint16_t handle,
a = l->data;
status = att_check_reqs(channel, ATT_OP_READ_REQ, a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status)
return enc_error_resp(ATT_OP_READ_REQ, handle, status, pdu,
len);
@@ -591,6 +603,10 @@ static uint16_t read_blob(struct gatt_channel *channel, uint16_t handle,
ATT_ECODE_INVALID_OFFSET, pdu, len);
status = att_check_reqs(channel, ATT_OP_READ_BLOB_REQ, a->read_reqs);
+
+ if (status == 0x00 && a->read_cb)
+ status = a->read_cb(a, a->cb_user_data);
+
if (status)
return enc_error_resp(ATT_OP_READ_BLOB_REQ, handle, status,
pdu, len);
@@ -623,6 +639,13 @@ static uint16_t write_value(struct gatt_channel *channel, uint16_t handle,
memcpy(&uuid, &a->uuid, sizeof(uuid_t));
attrib_db_update(handle, &uuid, value, vlen);
+ if (a->write_cb) {
+ status = a->write_cb(a, a->cb_user_data);
+ if (status)
+ return enc_error_resp(ATT_OP_WRITE_REQ, handle, status,
+ pdu, len);
+ }
+
return enc_write_resp(pdu, len);
}
@@ -1013,8 +1036,8 @@ void attrib_free_sdp(uint32_t sdp_handle)
remove_record_from_server(sdp_handle);
}
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len)
+struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,
+ int write_reqs, const uint8_t *value, int len)
{
struct attribute *a;
@@ -1030,7 +1053,7 @@ int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
database = g_slist_insert_sorted(database, a, attribute_cmp);
- return 0;
+ return a;
}
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
diff --git a/src/attrib-server.h b/src/attrib-server.h
index ecd695c..85f3bdb 100644
--- a/src/attrib-server.h
+++ b/src/attrib-server.h
@@ -25,8 +25,8 @@
int attrib_server_init(void);
void attrib_server_exit(void);
-int attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs, int write_reqs,
- const uint8_t *value, int len);
+struct attribute *attrib_db_add(uint16_t handle, uuid_t *uuid, int read_reqs,
+ int write_reqs, const uint8_t *value, int len);
int attrib_db_update(uint16_t handle, uuid_t *uuid, const uint8_t *value,
int len);
int attrib_db_del(uint16_t handle);
--
1.7.0.4
^ permalink raw reply related
* Re: [PATCH] Fix typo on DBG() string format
From: Johan Hedberg @ 2011-02-23 14:51 UTC (permalink / raw)
To: Anderson Lizardo; +Cc: linux-bluetooth
In-Reply-To: <1298464037-10700-1-git-send-email-anderson.lizardo@openbossa.org>
Hi Lizardo,
On Wed, Feb 23, 2011, Anderson Lizardo wrote:
> ---
> attrib/client.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/attrib/client.c b/attrib/client.c
> index 0f9ba3e..4635c75 100644
> --- a/attrib/client.c
> +++ b/attrib/client.c
> @@ -299,7 +299,7 @@ static void events_handler(const uint8_t *pdu, uint16_t len,
> NULL, NULL, NULL);
> case ATT_OP_HANDLE_NOTIFY:
> if (characteristic_set_value(chr, &pdu[3], len - 3) < 0)
> - DBG("Can't change Characteristic %0x02x", handle);
> + DBG("Can't change Characteristic 0x%02x", handle);
>
> g_slist_foreach(prim->watchers, update_watchers, chr);
> break;
Good catch. The patch has been pushed upstream.
Johan
^ permalink raw reply
* Re: [PATCH v2] Check malformed notification/indication PDU
From: Johan Hedberg @ 2011-02-23 14:49 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <1298463393-25123-1-git-send-email-epx@signove.com>
Hi Elvis,
On Wed, Feb 23, 2011, Elvis Pf??tzenreuter wrote:
> This patch implements discard of obviously malformed
> GATT notification/indication PDUs.
> ---
> attrib/client.c | 10 +++++++++-
> 1 files changed, 9 insertions(+), 1 deletions(-)
Pushed upstream. Thanks.
Johan
^ permalink raw reply
* Re: [PATCH 5/6] Move pcsuite drivers to its own plugin
From: Johan Hedberg @ 2011-02-23 14:44 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: linux-bluetooth
In-Reply-To: <1298454881-7941-5-git-send-email-luiz.dentz@gmail.com>
Hi Luiz,
On Wed, Feb 23, 2011, Luiz Augusto von Dentz wrote:
> This make it easier to enable/disable this funcionality as a whole.
> ---
> Makefile.am | 6 +-
> configure.ac | 9 +-
> plugins/ftp.c | 165 ++------------------------
> plugins/nokia-backup.c | 309 ------------------------------------------------
> 4 files changed, 16 insertions(+), 473 deletions(-)
> delete mode 100644 plugins/nokia-backup.c
It seems like you've forgotten to do git add plugins/pcsuite.c?
Anyway, I went ahead and applied patches 1-4.
Johan
^ permalink raw reply
* Re: [PATCHv2 2/5] Initial Client Characteristic Configuration implementation
From: Anderson Lizardo @ 2011-02-23 14:29 UTC (permalink / raw)
To: Anderson Lizardo, linux-bluetooth; +Cc: Johan Hedberg
In-Reply-To: <20110223032608.GE16014@jh-x301>
Hi Johan,
On Wed, Feb 23, 2011 at 12:26 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> On Tue, Feb 22, 2011, Anderson Lizardo wrote:
>> +static uint8_t client_set_notifications(struct attribute *attr,
>> + gpointer user_data)
>> +{
>> + struct gatt_channel *channel = user_data;
>> + struct attribute *a, *last_chr_val = NULL;
>> + uint16_t handle, cfg_val;
>> + uuid_t uuid;
>> + GSList *l;
>> +
>> + cfg_val = att_get_u16(attr->data);
>> +
>> + sdp_uuid16_create(&uuid, GATT_CHARAC_UUID);
>> + for (l = database, handle = 0; l != NULL; l = l->next) {
>> + a = l->data;
>
> The variable "a" is only used inside the for-loop so it should be
> declared inside it as well. I think you can move handle inside the loop
> as well as long as you declare it static (so it only gets initialized to
> 0 on the first iteration).
Both changes will be incorporated on the v3.
>
> Johan
>
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* Re: [PATCHv2 1/5] Add read/write callbacks to attribute server
From: Anderson Lizardo @ 2011-02-23 14:28 UTC (permalink / raw)
To: Anderson Lizardo, linux-bluetooth; +Cc: Johan Hedberg
In-Reply-To: <20110223032154.GD16014@jh-x301>
Hi Johan,
On Wed, Feb 23, 2011 at 12:21 AM, Johan Hedberg <johan.hedberg@gmail.com> wrote:
> On Tue, Feb 22, 2011, Anderson Lizardo wrote:
>> +struct attribute;
>> +
>> +typedef uint8_t (*att_cb_t)(struct attribute *a, gpointer user_data);
>> +
>> struct attribute {
>> uint16_t handle;
>> uuid_t uuid;
>> int read_reqs;
>> int write_reqs;
>> + att_cb_t read_cb;
>> + att_cb_t write_cb;
>> + gpointer cb_user_data;
>> int len;
>> uint8_t data[0];
>> };
>
> I'm not really a fan of the needed forward declaration here. I can't
> find you using "att_cb_t" anywhere else in your patches, so how about
> just having the full type of the callbacks inside the struct definition
> and skip the typedef completely?
Sure, I'll drop the typedef and send a v3.
Regards,
--
Anderson Lizardo
Instituto Nokia de Tecnologia - INdT
Manaus - Brazil
^ permalink raw reply
* [PATCH v3 3/7] Create helper functions to deal with handles on interactive gatttool
From: Sheldon Demario @ 2011-02-23 14:20 UTC (permalink / raw)
To: linux-bluetooth; +Cc: Sheldon Demario
In-Reply-To: <20110223030903.GB16014@jh-x301>
---
attrib/interactive.c | 48 +++++++++++++++++++++++++++++++-----------------
1 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/attrib/interactive.c b/attrib/interactive.c
index 7cc03bc..ed45894 100644
--- a/attrib/interactive.c
+++ b/attrib/interactive.c
@@ -238,36 +238,50 @@ static void cmd_primary(int argcp, char **argvp)
gatt_discover_primary(attrib, &uuid, primary_by_uuid_cb, NULL);
}
-static void cmd_char(int argcp, char **argvp)
+static int strtohandle(int *dst, const char *src)
{
- int start = 0x0001;
- int end = 0xffff;
+ char *e;
- if (conn_state != STATE_CONNECTED) {
- printf("Command failed: disconnected\n");
- return;
- }
+ errno = 0;
+ *dst = strtoll(src, &e, 16);
+ if (errno != 0 || *e != '\0')
+ return -1;
- if (argcp > 1) {
- char *e;
+ return 0;
+}
- start = strtoll(argvp[1], &e, 16);
- if (errno != 0 || *e != '\0') {
+static int set_handles(int *start, int *end, int argcp, char **argvp)
+{
+ if (argcp > 1) {
+ if (strtohandle(start, argvp[1])) {
printf("Invalid start handle: %s\n", argvp[1]);
- return;
+ return -1;
}
}
if (argcp > 2) {
- char *e;
-
- end = strtoll(argvp[2], &e, 16);
- if (errno != 0 || *e != '\0') {
+ if (strtohandle(end, argvp[2])) {
printf("Invalid end handle: %s\n", argvp[2]);
- return;
+ return -1;
}
}
+ return 0;
+}
+
+static void cmd_char(int argcp, char **argvp)
+{
+ int start = 0x0001;
+ int end = 0xffff;
+
+ if (conn_state != STATE_CONNECTED) {
+ printf("Command failed: disconnected\n");
+ return;
+ }
+
+ if (set_handles(&start, &end, argcp, argvp))
+ return;
+
gatt_discover_char(attrib, start, end, char_cb, NULL);
return;
--
1.7.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox