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_ti.c
Views: 3959
1
/*
2
*
3
* BlueZ - Bluetooth protocol stack for Linux
4
*
5
* Copyright (C) 2007-2008 Texas Instruments, Inc.
6
* Copyright (C) 2005-2010 Marcel Holtmann <[email protected]>
7
*
8
*
9
* This program is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License as published by
11
* the Free Software Foundation; either version 2 of the License, or
12
* (at your option) any later version.
13
*
14
* This program is distributed in the hope that it will be useful,
15
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
* GNU General Public License for more details.
18
*
19
* You should have received a copy of the GNU General Public License
20
* along with this program; if not, write to the Free Software
21
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
*
23
*/
24
25
#ifdef HAVE_CONFIG_H
26
#include <config.h>
27
#endif
28
29
#include <stdio.h>
30
#include <errno.h>
31
#include <unistd.h>
32
#include <stdlib.h>
33
#include <termios.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <sys/types.h>
37
#include <sys/param.h>
38
#include <sys/ioctl.h>
39
40
#include <bluetooth/bluetooth.h>
41
#include <bluetooth/hci.h>
42
#include <bluetooth/hci_lib.h>
43
44
#include "hciattach.h"
45
46
#ifdef HCIATTACH_DEBUG
47
#define DPRINTF(x...) printf(x)
48
#else
49
#define DPRINTF(x...)
50
#endif
51
52
#define HCIUARTGETDEVICE _IOR('U', 202, int)
53
54
#define MAKEWORD(a, b) ((uint16_t)(((uint8_t)(a)) | ((uint16_t)((uint8_t)(b))) << 8))
55
56
#define TI_MANUFACTURER_ID 13
57
58
#define FIRMWARE_DIRECTORY "/lib/firmware/ti-connectivity/"
59
60
#define ACTION_SEND_COMMAND 1
61
#define ACTION_WAIT_EVENT 2
62
#define ACTION_SERIAL 3
63
#define ACTION_DELAY 4
64
#define ACTION_RUN_SCRIPT 5
65
#define ACTION_REMARKS 6
66
67
#define BRF_DEEP_SLEEP_OPCODE_BYTE_1 0x0c
68
#define BRF_DEEP_SLEEP_OPCODE_BYTE_2 0xfd
69
#define BRF_DEEP_SLEEP_OPCODE \
70
(BRF_DEEP_SLEEP_OPCODE_BYTE_1 | (BRF_DEEP_SLEEP_OPCODE_BYTE_2 << 8))
71
72
#define FILE_HEADER_MAGIC 0x42535442
73
74
/*
75
* BRF Firmware header
76
*/
77
struct bts_header {
78
uint32_t magic;
79
uint32_t version;
80
uint8_t future[24];
81
uint8_t actions[0];
82
}__attribute__ ((packed));
83
84
/*
85
* BRF Actions structure
86
*/
87
struct bts_action {
88
uint16_t type;
89
uint16_t size;
90
uint8_t data[0];
91
} __attribute__ ((packed));
92
93
struct bts_action_send {
94
uint8_t data[0];
95
} __attribute__ ((packed));
96
97
struct bts_action_wait {
98
uint32_t msec;
99
uint32_t size;
100
uint8_t data[0];
101
}__attribute__ ((packed));
102
103
struct bts_action_delay {
104
uint32_t msec;
105
}__attribute__ ((packed));
106
107
struct bts_action_serial {
108
uint32_t baud;
109
uint32_t flow_control;
110
}__attribute__ ((packed));
111
112
static FILE *bts_load_script(const char *file_name, uint32_t *version)
113
{
114
struct bts_header header;
115
FILE *fp;
116
117
fp = fopen(file_name, "rb");
118
if (!fp) {
119
perror("can't open firmware file");
120
return NULL;
121
}
122
123
if (1 != fread(&header, sizeof(struct bts_header), 1, fp)) {
124
perror("can't read firmware file");
125
goto errclose;
126
}
127
128
if (header.magic != FILE_HEADER_MAGIC) {
129
fprintf(stderr, "%s not a legal TI firmware file\n", file_name);
130
goto errclose;
131
}
132
133
if (NULL != version)
134
*version = header.version;
135
136
return fp;
137
138
errclose:
139
fclose(fp);
140
141
return NULL;
142
}
143
144
static unsigned long bts_fetch_action(FILE *fp, unsigned char *action_buf,
145
unsigned long buf_size, uint16_t *action_type)
146
{
147
struct bts_action action_hdr;
148
unsigned long nread;
149
150
if (!fp)
151
return 0;
152
153
if (1 != fread(&action_hdr, sizeof(struct bts_action), 1, fp))
154
return 0;
155
156
if (action_hdr.size > buf_size) {
157
fprintf(stderr, "bts_next_action: not enough space to read next action\n");
158
return 0;
159
}
160
161
nread = fread(action_buf, sizeof(uint8_t), action_hdr.size, fp);
162
if (nread != (action_hdr.size)) {
163
fprintf(stderr, "bts_next_action: fread failed to read next action\n");
164
return 0;
165
}
166
167
*action_type = action_hdr.type;
168
169
return nread * sizeof(uint8_t);
170
}
171
172
static void bts_unload_script(FILE *fp)
173
{
174
if (fp)
175
fclose(fp);
176
}
177
178
static int is_it_texas(const uint8_t *respond)
179
{
180
uint16_t manufacturer_id;
181
182
manufacturer_id = MAKEWORD(respond[11], respond[12]);
183
184
return TI_MANUFACTURER_ID == manufacturer_id ? 1 : 0;
185
}
186
187
static const char *get_firmware_name(const uint8_t *respond)
188
{
189
static char firmware_file_name[PATH_MAX] = {0};
190
uint16_t version = 0, chip = 0, min_ver = 0, maj_ver = 0;
191
192
version = MAKEWORD(respond[13], respond[14]);
193
chip = (version & 0x7C00) >> 10;
194
min_ver = (version & 0x007F);
195
maj_ver = (version & 0x0380) >> 7;
196
197
if (version & 0x8000)
198
maj_ver |= 0x0008;
199
200
sprintf(firmware_file_name, FIRMWARE_DIRECTORY "TIInit_%d.%d.%d.bts", chip, maj_ver, min_ver);
201
202
return firmware_file_name;
203
}
204
205
static void brf_delay(struct bts_action_delay *delay)
206
{
207
usleep(1000 * delay->msec);
208
}
209
210
static int brf_set_serial_params(struct bts_action_serial *serial_action,
211
int fd, int *speed, struct termios *ti)
212
{
213
fprintf(stderr, "texas: changing baud rate to %u, flow control to %u\n",
214
serial_action->baud, serial_action->flow_control );
215
tcflush(fd, TCIOFLUSH);
216
217
if (serial_action->flow_control)
218
ti->c_cflag |= CRTSCTS;
219
else
220
ti->c_cflag &= ~CRTSCTS;
221
222
if (tcsetattr(fd, TCSANOW, ti) < 0) {
223
perror("Can't set port settings");
224
return -1;
225
}
226
227
tcflush(fd, TCIOFLUSH);
228
229
if (set_speed(fd, ti, serial_action->baud) < 0) {
230
perror("Can't set baud rate");
231
return -1;
232
}
233
234
if (speed)
235
*speed = serial_action->baud;
236
237
return 0;
238
}
239
240
static int brf_send_command_socket(int fd, struct bts_action_send *send_action)
241
{
242
char response[1024] = {0};
243
hci_command_hdr *cmd = (hci_command_hdr *) send_action->data;
244
uint16_t opcode = cmd->opcode;
245
246
struct hci_request rq;
247
memset(&rq, 0, sizeof(rq));
248
rq.ogf = cmd_opcode_ogf(opcode);
249
rq.ocf = cmd_opcode_ocf(opcode);
250
rq.event = EVT_CMD_COMPLETE;
251
rq.cparam = &send_action->data[3];
252
rq.clen = send_action->data[2];
253
rq.rparam = response;
254
rq.rlen = sizeof(response);
255
256
if (hci_send_req(fd, &rq, 15) < 0) {
257
perror("Cannot send hci command to socket");
258
return -1;
259
}
260
261
/* verify success */
262
if (response[0]) {
263
errno = EIO;
264
return -1;
265
}
266
267
return 0;
268
}
269
270
static int brf_send_command_file(int fd, struct bts_action_send *send_action,
271
long size)
272
{
273
unsigned char response[1024] = {0};
274
long ret = 0;
275
276
/* send command */
277
if (size != write(fd, send_action, size)) {
278
perror("Texas: Failed to write action command");
279
return -1;
280
}
281
282
/* read response */
283
ret = read_hci_event(fd, response, sizeof(response));
284
if (ret < 0) {
285
perror("texas: failed to read command response");
286
return -1;
287
}
288
289
/* verify success */
290
if (ret < 7 || 0 != response[6]) {
291
fprintf( stderr, "TI init command failed.\n" );
292
errno = EIO;
293
return -1;
294
}
295
296
return 0;
297
}
298
299
300
static int brf_send_command(int fd, struct bts_action_send *send_action,
301
long size, int hcill_installed)
302
{
303
int ret = 0;
304
char *fixed_action;
305
306
/* remove packet type when giving to socket API */
307
if (hcill_installed) {
308
fixed_action = ((char *) send_action) + 1;
309
ret = brf_send_command_socket(fd, (struct bts_action_send *) fixed_action);
310
} else {
311
ret = brf_send_command_file(fd, send_action, size);
312
}
313
314
return ret;
315
}
316
317
static int brf_do_action(uint16_t brf_type, uint8_t *brf_action, long brf_size,
318
int fd, int *speed, struct termios *ti, int hcill_installed)
319
{
320
int ret = 0;
321
322
switch (brf_type) {
323
case ACTION_SEND_COMMAND:
324
DPRINTF("W");
325
ret = brf_send_command(fd,
326
(struct bts_action_send *) brf_action,
327
brf_size, hcill_installed);
328
break;
329
case ACTION_WAIT_EVENT:
330
DPRINTF("R");
331
break;
332
case ACTION_SERIAL:
333
DPRINTF("S");
334
ret = brf_set_serial_params((struct bts_action_serial *) brf_action, fd, speed, ti);
335
break;
336
case ACTION_DELAY:
337
DPRINTF("D");
338
brf_delay((struct bts_action_delay *) brf_action);
339
break;
340
case ACTION_REMARKS:
341
DPRINTF("C");
342
break;
343
default:
344
fprintf(stderr, "brf_init: unknown firmware action type (%d)\n", brf_type);
345
break;
346
}
347
348
return ret;
349
}
350
351
/*
352
* tests whether a given brf action is a HCI_VS_Sleep_Mode_Configurations cmd
353
*/
354
static int brf_action_is_deep_sleep(uint8_t *brf_action, long brf_size,
355
uint16_t brf_type)
356
{
357
uint16_t opcode;
358
359
if (brf_type != ACTION_SEND_COMMAND)
360
return 0;
361
362
if (brf_size < 3)
363
return 0;
364
365
if (brf_action[0] != HCI_COMMAND_PKT)
366
return 0;
367
368
/* HCI data is little endian */
369
opcode = brf_action[1] | (brf_action[2] << 8);
370
371
if (opcode != BRF_DEEP_SLEEP_OPCODE)
372
return 0;
373
374
/* action is deep sleep configuration command ! */
375
return 1;
376
}
377
378
/*
379
* This function is called twice.
380
* The first time it is called, it loads the brf script, and executes its
381
* commands until it reaches a deep sleep command (or its end).
382
* The second time it is called, it assumes HCILL protocol is set up,
383
* and sends rest of brf script via the supplied socket.
384
*/
385
static int brf_do_script(int fd, int *speed, struct termios *ti, const char *bts_file)
386
{
387
int ret = 0, hcill_installed = bts_file ? 0 : 1;
388
uint32_t vers;
389
static FILE *brf_script_file = NULL;
390
static uint8_t brf_action[512];
391
static long brf_size;
392
static uint16_t brf_type;
393
394
/* is it the first time we are called ? */
395
if (0 == hcill_installed) {
396
DPRINTF("Sending script to serial device\n");
397
brf_script_file = bts_load_script(bts_file, &vers );
398
if (!brf_script_file) {
399
fprintf(stderr, "Warning: cannot find BTS file: %s\n",
400
bts_file);
401
return 0;
402
}
403
404
fprintf( stderr, "Loaded BTS script version %u\n", vers );
405
406
brf_size = bts_fetch_action(brf_script_file, brf_action,
407
sizeof(brf_action), &brf_type);
408
if (brf_size == 0) {
409
fprintf(stderr, "Warning: BTS file is empty !");
410
return 0;
411
}
412
}
413
else {
414
DPRINTF("Sending script to bluetooth socket\n");
415
}
416
417
/* execute current action and continue to parse brf script file */
418
while (brf_size != 0) {
419
ret = brf_do_action(brf_type, brf_action, brf_size,
420
fd, speed, ti, hcill_installed);
421
if (ret == -1)
422
break;
423
424
brf_size = bts_fetch_action(brf_script_file, brf_action,
425
sizeof(brf_action), &brf_type);
426
427
/* if this is the first time we run (no HCILL yet) */
428
/* and a deep sleep command is encountered */
429
/* we exit */
430
if (!hcill_installed &&
431
brf_action_is_deep_sleep(brf_action,
432
brf_size, brf_type))
433
return 0;
434
}
435
436
bts_unload_script(brf_script_file);
437
brf_script_file = NULL;
438
DPRINTF("\n");
439
440
return ret;
441
}
442
443
int texas_init(int fd, int *speed, struct termios *ti)
444
{
445
struct timespec tm = {0, 50000};
446
char cmd[4];
447
unsigned char resp[100]; /* Response */
448
const char *bts_file;
449
int n;
450
451
memset(resp,'\0', 100);
452
453
/* It is possible to get software version with manufacturer specific
454
HCI command HCI_VS_TI_Version_Number. But the only thing you get more
455
is if this is point-to-point or point-to-multipoint module */
456
457
/* Get Manufacturer and LMP version */
458
cmd[0] = HCI_COMMAND_PKT;
459
cmd[1] = 0x01;
460
cmd[2] = 0x10;
461
cmd[3] = 0x00;
462
463
do {
464
n = write(fd, cmd, 4);
465
if (n < 0) {
466
perror("Failed to write init command (READ_LOCAL_VERSION_INFORMATION)");
467
return -1;
468
}
469
if (n < 4) {
470
fprintf(stderr, "Wanted to write 4 bytes, could only write %d. Stop\n", n);
471
return -1;
472
}
473
474
/* Read reply. */
475
if (read_hci_event(fd, resp, 100) < 0) {
476
perror("Failed to read init response (READ_LOCAL_VERSION_INFORMATION)");
477
return -1;
478
}
479
480
/* Wait for command complete event for our Opcode */
481
} while (resp[4] != cmd[1] && resp[5] != cmd[2]);
482
483
/* Verify manufacturer */
484
if (! is_it_texas(resp)) {
485
fprintf(stderr,"ERROR: module's manufacturer is not Texas Instruments\n");
486
return -1;
487
}
488
489
fprintf(stderr, "Found a Texas Instruments' chip!\n");
490
491
bts_file = get_firmware_name(resp);
492
fprintf(stderr, "Firmware file : %s\n", bts_file);
493
494
n = brf_do_script(fd, speed, ti, bts_file);
495
496
nanosleep(&tm, NULL);
497
498
return n;
499
}
500
501
int texas_post(int fd, struct termios *ti)
502
{
503
int dev_id, dd, ret = 0;
504
505
sleep(1);
506
507
dev_id = ioctl(fd, HCIUARTGETDEVICE, 0);
508
if (dev_id < 0) {
509
perror("cannot get device id");
510
return -1;
511
}
512
513
DPRINTF("\nAdded device hci%d\n", dev_id);
514
515
dd = hci_open_dev(dev_id);
516
if (dd < 0) {
517
perror("HCI device open failed");
518
return -1;
519
}
520
521
if (ioctl(dd, HCIDEVUP, dev_id) < 0 && errno != EALREADY) {
522
fprintf(stderr, "Can't init device hci%d: %s (%d)", dev_id,
523
strerror(errno), errno);
524
hci_close_dev(dd);
525
return -1;
526
}
527
528
ret = brf_do_script(dd, NULL, ti, NULL);
529
530
hci_close_dev(dd);
531
532
return ret;
533
}
534
535