1 /*
2 * Copyright (C) 2019-2020 Alibaba Group Holding Limited
3 */
4
5
6 //#include <aos/osal_debug.h>
7 #include <aos/kernel.h>
8 #include <aos/ble.h>
9 #include <aos/gatt.h>
10 //#include <yoc/partition.h>
11
12 #include <yoc/ota_server.h>
13
14 #define OTA_PACKET_SIZE (8192)
15
16 #define OTA_PACKET_START (0xFF)
17 #define OTA_PACKET_END (0xFE)
18
19 #ifndef MIN
20 # define MIN(a,b) ((a) < (b) ? (a) : (b))
21 #endif
22
23 enum ota_cmd {
24 OTA_CMD_START = 0x01,
25 OTA_CMD_STOP = 0x02,
26 OTA_CMD_REQUEST = 0x03,
27 OTA_CMD_COMPLETE = 0x04,
28 };
29
30 typedef struct _ota_start_t {
31 uint32_t cmd: 8;
32 uint32_t firmware_size: 24;
33 uint16_t packet_size;
34 uint8_t timeout;
35 } ota_start_t;
36
37 struct ota_rx_t {
38 uint8_t rx_buf[OTA_PACKET_SIZE];
39 uint16_t rx_len;
40 uint16_t expect_len;
41 uint16_t packet_id;
42 uint16_t packet_crc;
43 };
44
45 static struct ota_rx_t ota_rx = {0};
46
47 static struct ota_ctrl_t {
48 ota_state_en st;
49 uint32_t firmware_size;
50 uint16_t packet_size;
51 uint8_t timeout;
52 uint16_t expect_packet_count;
53 uint16_t recv_packet_count;
54 uint8_t retry_count;
55 aos_timer_t timer;
56 ota_event_callback_t cb;
57 } ota_ctrl;
58
59 #define TAG "OTA"
60
61 #define YOC_OTA_SERVICE_UUID \
62 UUID128_DECLARE(0x7e, 0x31, 0x35, 0xd4, 0x12, 0xf3, 0x11, 0xe9, 0xab, 0x14, 0xd6, 0x63, 0xbd, \
63 0x87, 0x3d, 0x93)
64
65 #define YOC_OTA_RX_UUID \
66 UUID128_DECLARE(0x7e, 0x31, 0x35, 0xd4, 0x12, 0xf3, 0x11, 0xe9, 0xab, 0x14, 0xd6, 0x63, 0xbd, \
67 0x87, 0x3d, 0x94)
68
69 #define YOC_OTA_TX_UUID \
70 UUID128_DECLARE(0x7e, 0x31, 0x35, 0xd4, 0x12, 0xf3, 0x11, 0xe9, 0xab, 0x14, 0xd6, 0x63, 0xbd, \
71 0x87, 0x3d, 0x95)
72
73 static int16_t g_yoc_ota_handle = -1;
74 static int16_t g_conn_hanlde = -1;
75 static int16_t g_tx_ccc_value = 0;
76
77 static char rx_char_des[] = "YoC OTA RX";
78 static char tx_char_des[] = "YoC OTA TX";
79
80 enum {
81 YOC_OTA_IDX_SVC,
82
83 YOC_OTA_IDX_RX_CHAR,
84 YOC_OTA_IDX_RX_VAL,
85 YOC_OTA_IDX_RX_DES,
86
87 YOC_OTA_IDX_TX_CHAR,
88 YOC_OTA_IDX_TX_VAL,
89 YOC_OTA_IDX_TX_CCC,
90 YOC_OTA_IDX_TX_DES,
91
92 YOC_OTA_IDX_MAX,
93 };
94
95 //static struct bt_gatt_ccc_cfg_t ccc_data[2] = {};
96 static gatt_service uart_service;
97
98 static gatt_attr_t uart_attrs[YOC_OTA_IDX_MAX] = {
99 [YOC_OTA_IDX_SVC] = GATT_PRIMARY_SERVICE_DEFINE(YOC_OTA_SERVICE_UUID),
100
101 [YOC_OTA_IDX_RX_CHAR] = GATT_CHAR_DEFINE(YOC_OTA_RX_UUID, GATT_CHRC_PROP_WRITE_WITHOUT_RESP),
102 [YOC_OTA_IDX_RX_VAL] =
103 GATT_CHAR_VAL_DEFINE(YOC_OTA_RX_UUID, GATT_PERM_READ | GATT_PERM_WRITE),
104 [YOC_OTA_IDX_RX_DES] = GATT_CHAR_CUD_DEFINE(rx_char_des, GATT_PERM_READ),
105
106 [YOC_OTA_IDX_TX_CHAR] =
107 GATT_CHAR_DEFINE(YOC_OTA_TX_UUID, GATT_CHRC_PROP_NOTIFY | GATT_CHRC_PROP_READ),
108 [YOC_OTA_IDX_TX_VAL] = GATT_CHAR_VAL_DEFINE(YOC_OTA_TX_UUID, GATT_PERM_READ),
109 [YOC_OTA_IDX_TX_CCC] = GATT_CHAR_CCC_DEFINE(),
110 [YOC_OTA_IDX_TX_DES] = GATT_CHAR_CUD_DEFINE(tx_char_des, GATT_PERM_READ),
111 };
112
113 static partition_t ota_partition_handle = -1;
114 static partition_info_t *ota_partition_info;
115
116 extern uint16_t crc16(uint16_t sedd, const volatile void *p_data, uint32_t size);
117
ota_status_change(int state)118 static void ota_status_change(int state)
119 {
120 ota_ctrl.st = state;
121
122 if (ota_ctrl.cb) {
123 ota_ctrl.cb(state);
124 }
125
126 LOGD(TAG, "%d->%d", ota_ctrl.st, state);
127 }
128
ota_reset()129 static void ota_reset()
130 {
131 ota_ctrl.st = 0;
132 ota_ctrl.firmware_size = 0;
133 ota_ctrl.packet_size = 0;
134 ota_ctrl.timeout = 0;
135 ota_ctrl.expect_packet_count = 0;
136 ota_ctrl.recv_packet_count = 0;
137 ota_ctrl.retry_count = 0;
138 aos_timer_stop(&ota_ctrl.timer);
139 memset(&ota_rx, 0, sizeof(ota_rx));
140 }
141
ota_reset_rx()142 static void ota_reset_rx()
143 {
144 memset(&ota_rx, 0, sizeof(ota_rx));
145 }
146
ota_partition_erase()147 static int ota_partition_erase()
148 {
149 if (partition_erase(ota_partition_handle, 0, (ota_partition_info->length + ota_partition_info->sector_size - 1) / ota_partition_info->sector_size) < 0) {
150 LOGE(TAG, "erase addr:%x\n");
151 return -1;
152 }
153
154 LOGD(TAG, "erase length %d block %d succeed", ota_partition_info->length, (ota_partition_info->length + ota_partition_info->sector_size - 1) / ota_partition_info->sector_size);
155
156 return 0;
157 }
158
ota_partition_write(uint8_t * buffer,int length,int offset)159 static int ota_partition_write(uint8_t *buffer, int length, int offset)
160 {
161 if (partition_write(ota_partition_handle, offset + (ota_partition_info->sector_size << 1), (void *)buffer, length) >= 0) {
162 LOGD(TAG, "write addr:%x length:%x\n", offset, length);
163
164 return length;
165 }
166
167 LOGE(TAG, "write addr fail:%x length:%x\n", offset, length);
168 return -1;
169 }
170
ota_partition_size()171 static inline uint32_t ota_partition_size()
172 {
173 return ota_partition_info->length - (ota_partition_info->sector_size << 1);
174 }
175
conn_change(ble_event_en event,void * event_data)176 static void conn_change(ble_event_en event, void *event_data)
177 {
178 evt_data_gap_conn_change_t *e = (evt_data_gap_conn_change_t *)event_data;
179
180 if (e->connected == CONNECTED) {
181 g_conn_hanlde = e->conn_handle;
182 } else {
183 g_conn_hanlde = -1;
184 ota_reset();
185 ota_partition_erase();
186 ota_status_change(OTA_ST_IDLE);
187 }
188 }
189
ota_recv_data(const uint8_t * data,uint16_t len)190 static inline int ota_recv_data(const uint8_t *data, uint16_t len)
191 {
192 if (!data || !len || !ota_rx.expect_len) {
193 return -1;
194 }
195
196 uint16_t cp_size = MIN(ota_rx.expect_len - ota_rx.rx_len, len);
197
198 memcpy(ota_rx.rx_buf + ota_rx.rx_len, data, cp_size);
199
200 ota_rx.rx_len += cp_size;
201
202 if (ota_rx.rx_len >= ota_rx.expect_len) {
203 aos_timer_stop(&ota_ctrl.timer);
204 }
205
206 /* the last data */
207 if (ota_rx.rx_len >= ota_rx.expect_len) {
208 uint16_t crc = crc16(0, ota_rx.rx_buf, ota_rx.rx_len);
209
210 if (crc == ota_rx.packet_crc) {
211 ota_status_change(OTA_ST_FLASH);
212 } else {
213 LOGE(TAG, "crc err %x %x", crc, ota_rx.packet_crc);
214 ota_status_change(OTA_ST_REQUEST);
215 }
216 }
217
218 if (ota_rx.rx_len > ota_rx.expect_len) {
219 LOGE(TAG, "ota packet err len %d,cp size %d, rx len %d expect len %d", len, cp_size , ota_ctrl.expect_packet_count, ota_rx.rx_len, ota_rx.expect_len);
220 ota_status_change(OTA_ST_REQUEST);
221 }
222
223 return 0;
224 }
225
event_char_write(ble_event_en event,void * event_data)226 void event_char_write(ble_event_en event, void *event_data)
227 {
228 evt_data_gatt_char_write_t *e = (evt_data_gatt_char_write_t *)event_data;
229 int16_t hande_offset = 0;
230
231 if (g_conn_hanlde != e->conn_handle) {
232 return;
233 }
234
235 if (e->char_handle > g_yoc_ota_handle && e->char_handle < g_yoc_ota_handle + YOC_OTA_IDX_MAX) {
236 hande_offset = e->char_handle - g_yoc_ota_handle;
237 } else {
238 return;
239 }
240
241 switch (hande_offset) {
242 case YOC_OTA_IDX_RX_VAL: {
243 switch (ota_ctrl.st) {
244 case OTA_ST_IDLE: {
245 /* ota start */
246 if (e->len == 9 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_CMD_START
247 && e->data[e->len - 1] == OTA_PACKET_END) {
248 uint32_t firmware_size = e->data[2] << 16 | e->data[3] << 8 | e->data[4];
249 uint16_t packet_size = e->data[5] << 8 | e->data[6];
250 uint8_t timeout = e->data[7];
251
252 if (firmware_size > ota_partition_size() || packet_size > OTA_PACKET_SIZE) {
253 LOGE(TAG, "unsupport ota param %d %d", firmware_size, packet_size);
254 return;
255 }
256
257 ota_ctrl.firmware_size = firmware_size;
258 ota_ctrl.packet_size = packet_size;
259 ota_ctrl.timeout = timeout;
260 /* ota data formate */
261 /* |head | packet id | crc16 | firmware | tail | */
262 /* |2Bytes| 2bytes |2bytes |firmware size| 2Bytes| */
263 ota_ctrl.expect_packet_count = (firmware_size + packet_size - 1) / packet_size;
264 LOGI(TAG, "ota start firmware size %d packet size %d timeout %d expect packet count %d",
265 firmware_size, packet_size, timeout, ota_ctrl.expect_packet_count);
266 ota_status_change(OTA_ST_START);
267 } else {
268 LOGE(TAG, "unkonw packet, drop %d", e->len);
269 }
270
271 break;
272 }
273
274 case OTA_ST_DL: {
275 /* ota stop */
276 if (e->len == 3 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_CMD_STOP
277 && e->data[2] == OTA_PACKET_END) {
278 LOGI(TAG, "ota stop");
279 ota_reset();
280 ota_status_change(OTA_ST_STOP);
281 }
282 /* ota complete */
283 else if (e->len == 3 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_CMD_COMPLETE
284 && e->data[2] == OTA_PACKET_END) {
285 LOGI(TAG, "ota complelte");
286 ota_status_change(OTA_ST_COMPLETE);
287 }
288 /* ota data */
289 else if (e->len > 6 && e->data[0] == OTA_PACKET_START && e->data[1] == OTA_PACKET_END && ota_rx.expect_len == 0) {
290 uint16_t packet_id = e->data[2] << 8 | e->data[3];
291 uint16_t packet_crc = e->data[4] << 8 | e->data[5];
292
293 if (packet_id >= ota_ctrl.expect_packet_count) {
294 LOGE(TAG, "packet id overflow, drop %d\n", packet_id);
295 return;
296 }
297
298 if (packet_id == ota_ctrl.expect_packet_count - 1) {
299 ota_rx.expect_len = ota_ctrl.firmware_size % ota_ctrl.packet_size;
300 } else {
301 ota_rx.expect_len = ota_ctrl.packet_size;
302 }
303
304 ota_rx.packet_id = packet_id;
305 ota_rx.packet_crc = packet_crc;
306 ota_recv_data(e->data + 6, e->len - 6);
307 } else if (ota_rx.expect_len) {
308 ota_recv_data(e->data, e->len);
309 }
310
311 break;
312 }
313
314 default:
315 LOGE(TAG, "invaild st %d\n", ota_ctrl.st);
316 break;
317 }
318 }
319 break;
320 }
321
322 e->len = 0;
323 return;
324 }
325
event_char_read(ble_event_en event,void * event_data)326 void event_char_read(ble_event_en event, void *event_data)
327 {
328 evt_data_gatt_char_read_t *e = (evt_data_gatt_char_read_t *)event_data;
329 int16_t hande_offset = 0;
330
331 if (g_conn_hanlde == e->conn_handle) {
332 if (e->char_handle > g_yoc_ota_handle) {
333 hande_offset = e->char_handle - g_yoc_ota_handle;
334 } else {
335 return;
336 }
337
338 switch (hande_offset) {
339 case YOC_OTA_IDX_RX_VAL:
340 memcpy(e->data, ota_rx.rx_buf, MIN(e->len, sizeof(ota_rx.rx_buf)));
341 e->len = MIN(e->len, sizeof(ota_rx.rx_buf));
342 return;
343
344 case YOC_OTA_IDX_RX_DES:
345 memcpy(e->data, rx_char_des, MIN(e->len, strlen(rx_char_des)));
346 e->len = MIN(e->len, strlen(rx_char_des));
347 return;
348
349 case YOC_OTA_IDX_TX_DES:
350 memcpy(e->data, tx_char_des, MIN(e->len, strlen(tx_char_des)));
351 e->len = MIN(e->len, strlen(tx_char_des));
352 return;
353 }
354 }
355
356 e->len = 0;
357 return;
358 }
359
event_char_ccc_change(ble_event_en event,void * event_data)360 void event_char_ccc_change(ble_event_en event, void *event_data)
361 {
362 evt_data_gatt_char_ccc_change_t *e = (evt_data_gatt_char_ccc_change_t *)event_data;
363
364 if (e->char_handle != g_yoc_ota_handle + YOC_OTA_IDX_TX_CCC) {
365 return;
366 }
367
368 g_tx_ccc_value = e->ccc_value;
369
370 LOGD(TAG, "ccc %d %d\n", e->char_handle, e->ccc_value);
371 }
372
mtu_exchange(ble_event_en event,void * event_data)373 static void mtu_exchange(ble_event_en event, void *event_data)
374 {
375 evt_data_gatt_mtu_exchange_t *e = (evt_data_gatt_mtu_exchange_t *)event_data;
376
377 if (e->err == 0) {
378 LOGD(TAG, "mtu get %d", ble_stack_gatt_mtu_get(e->conn_handle));
379 } else {
380 LOGE(TAG, "mtu exchange fail, %d", e->err);
381 }
382 }
383
event_callback(ble_event_en event,void * event_data)384 static int event_callback(ble_event_en event, void *event_data)
385 {
386 switch (event) {
387 case EVENT_GAP_CONN_CHANGE:
388 conn_change(event, event_data);
389 break;
390
391 case EVENT_GATT_CHAR_READ:
392 event_char_read(event, event_data);
393 break;
394
395 case EVENT_GATT_CHAR_WRITE:
396 event_char_write(event, event_data);
397 break;
398
399 case EVENT_GATT_CHAR_CCC_CHANGE:
400 event_char_ccc_change(event, event_data);
401 break;
402
403 case EVENT_GATT_MTU_EXCHANGE:
404 mtu_exchange(event, event_data);
405 break;
406
407 default:
408 break;
409 }
410
411 return 0;
412 }
413
414
415 static ble_event_cb_t ble_ota_cb = {
416 .callback = event_callback,
417 };
418
ota_request(uint32_t offset)419 static inline int ota_request(uint32_t offset)
420 {
421 LOGI(TAG, "request %d", offset);
422
423 ota_reset_rx();
424
425 aos_timer_change(&ota_ctrl.timer, ota_ctrl.timeout * 1000);
426 aos_timer_start(&ota_ctrl.timer);
427 static uint8_t send_buf[6] = {0xff, 0x03, 0x00, 0x00, 0x00, 0xfe};
428 send_buf[2] = offset >> 16 & 0xFF;
429 send_buf[3] = offset >> 8 & 0xFF;
430 send_buf[4] = offset >> 0 & 0xFF;
431 return ble_stack_gatt_notificate(g_conn_hanlde, g_yoc_ota_handle + YOC_OTA_IDX_TX_VAL, send_buf, sizeof(send_buf));
432 }
433
ble_ota_process()434 void ble_ota_process()
435 {
436 if (g_conn_hanlde == -1) {
437 return;
438 }
439
440 switch (ota_ctrl.st) {
441 case OTA_ST_START: {
442 /* ota start response */
443 if (g_tx_ccc_value != CCC_VALUE_NOTIFY) {
444 aos_msleep(10);
445 ota_status_change(OTA_ST_START);
446 } else {
447 conn_param_t param = {
448 0x06,
449 0x06,
450 0,
451 100,
452 };
453 ble_stack_connect_param_update(g_conn_hanlde, ¶m);
454
455 uint8_t send_buf[4] = {0xff, 0x01, 0x01, 0xfe};
456 ble_stack_gatt_notificate(g_conn_hanlde, g_yoc_ota_handle + YOC_OTA_IDX_TX_VAL, send_buf, sizeof(send_buf));
457 ota_status_change(OTA_ST_REQUEST);
458 }
459 }
460 break;
461
462 case OTA_ST_REQUEST: {
463 uint32_t offset;
464 offset = ota_ctrl.packet_size * ota_ctrl.recv_packet_count;
465 ota_ctrl.retry_count++;
466
467 if (ota_ctrl.retry_count > 10) {
468 LOGE(TAG, "out of max try count %d", ota_ctrl.retry_count);
469 ota_reset();
470 ota_status_change(OTA_ST_IDLE);
471 ble_stack_disconnect(g_conn_hanlde);
472 return;
473 }
474
475 ota_request(offset);
476
477 ota_status_change(OTA_ST_DL);
478
479 }
480 break;
481
482 case OTA_ST_FLASH: {
483 ota_ctrl.retry_count = 0;
484
485 ota_partition_write(ota_rx.rx_buf, ota_rx.rx_len, ota_ctrl.recv_packet_count * ota_ctrl.packet_size);
486
487 ota_ctrl.recv_packet_count++;
488
489 if (ota_ctrl.recv_packet_count < ota_ctrl.expect_packet_count) {
490 ota_status_change(OTA_ST_REQUEST);
491 } else {
492 LOGI(TAG, "all packet recv, %d", ota_ctrl.recv_packet_count);
493 ota_status_change(OTA_ST_COMPLETE);
494 }
495 }
496 break;
497
498 case OTA_ST_STOP: {
499 LOGI(TAG, "ota stop");
500 /* may disconnect */
501
502 ota_status_change(OTA_ST_IDLE);
503 }
504 break;
505
506 case OTA_ST_COMPLETE: {
507 LOGI(TAG, "ota reboot");
508 /* may disconnect */
509 /* ota start response */
510 uint8_t send_buf[4] = {0xff, 0x04, 0x00, 0xfe};
511 ble_stack_gatt_notificate(g_conn_hanlde, g_yoc_ota_handle + YOC_OTA_IDX_TX_VAL, send_buf, sizeof(send_buf));
512 extern void mdelay(uint32_t ms);
513 mdelay(100);
514
515 aos_reboot();
516 }
517 break;
518
519 default:
520 break;
521 }
522 }
523
ota_timeout(void * arg1,void * arg2)524 static void ota_timeout(void *arg1, void *arg2)
525 {
526 ota_reset_rx();
527 ota_status_change(OTA_ST_REQUEST);
528 LOGW(TAG, "timeout");
529 }
530
ble_ota_init(ota_event_callback_t cb)531 int ble_ota_init(ota_event_callback_t cb)
532 {
533 int ret;
534
535 init_param_t init = {
536 .dev_name = NULL,
537 .dev_addr = NULL,
538 .conn_num_max = 1,
539 };
540
541 ble_stack_init(&init);
542
543 ble_stack_event_register(&ble_ota_cb);
544
545 ret = ble_stack_gatt_registe_service(&uart_service, uart_attrs, BLE_ARRAY_NUM(uart_attrs));
546
547 if (ret < 0) {
548 return 0;
549 }
550
551 g_yoc_ota_handle = ret;
552
553 if (ota_partition_handle < 0) {
554 ota_partition_handle = partition_open("misc");
555
556 if (ota_partition_handle < 0) {
557 LOGD(TAG, "ota partition open fail %d", ret);
558 }
559
560 ota_partition_info = hal_flash_get_info(ota_partition_handle);
561 }
562
563 aos_timer_new_ext(&ota_ctrl.timer, ota_timeout, NULL, 1000, 0, 0);
564
565 ota_reset();
566
567 ota_partition_erase();
568
569 ota_ctrl.cb = cb;
570
571 return 0;
572 }
573
574