void uevents_setup(void) { OUTC(PRE "setting up uevent..."); ep_fd=(k_i)sysc(epoll_create1,1,0); if(K_ISERR(ep_fd)){ OUT("ERROR(%d):unable to create epoll fd\n",ep_fd); sysc(exit_group,1,-1); } //---------------------------------------------------------------------------- //blocking socket s=(k_i)sysc(socket,3,K_PF_NETLINK,K_SOCK_RAW, K_NETLINK_KOBJECT_UEVENT); if(K_ISERR(s)){ OUT("ERROR(%d):unable to create uevent netlink socket\n",s); sysc(exit_group,1,-1); } //---------------------------------------------------------------------------- k_i recv_buf_sz=128*1024;//128k for kernel buffering k_l r=sysc(setsockopt,5,s,K_SOL_SOCKET,K_SO_RCVBUFFORCE,&recv_buf_sz, sizeof(recv_buf_sz)); if(K_ISERR(r)){ OUT("ERROR(%ld):unable to force the size of the socket buffer\n",r); sysc(exit_group,1,-1); } //---------------------------------------------------------------------------- //uevent groups-->only one: 1 struct k_sockaddr_nl addr={K_AF_NETLINK,0,0,1}; r=sysc(bind,3,s,&addr,sizeof(addr)); if(K_ISERR(r)){ OUT("ERROR(%ld):unable to bind address to uevent netlink socket\n",r); sysc(exit_group,1,-1); } //---------------------------------------------------------------------------- struct k_epoll_event ep_evt; u_memset(&ep_evt,0,sizeof(ep_evt)); ep_evt.events=K_EPOLLIN; ep_evt.data.fd=s; r=sysc(epoll_ctl,4,ep_fd,K_EPOLL_CTL_ADD,s,&ep_evt); if(K_ISERR(r)){ OUT("ERROR(%ld):unable to register uevent netlink socket to epoll\n",r); sysc(exit_group,1,-1); } OUTC("done\n"); }
void uevents_cleanup(void) { k_l r; do r=sysc(close,1,ep_fd); while(r==-K_EINTR); if(K_ISERR(r)){ OUT("ERROR(%ld):unable to close epoll fd\n",r); sysc(exit_group,1,-1); } do r=sysc(close,1,s); while(r==-K_EINTR); if(K_ISERR(r)){ OUT("ERROR(%ld):unable to close netlink socket\n",r); sysc(exit_group,1,-1); } }
void wl_display_req_sync(k_u32 callback_id) { k_u32 req[REQ_SYNC_DWS]; req[0]=WL_DISPLAY_ID; req[1]=((REQ_SYNC_DWS*sizeof(k_u32))<<16)|WL_DISPLAY_SYNC; req[2]=callback_id; struct k_io_vec iov; iov.base=&req; iov.len=sizeof(req); struct k_msg_hdr msg; u_memset(&msg,0,sizeof(msg)); msg.iov=&iov; msg.iov_len=1; k_l r; do r=sysc(sendmsg,3,srv_so,&msg,0);while(r==-K_EINTR); if(K_ISERR(r)){ PERR("FATAL(%d):unable to send the sync request\n",r); sysc(exit_group,1,-1); } if(!r) sysc(exit_group,1,0);//server is gone }
static void uevent_msg(void) { k_u8 buf[8192];//presume 8kB is enough for one message u_memset(buf,0,sizeof(buf)); struct k_io_vec io_vec; io_vec.base=buf; io_vec.len=sizeof(buf); struct k_msg_hdr msg; u_memset(&msg,0,sizeof(msg)); msg.iov=&io_vec; msg.iov_len=1; k_l r; do r=sysc(recvmsg,3,s,&msg,0); while(r==-K_EINTR); if(K_ISERR(r)){ OUT("ERROR(%ld):unable to receive the uevent\n",r); sysc(exit_group,1,-1); } if(msg.flgs&K_MSG_TRUNC){ OUT("ERROR:the uevent was truncated(flags=0x%x)\n",msg.flgs); sysc(exit_group,1,-1); } uevent_process(&buf[0],(k_i)r); }
void wl_shm_req_create_pool(k_u32 shm,k_u32 shm_pool,k_i fd,k_u32 sz) { k_u32 req[REQ_PAYLOAD_CREATE_POOL_DWS]; req[0]=shm; req[1]=(REQ_PAYLOAD_CREATE_POOL_DWS*sizeof(k_u32))<<16|WL_SHM_CREATE_POOL; req[2]=shm_pool; req[3]=sz; struct k_io_vec iov; iov.base=&req; iov.len=REQ_PAYLOAD_CREATE_POOL_DWS*sizeof(k_u32); struct k_msg_hdr msg; k_u8 cmsg_buf[K_CMSG_SPACE(sizeof(fd))]; u_memset(&msg,0,sizeof(msg)); u_memset(cmsg_buf,0,sizeof(cmsg_buf)); msg.ctl=cmsg_buf; msg.ctl_len=sizeof(cmsg_buf); struct k_cmsg_hdr *cmsg=K_CMSG_FIRSTHDR(&msg); cmsg->lvl=K_SOL_SOCKET; cmsg->type=K_SCM_RIGHTS; cmsg->len=K_CMSG_LEN(sizeof(fd)); msg.iov=&iov; msg.iov_len=1; *((k_i*)(K_CMSG_DATA(K_CMSG_FIRSTHDR(&msg))))=fd; k_l r; do r=sysc(sendmsg,3,srv_so,&msg,0);while(r==-K_EINTR); if(K_ISERR(r)){ PERR("FATAL(%ld):unable to send the shm create_pool request\n",r); sysc(exit_group,1,-1); } if(r!=REQ_PAYLOAD_CREATE_POOL_DWS*sizeof(k_u32)){ PERR("FATAL:shm::create_pool request only %ld/%ld was sent\n",r, REQ_PAYLOAD_CREATE_POOL_DWS*sizeof(k_u32)); sysc(exit_group,1,-1); } if(!r) sysc(exit_group,1,0);//server is gone }
void uevents_process(void) { OUTC(PRE "processing uevents...\n"); while(1){ k_l r; static struct k_epoll_event evts;//uevent netlink event do{ u_memset(&evts,0,sizeof(evts)); r=sysc(epoll_wait,4,ep_fd,&evts,1,UEVENTS_TIMEOUT); }while(r==-K_EINTR); if(K_ISERR(r)){ OUT(PRE "ERROR(%ld):error epolling uevent netlink socket\n",r); sysc(exit_group,1,-1); } if(!r) break;//assume no more uevents if(evts.events&K_EPOLLIN) uevent_msg(); else{ OUT(PRE "ERROR:unmanaged epolling event on uevent netlink socket" "(events=%u)\n",evts.events); sysc(exit_group,1,-1); } } OUTC(PRE "uevents processed\n"); }