1 /* 2 * 3 * BlueZ - Bluetooth protocol stack for Linux 4 * 5 * Copyright (C) 2005-2010 Marcel Holtmann <marcel (at) holtmann.org> 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 <errno.h> 30 #include <stdlib.h> 31 #include <getopt.h> 32 #include <sys/ioctl.h> 33 #include <sys/socket.h> 34 35 #include <bluetooth/bluetooth.h> 36 #include <bluetooth/hci.h> 37 #include <bluetooth/hci_lib.h> 38 39 #if 0 40 #define OCF_ERICSSON_SEND_LMP 0x0021 41 typedef struct { 42 uint16_t handle; 43 uint8_t length; 44 uint8_t data[17]; 45 } __attribute__ ((packed)) ericsson_send_lmp_cp; 46 #define ERICSSON_SEND_LMP_CP_SIZE 20 47 48 static int ericsson_send_lmp(int dd, uint16_t handle, uint8_t length, uint8_t *data) 49 { 50 struct hci_request rq; 51 ericsson_send_lmp_cp cp; 52 53 memset(&cp, 0, sizeof(cp)); 54 cp.handle = htobs(handle); 55 cp.length = length; 56 memcpy(cp.data, data, length); 57 58 memset(&rq, 0, sizeof(rq)); 59 rq.ogf = OGF_VENDOR_CMD; 60 rq.ocf = OCF_ERICSSON_SEND_LMP; 61 rq.cparam = &cp; 62 rq.clen = ERICSSON_SEND_LMP_CP_SIZE; 63 rq.rparam = NULL; 64 rq.rlen = 0; 65 66 if (hci_send_req(dd, &rq, 1000) < 0) 67 return -1; 68 69 return 0; 70 } 71 #endif 72 73 #define OCF_ERICSSON_WRITE_EVENTS 0x0043 74 typedef struct { 75 uint8_t mask; 76 uint8_t opcode; 77 uint8_t opcode_ext; 78 } __attribute__ ((packed)) ericsson_write_events_cp; 79 #define ERICSSON_WRITE_EVENTS_CP_SIZE 3 80 81 static int ericsson_write_events(int dd, uint8_t mask) 82 { 83 struct hci_request rq; 84 ericsson_write_events_cp cp; 85 86 memset(&cp, 0, sizeof(cp)); 87 cp.mask = mask; 88 cp.opcode = 0x00; 89 cp.opcode_ext = 0x00; 90 91 memset(&rq, 0, sizeof(rq)); 92 rq.ogf = OGF_VENDOR_CMD; 93 rq.ocf = OCF_ERICSSON_WRITE_EVENTS; 94 rq.cparam = &cp; 95 rq.clen = ERICSSON_WRITE_EVENTS_CP_SIZE; 96 rq.rparam = NULL; 97 rq.rlen = 0; 98 99 if (hci_send_req(dd, &rq, 1000) < 0) 100 return -1; 101 102 return 0; 103 } 104 105 static void usage(void) 106 { 107 printf("lmptest - Utility for testing special LMP functions\n\n"); 108 printf("Usage:\n" 109 "\tlmptest [-i <dev>]\n"); 110 } 111 112 static struct option main_options[] = { 113 { "device", 1, 0, 'i' }, 114 { "help", 0, 0, 'h' }, 115 { 0, 0, 0, 0 } 116 }; 117 118 int main(int argc, char *argv[]) 119 { 120 struct hci_version ver; 121 int dd, opt, dev = 0; 122 123 while ((opt=getopt_long(argc, argv, "+i:h", main_options, NULL)) != -1) { 124 switch (opt) { 125 case 'i': 126 dev = hci_devid(optarg); 127 if (dev < 0) { 128 perror("Invalid device"); 129 exit(1); 130 } 131 break; 132 133 case 'h': 134 default: 135 usage(); 136 exit(0); 137 } 138 } 139 140 argc -= optind; 141 argv += optind; 142 optind = 0; 143 144 dd = hci_open_dev(dev); 145 if (dd < 0) { 146 fprintf(stderr, "Can't open device hci%d: %s (%d)\n", 147 dev, strerror(errno), errno); 148 exit(1); 149 } 150 151 if (hci_read_local_version(dd, &ver, 1000) < 0) { 152 fprintf(stderr, "Can't read version for hci%d: %s (%d)\n", 153 dev, strerror(errno), errno); 154 hci_close_dev(dd); 155 exit(1); 156 } 157 158 if (ver.manufacturer != 37 && ver.manufacturer != 48) { 159 fprintf(stderr, "Can't find supported device hci%d: %s (%d)\n", 160 dev, strerror(ENOSYS), ENOSYS); 161 hci_close_dev(dd); 162 exit(1); 163 } 164 165 if (ericsson_write_events(dd, 0x03) < 0) { 166 fprintf(stderr, "Can't activate events for hci%d: %s (%d)\n", 167 dev, strerror(errno), errno); 168 hci_close_dev(dd); 169 exit(1); 170 } 171 172 hci_close_dev(dd); 173 174 return 0; 175 } 176