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 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); } }
ulinux_l arch_sigaction(ulinux_l num,struct ulinux_sigaction *kact, struct ulinux_sigaction *okact) { kact->sa_flags|=SA_RESTORER;//*MUST* have a restorer on x86_64, see above kact->sa_restorer=restore_rt;//bear rt_sigreturn syscall return sysc(rt_sigaction,4,num,kact,okact,sizeof(ulinux_ul)); }
static void ev_format(k_u32 fmt) { if(fmts_n>=FMTS_N_MAX) { PERRC("FATAL:too many shm formats\n"); sysc(exit_group,1,-1); } fmts[fmts_n++]=fmt; //DEBUG PERR("shm:received format %u\n",fmt); }
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 }
//------------------------------------------------------------------------------ k_u32 display_get_registry(void *registry_listener) { k_u32 registry_id=objs_add(WL_REGISTRY,registry_listener); if(registry_id==OBJS_MAX){ PERRC("FATAL:unable to add a registry object\n"); sysc(exit_group,1,-1); } wl_display_req_get_registry(registry_id); return registry_id; }
k_u32 shm_create_pool(k_i fd,k_u32 sz,void *listener) { k_u32 shm_pool_id=objs_add(WL_SHM_POOL,listener); if(shm_pool_id==OBJS_MAX) { PERRC("FATAL:unable to install the shm pool object\n"); sysc(exit_group,1,-1); } wl_shm_req_create_pool(id,shm_pool_id,fd,sz); return shm_pool_id; }
k_u32 registry_bind(struct gbl *g,void *listener) { k_u32 g_id=objs_add(g->itf,listener); if(g_id==OBJS_MAX){ PERRC("FATAL:registry::bind unable to add the object\n"); sysc(exit_group,1,-1); } wl_registry_req_bind(registry_id,g,g_id); return g_id; }
void shm_bind(void) { k_u shm; //we work with the first shm object advertized in the registry for(shm=0; shm<REGISTRY_N_MAX; ++shm) if(registry[shm].itf==WL_SHM) break; if(shm==REGISTRY_N_MAX) { PERRC("FATAL:unable to find a shm singleton in registry\n"); sysc(exit_group,1,-1); } id=registry_bind(®istry[shm],&shm_listener); }
void registry_add(k_u32 name,enum wl_itfs itf) { k_u i; for(i=0;i<REGISTRY_N_MAX;++i) if(registry[i].itf==WL_INVALID) break; if(i==REGISTRY_N_MAX){ PERR("FATAL:no room for global object name=%u interface=%s\n",name, wl_itfs_strs[itf]); sysc(exit_group,1,-1); } //DEBUG PERR("registry:adding object name=%u itf=%s\n",name,wl_itfs_strs[itf]); registry[i].itf=itf; registry[i].name=name; }
void display_sync(void (*done)(k_u32 serial)) { callbacks_listener.done=done; k_u32 callback_id=objs_add(WL_CALLBACK,&callbacks_listener); if(callback_id==OBJS_MAX){ PERRC("FATAL:unable to add a callback object\n"); sysc(exit_group,1,-1); } callbacks_id=callback_id;//record the current callback id wl_display_req_sync(callback_id); }
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"); }
static void ev_error(k_u32 id,k_u32 code,k_u8 *str) { PERR("FATAL:error received from the server, id=%u, code=%u, string=%s\n",id, code,str); sysc(exit_group,1,-1); }