CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
orangepi-xunlong

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: orangepi-xunlong/orangepi-build
Path: blob/next/external/cache/sources/hcitools/hciattach_intel.c
Views: 3959
1
/*
2
*
3
* BlueZ - Bluetooth protocol stack for Linux
4
*
5
* Copyright (C) 2012 Intel Corporation. All rights reserved.
6
*
7
*
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
12
*
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
17
*
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
*
22
*/
23
24
#ifdef HAVE_CONFIG_H
25
#include <config.h>
26
#endif
27
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <unistd.h>
31
#include <string.h>
32
#include <errno.h>
33
#include <fcntl.h>
34
#include <sys/param.h>
35
#include <sys/ioctl.h>
36
#include <time.h>
37
38
#include <bluetooth/bluetooth.h>
39
#include <bluetooth/hci.h>
40
#include <bluetooth/hci_lib.h>
41
42
#include "hciattach.h"
43
44
#ifdef INTEL_DEBUG
45
#define DBGPRINT(fmt, args...) printf("DBG: " fmt "\n", ## args)
46
#define PRINT_PACKET(buf, len, msg) { \
47
int i; \
48
printf("%s\n", msg); \
49
for (i = 0; i < len; i++) \
50
printf("%02X ", buf[i]); \
51
printf("\n"); \
52
}
53
#else
54
#define DBGPRINT(fmt, args...)
55
#define PRINT_PACKET(buf, len, msg)
56
#endif
57
58
#define PATCH_SEQ_EXT ".bseq"
59
#define PATCH_FILE_PATH "/lib/firmware/intel/"
60
#define PATCH_MAX_LEN 260
61
#define PATCH_TYPE_CMD 1
62
#define PATCH_TYPE_EVT 2
63
64
#define INTEL_VER_PARAM_LEN 9
65
#define INTEL_MFG_PARAM_LEN 2
66
67
/**
68
* A data structure for a patch entry.
69
*/
70
struct patch_entry {
71
int type;
72
int len;
73
unsigned char data[PATCH_MAX_LEN];
74
};
75
76
/**
77
* A structure for patch context
78
*/
79
struct patch_ctx {
80
int dev;
81
int fd;
82
int patch_error;
83
int reset_enable_patch;
84
};
85
86
/**
87
* Send HCI command to the controller
88
*/
89
static int intel_write_cmd(int dev, unsigned char *buf, int len)
90
{
91
int ret;
92
93
PRINT_PACKET(buf, len, "<----- SEND CMD: ");
94
95
ret = write(dev, buf, len);
96
if (ret < 0)
97
return -errno;
98
99
if (ret != len)
100
return -1;
101
102
return ret;
103
}
104
105
/**
106
* Read the event from the controller
107
*/
108
static int intel_read_evt(int dev, unsigned char *buf, int len)
109
{
110
int ret;
111
112
ret = read_hci_event(dev, buf, len);
113
if (ret < 0)
114
return -1;
115
116
PRINT_PACKET(buf, ret, "-----> READ EVT: ");
117
118
return ret;
119
}
120
121
/**
122
* Validate HCI events
123
*/
124
static int validate_events(struct patch_entry *event,
125
struct patch_entry *entry)
126
{
127
if (event == NULL || entry == NULL) {
128
DBGPRINT("invalid patch entry parameters");
129
return -1;
130
}
131
132
if (event->len != entry->len) {
133
DBGPRINT("lengths are mismatched:[%d|%d]",
134
event->len, entry->len);
135
return -1;
136
}
137
138
if (memcmp(event->data, entry->data, event->len)) {
139
DBGPRINT("data is mismatched");
140
return -1;
141
}
142
143
return 0;
144
}
145
146
/**
147
* Read the next patch entry one line at a time
148
*/
149
static int get_next_patch_entry(int fd, struct patch_entry *entry)
150
{
151
int size;
152
char rb;
153
154
if (read(fd, &rb, 1) <= 0)
155
return 0;
156
157
entry->type = rb;
158
159
switch (entry->type) {
160
case PATCH_TYPE_CMD:
161
entry->data[0] = HCI_COMMAND_PKT;
162
163
if (read(fd, &entry->data[1], 3) < 0)
164
return -1;
165
166
size = (int)entry->data[3];
167
168
if (read(fd, &entry->data[4], size) < 0)
169
return -1;
170
171
entry->len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + size;
172
173
break;
174
175
case PATCH_TYPE_EVT:
176
entry->data[0] = HCI_EVENT_PKT;
177
178
if (read(fd, &entry->data[1], 2) < 0)
179
return -1;
180
181
size = (int)entry->data[2];
182
183
if (read(fd, &entry->data[3], size) < 0)
184
return -1;
185
186
entry->len = HCI_TYPE_LEN + HCI_EVENT_HDR_SIZE + size;
187
188
break;
189
190
default:
191
fprintf(stderr, "invalid patch entry(%d)\n", entry->type);
192
return -1;
193
}
194
195
return entry->len;
196
}
197
198
/**
199
* Download the patch set to the controller and verify the event
200
*/
201
static int intel_download_patch(struct patch_ctx *ctx)
202
{
203
int ret;
204
struct patch_entry entry;
205
struct patch_entry event;
206
207
DBGPRINT("start patch downloading");
208
209
do {
210
ret = get_next_patch_entry(ctx->fd, &entry);
211
if (ret <= 0) {
212
ctx->patch_error = 1;
213
break;
214
}
215
216
switch (entry.type) {
217
case PATCH_TYPE_CMD:
218
ret = intel_write_cmd(ctx->dev,
219
entry.data,
220
entry.len);
221
if (ret <= 0) {
222
fprintf(stderr, "failed to send cmd(%d)\n",
223
ret);
224
return ret;
225
}
226
break;
227
228
case PATCH_TYPE_EVT:
229
ret = intel_read_evt(ctx->dev, event.data,
230
sizeof(event.data));
231
if (ret <= 0) {
232
fprintf(stderr, "failed to read evt(%d)\n",
233
ret);
234
return ret;
235
}
236
event.len = ret;
237
238
if (validate_events(&event, &entry) < 0) {
239
DBGPRINT("events are mismatched");
240
ctx->patch_error = 1;
241
return -1;
242
}
243
break;
244
245
default:
246
fprintf(stderr, "unknown patch type(%d)\n",
247
entry.type);
248
return -1;
249
}
250
} while (1);
251
252
return ret;
253
}
254
255
static int open_patch_file(struct patch_ctx *ctx, char *fw_ver)
256
{
257
char patch_file[PATH_MAX];
258
259
snprintf(patch_file, PATH_MAX, "%s%s%s", PATCH_FILE_PATH,
260
fw_ver, PATCH_SEQ_EXT);
261
DBGPRINT("PATCH_FILE: %s", patch_file);
262
263
ctx->fd = open(patch_file, O_RDONLY);
264
if (ctx->fd < 0) {
265
DBGPRINT("cannot open patch file. go to post patch");
266
return -1;
267
}
268
269
return 0;
270
}
271
272
/**
273
* Prepare the controller for patching.
274
*/
275
static int pre_patch(struct patch_ctx *ctx)
276
{
277
int ret, i;
278
struct patch_entry entry;
279
char fw_ver[INTEL_VER_PARAM_LEN * 2];
280
281
DBGPRINT("start pre_patch");
282
283
entry.data[0] = HCI_COMMAND_PKT;
284
entry.data[1] = 0x11;
285
entry.data[2] = 0xFC;
286
entry.data[3] = 0x02;
287
entry.data[4] = 0x01;
288
entry.data[5] = 0x00;
289
entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + INTEL_MFG_PARAM_LEN;
290
291
ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
292
if (ret < 0) {
293
fprintf(stderr, "failed to send cmd(%d)\n", ret);
294
return ret;
295
}
296
297
ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
298
if (ret < 0) {
299
fprintf(stderr, "failed to read evt(%d)\n", ret);
300
return ret;
301
}
302
entry.len = ret;
303
304
if (entry.data[6] != 0x00) {
305
DBGPRINT("command failed. status=%02x", entry.data[6]);
306
ctx->patch_error = 1;
307
return -1;
308
}
309
310
entry.data[0] = HCI_COMMAND_PKT;
311
entry.data[1] = 0x05;
312
entry.data[2] = 0xFC;
313
entry.data[3] = 0x00;
314
entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE;
315
316
ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
317
if (ret < 0) {
318
fprintf(stderr, "failed to send cmd(%d)\n", ret);
319
return ret;
320
}
321
322
ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
323
if (ret < 0) {
324
fprintf(stderr, "failed to read evt(%d)\n", ret);
325
return ret;
326
}
327
entry.len = ret;
328
329
if (entry.data[6] != 0x00) {
330
DBGPRINT("command failed. status=%02x", entry.data[6]);
331
ctx->patch_error = 1;
332
return -1;
333
}
334
335
for (i = 0; i < INTEL_VER_PARAM_LEN; i++)
336
sprintf(&fw_ver[i*2], "%02x", entry.data[7+i]);
337
338
if (open_patch_file(ctx, fw_ver) < 0) {
339
ctx->patch_error = 1;
340
return -1;
341
}
342
343
return ret;
344
}
345
346
/*
347
* check the event is startup event
348
*/
349
static int is_startup_evt(unsigned char *buf)
350
{
351
if (buf[1] == 0xFF && buf[2] == 0x01 && buf[3] == 0x00)
352
return 1;
353
354
return 0;
355
}
356
357
/**
358
* Finalize the patch process and reset the controller
359
*/
360
static int post_patch(struct patch_ctx *ctx)
361
{
362
int ret;
363
struct patch_entry entry;
364
365
DBGPRINT("start post_patch");
366
367
entry.data[0] = HCI_COMMAND_PKT;
368
entry.data[1] = 0x11;
369
entry.data[2] = 0xFC;
370
entry.data[3] = 0x02;
371
entry.data[4] = 0x00;
372
if (ctx->reset_enable_patch)
373
entry.data[5] = 0x02;
374
else
375
entry.data[5] = 0x01;
376
377
entry.len = HCI_TYPE_LEN + HCI_COMMAND_HDR_SIZE + INTEL_MFG_PARAM_LEN;
378
379
ret = intel_write_cmd(ctx->dev, entry.data, entry.len);
380
if (ret < 0) {
381
fprintf(stderr, "failed to send cmd(%d)\n", ret);
382
return ret;
383
}
384
385
ret = intel_read_evt(ctx->dev, entry.data, sizeof(entry.data));
386
if (ret < 0) {
387
fprintf(stderr, "failed to read evt(%d)\n", ret);
388
return ret;
389
}
390
entry.len = ret;
391
392
if (entry.data[6] != 0x00) {
393
fprintf(stderr, "cmd failed. st=%02x\n", entry.data[6]);
394
return -1;
395
}
396
397
do {
398
ret = intel_read_evt(ctx->dev, entry.data,
399
sizeof(entry.data));
400
if (ret < 0) {
401
fprintf(stderr, "failed to read cmd(%d)\n", ret);
402
return ret;
403
}
404
entry.len = ret;
405
} while (!is_startup_evt(entry.data));
406
407
return ret;
408
}
409
410
/**
411
* Main routine that handles the device patching process.
412
*/
413
static int intel_patch_device(struct patch_ctx *ctx)
414
{
415
int ret;
416
417
ret = pre_patch(ctx);
418
if (ret < 0) {
419
if (!ctx->patch_error) {
420
fprintf(stderr, "I/O error: pre_patch failed\n");
421
return ret;
422
}
423
424
DBGPRINT("patch failed. proceed to post patch");
425
goto post_patch;
426
}
427
428
ret = intel_download_patch(ctx);
429
if (ret < 0) {
430
if (!ctx->patch_error) {
431
fprintf(stderr, "I/O error: download_patch failed\n");
432
close(ctx->fd);
433
return ret;
434
}
435
} else {
436
DBGPRINT("patch done");
437
ctx->reset_enable_patch = 1;
438
}
439
440
close(ctx->fd);
441
442
post_patch:
443
ret = post_patch(ctx);
444
if (ret < 0) {
445
fprintf(stderr, "post_patch failed(%d)\n", ret);
446
return ret;
447
}
448
449
return 0;
450
}
451
452
static int set_rts(int dev, int rtsval)
453
{
454
int arg;
455
456
if (ioctl(dev, TIOCMGET, &arg) < 0) {
457
perror("cannot get TIOCMGET");
458
return -errno;
459
}
460
if (rtsval)
461
arg |= TIOCM_RTS;
462
else
463
arg &= ~TIOCM_RTS;
464
465
if (ioctl(dev, TIOCMSET, &arg) == -1) {
466
perror("cannot set TIOCMGET");
467
return -errno;
468
}
469
470
return 0;
471
}
472
473
static unsigned char get_intel_speed(int speed)
474
{
475
switch (speed) {
476
case 9600:
477
return 0x00;
478
case 19200:
479
return 0x01;
480
case 38400:
481
return 0x02;
482
case 57600:
483
return 0x03;
484
case 115200:
485
return 0x04;
486
case 230400:
487
return 0x05;
488
case 460800:
489
return 0x06;
490
case 921600:
491
return 0x07;
492
case 1843200:
493
return 0x08;
494
case 3250000:
495
return 0x09;
496
case 2000000:
497
return 0x0A;
498
case 3000000:
499
return 0x0B;
500
default:
501
return 0xFF;
502
}
503
}
504
505
/**
506
* if it failed to change to new baudrate, it will rollback
507
* to initial baudrate
508
*/
509
static int change_baudrate(int dev, int init_speed, int *speed,
510
struct termios *ti)
511
{
512
int ret;
513
unsigned char br;
514
unsigned char cmd[5];
515
unsigned char evt[7];
516
517
DBGPRINT("start baudrate change");
518
519
ret = set_rts(dev, 0);
520
if (ret < 0) {
521
fprintf(stderr, "failed to clear RTS\n");
522
return ret;
523
}
524
525
cmd[0] = HCI_COMMAND_PKT;
526
cmd[1] = 0x06;
527
cmd[2] = 0xFC;
528
cmd[3] = 0x01;
529
530
br = get_intel_speed(*speed);
531
if (br == 0xFF) {
532
fprintf(stderr, "speed %d is not supported\n", *speed);
533
return -1;
534
}
535
cmd[4] = br;
536
537
ret = intel_write_cmd(dev, cmd, sizeof(cmd));
538
if (ret < 0) {
539
fprintf(stderr, "failed to send cmd(%d)\n", ret);
540
return ret;
541
}
542
543
/*
544
* wait for buffer to be consumed by the controller
545
*/
546
usleep(300000);
547
548
if (set_speed(dev, ti, *speed) < 0) {
549
fprintf(stderr, "can't set to new baud rate\n");
550
return -1;
551
}
552
553
ret = set_rts(dev, 1);
554
if (ret < 0) {
555
fprintf(stderr, "failed to set RTS\n");
556
return ret;
557
}
558
559
ret = intel_read_evt(dev, evt, sizeof(evt));
560
if (ret < 0) {
561
fprintf(stderr, "failed to read evt(%d)\n", ret);
562
return ret;
563
}
564
565
if (evt[4] != 0x00) {
566
fprintf(stderr,
567
"failed to change speed. use default speed %d\n",
568
init_speed);
569
*speed = init_speed;
570
}
571
572
return 0;
573
}
574
575
/**
576
* An entry point for Intel specific initialization
577
*/
578
int intel_init(int dev, int init_speed, int *speed, struct termios *ti)
579
{
580
int ret = 0;
581
struct patch_ctx ctx;
582
583
if (change_baudrate(dev, init_speed, speed, ti) < 0)
584
return -1;
585
586
ctx.dev = dev;
587
ctx.patch_error = 0;
588
ctx.reset_enable_patch = 0;
589
590
ret = intel_patch_device(&ctx);
591
if (ret < 0)
592
fprintf(stderr, "failed to initialize the device");
593
594
return ret;
595
}
596
597