1 /*
2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
17 * under the License.
18 */
19
20 #include <assert.h>
21 #include <string.h>
22 #include <stdio.h>
23 #include <errno.h>
24
25 /* BLE */
26 #include "nimble/ble.h"
27 #include "host/ble_hs.h"
28 #include "host/ble_hs_adv.h"
29 #include "host/ble_uuid.h"
30 #include "host/ble_att.h"
31 #include "host/ble_gap.h"
32 #include "host/ble_gatt.h"
33 #include "host/ble_l2cap.h"
34 #include "host/ble_sm.h"
35
36 /* bluetooth transport. */
37 #include "nimble/ble_hci_trans.h"
38
39 /* Mandatory services. */
40 #include "services/gap/ble_svc_gap.h"
41 #include "services/gatt/ble_svc_gatt.h"
42
43 /* Newtmgr include */
44 #include "bleuart/bleuart.h"
45
46 #include <rtthread.h>
47 #include <rtdevice.h>
48
49 static int bleuart_gap_event(struct ble_gap_event *event, void *arg);
50
51 /**
52 * Enables advertising with the following parameters:
53 * o General discoverable mode.
54 * o Undirected connectable mode.
55 */
56 static void
bleuart_advertise(void)57 bleuart_advertise(void)
58 {
59 struct ble_gap_adv_params adv_params;
60 struct ble_hs_adv_fields fields;
61 int rc;
62
63 /*
64 * Set the advertisement data included in our advertisements:
65 * o Flags (indicates advertisement type and other general info).
66 * o Advertising tx power.
67 * o 128 bit UUID
68 */
69
70 memset(&fields, 0, sizeof fields);
71
72 /* Advertise two flags:
73 * o Discoverability in forthcoming advertisement (general)
74 * o BLE-only (BR/EDR unsupported).
75 */
76 fields.flags = BLE_HS_ADV_F_DISC_GEN |
77 BLE_HS_ADV_F_BREDR_UNSUP;
78
79 /* Indicate that the TX power level field should be included; have the
80 * stack fill this value automatically. This is done by assiging the
81 * special value BLE_HS_ADV_TX_PWR_LVL_AUTO.
82 */
83 fields.tx_pwr_lvl_is_present = 1;
84 fields.tx_pwr_lvl = BLE_HS_ADV_TX_PWR_LVL_AUTO;
85
86 fields.uuids128 = BLE_UUID128(&gatt_svr_svc_uart_uuid.u);
87 fields.num_uuids128 = 1;
88 fields.uuids128_is_complete = 1;
89
90 rc = ble_gap_adv_set_fields(&fields);
91 if (rc != 0) {
92 return;
93 }
94
95 memset(&fields, 0, sizeof fields);
96 fields.name = (uint8_t *)ble_svc_gap_device_name();
97 fields.name_len = strlen((char *)fields.name);
98 fields.name_is_complete = 1;
99
100 rc = ble_gap_adv_rsp_set_fields(&fields);
101 if (rc != 0) {
102 return;
103 }
104
105 /* Begin advertising. */
106 memset(&adv_params, 0, sizeof adv_params);
107 adv_params.conn_mode = BLE_GAP_CONN_MODE_UND;
108 adv_params.disc_mode = BLE_GAP_DISC_MODE_GEN;
109 rc = ble_gap_adv_start(BLE_OWN_ADDR_PUBLIC, NULL, BLE_HS_FOREVER,
110 &adv_params, bleuart_gap_event, NULL);
111 if (rc != 0) {
112 return;
113 }
114 }
115
116 /**
117 * The nimble host executes this callback when a GAP event occurs. The
118 * application associates a GAP event callback with each connection that forms.
119 * bleuart uses the same callback for all connections.
120 *
121 * @param event The type of event being signalled.
122 * @param ctxt Various information pertaining to the event.
123 * @param arg Application-specified argument; unuesd by
124 * bleuart.
125 *
126 * @return 0 if the application successfully handled the
127 * event; nonzero on failure. The semantics
128 * of the return code is specific to the
129 * particular GAP event being signalled.
130 */
131 static int
bleuart_gap_event(struct ble_gap_event * event,void * arg)132 bleuart_gap_event(struct ble_gap_event *event, void *arg)
133 {
134 struct ble_gap_conn_desc desc;
135 int rc;
136
137 switch (event->type) {
138 case BLE_GAP_EVENT_CONNECT:
139 /* A new connection was established or a connection attempt failed. */
140 if (event->connect.status == 0) {
141 rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
142 assert(rc == 0);
143 bleuart_set_conn_handle(event->connect.conn_handle);
144 }
145
146 if (event->connect.status != 0) {
147 /* Connection failed; resume advertising. */
148 bleuart_advertise();
149 }
150 return 0;
151
152 case BLE_GAP_EVENT_DISCONNECT:
153 /* Connection terminated; resume advertising. */
154 bleuart_advertise();
155 return 0;
156
157
158 case BLE_GAP_EVENT_ADV_COMPLETE:
159 /* Advertising terminated; resume advertising. */
160 bleuart_advertise();
161 return 0;
162
163 case BLE_GAP_EVENT_REPEAT_PAIRING:
164 /* We already have a bond with the peer, but it is attempting to
165 * establish a new secure link. This app sacrifices security for
166 * convenience: just throw away the old bond and accept the new link.
167 */
168
169 /* Delete the old bond. */
170 rc = ble_gap_conn_find(event->repeat_pairing.conn_handle, &desc);
171 assert(rc == 0);
172 ble_store_util_delete_peer(&desc.peer_id_addr);
173
174 /* Return BLE_GAP_REPEAT_PAIRING_RETRY to indicate that the host should
175 * continue with the pairing operation.
176 */
177 return BLE_GAP_REPEAT_PAIRING_RETRY;
178 }
179
180 return 0;
181 }
182
183 static void
bleuart_on_sync(void)184 bleuart_on_sync(void)
185 {
186 /* Begin advertising. */
187 bleuart_advertise();
188 }
189
190 /**
191 * main
192 *
193 * The main task for the project. This function initializes the packages,
194 * then starts serving events from default event queue.
195 *
196 * @return int NOTE: this function should never return!
197 */
bleuart_entry(void)198 int bleuart_entry(void)
199 {
200 int rc;
201 static int init_flag = 0;
202
203 if (init_flag == 0)
204 {
205 init_flag = 1;
206
207 /* Initialize the BLE host. */
208 ble_hs_cfg.sync_cb = bleuart_on_sync;
209 ble_hs_cfg.store_status_cb = ble_store_util_status_rr;
210
211 rc = bleuart_gatt_svr_init();
212 assert(rc == 0);
213
214 /* Set the default device name. */
215 rc = ble_svc_gap_device_name_set("Mynewt_BLEuart");
216 assert(rc == 0);
217
218 /* startup bluetooth host stack*/
219 ble_hs_thread_startup();
220 }
221
222 bleuart_init();
223
224 return 0;
225 }
226
227 MSH_CMD_EXPORT_ALIAS(bleuart_entry, bleuart, "bluetooth uart sample");
228