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