Statistics
| Branch: | Tag: | Revision:

amiro-os / unittests / periphery-lld / src / ut_alld_bq27500.c @ f3ac1c96

History | View | Annotate | Download (25.9 KB)

1 e545e620 Thomas Schöpping
/*
2
AMiRo-OS is an operating system designed for the Autonomous Mini Robot (AMiRo) platform.
3 84f0ce9e Thomas Schöpping
Copyright (C) 2016..2019  Thomas Schöpping et al.
4 e545e620 Thomas Schöpping

5
This program is free software: you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation, either version 3 of the License, or
8
(at your option) any later version.
9

10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14

15
You should have received a copy of the GNU General Public License
16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include <ut_alld_bq27500.h>
20
21
#if ((AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_BQ27500)) || defined(__DOXYGEN__)
22
23
#include <string.h>
24 f3ac1c96 Thomas Schöpping
25
/******************************************************************************/
26
/* LOCAL DEFINITIONS                                                          */
27
/******************************************************************************/
28 e545e620 Thomas Schöpping
#include <aos_debug.h>
29
#include <chprintf.h>
30
#include <aos_thread.h>
31
#include <alld_bq27500.h>
32
33 57a5ea60 Marc Rothmann
// change saved unseal keys to test bruteforcing
34
#ifdef BQ27500_UT_TEST_BRUTEFORCE
35
36
#ifdef BQ27500_LLD_DEFAULT_UNSEAL_KEY0
37
#undef BQ27500_LLD_DEFAULT_UNSEAL_KEY0
38
#define BQ27500_LLD_DEFAULT_UNSEAL_KEY0 0x1234
39
#endif
40
41
#ifdef BQ27500_LLD_DEFAULT_UNSEAL_KEY1
42
#undef BQ27500_LLD_DEFAULT_UNSEAL_KEY1
43
#define BQ27500_LLD_DEFAULT_UNSEAL_KEY1 0x5678
44
#endif
45
46
#endif
47
48 f3ac1c96 Thomas Schöpping
/******************************************************************************/
49
/* EXPORTED VARIABLES                                                         */
50
/******************************************************************************/
51
52
/******************************************************************************/
53
/* LOCAL TYPES                                                                */
54
/******************************************************************************/
55
56
/******************************************************************************/
57
/* LOCAL VARIABLES                                                            */
58
/******************************************************************************/
59
60
/******************************************************************************/
61
/* LOCAL FUNCTIONS                                                            */
62
/******************************************************************************/
63
64 57a5ea60 Marc Rothmann
bq27500_lld_control_status_t _try_unseal(BQ27500Driver* driver, uint16_t key0, uint16_t key1, apalTime_t timeout) {
65
  uint16_t dst;
66
  bq27500_lld_control_status_t ctrl;
67
  bq27500_lld_send_ctnl_data(driver, key1, timeout);
68
  aosThdUSleep(1);
69
  bq27500_lld_send_ctnl_data(driver, key0, timeout);
70
  aosThdUSleep(1);
71
  bq27500_lld_sub_command_call(driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, timeout);
72
  aosThdUSleep(1);
73
  bq27500_lld_std_command(driver, BQ27500_LLD_STD_CMD_Control, &dst, timeout);
74
  bq27500_lld_sub_command_read(driver, &ctrl.value, timeout);
75
  return ctrl;
76
}
77
78
uint8_t _bruteforce_sealed_key_bitflips(BaseSequentialStream* stream, BQ27500Driver* driver, uint16_t key0, uint16_t key1, apalTime_t timeout) {
79
  bq27500_lld_control_status_t ctrl;
80
  uint16_t k0;
81
  uint16_t k1 = key1;
82
  for (uint8_t i = 0; i < 16; i++) {
83
    k0 = key0 ^ (1 << i); // flip bit i
84
    ctrl = _try_unseal(driver, k0, k1, timeout);
85
    if (ctrl.content.ss == 0x0) {
86
      chprintf(stream, "\t\tSUCCESS!\n");
87
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
88
      return 1;
89
    }
90
  }
91
  k0 = key0;
92
  for (uint8_t i = 0; i < 16; i++) {
93
    k1 = key1 ^ (1 << i); // flip bit i
94
    ctrl = _try_unseal(driver, k0, k1, timeout);
95
    if (ctrl.content.ss == 0x0) {
96
      chprintf(stream, "\t\tSUCCESS!\n");
97
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
98
      return 1;
99
    }
100
  }
101
  return 0;
102
}
103
104
void _bruteforce_sealed_key(BaseSequentialStream* stream, BQ27500Driver* driver, apalTime_t timeout) {
105
  chprintf(stream, "start bruteforcing sealed keys...\n");
106
  bq27500_lld_control_status_t ctrl;
107
  uint16_t key0_reversed = 0x7236;
108
  uint16_t key1_reversed = 0x1404;
109
  uint16_t key0 = BQ27500_LLD_DEFAULT_UNSEAL_KEY0;
110
  uint16_t key1 = BQ27500_LLD_DEFAULT_UNSEAL_KEY1;
111
  uint16_t k0 = key0;
112
  uint16_t k1 = key1;
113
114
  // testing default keys in different orders
115
  chprintf(stream, "\ttry reversed byte order and different key order...\n");
116
  // default unseal keys
117
  ctrl = _try_unseal(driver, k0, k1, timeout);
118
  if (ctrl.content.ss == 0x0) {
119
    chprintf(stream, "\t\tSUCCESS!\n");
120
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
121
    return;
122
  }
123
  // default unseal keys in reversed order
124
  ctrl = _try_unseal(driver, k1, k0, timeout);
125
  if (ctrl.content.ss == 0x0) {
126
    chprintf(stream, "\t\tSUCCESS!\n");
127
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
128
    return;
129
  }
130
  // byte reversed keys
131
  k0 = key0_reversed;
132
  k1 = key1_reversed;
133
  ctrl = _try_unseal(driver, k0, k1, timeout);
134
  if (ctrl.content.ss == 0x0) {
135
    chprintf(stream, "\t\tSUCCESS!\n");
136
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
137
    return;
138
  }
139
  // byte reversed keys in reversed order
140
  ctrl = _try_unseal(driver, k1, k0, timeout);
141
  if (ctrl.content.ss == 0x0) {
142
    chprintf(stream, "\t\tSUCCESS!\n");
143
    chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", k0, k1);
144
    return;
145
  }
146
  chprintf(stream, "\t\tfailed\n");
147
148
149
  // testing single bit flips of the default keys in different orders
150
  chprintf(stream, "\ttry single bit flips of default keys...\n");
151
  // default unseal keys
152
  uint8_t result = 0;
153
  result = _bruteforce_sealed_key_bitflips(stream, driver, key0, key1, timeout);
154
  if (result == 1) {
155
    return;
156
  }
157
  // default unseal keys in reversed order
158
  result = _bruteforce_sealed_key_bitflips(stream, driver, key1, key0, timeout);
159
  if (result == 1) {
160
    return;
161
  }
162
  // byte reversed keys
163
  result = _bruteforce_sealed_key_bitflips(stream, driver, key0_reversed, key1_reversed, timeout);
164
  if (result == 1) {
165
    return;
166
  }
167
  // byte reversed keys in reversed order
168
  result = _bruteforce_sealed_key_bitflips(stream, driver, key1_reversed, key0_reversed, timeout);
169
  if (result == 1) {
170
    return;
171
  }
172
  chprintf(stream, "\t\tfailed\n");
173
174
175
  // bruteforcing one of the keys, assuming only one of them was changed
176
  chprintf(stream, "\ttry bruteforcing a single key...\n");
177
  // default unseal key0
178
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
179
    ctrl = _try_unseal(driver, key0, i, timeout);
180
    if (ctrl.content.ss == 0x0) {
181
      chprintf(stream, "\t\tSUCCESS!\n");
182
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key0, i);
183
      return;
184
    }
185
  }
186
  chprintf(stream, "\t\tkey failed. 1/8\n");
187
  // reversed unseal key0
188
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
189
    ctrl = _try_unseal(driver, key0_reversed, i, timeout);
190
    if (ctrl.content.ss == 0x0) {
191
      chprintf(stream, "\t\tSUCCESS!\n");
192
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key0_reversed, i);
193
      return;
194
    }
195
  }
196
  chprintf(stream, "\t\tkey failed. 2/8\n");
197
  // default unseal key0 in reversed order
198
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
199
    ctrl = _try_unseal(driver, i, key0, timeout);
200
    if (ctrl.content.ss == 0x0) {
201
      chprintf(stream, "\t\tSUCCESS!\n");
202
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key0);
203
      return;
204
    }
205
  }
206
  chprintf(stream, "\t\tkey failed. 3/8\n");
207
  // reversed unseal key0 in reversed order
208
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
209
    ctrl = _try_unseal(driver, i, key0_reversed, timeout);
210
    if (ctrl.content.ss == 0x0) {
211
      chprintf(stream, "\t\tSUCCESS!\n");
212
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key0_reversed);
213
      return;
214
    }
215
  }
216
  chprintf(stream, "\t\tkey failed. 4/8\n");
217
  // default unseal key1
218
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
219
    ctrl = _try_unseal(driver, i, key1, timeout);
220
    if (ctrl.content.ss == 0x0) {
221
      chprintf(stream, "\t\tSUCCESS!\n");
222
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key1);
223
      return;
224
    }
225
  }
226
  chprintf(stream, "\t\tkey failed. 5/8\n");
227
  // reversed unseal key1
228
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
229
    ctrl = _try_unseal(driver, i, key1_reversed, timeout);
230
    if (ctrl.content.ss == 0x0) {
231
      chprintf(stream, "\t\tSUCCESS!\n");
232
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, key1_reversed);
233
      return;
234
    }
235
  }
236
  chprintf(stream, "\t\tkey failed. 6/8\n");
237
  // default unseal key1 in reversed order
238
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
239
    ctrl = _try_unseal(driver, key1, i, timeout);
240
    if (ctrl.content.ss == 0x0) {
241
      chprintf(stream, "\t\tSUCCESS!\n");
242
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key1, i);
243
      return;
244
    }
245
  }
246
  chprintf(stream, "\t\tkey failed. 7/8\n");
247
  // reversed unseal key1 in reversed order
248
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
249
    ctrl = _try_unseal(driver, key1_reversed, i, timeout);
250
    if (ctrl.content.ss == 0x0) {
251
      chprintf(stream, "\t\tSUCCESS!\n");
252
      chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", key1_reversed, i);
253
      return;
254
    }
255
  }
256
  chprintf(stream, "\t\tkey failed. 8/8\n");
257
  chprintf(stream, "\t\tfailed\n");
258
259
260
  // full bruteforce
261
  chprintf(stream, "\tbruteforcing both keys...\t");
262
  for (uint32_t i = 0; i <= 0xFFFF; i++) {
263
    chprintf(stream, "\t\ti: %u\n", i);
264
    for (uint32_t j = 0; j <= 0xFFFF; j++) {
265
      ctrl = _try_unseal(driver, i, j, timeout);
266
      if (ctrl.content.ss == 0x0) {
267
        chprintf(stream, "\t\tSUCCESS!\n");
268
        chprintf(stream, "\t\tkey0: 0x%X, key1: 0x%X\n", i, j);
269
        return;
270
      }
271
    }
272
  }
273
274
  chprintf(stream, "\t\tfailed, no keys could be found");
275
}
276
277 f3ac1c96 Thomas Schöpping
/******************************************************************************/
278
/* EXPORTED FUNCTIONS                                                         */
279
/******************************************************************************/
280
281 e545e620 Thomas Schöpping
aos_utresult_t utAlldBq27500Func(BaseSequentialStream* stream, aos_unittest_t* ut)
282
{
283
  aosDbgCheck(ut->data != NULL && ((ut_bq27500data_t*)(ut->data))->driver != NULL);
284
285
  // local variables
286
  aos_utresult_t result = {0, 0};
287
  uint32_t status;
288
  bq27500_lld_batlow_t bl;
289
  bq27500_lld_batgood_t bg;
290
  uint16_t dst;
291
  bq27500_lld_flags_t flags;
292
  uint16_t subdata = 0;
293
  uint8_t original_length;
294
  char original_name[8+1];
295
  uint8_t val = 0x00;
296
  uint8_t block[32];
297
  char new_name[] = "test";
298
  uint8_t new_lenght;
299
  char name[8+1] = {'\0'};
300
  uint8_t sum = 0;
301
  bool success;
302
  bool success2;
303
304
  chprintf(stream, "read battery low gpio...\n");
305
  status = bq27500_lld_read_batlow(((ut_bq27500data_t*)ut->data)->driver, &bl);
306
  chprintf(stream, "\t\tbattery low: 0x%X\n", bl);
307
  if (status == APAL_STATUS_SUCCESS) {
308
    aosUtPassed(stream, &result);
309
  } else {
310
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
311
  }
312
313
  chprintf(stream, "read battery good gpio...\n");
314
  status = bq27500_lld_read_batgood(((ut_bq27500data_t*)ut->data)->driver, &bg);
315
  chprintf(stream, "\t\tbattery good: 0x%X\n", bg);
316
  if (status == APAL_STATUS_SUCCESS) {
317
    aosUtPassed(stream, &result);
318
  } else {
319
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
320
  }
321
322
  chprintf(stream, "std command FLAGS...\n");
323
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Flags, &flags.value, ((ut_bq27500data_t*)ut->data)->timeout);
324
  chprintf(stream, "\t\tflags: 0x%04X\n", flags.value);
325
  chprintf(stream, "\t\tbattery detected: 0x%X\n", flags.content.bat_det);
326
  chprintf(stream, "\t\tbattery fully charged: 0x%X\n", flags.content.fc);
327
  if (status == APAL_STATUS_SUCCESS) {
328
    aosUtPassed(stream, &result);
329
  } else {
330
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
331
  }
332
333
  chprintf(stream, "std command CTNL...\n");
334
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
335
  if (status == APAL_STATUS_SUCCESS) {
336
    aosUtPassed(stream, &result);
337
  } else {
338
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
339
  }
340
341
  chprintf(stream, "sub command: CTRL Status...\n");
342 57a5ea60 Marc Rothmann
  aosThdUSleep(1);
343 e545e620 Thomas Schöpping
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
344 57a5ea60 Marc Rothmann
  aosThdUSleep(1);
345 e545e620 Thomas Schöpping
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
346 57a5ea60 Marc Rothmann
  aosThdUSleep(1);
347 e545e620 Thomas Schöpping
  bq27500_lld_control_status_t ctrl;
348
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
349
  chprintf(stream, "\t\tdst: 0x%X\n", ctrl.value);
350
  chprintf(stream, "\t\tsleep: 0x%X\n", ctrl.content.sleep);
351
  chprintf(stream, "\t\thibernate: 0x%X\n", ctrl.content.hibernate);
352
  if (status == APAL_STATUS_SUCCESS) {
353
    aosUtPassed(stream, &result);
354
  } else {
355
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
356
  }
357
358
  chprintf(stream, "sub command: firmware version...\n");
359
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_FW_VERSION, ((ut_bq27500data_t*)ut->data)->timeout);
360
  aosThdMSleep(1);
361
  bq27500_lld_version_t version;
362
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &version.value, ((ut_bq27500data_t*)ut->data)->timeout);
363
  chprintf(stream, "\t\tfirmware version: %X%X-%X%X\n", version.content.major_high, version.content.major_low, version.content.minor_high, version.content.minor_low);
364
  if (status == APAL_STATUS_SUCCESS) {
365
    aosUtPassed(stream, &result);
366
  } else {
367
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
368
  }
369
370
  chprintf(stream, "sub command: hardware version...\n");
371
  status = bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_HW_VERSION, ((ut_bq27500data_t*)ut->data)->timeout);
372
  aosThdMSleep(1);
373
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &version.value, ((ut_bq27500data_t*)ut->data)->timeout);
374
  chprintf(stream, "\t\thardware version: %X%X-%X%X\n", version.content.major_high, version.content.major_low, version.content.minor_high, version.content.minor_low);
375
  if (status == APAL_STATUS_SUCCESS) {
376
    aosUtPassed(stream, &result);
377
  } else {
378
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
379
  }
380
381
  chprintf(stream, "ext command: device name length...\n");
382
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceNameLength, BQ27500_LLD_EXT_CMD_READ, &original_length, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
383
  chprintf(stream, "\t\tdevice name length: %d \n", original_length);
384
  if (status == APAL_STATUS_SUCCESS && original_length <= 8) {
385
    aosUtPassed(stream, &result);
386
  } else {
387
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
388
    original_length = 8;
389
  }
390
391
  chprintf(stream, "ext command: device name (read)...\n");
392
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceName, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)original_name, original_length, 0, ((ut_bq27500data_t*)ut->data)->timeout);
393
  original_name[original_length] = '\0';
394
  chprintf(stream, "\t\tdevice name: %s\n", original_name);
395
  if (status == APAL_STATUS_SUCCESS) {
396
    aosUtPassed(stream, &result);
397
  } else {
398
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
399
  }
400
401
  chprintf(stream, "battery info std commands...\n");
402
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Temperatur, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
403
  chprintf(stream, "\t\ttemperature: %fK (%fC) \n", (float)dst/10.0f, (float)dst/10.0f-273.5f);
404
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_FullAvailableCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
405
  chprintf(stream, "\t\tfull available capacity: %umAh \n", dst);
406
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_FullChargeCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
407
  chprintf(stream, "\t\tfull charge capacity: %umAh \n", dst);
408
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_RemainingCapacity, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
409
  chprintf(stream, "\t\tremaining capacity: %umAh \n", dst);
410
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Voltage, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
411
  chprintf(stream, "\t\tvoltage: %umV \n", dst);
412
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_AverageCurrent, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
413
  chprintf(stream, "\t\taverage current: %dmA \n", (int8_t)dst);
414
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_AveragePower, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
415
  chprintf(stream, "\t\taverage power: %dmW \n", (int8_t)dst);
416
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_TimeToFull, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
417
  if (dst != (uint16_t)~0) {
418
    chprintf(stream, "\t\ttime to full: %umin \n", dst);
419
  } else {
420
    chprintf(stream, "\t\ttime to full: (not charging) \n", dst);
421
  }
422
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_TimeToEmpty, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
423
  if (dst != (uint16_t)~0) {
424
    chprintf(stream, "\t\ttime to empty: %umin \n", dst);
425
  } else {
426
    chprintf(stream, "\t\ttime to empty: (not discharging) \n", dst);
427
  }
428
  if (status == APAL_STATUS_SUCCESS) {
429
    aosUtPassed(stream, &result);
430
  } else {
431
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
432
  }
433
434
  chprintf(stream, "check sealed state...\n");
435
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
436
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
437
  aosThdMSleep(1);
438
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
439
  chprintf(stream, "\t\tsealed: 0x%X\n", ctrl.content.ss);
440
  chprintf(stream, "\t\tfull access sealed: 0x%X\n", ctrl.content.fas);
441
  if (status == APAL_STATUS_SUCCESS) {
442
    aosUtPassed(stream, &result);
443
  } else {
444
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
445
  }
446
447
  chprintf(stream, "unseale...\n");
448
  status = bq27500_lld_send_ctnl_data(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_DEFAULT_UNSEAL_KEY1, ((ut_bq27500data_t*)ut->data)->timeout);
449 57a5ea60 Marc Rothmann
  aosThdMSleep(1);
450 e545e620 Thomas Schöpping
  status |= bq27500_lld_send_ctnl_data(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_DEFAULT_UNSEAL_KEY0, ((ut_bq27500data_t*)ut->data)->timeout);
451 57a5ea60 Marc Rothmann
  aosThdMSleep(1);
452 e545e620 Thomas Schöpping
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
453 57a5ea60 Marc Rothmann
  aosThdMSleep(1);
454 e545e620 Thomas Schöpping
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
455
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
456
  if (status == APAL_STATUS_SUCCESS && ctrl.content.ss == 0x0) {
457
    aosUtPassed(stream, &result);
458
  } else {
459
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
460 57a5ea60 Marc Rothmann
    _bruteforce_sealed_key(stream, ((ut_bq27500data_t*)ut->data)->driver, ((ut_bq27500data_t*)ut->data)->timeout);
461 e545e620 Thomas Schöpping
  }
462
463
  chprintf(stream, "read device name from data flash...\n");
464
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataControl, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
465
  aosThdMSleep(50);
466
  val = 0x30;
467
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashClass, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
468
  aosThdMSleep(50);
469
  val = 0;
470
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashBlock, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
471
  aosThdMSleep(50);
472
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)block, original_length, 13, ((ut_bq27500data_t*)ut->data)->timeout);
473
  block[original_length] = '\0';
474
  chprintf(stream, "\t\tdevice name: %s\n", block);
475
  if (status == APAL_STATUS_SUCCESS && (strcmp((char*)block, (char*)original_name) == 0)) {
476
    aosUtPassed(stream, &result);
477
  } else {
478
    chprintf(stream, "\t\tread data: ");
479
    for (uint8_t blockIdx = 0; blockIdx < original_length; blockIdx++) {
480
      chprintf(stream, "0x%02X\n", block[blockIdx]);
481
    }
482
    aosUtFailedMsg(stream, &result, "0x%08X\n", status);
483
  }
484
485
  chprintf(stream, "change device name in data flash to \"test\"...\n");
486
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_WRITE, (uint8_t*)new_name, 5, 13, ((ut_bq27500data_t*)ut->data)->timeout);
487
  aosThdMSleep(50);
488
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)block, 32, 0, ((ut_bq27500data_t*)ut->data)->timeout);
489
  // compute blockdata checksum
490
  status |= bq27500_lld_compute_blockdata_checksum(block, &sum);
491
  // write checksum to BlockDataChecksum, triggering the write of BlackData
492
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataCheckSum, BQ27500_LLD_EXT_CMD_WRITE, &sum, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
493
  aosThdMSleep(50);
494
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceNameLength, BQ27500_LLD_EXT_CMD_READ, &new_lenght, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
495
  aosThdMSleep(50);
496
  // read out device name, to see if changing it was successfull
497
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceName, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)name, new_lenght, 0, ((ut_bq27500data_t*)ut->data)->timeout);
498
  name[new_lenght] = '\0';
499
  chprintf(stream, "\t\tdevice name: %s\n", name);
500
  success = (strcmp(name, new_name) == 0);
501
502
  // change device name back to original name
503
  val = 0x00;
504
  status = bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataControl, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
505
  aosThdMSleep(50);
506
  val = 0x30;
507
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashClass, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
508
  aosThdMSleep(50);
509
  val = 0;
510
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DataFlashBlock, BQ27500_LLD_EXT_CMD_WRITE, &val, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
511
  aosThdMSleep(50);
512
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_WRITE, (uint8_t*)original_name, 7, 13, ((ut_bq27500data_t*)ut->data)->timeout);
513
  aosThdMSleep(50);
514
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockData, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)block, 32, 0, ((ut_bq27500data_t*)ut->data)->timeout);
515
  // compute blockdata checksum
516
  sum = 0;
517
  status |= bq27500_lld_compute_blockdata_checksum(block, &sum);
518
  // write checksum to BlockDataChecksum, triggering the write of BlackData
519
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_BlockDataCheckSum, BQ27500_LLD_EXT_CMD_WRITE, &sum, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
520
  aosThdMSleep(1000);
521
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceNameLength, BQ27500_LLD_EXT_CMD_READ, &original_length, 1, 0, ((ut_bq27500data_t*)ut->data)->timeout);
522
  aosThdMSleep(50);
523
  // read device name, to see if changing it back to the original name was successfull
524
  status |= bq27500_lld_ext_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_EXT_CMD_DeviceName, BQ27500_LLD_EXT_CMD_READ, (uint8_t*)name, original_length, 0, ((ut_bq27500data_t*)ut->data)->timeout);
525
  success2 = (strcmp(name, original_name) == 0);
526
  name[original_length] = '\0';
527
  chprintf(stream, "\t\tchanged back to name: %s, original_name: %s\n", name, original_name);
528
  if (status == APAL_STATUS_OK && ((success && success2) || (ctrl.content.sleep == 0))) {
529
    aosUtPassed(stream, &result);
530
  } else {
531
    aosUtFailedMsg(stream, &result, "0x%08X, changing: 0x%X - changing back: 0x%X\n", status, success, success2);
532
  }
533
534
  chprintf(stream, "seal...\n");
535
  status = bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
536
  aosThdMSleep(50);
537
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_SEALED, ((ut_bq27500data_t*)ut->data)->timeout);
538
  aosThdMSleep(50);
539
  status |= bq27500_lld_std_command(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_STD_CMD_Control, &dst, ((ut_bq27500data_t*)ut->data)->timeout);
540
  aosThdMSleep(50);
541
  status |= bq27500_lld_sub_command_call(((ut_bq27500data_t*)ut->data)->driver, BQ27500_LLD_SUB_CMD_CONTROL_STATUS, ((ut_bq27500data_t*)ut->data)->timeout);
542
  aosThdMSleep(50);
543
  status |= bq27500_lld_sub_command_read(((ut_bq27500data_t*)ut->data)->driver, &ctrl.value, ((ut_bq27500data_t*)ut->data)->timeout);
544
  if (status == APAL_STATUS_SUCCESS && ctrl.content.ss == 0x1) {
545
    aosUtPassed(stream, &result);
546
  } else {
547
    chprintf(stream, "\tfailed (0x%X)\n", status);
548
    aosUtFailedMsg(stream, &result, "0x%08X, ctrl 0x%X\n", status, subdata);
549
    ++result.failed;
550
  }
551
552
  aosUtInfoMsg(stream,"driver object memory footprint: %u bytes\n", sizeof(BQ27500Driver));
553
554
  return result;
555
}
556
557
#endif /* (AMIROOS_CFG_TESTS_ENABLE == true) && defined(AMIROLLD_CFG_USE_BQ27500) */