void bu_hci::enque_acl(uint16_t handle, uint16_t cid, const sdata& sd) { TRACE("::"<<__FUNCTION__); bybuff aclbuf; uint16_t hf = (handle | (ACL_START_NO_FLUSH << 12)); #ifdef DEBUG //bybuff tr(sd.data, sd.len); //TRACE("toQ: handle:" << int(handle) << ", cid: " << int(cid)); //TRACE("toQ: [" <<int(tr.length())<<"]" << tr.to_string()); #endif // DEBUG aclbuf << uint16_t(sd.len); aclbuf << uint16_t(cid); aclbuf.append(sd.data, sd.len); int mtu = int(this->_aclMtu); int len = int(aclbuf.length()); int accum = 0; const uint8_t* paclbuff = aclbuf.buffer(); while(len > 0) { AclChunk a; int tocpy = std::min(mtu, len); a.acl.aclpkt = uint8_t(HCI_ACLDATA_PKT); a.acl.aclhndl = btohs((uint16_t(hf))); a.acl.length = btohs((uint16_t(tocpy))); hf |= (ACL_CONT << 12); a.aclsz = 5 + tocpy; ::memcpy(a.acl.buff, paclbuff + accum, tocpy); accum += tocpy; len -= tocpy; std::deque<AclChunk>& r = _aclOut[handle]; r.push_back(a); // TRACE("Adding hander " << int(handle)); } // TRACE("\nin Q: [" <<int(aclbuf.length())<<"]" << aclbuf.to_string()); // TRACE("Queue: " << _aclOut.size() << " of "<<_aclOut[handle].size() << " chunks"); flush_acl(); }
int bu_hci::on_sock_data(uint8_t code, const sdata& buffer) //received { uint8_t eventType = buffer.data[0]; uint16_t blen = buffer.len; std::string scase="NOT HANDLED "; bybuff trace(buffer.data, buffer.len); TRACE("{-->["<< int(buffer.len) <<"]"<< trace.to_string()); if (HCI_EVENT_PKT == eventType) { uint8_t subEventType = buffer.data[1]; //_TRACE(" Event:" << int(eventType) << ", subevent:" << int(subEventType)); switch(subEventType) { case EVT_DISCONN_COMPLETE: scase="EVT_DISCONN_COMPLETE"; { evt_disconn_complete* pdc = (evt_disconn_complete*)(buffer.data+4); pdc->handle = htobs(pdc->handle); memcpy(&_dcached, pdc, sizeof(_dcached)); #ifdef ACL_MTU_FRAG flush_acl(); #endif //ACL_MTU_FRAG _clear(); _pev->on_disconnect(pdc); _connected=false; } break; case EVT_ENCRYPT_CHANGE: scase="EVT_ENCRYPT_CHANGE"; { evt_encrypt_change* pec = (evt_encrypt_change*)(buffer.data+4); pec->handle=htobs(pec->handle); _pev->on_encrypt_chnage(pec); } break; case EVT_CMD_COMPLETE: scase=" [EVT_CMD_COMPLETE]"; { no_evt_cmd_complete* necc = (no_evt_cmd_complete*)(buffer.data+3); necc->cmd=htobs(necc->cmd); this->_oncmd_complette(necc); } break; case EVT_LE_META_EVENT: scase="EVT_LE_META_EVENT"; { no_evt_le_meta_event* pev = (no_evt_le_meta_event*)(buffer.data+3); this->_onmeta(pev); } break; case EVT_CONN_REQUEST: scase="EVT_CONN_REQUEST"; { evt_conn_request* preq= (evt_conn_request*)(buffer.data+4); bdaddr_t dest; baswap(&dest, &preq->bdaddr); memcpy(&preq->bdaddr,&dest,sizeof(dest)); } break; case EVT_CMD_STATUS: //OCF_AUTH_REQUESTED scase="EVT_CMD_STATUS"; { evt_cmd_status* pevs = (evt_cmd_status*)(buffer.data+4); pevs->opcode = htobs(pevs->opcode); uint16_t ogf = CMD_OPCODE_OGF(pevs->opcode); uint16_t ocf = CMD_OPCODE_OCF(pevs->opcode); TRACE("CMD_STATUS status:" <<int(pevs->status)<<" ncmd:" << int(pevs->ncmd) << " opcode(C/G):" << std::hex<<int(ocf) <<"/"<<int(ogf) << std::dec); if(ocf == OCF_EXIT_PERIODIC_INQUIRY) { //send_cmd(OCF_INQUIRY_CANCEL, OGF_LINK_CTL,0,0); } } break; case EVT_REMOTE_NAME_REQ_COMPLETE: scase="EVT_REMOTE_NAME_REQ_COMPLETE"; { evt_remote_name_req_complete* pnc = (evt_remote_name_req_complete*)(buffer.data+4); TRACE("remote name: " << pnc->name); } break; #ifdef ACL_MTU_FRAG case EVT_NUM_COMP_PKTS: scase="EVT_NUM_COMP_PKTS"; { uint8_t nhandles = uint8_t(buffer.data[3]); // TRACE("GOT number of completted acl packets:" << int(nhandles)); for(uint8_t h=0; h<nhandles; h++) { no_acl_handler_packet* pconfirm = (no_acl_handler_packet*)(buffer.data + 4 + (h*4)); pconfirm->handler = htobs(pconfirm->handler); pconfirm->packet = htobs(pconfirm->packet); // TRACE("GOT Pending handler:" << int(pconfirm->handler) << ", " << int(pconfirm->packet)); const auto& ah = _aclPending.find(pconfirm->handler); if(ah == this->_aclPending.end()) { // TRACE("HANDLER "<< int(pconfirm->handler) <<" NOT FOUND"); continue; } else { ah->second -= pconfirm->packet; if(ah->second <= 0) { // TRACE("DELETE ALL HANDLER packets:" <<",["<<int(pconfirm->handler) <<"]" << int(ah->second)); _erase_AclOut(ah->first); } } } this->flush_acl(); } break; #endif //ACL_MTU_FRAG default: break; }//switch } else if (HCI_ACLDATA_PKT == eventType) { uint16_t val = oa2t<uint16_t>(buffer.data,1); uint16_t flags = acl_flags(val); uint16_t handle = acl_handle(val); if(ACL_START_NO_FLUSH == flags) { //_clear_aclInQueue(); TODO scase="ACL_START_NO_FLUSH"; flags = ACL_START; } if (ACL_START == flags) { uint16_t cid = oa2t<uint16_t>(buffer.data,7); uint16_t expectedlen = oa2t<uint16_t>(buffer.data,5); uint16_t chunklen = blen-9; sdata sd; scase="ACL_START"; sd.len = expectedlen; sd.data = buffer.data + 9; if (expectedlen == chunklen) { _pev->on_acl_packet(handle,cid, sd); } else { /// assert(_aclIn.find(handle) == _aclIn.end()); //accumulate data bt handler if(_aclIn.find(handle) == _aclIn.end()) { no_acl_start_len_dynamic* pd = new(no_acl_start_len_dynamic); pd->cit = (cid); pd->len = (chunklen); pd->expectedlen = (expectedlen); pd->byarr.insert(pd->byarr.end(), sd.data, sd.data + sd.len); _aclIn[handle] = pd; } else { _TRACE("ERROR AHNDLER NOT FOUND ....!. \n" << handle); } } } else if (ACL_CONT == flags) { /// keep accumulating, or discard uint16_t chunklen = blen-9; sdata sd; scase="ACL_CONT"; auto el = _aclIn.find(handle); if (el == _aclIn.end()) return true; no_acl_start_len_dynamic* pd = el->second; pd->len += chunklen; pd->byarr.insert(pd->byarr.end(), sd.data, sd.data + sd.len); //assert(pd->expectedlen == expectedlen); if(pd->expectedlen == pd->len ) { sd.len = pd->len; sd.data = &pd->byarr[0]; _pev->on_acl_packet(handle, pd->cit, sd); delete pd; _aclIn.erase(handle); } } else { _TRACE("!!! HCI_ACLDATA_PKT unknown flag: " << std::hex << int(flags) << std::dec); } } else{ _TRACE("!!! NO KNOWN on_sock_data EVENTTYPE " << std::hex << int(eventType) << std::dec ); } //TRACE("HCI: " << scase << " }"); return true; }
int devnode_acl(const char *path, bool flush, bool del, uid_t old_uid, bool add, uid_t new_uid) { acl_t acl; int r = 0; bool changed = false; assert(path); acl = acl_get_file(path, ACL_TYPE_ACCESS); if (!acl) return -errno; if (flush) { r = flush_acl(acl); if (r < 0) goto finish; if (r > 0) changed = true; } else if (del && old_uid > 0) { acl_entry_t entry; r = acl_find_uid(acl, old_uid, &entry); if (r < 0) goto finish; if (r > 0) { if (acl_delete_entry(acl, entry) < 0) { r = -errno; goto finish; } changed = true; } } if (add && new_uid > 0) { acl_entry_t entry; acl_permset_t permset; int rd, wt; r = acl_find_uid(acl, new_uid, &entry); if (r < 0) goto finish; if (r == 0) { if (acl_create_entry(&acl, &entry) < 0) { r = -errno; goto finish; } if (acl_set_tag_type(entry, ACL_USER) < 0 || acl_set_qualifier(entry, &new_uid) < 0) { r = -errno; goto finish; } } if (acl_get_permset(entry, &permset) < 0) { r = -errno; goto finish; } rd = acl_get_perm(permset, ACL_READ); if (rd < 0) { r = -errno; goto finish; } wt = acl_get_perm(permset, ACL_WRITE); if (wt < 0) { r = -errno; goto finish; } if (!rd || !wt) { if (acl_add_perm(permset, ACL_READ|ACL_WRITE) < 0) { r = -errno; goto finish; } changed = true; } } if (!changed) goto finish; if (acl_calc_mask(&acl) < 0) { r = -errno; goto finish; } if (acl_set_file(path, ACL_TYPE_ACCESS, acl) < 0) { r = -errno; goto finish; } r = 0; finish: acl_free(acl); return r; }