XCP_SIM
winbt.c
1 /*
2  * BlueParrot XCP
3  *
4  * (C) 2021 by Christoph Schueler <github.com/Christoph2,
5  * cpu12.gems@googlemail.com>
6  *
7  * All Rights Reserved
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 along
20  * with this program; if not, write to the Free Software Foundation, Inc.,
21  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  *
23  * s. FLOSS-EXCEPTION.txt
24  */
25 
27 #include "xcp.h"
28 #include "xcp_eth.h"
29 #include "xcp_hw.h"
32 #include <BluetoothAPIs.h>
33 #include <Winsock2.h>
34 #include <Ws2bth.h>
35 #include <initguid.h>
36 #include <memory.h>
37 #include <stdint.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 
41 DEFINE_GUID(ASAM_XCP_ON_BT_GUID, 0xDC3CCEDC, 0xF7DE, 0x56E8, 0x87, 0x6F, 0x78, 0x1C, 0x07, 0x3C, 0x9B, 0x77);
42 
43 extern XcpTl_ConnectionType XcpTl_Connection;
44 SOCKADDR_BTH XcpTl_LocalBtAddress;
45 
46 static void PrintBthAddr(SOCKADDR_BTH *addr);
47 
48 void XcpTl_Init(void) {
49  WSADATA wsa;
50  GUID Xcp_ServiceID = ASAM_XCP_ON_BT_GUID;
51  WSAQUERYSET service;
52  CSADDR_INFO csAddr;
53 
54  ZeroMemory(&service, sizeof(service));
55  ZeroMemory(&csAddr, sizeof(csAddr));
56  ZeroMemory(&XcpTl_LocalBtAddress, sizeof(XcpTl_LocalBtAddress));
57  ZeroMemory(&XcpTl_Connection, sizeof(XcpTl_ConnectionType));
58 
59  XcpTl_Connection.socketType = SOCK_STREAM;
60 
61  if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
62  XcpHw_ErrorMsg("XcpTl_Init:WSAStartup()", WSAGetLastError());
63  exit(EXIT_FAILURE);
64  } else {
65  XcpTl_Connection.boundSocket = socket(AF_BTH, SOCK_STREAM, BTHPROTO_RFCOMM);
66  if (XcpTl_Connection.boundSocket == INVALID_SOCKET) {
67  XcpHw_ErrorMsg("XcpTl_Init::socket()", WSAGetLastError());
68  return;
69  }
70  }
71 
72  XcpTl_LocalBtAddress.addressFamily = AF_BTH;
73  XcpTl_LocalBtAddress.btAddr = 0;
74  XcpTl_LocalBtAddress.serviceClassId = GUID_NULL;
75  XcpTl_LocalBtAddress.port = BT_PORT_ANY;
76 
77  if (bind(XcpTl_Connection.boundSocket, (struct sockaddr *)&XcpTl_LocalBtAddress, sizeof(SOCKADDR_BTH)) == SOCKET_ERROR) {
78  XcpHw_ErrorMsg("XcpTl_Init::bind()", WSAGetLastError());
79  return;
80  /* } else {
81  int length = sizeof(SOCKADDR_BTH);
82 
83  getsockname(XcpTl_Connection.boundSocket, (struct sockaddr *)&XcpTl_LocalBtAddress, &length);
84  printf("Local Bluetooth device is: [NAP: %04x SAP: %08x] Server channel = %04x\n", GET_NAP(XcpTl_LocalBtAddress.btAddr),
85  GET_SAP(XcpTl_LocalBtAddress.btAddr), XcpTl_LocalBtAddress.port); printf("MAC: 0x%012x Port: %x\n",
86  XcpTl_LocalBtAddress.btAddr, XcpTl_LocalBtAddress.port);
87  */
88  }
89 
90  int size = sizeof(SOCKADDR_BTH);
91 
92  if (getsockname(XcpTl_Connection.boundSocket, (struct sockaddr *)&XcpTl_LocalBtAddress, &size) == SOCKET_ERROR) {
93  XcpHw_ErrorMsg("XcpTl_Init::getsockname()", WSAGetLastError());
94  return;
95  }
96 
97  if (listen(XcpTl_Connection.boundSocket, 1) == SOCKET_ERROR) {
98  XcpHw_ErrorMsg("XcpTl_Init::listen()", WSAGetLastError());
99  return;
100  }
101 
102  service.dwSize = sizeof(service);
103  service.lpszServiceInstanceName = "XCPonBth";
104  service.lpszComment = "Measure and calibrate with XCP on Bluetooth -- Have fun :-)";
105  service.lpServiceClassId = &Xcp_ServiceID;
106  service.dwNumberOfCsAddrs = 1;
107  service.dwNameSpace = NS_BTH;
108  csAddr.LocalAddr.iSockaddrLength = sizeof(SOCKADDR_BTH);
109  csAddr.LocalAddr.lpSockaddr = (struct sockaddr *)&XcpTl_LocalBtAddress;
110  csAddr.iSocketType = SOCK_STREAM;
111  csAddr.iProtocol = BTHPROTO_RFCOMM;
112  service.lpcsaBuffer = &csAddr;
113 
114  if (WSASetService(&service, RNRSERVICE_REGISTER, 0) == SOCKET_ERROR) {
115  XcpHw_ErrorMsg("XcpTl_Init::WSASetService()", WSAGetLastError());
116  }
117 }
118 
119 void XcpTl_DeInit(void) {
120  closesocket(XcpTl_Connection.boundSocket);
121  WSACleanup();
122 }
123 
124 void XcpTl_Send(uint8_t const *buf, uint16_t len) {
125  XCP_TL_ENTER_CRITICAL();
126 
127  if (send(XcpTl_Connection.connectedSocket, (char const *)buf, len, 0) == SOCKET_ERROR) {
128  XcpHw_ErrorMsg("XcpTl_Send:send()", WSAGetLastError());
129  closesocket(XcpTl_Connection.connectedSocket);
130  }
131  XCP_TL_LEAVE_CRITICAL();
132 }
133 
134 void XcpTl_PrintBtDetails(void) {
135  printf("XCPonBth -- Listening on ");
136  PrintBthAddr(&XcpTl_LocalBtAddress);
137  printf(" channel %u\n\r", (unsigned int)XcpTl_LocalBtAddress.port);
138 }
139 
140 static void PrintBthAddr(SOCKADDR_BTH *addr) {
141  uint8_t mac[6] = {0};
142  uint8_t idx = 0;
143 
144  mac[0] = (addr->btAddr >> 40) & 0xff;
145  mac[1] = (addr->btAddr >> 32) & 0xff;
146  mac[2] = (addr->btAddr >> 24) & 0xff;
147  mac[3] = (addr->btAddr >> 16) & 0xff;
148  mac[4] = (addr->btAddr >> 8) & 0xff;
149  mac[5] = (addr->btAddr) & 0xff;
150 
151  for (idx = 0; idx < 6; ++idx) {
152  printf("%02X", mac[idx]);
153  if (idx < 5) {
154  printf(":");
155  }
156  }
157 }