xref: /btstack/example/pbap_client_demo.c (revision f1b34e8dd9b1fdccaf026fb61fff3e60bf7a0dd7)
1*f1b34e8dSMatthias Ringwald /*
2*f1b34e8dSMatthias Ringwald  * Copyright (C) 2014 BlueKitchen GmbH
3*f1b34e8dSMatthias Ringwald  *
4*f1b34e8dSMatthias Ringwald  * Redistribution and use in source and binary forms, with or without
5*f1b34e8dSMatthias Ringwald  * modification, are permitted provided that the following conditions
6*f1b34e8dSMatthias Ringwald  * are met:
7*f1b34e8dSMatthias Ringwald  *
8*f1b34e8dSMatthias Ringwald  * 1. Redistributions of source code must retain the above copyright
9*f1b34e8dSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer.
10*f1b34e8dSMatthias Ringwald  * 2. Redistributions in binary form must reproduce the above copyright
11*f1b34e8dSMatthias Ringwald  *    notice, this list of conditions and the following disclaimer in the
12*f1b34e8dSMatthias Ringwald  *    documentation and/or other materials provided with the distribution.
13*f1b34e8dSMatthias Ringwald  * 3. Neither the name of the copyright holders nor the names of
14*f1b34e8dSMatthias Ringwald  *    contributors may be used to endorse or promote products derived
15*f1b34e8dSMatthias Ringwald  *    from this software without specific prior written permission.
16*f1b34e8dSMatthias Ringwald  * 4. Any redistribution, use, or modification is done solely for
17*f1b34e8dSMatthias Ringwald  *    personal benefit and not for any commercial purpose or for
18*f1b34e8dSMatthias Ringwald  *    monetary gain.
19*f1b34e8dSMatthias Ringwald  *
20*f1b34e8dSMatthias Ringwald  * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS
21*f1b34e8dSMatthias Ringwald  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*f1b34e8dSMatthias Ringwald  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23*f1b34e8dSMatthias Ringwald  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MATTHIAS
24*f1b34e8dSMatthias Ringwald  * RINGWALD OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25*f1b34e8dSMatthias Ringwald  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26*f1b34e8dSMatthias Ringwald  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
27*f1b34e8dSMatthias Ringwald  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
28*f1b34e8dSMatthias Ringwald  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29*f1b34e8dSMatthias Ringwald  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
30*f1b34e8dSMatthias Ringwald  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31*f1b34e8dSMatthias Ringwald  * SUCH DAMAGE.
32*f1b34e8dSMatthias Ringwald  *
33*f1b34e8dSMatthias Ringwald  * Please inquire about commercial licensing options at
34*f1b34e8dSMatthias Ringwald  * [email protected]
35*f1b34e8dSMatthias Ringwald  *
36*f1b34e8dSMatthias Ringwald  */
37*f1b34e8dSMatthias Ringwald 
38*f1b34e8dSMatthias Ringwald #include "btstack_config.h"
39*f1b34e8dSMatthias Ringwald 
40*f1b34e8dSMatthias Ringwald #include <stdint.h>
41*f1b34e8dSMatthias Ringwald #include <stdio.h>
42*f1b34e8dSMatthias Ringwald #include <stdlib.h>
43*f1b34e8dSMatthias Ringwald #include <string.h>
44*f1b34e8dSMatthias Ringwald 
45*f1b34e8dSMatthias Ringwald #include "btstack_run_loop.h"
46*f1b34e8dSMatthias Ringwald #include "l2cap.h"
47*f1b34e8dSMatthias Ringwald #include "rfcomm.h"
48*f1b34e8dSMatthias Ringwald #include "btstack_event.h"
49*f1b34e8dSMatthias Ringwald #include "classic/goep_client.h"
50*f1b34e8dSMatthias Ringwald #include "classic/pbap_client.h"
51*f1b34e8dSMatthias Ringwald 
52*f1b34e8dSMatthias Ringwald #ifdef HAVE_POSIX_STDIN
53*f1b34e8dSMatthias Ringwald #include <unistd.h>
54*f1b34e8dSMatthias Ringwald #include "stdin_support.h"
55*f1b34e8dSMatthias Ringwald #endif
56*f1b34e8dSMatthias Ringwald 
57*f1b34e8dSMatthias Ringwald #ifndef HAVE_POSIX_STDIN
58*f1b34e8dSMatthias Ringwald static int step = 0;
59*f1b34e8dSMatthias Ringwald #endif
60*f1b34e8dSMatthias Ringwald 
61*f1b34e8dSMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
62*f1b34e8dSMatthias Ringwald 
63*f1b34e8dSMatthias Ringwald static bd_addr_t    remote_addr;
64*f1b34e8dSMatthias Ringwald // MBP2016 "F4-0F-24-3B-1B-E1"
65*f1b34e8dSMatthias Ringwald // Nexus 7 "30-85-A9-54-2E-78"
66*f1b34e8dSMatthias Ringwald static const char * remote_addr_string = "30-85-A9-54-2E-78";
67*f1b34e8dSMatthias Ringwald 
68*f1b34e8dSMatthias Ringwald static btstack_packet_callback_registration_t hci_event_callback_registration;
69*f1b34e8dSMatthias Ringwald static uint16_t pbap_cid;
70*f1b34e8dSMatthias Ringwald 
71*f1b34e8dSMatthias Ringwald #ifdef HAVE_POSIX_STDIN
72*f1b34e8dSMatthias Ringwald 
73*f1b34e8dSMatthias Ringwald // Testig User Interface
74*f1b34e8dSMatthias Ringwald static void show_usage(void){
75*f1b34e8dSMatthias Ringwald     bd_addr_t iut_address;
76*f1b34e8dSMatthias Ringwald     gap_local_bd_addr(iut_address);
77*f1b34e8dSMatthias Ringwald 
78*f1b34e8dSMatthias Ringwald     printf("\n--- Bluetooth PBAP Client (HF) Test Console %s ---\n", bd_addr_to_str(iut_address));
79*f1b34e8dSMatthias Ringwald     printf("\n");
80*f1b34e8dSMatthias Ringwald     printf("a - establish PBAP connection to %s\n", bd_addr_to_str(remote_addr));
81*f1b34e8dSMatthias Ringwald     printf("b - set phonebook '/telecom/pb'\n");
82*f1b34e8dSMatthias Ringwald     printf("c - set phonebook '/SIM1/telecom/pb'\n");
83*f1b34e8dSMatthias Ringwald     printf("d - pull phonebook\n");
84*f1b34e8dSMatthias Ringwald     printf("e - disconnnect\n");
85*f1b34e8dSMatthias Ringwald     printf("---\n");
86*f1b34e8dSMatthias Ringwald     printf("Ctrl-c - exit\n");
87*f1b34e8dSMatthias Ringwald     printf("---\n");
88*f1b34e8dSMatthias Ringwald }
89*f1b34e8dSMatthias Ringwald 
90*f1b34e8dSMatthias Ringwald static void stdin_process(btstack_data_source_t *ds, btstack_data_source_callback_type_t callback_type){
91*f1b34e8dSMatthias Ringwald     UNUSED(ds);
92*f1b34e8dSMatthias Ringwald     UNUSED(callback_type);
93*f1b34e8dSMatthias Ringwald 
94*f1b34e8dSMatthias Ringwald     char cmd = btstack_stdin_read();
95*f1b34e8dSMatthias Ringwald 
96*f1b34e8dSMatthias Ringwald     switch (cmd){
97*f1b34e8dSMatthias Ringwald         case 'a':
98*f1b34e8dSMatthias Ringwald             printf("[+] Connecting to %s...\n", bd_addr_to_str(remote_addr));
99*f1b34e8dSMatthias Ringwald             pbap_connect(&packet_handler, remote_addr, &pbap_cid);
100*f1b34e8dSMatthias Ringwald             break;
101*f1b34e8dSMatthias Ringwald         case 'b':
102*f1b34e8dSMatthias Ringwald             printf("[+] Set Phonebook 'telecom/pb'\n");
103*f1b34e8dSMatthias Ringwald             pbap_set_phonebook(pbap_cid, "telecom/pb");
104*f1b34e8dSMatthias Ringwald             break;
105*f1b34e8dSMatthias Ringwald         case 'c':
106*f1b34e8dSMatthias Ringwald             printf("[+] Set Phonebook 'SIM1/telecom/pb'\n");
107*f1b34e8dSMatthias Ringwald             pbap_set_phonebook(pbap_cid, "SIM1/telecom/pb");
108*f1b34e8dSMatthias Ringwald             break;
109*f1b34e8dSMatthias Ringwald         case 'd':
110*f1b34e8dSMatthias Ringwald             pbap_pull_phonebook(pbap_cid);
111*f1b34e8dSMatthias Ringwald             break;
112*f1b34e8dSMatthias Ringwald         case 'e':
113*f1b34e8dSMatthias Ringwald             pbap_disconnect(pbap_cid);
114*f1b34e8dSMatthias Ringwald             break;
115*f1b34e8dSMatthias Ringwald         default:
116*f1b34e8dSMatthias Ringwald             show_usage();
117*f1b34e8dSMatthias Ringwald             break;
118*f1b34e8dSMatthias Ringwald     }
119*f1b34e8dSMatthias Ringwald }
120*f1b34e8dSMatthias Ringwald 
121*f1b34e8dSMatthias Ringwald // packet handler for interactive console
122*f1b34e8dSMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
123*f1b34e8dSMatthias Ringwald     UNUSED(channel);
124*f1b34e8dSMatthias Ringwald     UNUSED(size);
125*f1b34e8dSMatthias Ringwald     int i;
126*f1b34e8dSMatthias Ringwald     switch (packet_type){
127*f1b34e8dSMatthias Ringwald         case HCI_EVENT_PACKET:
128*f1b34e8dSMatthias Ringwald             switch (hci_event_packet_get_type(packet)) {
129*f1b34e8dSMatthias Ringwald                 case BTSTACK_EVENT_STATE:
130*f1b34e8dSMatthias Ringwald                     // BTstack activated, get started
131*f1b34e8dSMatthias Ringwald                     if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
132*f1b34e8dSMatthias Ringwald                         show_usage();
133*f1b34e8dSMatthias Ringwald                     }
134*f1b34e8dSMatthias Ringwald                     break;
135*f1b34e8dSMatthias Ringwald                 case HCI_EVENT_PBAP_META:
136*f1b34e8dSMatthias Ringwald                     switch (hci_event_pbap_meta_get_subevent_code(packet)){
137*f1b34e8dSMatthias Ringwald                         case PBAP_SUBEVENT_CONNECTION_OPENED:
138*f1b34e8dSMatthias Ringwald                             printf("[+] Connected\n");
139*f1b34e8dSMatthias Ringwald                             break;
140*f1b34e8dSMatthias Ringwald                         case PBAP_SUBEVENT_CONNECTION_CLOSED:
141*f1b34e8dSMatthias Ringwald                             printf("[+] Connection closed\n");
142*f1b34e8dSMatthias Ringwald                             break;
143*f1b34e8dSMatthias Ringwald                         case PBAP_SUBEVENT_OPERATION_COMPLETED:
144*f1b34e8dSMatthias Ringwald                             printf("[+] Operation complete\n");
145*f1b34e8dSMatthias Ringwald                             break;
146*f1b34e8dSMatthias Ringwald                         default:
147*f1b34e8dSMatthias Ringwald                             break;
148*f1b34e8dSMatthias Ringwald                     }
149*f1b34e8dSMatthias Ringwald                     break;
150*f1b34e8dSMatthias Ringwald                 default:
151*f1b34e8dSMatthias Ringwald                     break;
152*f1b34e8dSMatthias Ringwald             }
153*f1b34e8dSMatthias Ringwald             break;
154*f1b34e8dSMatthias Ringwald         case PBAP_DATA_PACKET:
155*f1b34e8dSMatthias Ringwald             for (i=0;i<size;i++){
156*f1b34e8dSMatthias Ringwald                 printf("%c", packet[i]);
157*f1b34e8dSMatthias Ringwald             }
158*f1b34e8dSMatthias Ringwald             break;
159*f1b34e8dSMatthias Ringwald         default:
160*f1b34e8dSMatthias Ringwald             break;
161*f1b34e8dSMatthias Ringwald     }
162*f1b34e8dSMatthias Ringwald }
163*f1b34e8dSMatthias Ringwald #else
164*f1b34e8dSMatthias Ringwald 
165*f1b34e8dSMatthias Ringwald // packet handler for emdded system with fixed operation sequence
166*f1b34e8dSMatthias Ringwald static void packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size){
167*f1b34e8dSMatthias Ringwald     UNUSED(channel);
168*f1b34e8dSMatthias Ringwald     UNUSED(size);
169*f1b34e8dSMatthias Ringwald     int i;
170*f1b34e8dSMatthias Ringwald     switch (packet_type){
171*f1b34e8dSMatthias Ringwald         case HCI_EVENT_PACKET:
172*f1b34e8dSMatthias Ringwald             switch (hci_event_packet_get_type(packet)) {
173*f1b34e8dSMatthias Ringwald                 case BTSTACK_EVENT_STATE:
174*f1b34e8dSMatthias Ringwald                     // BTstack activated, get started
175*f1b34e8dSMatthias Ringwald                     if (btstack_event_state_get_state(packet) == HCI_STATE_WORKING){
176*f1b34e8dSMatthias Ringwald                         printf("[+] Connect to Phone Book Server on %s\n", bd_addr_to_str(remote_addr));
177*f1b34e8dSMatthias Ringwald                         pbap_connect(&packet_handler, remote_addr, &pbap_cid);
178*f1b34e8dSMatthias Ringwald                     }
179*f1b34e8dSMatthias Ringwald                     break;
180*f1b34e8dSMatthias Ringwald                 case HCI_EVENT_PBAP_META:
181*f1b34e8dSMatthias Ringwald                     switch (hci_event_pbap_meta_get_subevent_code(packet)){
182*f1b34e8dSMatthias Ringwald                         case PBAP_SUBEVENT_CONNECTION_OPENED:
183*f1b34e8dSMatthias Ringwald                             printf("[+] Connected\n");
184*f1b34e8dSMatthias Ringwald                             printf("[+] Pull phonebook\n");
185*f1b34e8dSMatthias Ringwald                             pbap_pull_phonebook(pbap_cid);
186*f1b34e8dSMatthias Ringwald                             break;
187*f1b34e8dSMatthias Ringwald                         case PBAP_SUBEVENT_CONNECTION_CLOSED:
188*f1b34e8dSMatthias Ringwald                             printf("[+] Connection closed\n");
189*f1b34e8dSMatthias Ringwald                             break;
190*f1b34e8dSMatthias Ringwald                         case PBAP_SUBEVENT_OPERATION_COMPLETED:
191*f1b34e8dSMatthias Ringwald                             printf("[+] Operation complete\n");
192*f1b34e8dSMatthias Ringwald                             printf("[+] Pull Phonebook complete\n");
193*f1b34e8dSMatthias Ringwald                             pbap_disconnect(pbap_cid);
194*f1b34e8dSMatthias Ringwald                             break;
195*f1b34e8dSMatthias Ringwald                         default:
196*f1b34e8dSMatthias Ringwald                             break;
197*f1b34e8dSMatthias Ringwald                     }
198*f1b34e8dSMatthias Ringwald                     break;
199*f1b34e8dSMatthias Ringwald                 default:
200*f1b34e8dSMatthias Ringwald                     break;
201*f1b34e8dSMatthias Ringwald             }
202*f1b34e8dSMatthias Ringwald             break;
203*f1b34e8dSMatthias Ringwald         case PBAP_DATA_PACKET:
204*f1b34e8dSMatthias Ringwald             for (i=0;i<size;i++){
205*f1b34e8dSMatthias Ringwald                 printf("%c", packet[i]);
206*f1b34e8dSMatthias Ringwald             }
207*f1b34e8dSMatthias Ringwald             break;
208*f1b34e8dSMatthias Ringwald         default:
209*f1b34e8dSMatthias Ringwald             break;
210*f1b34e8dSMatthias Ringwald     }
211*f1b34e8dSMatthias Ringwald }
212*f1b34e8dSMatthias Ringwald #endif
213*f1b34e8dSMatthias Ringwald 
214*f1b34e8dSMatthias Ringwald int btstack_main(int argc, const char * argv[]);
215*f1b34e8dSMatthias Ringwald int btstack_main(int argc, const char * argv[]){
216*f1b34e8dSMatthias Ringwald 
217*f1b34e8dSMatthias Ringwald     (void)argc;
218*f1b34e8dSMatthias Ringwald     (void)argv;
219*f1b34e8dSMatthias Ringwald 
220*f1b34e8dSMatthias Ringwald     sscanf_bd_addr(remote_addr_string, remote_addr);
221*f1b34e8dSMatthias Ringwald 
222*f1b34e8dSMatthias Ringwald     // register for HCI events
223*f1b34e8dSMatthias Ringwald     hci_event_callback_registration.callback = &packet_handler;
224*f1b34e8dSMatthias Ringwald     hci_add_event_handler(&hci_event_callback_registration);
225*f1b34e8dSMatthias Ringwald 
226*f1b34e8dSMatthias Ringwald     // init L2CAP
227*f1b34e8dSMatthias Ringwald     l2cap_init();
228*f1b34e8dSMatthias Ringwald 
229*f1b34e8dSMatthias Ringwald     // init RFCOM
230*f1b34e8dSMatthias Ringwald     rfcomm_init();
231*f1b34e8dSMatthias Ringwald 
232*f1b34e8dSMatthias Ringwald     // init GOEP Client
233*f1b34e8dSMatthias Ringwald     goep_client_init();
234*f1b34e8dSMatthias Ringwald 
235*f1b34e8dSMatthias Ringwald     // init PBAP Client
236*f1b34e8dSMatthias Ringwald     pbap_client_init();
237*f1b34e8dSMatthias Ringwald 
238*f1b34e8dSMatthias Ringwald #ifdef HAVE_POSIX_STDIN
239*f1b34e8dSMatthias Ringwald     btstack_stdin_setup(stdin_process);
240*f1b34e8dSMatthias Ringwald #endif
241*f1b34e8dSMatthias Ringwald 
242*f1b34e8dSMatthias Ringwald     // turn on!
243*f1b34e8dSMatthias Ringwald     hci_power_control(HCI_POWER_ON);
244*f1b34e8dSMatthias Ringwald 
245*f1b34e8dSMatthias Ringwald     return 0;
246*f1b34e8dSMatthias Ringwald }
247