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 "syscfg/syscfg.h"
21 #include "sysinit/sysinit.h"
22
23 #if MYNEWT_VAL(BLE_LL_DIRECT_TEST_MODE) == 1
24
25 #include <assert.h>
26 #include "os/os.h"
27 #include "stats/stats.h"
28 #include "controller/ble_ll.h"
29 #include "controller/ble_phy.h"
30 #include "controller/ble_ll_sched.h"
31 #include "controller/ble_ll_xcvr.h"
32 #include "ble_ll_dtm_priv.h"
33
34 STATS_SECT_START(ble_ll_dtm_stats)
35 STATS_SECT_ENTRY(rx_count)
36 STATS_SECT_ENTRY(tx_failed)
37 STATS_SECT_ENTRY(rx_failed)
38 STATS_SECT_END
39 STATS_SECT_DECL(ble_ll_dtm_stats) ble_ll_dtm_stats;
40
41 STATS_NAME_START(ble_ll_dtm_stats)
42 STATS_NAME(ble_ll_dtm_stats, rx_count)
43 STATS_NAME(ble_ll_dtm_stats, tx_failed)
44 STATS_NAME(ble_ll_dtm_stats, rx_failed)
45 STATS_NAME_END(ble_phy_stats)
46
47 struct dtm_ctx {
48 uint8_t payload_packet;
49 uint8_t itvl_rem_usec;
50 uint16_t num_of_packets;
51 uint32_t itvl_ticks;
52 int active;
53 uint8_t rf_channel;
54 uint8_t phy_mode;
55 struct os_mbuf *om;
56 struct ble_npl_event evt;
57 struct ble_ll_sched_item sch;
58 };
59
60 static struct dtm_ctx g_ble_ll_dtm_ctx;
61
62 static const uint8_t g_ble_ll_dtm_prbs9_data[] =
63 {
64 0xff, 0xc1, 0xfb, 0xe8, 0x4c, 0x90, 0x72, 0x8b,
65 0xe7, 0xb3, 0x51, 0x89, 0x63, 0xab, 0x23, 0x23,
66 0x02, 0x84, 0x18, 0x72, 0xaa, 0x61, 0x2f, 0x3b,
67 0x51, 0xa8, 0xe5, 0x37, 0x49, 0xfb, 0xc9, 0xca,
68 0x0c, 0x18, 0x53, 0x2c, 0xfd, 0x45, 0xe3, 0x9a,
69 0xe6, 0xf1, 0x5d, 0xb0, 0xb6, 0x1b, 0xb4, 0xbe,
70 0x2a, 0x50, 0xea, 0xe9, 0x0e, 0x9c, 0x4b, 0x5e,
71 0x57, 0x24, 0xcc, 0xa1, 0xb7, 0x59, 0xb8, 0x87,
72 0xff, 0xe0, 0x7d, 0x74, 0x26, 0x48, 0xb9, 0xc5,
73 0xf3, 0xd9, 0xa8, 0xc4, 0xb1, 0xd5, 0x91, 0x11,
74 0x01, 0x42, 0x0c, 0x39, 0xd5, 0xb0, 0x97, 0x9d,
75 0x28, 0xd4, 0xf2, 0x9b, 0xa4, 0xfd, 0x64, 0x65,
76 0x06, 0x8c, 0x29, 0x96, 0xfe, 0xa2, 0x71, 0x4d,
77 0xf3, 0xf8, 0x2e, 0x58, 0xdb, 0x0d, 0x5a, 0x5f,
78 0x15, 0x28, 0xf5, 0x74, 0x07, 0xce, 0x25, 0xaf,
79 0x2b, 0x12, 0xe6, 0xd0, 0xdb, 0x2c, 0xdc, 0xc3,
80 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, 0xe2,
81 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, 0x88,
82 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, 0x4e,
83 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, 0x32,
84 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, 0xa6,
85 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, 0xaf,
86 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, 0xd7,
87 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, 0xe1,
88 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, 0xf1,
89 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, 0x44,
90 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, 0x27,
91 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, 0x99,
92 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, 0xd3,
93 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, 0x57,
94 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, 0xeb,
95 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7
96 };
97
98 static const uint8_t g_ble_ll_dtm_prbs15_data[] =
99 {
100 0xff, 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc,
101 0xe2, 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8,
102 0x88, 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb,
103 0x4e, 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2,
104 0x32, 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8,
105 0xa6, 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad,
106 0xaf, 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92,
107 0xd7, 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee,
108 0xe1, 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e,
109 0xf1, 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64,
110 0x44, 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65,
111 0x27, 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59,
112 0x99, 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c,
113 0xd3, 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6,
114 0x57, 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9,
115 0xeb, 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7,
116 0xf0, 0x1f, 0xbc, 0x8f, 0xce, 0x04, 0x29, 0xb7,
117 0x78, 0x3e, 0x1b, 0x95, 0x38, 0xb6, 0x3a, 0x32,
118 0x22, 0x40, 0x88, 0x21, 0xa7, 0x1a, 0xf6, 0xb2,
119 0x13, 0x85, 0x5a, 0x7e, 0x93, 0xb4, 0x9f, 0xac,
120 0xcc, 0x80, 0x31, 0xc5, 0xd2, 0x5f, 0x34, 0xae,
121 0x69, 0x1e, 0xdf, 0x05, 0x6b, 0xbb, 0x41, 0xeb,
122 0xab, 0x02, 0xa5, 0x9e, 0xee, 0xc0, 0xb9, 0xe4,
123 0x75, 0x45, 0xc2, 0x1c, 0x7a, 0x9b, 0x85, 0x7b,
124 0xf8, 0x0f, 0xde, 0x47, 0x67, 0x82, 0x94, 0x5b,
125 0x3c, 0x9f, 0x8d, 0x4a, 0x1c, 0x5b, 0x1d, 0x19,
126 0x11, 0x20, 0xc4, 0x90, 0x53, 0x0d, 0x7b, 0xd9,
127 0x89, 0x42, 0x2d, 0xbf, 0x49, 0xda, 0x4f, 0x56,
128 0x66, 0xc0, 0x98, 0x62, 0xe9, 0x2f, 0x1a, 0xd7,
129 0x34, 0x8f, 0xef, 0x82, 0xb5, 0xdd, 0xa0, 0xf5,
130 0x55, 0x81, 0x52, 0x4f, 0x77, 0xe0, 0x5c, 0xf2,
131 0xba, 0x22, 0x61, 0x0e, 0xbd, 0xcd, 0xc2
132 };
133
134 static const uint8_t channel_rf_to_index[] = {
135 37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 38, 11 ,12, 13, 14, 15,
136 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
137 34, 35, 36, 39
138 };
139
140 #define BLE_DTM_SYNC_WORD (0x71764129)
141 #define BLE_DTM_CRC (0x555555)
142
143 static void
ble_ll_dtm_set_next(struct dtm_ctx * ctx)144 ble_ll_dtm_set_next(struct dtm_ctx *ctx)
145 {
146 struct ble_ll_sched_item *sch = &ctx->sch;
147
148 sch->start_time += ctx->itvl_ticks;
149 sch->remainder += ctx->itvl_rem_usec;
150 if (sch->remainder > 30) {
151 sch->start_time++;
152 sch->remainder -= 30;
153 }
154
155 sch->start_time -= g_ble_ll_sched_offset_ticks;
156 }
157
158 static void
ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event * evt)159 ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event *evt) {
160 /* It is called in LL context */
161 struct dtm_ctx *ctx = ble_npl_event_get_arg(evt);
162 int rc;
163 os_sr_t sr;
164
165 OS_ENTER_CRITICAL(sr);
166 if (!ctx->active || !ctx->om) {
167 OS_EXIT_CRITICAL(sr);
168 return;
169 }
170 OS_EXIT_CRITICAL(sr);
171
172 ble_ll_dtm_set_next(ctx);
173 rc = ble_ll_sched_dtm(&ctx->sch);
174 BLE_LL_ASSERT(rc == 0);
175 }
176
177 static int ble_ll_dtm_rx_start(void);
178
179 static void
ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event * evt)180 ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event *evt) {
181 if (ble_ll_dtm_rx_start() != 0) {
182 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
183 STATS_INC(ble_ll_dtm_stats, rx_failed);
184 }
185 }
186
187 static void
ble_ll_dtm_tx_done(void * arg)188 ble_ll_dtm_tx_done(void *arg)
189 {
190 struct dtm_ctx *ctx;
191
192 ctx = arg;
193 if (!ctx->active) {
194 return;
195 }
196
197 /* Reschedule event in LL context */
198 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt);
199
200 ble_ll_state_set(BLE_LL_STATE_STANDBY);
201 }
202
203 static int
ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item * sch)204 ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch)
205 {
206 struct dtm_ctx *ctx = sch->cb_arg;
207 int rc;
208
209 if (!ctx->active) {
210 return BLE_LL_SCHED_STATE_DONE;
211 }
212
213 rc = ble_phy_setchan(channel_rf_to_index[ctx->rf_channel],
214 BLE_DTM_SYNC_WORD, BLE_DTM_CRC);
215 if (rc != 0) {
216 BLE_LL_ASSERT(0);
217 return BLE_LL_SCHED_STATE_DONE;
218 }
219
220 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
221 ble_phy_mode_set(ctx->phy_mode, ctx->phy_mode);
222 #endif
223 ble_phy_set_txend_cb(ble_ll_dtm_tx_done, ctx);
224 ble_phy_txpwr_set(0);
225
226 sch->start_time += g_ble_ll_sched_offset_ticks;
227
228 rc = ble_phy_tx_set_start_time(sch->start_time, sch->remainder);
229 if (rc) {
230 goto resched;
231 }
232
233 rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, ctx->om, BLE_PHY_TRANSITION_NONE);
234 if (rc) {
235 goto resched;
236 }
237
238 ble_ll_state_set(BLE_LL_STATE_DTM);
239
240 return BLE_LL_SCHED_STATE_DONE;
241
242 resched:
243 /* Reschedule from LL task if late for this PDU */
244 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt);
245
246 STATS_INC(ble_ll_dtm_stats, tx_failed);
247
248 return BLE_LL_SCHED_STATE_DONE;
249 }
250
251 static void
ble_ll_dtm_calculate_itvl(struct dtm_ctx * ctx,uint8_t len,int phy_mode)252 ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len, int phy_mode)
253 {
254 uint32_t l;
255 uint32_t itvl_usec;
256 uint32_t itvl_ticks;
257
258 /* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */
259 l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode);
260 itvl_usec = ((l + 249 + 624) / 625) * 625;
261
262 itvl_ticks = os_cputime_usecs_to_ticks(itvl_usec);
263 ctx->itvl_rem_usec = (itvl_usec - os_cputime_ticks_to_usecs(itvl_ticks));
264 if (ctx->itvl_rem_usec == 31) {
265 ctx->itvl_rem_usec = 0;
266 ++itvl_ticks;
267 }
268 ctx->itvl_ticks = itvl_ticks;
269 }
270
271 static int
ble_ll_dtm_tx_create_ctx(uint8_t packet_payload,uint8_t len,uint8_t rf_channel,uint8_t phy_mode)272 ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len,
273 uint8_t rf_channel, uint8_t phy_mode)
274 {
275 int rc = 0;
276 uint8_t byte_pattern;
277 struct ble_mbuf_hdr *ble_hdr;
278 struct os_mbuf *m;
279 struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch;
280
281 /* MSYS is big enough to get continues memory */
282 m = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr));
283 g_ble_ll_dtm_ctx.om = m;
284 BLE_LL_ASSERT(g_ble_ll_dtm_ctx.om);
285
286 g_ble_ll_dtm_ctx.phy_mode = phy_mode;
287 g_ble_ll_dtm_ctx.rf_channel = rf_channel;
288
289 /* Set BLE transmit header */
290 ble_hdr = BLE_MBUF_HDR_PTR(m);
291 ble_hdr->txinfo.flags = 0;
292 ble_hdr->txinfo.offset = 0;
293 ble_hdr->txinfo.pyld_len = len;
294 ble_hdr->txinfo.hdr_byte = packet_payload;
295
296 switch(packet_payload) {
297 case 0x00:
298 if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs9_data, len)) {
299 return 1;
300 }
301 goto schedule;
302 case 0x01:
303 byte_pattern = 0x0F;
304 break;
305 case 0x02:
306 byte_pattern = 0x55;
307 break;
308 case 0x03:
309 if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs15_data, len)) {
310 return 1;
311 }
312 goto schedule;
313 case 0x04:
314 byte_pattern = 0xFF;
315 break;
316 case 0x05:
317 byte_pattern = 0x00;
318 break;
319 case 0x06:
320 byte_pattern = 0xF0;
321 break;
322 case 0x07:
323 byte_pattern = 0xAA;
324 break;
325 default:
326 return 1;
327 }
328
329 for (rc = 0; rc < len; rc++) {
330 if (os_mbuf_copyinto(m, rc, &byte_pattern, 1)) {
331 return 1;
332 }
333 }
334
335 schedule:
336
337 sch->sched_cb = ble_ll_dtm_tx_sched_cb;
338 sch->cb_arg = &g_ble_ll_dtm_ctx;
339 sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
340 sch->start_time = os_cputime_get32() +
341 os_cputime_usecs_to_ticks(5000);
342
343 /* Prepare os_event */
344 ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_tx_resched_cb,
345 &g_ble_ll_dtm_ctx);
346
347 ble_ll_dtm_calculate_itvl(&g_ble_ll_dtm_ctx, len, phy_mode);
348
349 /* Set some start point for TX packets */
350 rc = ble_ll_sched_dtm(sch);
351 BLE_LL_ASSERT(rc == 0);
352
353 ble_phy_enable_dtm();
354
355 g_ble_ll_dtm_ctx.active = 1;
356 return 0;
357 }
358
359 static int
ble_ll_dtm_rx_start(void)360 ble_ll_dtm_rx_start(void)
361 {
362 os_sr_t sr;
363 int rc;
364
365 rc = ble_phy_setchan(channel_rf_to_index[g_ble_ll_dtm_ctx.rf_channel],
366 BLE_DTM_SYNC_WORD, BLE_DTM_CRC);
367 if (rc) {
368 return rc;
369 }
370
371 #if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
372 ble_phy_mode_set(g_ble_ll_dtm_ctx.phy_mode, g_ble_ll_dtm_ctx.phy_mode);
373 #endif
374
375 OS_ENTER_CRITICAL(sr);
376 rc = ble_phy_rx_set_start_time(os_cputime_get32() +
377 g_ble_ll_sched_offset_ticks, 0);
378 OS_EXIT_CRITICAL(sr);
379 if (rc && rc != BLE_PHY_ERR_RX_LATE) {
380 return rc;
381 }
382
383 ble_ll_state_set(BLE_LL_STATE_DTM);
384
385 #ifdef BLE_XCVR_RFCLK
386 if (ble_ll_xcvr_rfclk_state() == BLE_RFCLK_STATE_OFF) {
387 ble_ll_xcvr_rfclk_start_now(os_cputime_get32());
388 }
389 #endif
390
391 return 0;
392 }
393
394 static int
ble_ll_dtm_rx_create_ctx(uint8_t rf_channel,uint8_t phy_mode)395 ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode)
396 {
397 g_ble_ll_dtm_ctx.phy_mode = phy_mode;
398 g_ble_ll_dtm_ctx.rf_channel = rf_channel;
399 g_ble_ll_dtm_ctx.active = 1;
400
401 STATS_CLEAR(ble_ll_dtm_stats, rx_count);
402
403 ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_rx_restart_cb,
404 NULL);
405
406 if (ble_ll_dtm_rx_start() != 0) {
407 return 1;
408 }
409
410 ble_phy_enable_dtm();
411
412 return 0;
413 }
414
415 static void
ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)416 ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)
417 {
418 os_sr_t sr;
419
420 OS_ENTER_CRITICAL(sr);
421 if (!ctx->active) {
422 OS_EXIT_CRITICAL(sr);
423 return;
424 }
425 OS_EXIT_CRITICAL(sr);
426
427 ble_ll_sched_rmv_elem(&ctx->sch);
428
429 ble_phy_disable();
430 ble_phy_disable_dtm();
431 ble_ll_state_set(BLE_LL_STATE_STANDBY);
432 #ifdef BLE_XCVR_RFCLK
433 ble_ll_xcvr_rfclk_stop();
434 #endif
435
436 os_mbuf_free_chain(ctx->om);
437 memset(ctx, 0, sizeof(*ctx));
438 }
439
440 int
ble_ll_dtm_tx_test(uint8_t * cmdbuf,bool enhanced)441 ble_ll_dtm_tx_test(uint8_t *cmdbuf, bool enhanced)
442 {
443 uint8_t tx_chan = cmdbuf[0];
444 uint8_t len = cmdbuf[1];
445 uint8_t packet_payload = cmdbuf[2];
446 uint8_t phy_mode = BLE_PHY_MODE_1M;
447
448 if (g_ble_ll_dtm_ctx.active) {
449 return BLE_ERR_CTLR_BUSY;
450 }
451
452 if (enhanced) {
453 switch (cmdbuf[3]) {
454 case BLE_HCI_LE_PHY_1M:
455 phy_mode = BLE_PHY_MODE_1M;
456 break;
457 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
458 case BLE_HCI_LE_PHY_2M:
459 phy_mode = BLE_PHY_MODE_2M;
460 break;
461 #endif
462 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
463 case BLE_HCI_LE_PHY_CODED_S8:
464 phy_mode = BLE_PHY_MODE_CODED_125KBPS;
465 break;
466 case BLE_HCI_LE_PHY_CODED_S2:
467 phy_mode = BLE_PHY_MODE_CODED_500KBPS;
468 break;
469 #endif
470 default:
471 return BLE_ERR_INV_HCI_CMD_PARMS;
472 }
473 }
474
475 if (tx_chan > 0x27 || packet_payload > 0x07) {
476 return BLE_ERR_INV_HCI_CMD_PARMS;
477 }
478
479 if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode)) {
480 return BLE_ERR_UNSPECIFIED;
481 }
482
483 return BLE_ERR_SUCCESS;
484 }
485
ble_ll_dtm_rx_test(uint8_t * cmdbuf,bool enhanced)486 int ble_ll_dtm_rx_test(uint8_t *cmdbuf, bool enhanced)
487 {
488 uint8_t rx_chan = cmdbuf[0];
489 uint8_t phy_mode = BLE_PHY_MODE_1M;
490
491 if (g_ble_ll_dtm_ctx.active) {
492 return BLE_ERR_CTLR_BUSY;
493 }
494
495 /*XXX What to do with modulation cmdbuf[2]? */
496
497 if (enhanced) {
498 switch (cmdbuf[1]) {
499 case BLE_HCI_LE_PHY_1M:
500 phy_mode = BLE_PHY_MODE_1M;
501 break;
502 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
503 case BLE_HCI_LE_PHY_2M:
504 phy_mode = BLE_PHY_MODE_2M;
505 break;
506 #endif
507 #if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
508 case BLE_HCI_LE_PHY_CODED:
509 phy_mode = BLE_PHY_MODE_CODED_500KBPS;
510 break;
511 #endif
512 default:
513 return BLE_ERR_INV_HCI_CMD_PARMS;
514 }
515 }
516
517 if (rx_chan > 0x27) {
518 return BLE_ERR_INV_HCI_CMD_PARMS;
519 }
520
521 if (ble_ll_dtm_rx_create_ctx(rx_chan, phy_mode)) {
522 return BLE_ERR_UNSPECIFIED;
523 }
524
525 return BLE_ERR_SUCCESS;
526 }
527
ble_ll_dtm_end_test(uint8_t * rsp,uint8_t * rsplen)528 int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen)
529 {
530 put_le16(rsp, g_ble_ll_dtm_ctx. num_of_packets);
531 *rsplen = 2;
532
533 ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
534 return BLE_ERR_SUCCESS;
535 }
536
ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr * rxhdr,uint32_t aa)537 int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa)
538 {
539 return 0;
540 }
541
542 void
ble_ll_dtm_rx_pkt_in(struct os_mbuf * rxpdu,struct ble_mbuf_hdr * hdr)543 ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
544 {
545 if (BLE_MBUF_HDR_CRC_OK(hdr)) {
546 /* XXX Compare data. */
547 g_ble_ll_dtm_ctx.num_of_packets++;
548 STATS_INC(ble_ll_dtm_stats, rx_count);
549 }
550
551 if (ble_ll_dtm_rx_start() != 0) {
552 ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
553 STATS_INC(ble_ll_dtm_stats, rx_failed);
554 }
555 }
556
557 int
ble_ll_dtm_rx_isr_end(uint8_t * rxbuf,struct ble_mbuf_hdr * rxhdr)558 ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
559 {
560 struct os_mbuf *rxpdu;
561
562 if (!g_ble_ll_dtm_ctx.active) {
563 return -1;
564 }
565
566 rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN);
567
568 /* Copy the received pdu and hand it up */
569 if (rxpdu) {
570 ble_phy_rxpdu_copy(rxbuf, rxpdu);
571 ble_ll_rx_pdu_in(rxpdu);
572 }
573
574 return 0;
575 }
576
577 void
ble_ll_dtm_wfr_timer_exp(void)578 ble_ll_dtm_wfr_timer_exp(void)
579 {
580 /* Should not be needed */
581 BLE_LL_ASSERT(0);
582 }
583
584
585 void
ble_ll_dtm_reset(void)586 ble_ll_dtm_reset(void)
587 {
588 ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
589 }
590
591 void
ble_ll_dtm_init(void)592 ble_ll_dtm_init(void)
593 {
594 int rc;
595
596 rc = stats_init_and_reg(STATS_HDR(ble_ll_dtm_stats),
597 STATS_SIZE_INIT_PARMS(ble_ll_dtm_stats, STATS_SIZE_32),
598 STATS_NAME_INIT_PARMS(ble_ll_dtm_stats),
599 "ble_ll_dtm");
600 SYSINIT_PANIC_ASSERT(rc == 0);
601 }
602 #endif
603