Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/next/external/cache/sources/hcitools/hciattach_tialt.c
Views: 3959
/*1*2* BlueZ - Bluetooth protocol stack for Linux3*4* Copyright (C) 2005-2010 Marcel Holtmann <[email protected]>5*6*7* This program is free software; you can redistribute it and/or modify8* it under the terms of the GNU General Public License as published by9* the Free Software Foundation; either version 2 of the License, or10* (at your option) any later version.11*12* This program is distributed in the hope that it will be useful,13* but WITHOUT ANY WARRANTY; without even the implied warranty of14* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the15* GNU General Public License for more details.16*17* You should have received a copy of the GNU General Public License18* along with this program; if not, write to the Free Software19* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA20*21*/2223#ifdef HAVE_CONFIG_H24#include <config.h>25#endif2627#include <stdio.h>28#include <errno.h>29#include <fcntl.h>30#include <unistd.h>31#include <stdlib.h>32#include <string.h>33#include <signal.h>34#include <syslog.h>35#include <termios.h>36#include <time.h>37#include <sys/time.h>38#include <sys/poll.h>39#include <sys/param.h>40#include <sys/ioctl.h>4142#include <bluetooth/bluetooth.h>43#include <bluetooth/hci.h>44#include <bluetooth/hci_lib.h>4546#include "hciattach.h"4748#define FAILIF(x, args...) do { \49if (x) { \50fprintf(stderr, ##args); \51return -1; \52} \53} while(0)5455typedef struct {56uint8_t uart_prefix;57hci_event_hdr hci_hdr;58evt_cmd_complete cmd_complete;59uint8_t status;60uint8_t data[16];61} __attribute__((packed)) command_complete_t;6263static int read_command_complete(int fd, unsigned short opcode, unsigned char len) {64command_complete_t resp;65/* Read reply. */66FAILIF(read_hci_event(fd, (unsigned char *)&resp, sizeof(resp)) < 0,67"Failed to read response");6869/* Parse speed-change reply */70FAILIF(resp.uart_prefix != HCI_EVENT_PKT,71"Error in response: not an event packet, but 0x%02x!\n",72resp.uart_prefix);7374FAILIF(resp.hci_hdr.evt != EVT_CMD_COMPLETE, /* event must be event-complete */75"Error in response: not a cmd-complete event, "76"but 0x%02x!\n", resp.hci_hdr.evt);7778FAILIF(resp.hci_hdr.plen < 4, /* plen >= 4 for EVT_CMD_COMPLETE */79"Error in response: plen is not >= 4, but 0x%02x!\n",80resp.hci_hdr.plen);8182/* cmd-complete event: opcode */83FAILIF(resp.cmd_complete.opcode != (uint16_t)opcode,84"Error in response: opcode is 0x%04x, not 0x%04x!",85resp.cmd_complete.opcode, opcode);8687return resp.status == 0 ? 0 : -1;88}8990typedef struct {91uint8_t uart_prefix;92hci_command_hdr hci_hdr;93uint32_t speed;94} __attribute__((packed)) texas_speed_change_cmd_t;9596static int texas_change_speed(int fd, uint32_t speed)97{98return 0;99}100101static int texas_load_firmware(int fd, const char *firmware) {102103int fw = open(firmware, O_RDONLY);104105fprintf(stdout, "Opening firmware file: %s\n", firmware);106107FAILIF(fw < 0,108"Could not open firmware file %s: %s (%d).\n",109firmware, strerror(errno), errno);110111fprintf(stdout, "Uploading firmware...\n");112do {113/* Read each command and wait for a response. */114unsigned char data[1024];115unsigned char cmdp[1 + sizeof(hci_command_hdr)];116hci_command_hdr *cmd = (hci_command_hdr *)(cmdp + 1);117int nr;118nr = read(fw, cmdp, sizeof(cmdp));119if (!nr)120break;121FAILIF(nr != sizeof(cmdp), "Could not read H4 + HCI header!\n");122FAILIF(*cmdp != HCI_COMMAND_PKT, "Command is not an H4 command packet!\n");123124FAILIF(read(fw, data, cmd->plen) != cmd->plen,125"Could not read %d bytes of data for command with opcode %04x!\n",126cmd->plen,127cmd->opcode);128129{130int nw;131#if 0132fprintf(stdout, "\topcode 0x%04x (%d bytes of data).\n",133cmd->opcode,134cmd->plen);135#endif136struct iovec iov_cmd[2];137iov_cmd[0].iov_base = cmdp;138iov_cmd[0].iov_len = sizeof(cmdp);139iov_cmd[1].iov_base = data;140iov_cmd[1].iov_len = cmd->plen;141nw = writev(fd, iov_cmd, 2);142FAILIF(nw != (int) sizeof(cmd) + cmd->plen,143"Could not send entire command (sent only %d bytes)!\n",144nw);145}146147/* Wait for response */148if (read_command_complete(fd,149cmd->opcode,150cmd->plen) < 0) {151return -1;152}153154} while(1);155fprintf(stdout, "Firmware upload successful.\n");156157close(fw);158return 0;159}160161int texasalt_init(int fd, int speed, struct termios *ti)162{163struct timespec tm = {0, 50000};164char cmd[4];165unsigned char resp[100]; /* Response */166int n;167168memset(resp,'\0', 100);169170/* It is possible to get software version with manufacturer specific171HCI command HCI_VS_TI_Version_Number. But the only thing you get more172is if this is point-to-point or point-to-multipoint module */173174/* Get Manufacturer and LMP version */175cmd[0] = HCI_COMMAND_PKT;176cmd[1] = 0x01;177cmd[2] = 0x10;178cmd[3] = 0x00;179180do {181n = write(fd, cmd, 4);182if (n < 0) {183perror("Failed to write init command (READ_LOCAL_VERSION_INFORMATION)");184return -1;185}186if (n < 4) {187fprintf(stderr, "Wanted to write 4 bytes, could only write %d. Stop\n", n);188return -1;189}190191/* Read reply. */192if (read_hci_event(fd, resp, 100) < 0) {193perror("Failed to read init response (READ_LOCAL_VERSION_INFORMATION)");194return -1;195}196197/* Wait for command complete event for our Opcode */198} while (resp[4] != cmd[1] && resp[5] != cmd[2]);199200/* Verify manufacturer */201if ((resp[11] & 0xFF) != 0x0d)202fprintf(stderr,"WARNING : module's manufacturer is not Texas Instrument\n");203204/* Print LMP version */205fprintf(stderr, "Texas module LMP version : 0x%02x\n", resp[10] & 0xFF);206207/* Print LMP subversion */208{209unsigned short lmp_subv = resp[13] | (resp[14] << 8);210unsigned short brf_chip = (lmp_subv & 0x7c00) >> 10;211static const char *c_brf_chip[8] = {212"unknown",213"unknown",214"brf6100",215"brf6150",216"brf6300",217"brf6350",218"unknown",219"wl1271"220};221char fw[100];222223fprintf(stderr, "Texas module LMP sub-version : 0x%04x\n", lmp_subv);224225fprintf(stderr,226"\tinternal version freeze: %d\n"227"\tsoftware version: %d\n"228"\tchip: %s (%d)\n",229lmp_subv & 0x7f,230((lmp_subv & 0x8000) >> (15-3)) | ((lmp_subv & 0x380) >> 7),231((brf_chip > 7) ? "unknown" : c_brf_chip[brf_chip]),232brf_chip);233234sprintf(fw, "/etc/firmware/%s.bin", c_brf_chip[brf_chip]);235texas_load_firmware(fd, fw);236237texas_change_speed(fd, speed);238}239nanosleep(&tm, NULL);240return 0;241}242243244