📄 bt_if.c
字号:
void bt_set_local_name(int bt_cfd, const unsigned char *name){ unsigned char buffer[248]; int i = 0; syslog(LOG_INFO, __FUNCTION__ ": %s", name); /* Hack to convert ISO 8859-1 to UTF-8 */ for (; *name && i < sizeof buffer - 3; name++) { if (*name < 128) { buffer[i++] = *name; } else { buffer[i++] = 0xC0 | (*name >> 6); buffer[i++] = 0x80 | (*name & 0x3F); } } buffer[i] = '\0';#ifndef BT_USERSTACK if (ioctl(bt_cfd, HCISETLOCALNAME, buffer) < 0) { perror(__FUNCTION__); exit(1); }#else hci_change_local_name(buffer);#endif}int bt_read_country_code(int bt_cfd){ int result;#ifndef BT_USERSTACK if (ioctl(bt_cfd, HCIREADCOUNTRYCODE, &result) < 0) { perror(__FUNCTION__); exit(1); } return result;#else return hci_read_country_code();#endif}/* ============================================================ *//* Misc functions *//* See bt_errno.h for error codes */const char *error_msg(int err){ int layer, code, msg; msg = -err; layer = MSG_GET_LAYER(msg); code = MSG_GET_CODE(msg); switch(layer) { case MSG_LAYER_HCI: switch(code) { case 0x00: return "HCI: Success!"; case 0x01: return "HCI: Unknown HCI Command"; case 0x02: return "HCI: No Connection"; case 0x03: return "HCI: Hardware Failure"; case 0x04: return "HCI: Page Timeout"; case 0x05: return "HCI: Authentication Failure"; case 0x06: return "HCI: Key Missing"; case 0x07: return "HCI: Memory Full"; case 0x08: return "HCI: Connection Timeout"; case 0x09: return "HCI: Max Number Of Connections"; case 0x0A: return "HCI: Max Number Of SCO Connections To A Device"; case 0x0B: return "HCI: ACL connection already exists"; case 0x0C: return "HCI: Command Disallowed"; case 0x0D: return "HCI: Host Rejected due to limited resources"; case 0x0E: return "HCI: Host Rejected due to security reasons"; case 0x0F: return "HCI: Host Rejected due to remote device is only a personal device"; case 0x10: return "HCI: Host Timeout"; case 0x11: return "HCI: Unsupported Feature or Parameter Value"; case 0x12: return "HCI: Invalid HCI Command Parameters"; case 0x13: return "HCI: Other End Terminated Connection: User Ended Connection"; case 0x14: return "HCI: Other End Terminated Connection: Low Resources"; case 0x15: return "HCI: Other End Terminated Connection: About to Power Off"; case 0x16: return "HCI: Connection Terminated by Local Host"; case 0x17: return "HCI: Repeated Attempts"; case 0x18: return "HCI: Pairing Not Allowed"; case 0x19: return "HCI: Unknown LMP PDU"; case 0x1A: return "HCI: Unsupported Remote Feature"; case 0x1B: return "HCI: SCO Offset Rejected"; case 0x1C: return "HCI: SCO Interval Rejected"; case 0x1D: return "HCI: SCO Air Mode Rejected"; case 0x1E: return "HCI: Invalid LMP Parameters"; case 0x1F: return "HCI: Unspecified Error"; case 0x20: return "HCI: Unsupported LMP Parameter Value"; case 0x21: return "HCI: Role Change Not Allowed"; case 0x22: return "HCI: LMP Response Timeout"; case 0x23: return "HCI: LMP Error Transaction Collision"; case 0x24: return "HCI: LMP PDU Not Allowed"; case 0x25: return "HCI: Encryption Mode Not Acceptable"; case 0x26: return "HCI: Unit Key Used"; case 0x27: return "HCI: QOS is Not Supported"; case 0x28: return "HCI: Instant Passed"; case 0x29: return "HCI: Pairing with Unit Key Not Supported"; default: return "HCI: No debug msg defined"; } case MSG_LAYER_L2CAP: switch(code) { case L2CAP_SUCCESS: return "L2CAP: Success"; case L2CAP_CON_PENDING: return "L2CAP: Connection Pending"; case L2CAP_PSMNEG: return "L2CAP: Connection Refused, PSM Not Accepted"; case L2CAP_SECNEG: return "L2CAP: Connection Refused, Authentication Failed"; case L2CAP_NOSRC: return "L2CAP: Connection Refused, No Resources"; case L2CAP_FAILED: return "L2CAP: General Error"; case L2CAP_CON_UNRESPONSIVE: return "L2CAP: No Reply From Remote"; case L2CAP_INVALID_STATE: return "L2CAP: Invalid State"; case L2CAP_NO_CONNECTION: return "L2CAP: No Connection"; case L2CAP_EXCEED_REMOTE_MTU: return "L2CAP: Trying to send a frame more than remote MTU"; case L2CAP_RTX_TIMEOUT: return "L2CAP: Timeout Waiting For Remote To Reply"; default: return "L2CAP: No debug msg defined"; } case MSG_LAYER_RFCOMM: switch(code) { case RFCOMM_INVALID_LINE: return "RFCOMM: Trying to use an invalid line"; case RFCOMM_SRVCHN_CONNECTED: return "RFCOMM: Serverchannel already connected"; case RFCOMM_NO_DATA_ALLOWED: return "RFCOMM: No data allowed on control channel"; case RFCOMM_NO_CONNECTION: return "RFCOMM: No connection"; case RFCOMM_BAD_MAGIC_NUMBER: return "RFCOMM: Bad magic number"; default: return "RFCOMM: No debug msg defined"; } case MSG_LAYER_SDP: switch(code) { default: return "SDP: No debug msg defined"; } case MSG_LAYER_TCS: switch(code) { default: return "TCS: No debug msg defined"; } case MSG_BT_INTERFACE: switch(code) { case BT_NOTCONNECTED: return "BT_INTERFACE: Line Not Connected"; case BT_ALREADYCONNECTED: return "BT_INTERFACE: Line Already Connected"; case BT_TIMEOUT: return "BT_INTERFACE: Timeout When Processing Command"; case BT_LINE_BUSY: return "BT_INTERFACE: Line Busy"; default: return "BT_INTERFACE: No debug msg defined"; } default: return "General Failure"; }}const char* psmname(unsigned short psm){ switch(psm) { case RFCOMM_LAYER: return "RCOMM"; case SDP_LAYER: return "SDP"; case TCS_LAYER: return "TCS"; default: return "UNKNOWN"; }}int open_device(char* dev, int flags, int role){ int fd;#ifdef BT_USERSTACK /* if opening bt dev or control dev simply discard and return fake fd */ if ((strncmp(dev, "/dev/ttyBT", 11) == 0) || (strcmp(dev, BT_CTRL_TTY) == 0)) return 0xb055e;#if 0 /* fixme */ if (use_local_socket) return open_socket(dev, role); else if (use_tcp_socket) return open_tcpsocket(dev, role);#endif#endif D(syslog(LOG_INFO, "Opening dev %s", dev)); if ((fd = open(dev, flags | O_NOCTTY)) < 0) { perror(__FUNCTION__); exit(1); } tcflush(fd, TCIOFLUSH); return fd;}void close_device(int fd){ D(syslog(LOG_INFO, __FUNCTION__)); #ifdef BT_USERSTACK /* if fake fd is used, ignore close since there are no open fd */ if (fd != 0xb055e) close(fd);#else if (fd != -1) close(fd);#endif}int start_sdp_server(void){ int sdpsrv_pid; char *args[] = { SDPSRV_CMD, SDPSRV_CONF, SDPSRV_PROC, NULL }; D(syslog(LOG_INFO, "Starting SDP server [%s]", SDPSRV_CMD)); if (!(sdpsrv_pid = vfork())) { execvp(SDPSRV_CMD, args); fprintf(stderr, "%s: no such file or directory\n", SDPSRV_CMD); syslog(LOG_INFO, "%s not found", SDPSRV_CMD); _exit(0); } return sdpsrv_pid;}/* ============================================================= *//* Functions used in usermode stack only *//* ============================================================= *//* * * FIXME -- NOT CHECKED AT ALL AFTER SPLIT UP OF BTD !!!! * */#ifdef BT_USERSTACK#if BT_DATADUMP_DEBUG#define BT_DATADUMP(str, data, len) print_data(str, data, len)#else#define BT_DATADUMP(str, data, len)#endif#if BT_DATA_DEBUG#if BT_USE_TIMESTAMPS#define BT_DATA(fmt...) do {print_time(1);printk(BT_DBG_STR"DATA " fmt);} while (0)#else#define BT_DATA(fmt...) printk(BT_DBG_STR"DATA " fmt)#endif /* BT_USE_TIMESTAMPS */#else /* BT_DATA_DEBUG */#define BT_DATA(fmt...)#endif /* BT_DATA_DEBUG */int init_read_thread(void){ printf("Initiating read thread\n"); if (pthread_create(&read_thread, NULL, (void*)hci_receive_thread, NULL) != 0) perror(__FUNCTION__); sleep(1); /* wait for thread to start */ return 0;}void hci_receive_thread(void){ fd_set rfd; char databuf[4096]; while (1) { FD_ZERO(&rfd); FD_SET(phys_fd, &rfd); select(phys_fd+1, &rfd, NULL, NULL, NULL); if (FD_ISSET(phys_fd, &rfd)) { int len = read(phys_fd, &databuf, 4096); if (len > 0) { BT_DATA("-->|X| %3d\n", len); BT_DATADUMP("-->|X|", databuf, len); hci_receive_data(databuf, len); } } }}voidinit_upper_pty(void){ printf(__FUNCTION__);// open_pty();// init_pty_thread(); }void init_userstack(){ /* Direct function calls instead of ioctls... */ init_read_thread(); /* Initialise all layers in the bluetooth stack */ DSYS("Initialising Bluetooth Stack\n"); hci_init(); l2cap_init(); rfcomm_init(); sdp_init(SERVER); tcs_init(); test_init(); btmem_init(); unplug_test_init(); bt_stat.bytes_received = 0; bt_stat.bytes_sent = 0; bt_initdone = 1;}/* ============================================================= *//* Stack interface functions */int bt_write_lower_driver(unsigned char *data, int len){ int i; BT_DATA("<--|X| %3d\n", len); BT_DATADUMP("<--|X|", data, len); i = write(phys_fd, data, len); return i;}/* Only works for the last connected rfcomm session */intbt_write_top(char *buf, int count, int line){ int retval; int bytes_sent = 0; BT_DATA(" |X|<-- %3d [%d]\n", count, line); BT_DATADUMP("|X|<--", buf, count); while (bytes_sent!=count) { retval = rfcomm_send_data(CREATE_RFCOMM_ID(line,test_dlci), buf + bytes_sent, count-bytes_sent); if (retval > 0) bytes_sent+=retval; else if (retval==0) usleep(1000); /* wait some ... */ else { printf("error\n"); return retval; } usleep(1000); /* wait some time ... */ }; bt_stat.bytes_sent+=bytes_sent; return bytes_sent;}int bt_receive_top(rfcomm_con *rfcomm, unsigned char *data, int len){ int n = 0; BT_DATA(" |X|--> %3d [%d]\n", len, rfcomm->line); BT_DATADUMP("|X|-->", data, len);#if 0 /* fixme */ if (modem_emulation && !modem_connected) { modem_emulator(0xb055e, data, len); return len; } /* FIXME<2> -- why is data echoed back if no application is running on top of PTY ?? */ if (!ready_for_ppp) return len; /* feed this to PTY connected to pppd or whatever application that may be running there... */ if ((n = write(pty_master_fd, data, len)) != len) { BT_DATA(__FUNCTION__ ": tried to write %d bytes, wrote %d\n", len, n); }#endif bt_stat.bytes_received+=n; return n;}voidbt_connect_ind(unsigned int con_id) { if (GET_PSM(con_id) == RFCOMM_LAYER) printf(__FUNCTION__ ": RFCOMM dlci : %d\n", GET_RFCOMMDLCI(con_id)); else printf(__FUNCTION__ ": psm %d\n", GET_PSM(con_id));}voidbt_connect_cfm(unsigned int con_id, int status){ unsigned short psm; int line; psm = GET_PSM(con_id); if (status) { /* fixme -- only works for rfcomm now */ line = GET_LINE(con_id); if ((line < 0) || (line > BT_NBR_DATAPORTS)) { fprintf(stderr, __FUNCTION__ ": invalid line (%d)\n", line); return; } fprintf(stderr, __FUNCTION__": failed, status %d [%s] line %d\n", status, psmname(psm), line); return; } switch (psm) { case RFCOMM_LAYER: printf(__FUNCTION__ ": [%s]\n", psmname(psm)); break; case SDP_LAYER: printf(__FUNCTION__ ": [%s]\n", psmname(psm)); break; case TCS_LAYER: printf(__FUNCTION__ ": [%s]\n", psmname(psm)); break; default: printf(__FUNCTION__ ": unknown layer %d\n", psm); break; }}voidbt_disconnect_ind(unsigned int con_id) { if (GET_PSM(con_id) == RFCOMM_LAYER) printf(__FUNCTION__ ": RFCOMM dlci : %d\n", GET_RFCOMMDLCI(con_id)); else printf(__FUNCTION__ ": psm %d\n", GET_PSM(con_id));}intbt_register_rfcomm(struct rfcomm_con *rfcomm, u8 dlci){ printf(__FUNCTION__ ": dlci %d\n", dlci); test_rfcomm = rfcomm; test_dlci = dlci; return 0;}s32bt_unregister_rfcomm(s32 line){ printf(__FUNCTION__ ": line %d\n", line); /* fixme -- stub for now */}s32bt_register_sdp(u8 line, u8 sdpID){ printf(__FUNCTION__ "\n"); return 0;}s32 bt_unregister_sdp(s32 line){ printf(__FUNCTION__ "\n"); return 0;}int bt_initiated(void){ return bt_initdone;}#endif /* BT_USERSTACK */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -