📄 sdp.c
字号:
l2cap->upper_con = (void*) sdp; } else DSYS(__FUNCTION__ " already sent back a pos response\n"); } else { D_ERR(__FUNCTION__ " couldn't find the correct sdp_connection\n"); bt_connect_cfm(CREATE_SDP_ID(sdp->line, 0), -1); }}/* Sends back info about MTU, outflow, flush timeout Get this data from some parameter area controlled by control block ? */void sdp_config_ind(l2cap_con* l2cap){ D_MISC(__FUNCTION__ " remote cid : %d\n", l2cap->remote_cid); /* FIXME -- Check whether the received params are acceptable, accept all for now */ /* check if we have sent a pos response yet */ if (!l2ca_remote_conf_done(l2cap)) { /* still haven't sent a pos configure response*/ if (l2ca_config_rsp(l2cap, 0, NULL, CONF_SUCCESS)) { D_ERR(__FUNCTION__ " Conf rsp failed\n"); } } else DSYS("already have sent back a pos response\n"); /* check if we received a pos response on a previous config req */ if (!l2ca_local_conf_done(l2cap)) { /* FIXME -- use real options not static values */ if (l2ca_config_req(l2cap, 0, NULL, 0, 0)) { D_ERR(__FUNCTION__ " Config request failed\n"); } } else D_REC("already ready with config req\n");}#ifdef __KERNEL__/*---------------------------------------------------------------------------*//* sdpStartRequest() - This function is used to initiate a SDP request. *//*---------------------------------------------------------------------------*/int sdpStartRequest(u8 sdpIndex, u8 sdpCommand, u8 *pduData, u16 pduLength){ s32 returnValue = -1; /*-------------------------------------------------------------------*/ /* Check the connection state. State must be SDP_CONNECTED. */ /*-------------------------------------------------------------------*/ if (sdp_con_list[sdpIndex].state == SDP_CONNECTED) { /*-----------------------------------------------------------*/ /* Initiate a query here. Send a SDP_SERVICESEARCH_REQ. */ /*-----------------------------------------------------------*/ sdp_tx_buf *sdp_buf; bt_tx_buf *tx_buf; u32 sdp_frame_len; u16 trans_id; /*-----------------------------------------------------------*/ /* What are we sending in the PDU? */ /* */ /* A BB CC D E F GG */ /* A = SDP_SERVICESEARCH_REQ */ /* BB = Transaction ID */ /* CC = PDU Length (not including header). */ /* D = Data Element Sequence Header (0x35) */ /* E = Number of bytes (which in this case is 3) */ /* F = UUID16_HDR (1 bytes) (0x19). */ /* GG = PublicBrowseGroup (0x1002). */ /* Total number of bytes 10. */ /*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/ /* Generate random tranaction ID. */ /*-----------------------------------------------------------*/ get_random_bytes(&trans_id, 2 /* bytes */); /*-----------------------------------------------------------*/ /* Allocate the buffer. */ /*-----------------------------------------------------------*/ sdp_frame_len = SDP_HDR_SIZE + pduLength; tx_buf = subscribe_bt_buf(sizeof(sdp_tx_buf) + sdp_frame_len); if (!tx_buf) { D_ERR(__FUNCTION__ " failed to get tx buffer\n"); } else { /*---------------------------------------------------*/ /* Set the current length of the transmission buffer */ /*---------------------------------------------------*/ tx_buf->cur_len = sdp_frame_len; /*---------------------------------------------------*/ /* Poke the SDP header. */ /* Notice that the "poking" is in little endian */ /*---------------------------------------------------*/ sdp_buf = (sdp_tx_buf*) (tx_buf->data); sdp_buf->frame[0] = sdpCommand; sdp_buf->frame[1] = (trans_id >> 8) & 0xff; sdp_buf->frame[2] = trans_id & 0xff; sdp_buf->frame[3] = (pduLength >> 8) & 0xff; sdp_buf->frame[4] = pduLength & 0xff; /*---------------------------------------------------*/ /* Copy the pduData. */ /*---------------------------------------------------*/ memcpy(&sdp_buf->frame[5], pduData, pduLength); /*---------------------------------------------------*/ /* Send the l2cap data transfer. */ /*---------------------------------------------------*/ l2cap_send_data(tx_buf, sdp_con_list[sdpIndex].l2cap); DSYS(__FUNCTION__ " Client finished sending data.\n"); returnValue = 0; } } else { /*-----------------------------------------------------------*/ /* No active SDP connection here!. This is an error. */ /*-----------------------------------------------------------*/ D_ERR(__FUNCTION__ " No active connection on SDP ID = %d\n", sdpIndex); } return returnValue;} /* End of sdpStartRequest() */#endif /* __KERNEL__ */void sdp_config_cfm(l2cap_con *l2cap, s32 status){ sdp_con *sdp = NULL; D_MISC(__FUNCTION__ ", remote cid : %d\n", l2cap->remote_cid); if (!l2cap->upper_con) { D_ERR("%s l.%d NULL/magic failed\n", __FILE__, __LINE__); return; } /*-------------------------------------------------------------------*/ /* Get a pointer to the correct SDP data connection structure entry. */ /*-------------------------------------------------------------------*/ sdp = (sdp_con *)l2cap->upper_con; /*-------------------------------------------------------------------*/ /* Set the state of this SDP connection to SDP_CONNECTED. */ /*-------------------------------------------------------------------*/ sdp->state = SDP_CONNECTED; /*-------------------------------------------------------------------*/ /* Check to see if we're the initiator on this running stack. If */ /* initator, this is a SDP client connection request. If not, then */ /* we're the server and must process requests. */ /*-------------------------------------------------------------------*/ if (sdp->initiator) { /*-----------------------------------------------------------*/ /* We are the initator. Therefore a SDP client on on this */ /* machine initiated the connection. Inform the "ioctl" or */ /* bluetooth layer. */ /*-----------------------------------------------------------*/ bt_connect_cfm(CREATE_SDP_ID(sdp->line, 0), ((sdp_con *)l2cap->upper_con)->id); } else { DSYS(__FUNCTION__ ", we are the server\n"); }}void sdp_disconnect_req(u32 sdp_id){ s32 err; /*-------------------------------------------------------------------*/ /* Get a handle to the proper SDP connection entry. */ /*-------------------------------------------------------------------*/ sdp_con *sdp = &sdp_con_list[sdp_id]; /*-------------------------------------------------------------------*/ /* Do some sanity checking. If the sdpConnectionIndex is within */ /* range AND the state is either SDP_CONNECTING or SDP_CONNECTED */ /* then disconnect this connection. */ /*-------------------------------------------------------------------*/ if (sdp_id <= MAX_NBR_SDP && (sdp->state == SDP_CONNECTING || sdp->state == SDP_CONNECTED)) { if ((err = l2ca_disconnect_req(sdp_con_list[sdp_id].l2cap)) != 0) { D_ERR(__FUNCTION__ ", An error with error code %d occured during disconnetion of sdp channel %d\n", err, sdp_id); sdp_con_list[sdp_id].state = SDP_DISCONNECTED; sdp_con_list[sdp_id].l2cap = NULL; } #if 0 /* sdp_disconnect_cfm wakes up this queue, but by the time we get here it already did, so we sleep forever! */else { interruptible_sleep_on(&sdp_disc_wq); }#endif }}void sdp_disconnect_ind(l2cap_con *l2cap) { sdp_con *sdp; D_MISC(__FUNCTION__ ", remote cid : %d\n", l2cap->remote_cid); sdp = (sdp_con*) l2cap->upper_con; sdp->state = SDP_DISCONNECTED; sdp->l2cap = NULL; l2ca_disconnect_rsp(l2cap);}void sdp_disconnect_cfm(l2cap_con *l2cap){ sdp_con *sdp; u8 line; D_MISC(__FUNCTION__ ", remote cid : %d\n", l2cap->remote_cid); sdp = (sdp_con*) l2cap->upper_con; line = sdp->line; sdp->state = SDP_DISCONNECTED; sdp->l2cap = NULL; bt_unregister_sdp(line); wake_up_interruptible(&sdp_disc_wq);}void sdp_receive_data(l2cap_con *l2cap, u8* data, u32 len){ sdp_con *sdp; data_struct *db_hdl; D_REC(__FUNCTION__ "\n"); if (role == 0) { print_data(__FUNCTION__, data, len); return; } PRINTPKT(__FUNCTION__, data, len); sdp = (sdp_con*) l2cap->upper_con;#ifndef __KERNEL__ if (sdp_sock < 0) { send_error_rsp(sdp, le16_to_cpu(get_unaligned((u16 *)&data[1])), 6); }#endif /*--------------------------------------------------------*/ /* If __KERNEL__ mode, we must bounce the received data */ /* up if this stack initiated the request. */ /*--------------------------------------------------------*/#if __KERNEL__ if (sdp->initiator) { u8 *dataPointer = NULL; /*------------------------------------------------------*/ /* Grab a copy of the data to send up. */ /*------------------------------------------------------*/ dataPointer = (u8 *) kmalloc(len, GFP_ATOMIC); memcpy(dataPointer, data, len); bt_send_sdp_data_received(sdp->line, dataPointer, len); } else#endif { db_hdl = (data_struct*)database_query.query; db_hdl->l2cap_mtu = l2cap->remote_mtu; db_hdl->sdp_con_id = sdp->id; db_hdl->len = len; memcpy(db_hdl->data, data, len); database_query.count = sizeof(data_struct) + len;#ifdef __KERNEL__ D_PROC("wake_up process %i (%s) awakening\n", current->pid, current->comm); wake_up_interruptible(&database_wq); D_PROC("wake_up process %i (%s) woke up\n", current->pid, current->comm);#else sdp_doquery(sdp_sock, database_query.query, database_query.count);#endif }}#ifndef __KERNEL__ s32send_error_rsp(sdp_con *sdp, u16 trans_id, u16 err_code){ sdp_tx_buf *sdp_buf; bt_tx_buf *tx_buf; u32 sdp_frame_len; u32 pdu_len; /* Since we do not send any error information the pdu length is just the size of the error code length, which is two bytes */ pdu_len = 2; sdp_frame_len = SDP_HDR_SIZE + pdu_len; tx_buf = subscribe_bt_buf(sizeof(sdp_tx_buf) + sdp_frame_len); if (!tx_buf) { D_ERR(__FUNCTION__ " failed to get tx buffer\n"); return -1; } tx_buf->cur_len = sdp_frame_len; sdp_buf = (sdp_tx_buf*) (tx_buf->data); sdp_buf->frame[0] = SDP_ERROR_RSP; sdp_buf->frame[1] = (trans_id >> 8) & 0xff; sdp_buf->frame[2] = trans_id & 0xff; sdp_buf->frame[3] = (pdu_len >> 8) & 0xff; sdp_buf->frame[4] = pdu_len & 0xff; sdp_buf->frame[5] = (err_code >> 8) & 0xff; sdp_buf->frame[6] = err_code & 0xff; return l2cap_send_data(tx_buf, sdp->l2cap);}#endif#ifdef __KERNEL__s32 sdp_proc_dir_entry_read(char *buf, char **start, off_t offset, s32 len, s32 unused){#ifdef USE_NEW_PROC return sdp_database_read(NULL, buf, len, 0);#else return sdp_database_read(NULL, NULL, buf, len);#endif}#ifdef USE_NEW_PROCssize_t sdp_database_read(struct file *f, char *buf, size_t count, loff_t *offset)#elses32 sdp_database_read(struct inode *inode, struct file * file, char * buf, s32 count)#endif{ s32 len; D_PROC(__FUNCTION__ " Someone is trying to read %d bytes from sdp proc-file\n", count); cli(); if (database_query.count <= 0) { D_PROC(__FUNCTION__ " No bytes available, going to sleep\n"); interruptible_sleep_on(&database_wq); } sti(); len = MIN(count, database_query.count); copy_to_user(buf, database_query.query, len); if (database_query.count > len) { memmove(database_query.query, database_query.query + len, database_query.count - len); } database_query.count -= len; D_PROC(__FUNCTION__ " Returning %d bytes\n", len); return len;}#ifdef USE_NEW_PROCssize_t sdp_database_write(struct file *f, const char *buf, size_t count, loff_t *offset)#elses32 sdp_database_write(struct inode *inode, struct file * file, const char * buf, s32 count)#endif{ static data_struct db_hdl; sdp_tx_buf *sdp_buf; s32 read1 = 0; s32 read2 = 0; D_PROC(__FUNCTION__ " Someone wrote %d bytes to sdp proc-file\n", count); if (!bt_initiated()) return 0; if (!db_write_tx_buf) { read1 = MIN(sizeof db_hdl - db_write_recv, count); copy_from_user(&db_hdl + db_write_recv, buf, read1); db_write_recv += read1; if (db_write_recv < sizeof db_hdl) return read1; db_write_tx_buf = subscribe_bt_buf(sizeof *sdp_buf + db_hdl.len); if (!db_write_tx_buf) { D_ERR(__FUNCTION__ " failed to get tx buffer\n"); db_write_recv -= read1; return -ENOMEM; } db_write_tx_buf->cur_len = db_hdl.len; count -= read1; buf += read1; db_write_recv = 0; } sdp_buf = (sdp_tx_buf*)db_write_tx_buf->data; if (db_write_recv < db_hdl.len) { read2 = MIN(db_hdl.len - db_write_recv, count); copy_from_user(sdp_buf->frame + db_write_recv, buf, read2); db_write_recv += read2; if (db_write_recv < db_hdl.len) return read1 + read2; } D_XMIT(__FUNCTION__ " preparing to send %d bytes data to sdp_con[%d]\n", db_hdl.len, db_hdl.sdp_con_id); PRINTPKT("Data to be sent to client:", db_hdl.data, db_hdl.len); l2cap_send_data(db_write_tx_buf, sdp_con_list[db_hdl.sdp_con_id].l2cap); db_write_tx_buf = NULL; db_write_recv = 0; return read1 + read2;}#else /* __KERNEL__ */s32 sdp_doquery(s32 fd, u8 *request, s32 len){ s32 n; u8 tmpbuf[512]; data_struct *db_hdl; s32 recv; D_XMIT("sdp_doquery : sending request %d bytes\n", len); write(fd, request, len); if ((n = read(fd, tmpbuf, 512)) < 0) return n; D_REC(__FUNCTION__ ", Received %d bytes\n", n); db_hdl = (data_struct*) tmpbuf; /* what if not all is written once */ for (recv = n; recv < sizeof *db_hdl + db_hdl->len; recv += n) if ((n = read(fd, tmpbuf + recv, 512 - recv)) < 0) return n; sdp_send_data(&sdp_con_list[db_hdl->sdp_con_id], db_hdl->data, db_hdl->len); return recv;}#endifs32sdp_send_data(sdp_con *sdp, u8 *data, u32 len){ sdp_tx_buf *sdp_buf; bt_tx_buf *tx_buf; tx_buf = subscribe_bt_buf(sizeof(sdp_tx_buf) + len); if (!tx_buf) { D_ERR("sdp_send_data: failed to get tx buffer\n"); return -1; } tx_buf->cur_len = len; sdp_buf = (sdp_tx_buf*) (tx_buf->data); memcpy(sdp_buf->frame, data, len); PRINTPKT("SDP sending:", (u8*) data, len); return l2cap_send_data(tx_buf, sdp->l2cap);}sdp_con* get_free_sdp_con(void){ s32 i = 0; while ((i < MAX_NBR_SDP) && (sdp_con_list[i].state != SDP_DISCONNECTED)) { i++; } if (i == MAX_NBR_SDP) { return 0; } return &sdp_con_list[i];}/****************** END OF FILE sdp.c ***************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -