void resmgr_enqueue_packet(event_bus_line_t *line, char *data, int size) { int nidx; struct _ocb_list *op; devi_attr_t *attr = line->attr; pthread_mutex_lock(&line->mutex); for (op = line->attr->ocb_list; op; op = op->next) { nidx = INC_PTR(line->head); if (nidx == op->ocb->read_ptr) { op->ocb->read_ptr = INC_PTR(op->ocb->read_ptr); } } switch (line->type) { case DEVI_CLASS_KBD: memcpy(&line->u.kq[line->head], data, size); break; case DEVI_CLASS_REL: { struct packet_rel *rel = (struct packet_rel *) data; struct _mouse_packet *mp = &line->u.mq[line->head]; memcpy(&mp->hdr.time, &rel->timestamp, sizeof(struct timespec)); mp->hdr.buttons = rel->buttons; mp->dx = rel->dx; mp->dy = rel->dy; if (verbosity) printf("EN: x: %d, y: %d, buttons: %x\n", rel->dx, rel->dy, rel->buttons); break; } case DEVI_CLASS_ABS: { struct packet_abs *abs = (struct packet_abs *) data; struct _touch1_packet *tp = &line->u.tq[line->head]; memcpy(&tp->hdr.time, &abs->timestamp, sizeof(struct timespec)); tp->hdr.buttons = abs->buttons; tp->x = abs->x; tp->y = abs->y; break; } default: break; } line->head = INC_PTR(line->head); if (attr->flags & DEVI_NOTIFICATION_ARMED) { iofunc_notify_trigger(attr->notify, 1, IOFUNC_NOTIFY_INPUT); attr->flags &= ~DEVI_NOTIFICATION_ARMED; } process_wait_queue(line->attr); pthread_mutex_unlock(&line->mutex); }
int io_read(resmgr_context_t *ctp, io_read_t *msg, struct ocb *ocb) { MQDEV *dev = ocb->ocb.attr; MQMSG *mp; static MQMSG dummy; MQWAIT *wp; int nonblock, status, n, rcvid; // Is queue open for read? if((status = iofunc_read_verify(ctp, msg, &ocb->ocb, &nonblock)) != EOK) { return status; } // If an xtype is specified make sure it is a mqueue. if((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE && (msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_MQUEUE) { return ENOSYS; } // Is the msg buffer too small for the queue? if(msg->i.nbytes < dev->mq_attr.mq_msgsize) { return EMSGSIZE; } // Are there waiting msgs. if(dev->mq_attr.mq_curmsgs == 0) { if(nonblock & O_NONBLOCK) { return EAGAIN; } if((wp = MemchunkMalloc(memchunk, sizeof(*wp))) == NULL) { return ENOMEM; } wp->rcvid = ctp->rcvid; wp->scoid = ctp->info.scoid; wp->coid = ctp->info.coid; wp->priority = 0; // Must get real priority from ctp->info wp->xtype = msg->i.xtype; LINK_PRI_CLIENT(&dev->waiting_read, wp); ++dev->mq_attr.mq_recvwait; return _RESMGR_NOREPLY; } // Reply with the data mp = (dev->mq_attr.mq_flags & MQ_SEMAPHORE) ? &dummy : dev->waiting_msg[0]; if(mp->nbytes) { dev->attr.flags |= (IOFUNC_ATTR_ATIME | IOFUNC_ATTR_DIRTY_TIME); } resmgr_endian_context(ctp, _IO_READ, S_IFNAM, msg->i.xtype); _IO_SET_READ_NBYTES(ctp, mp->nbytes); if((msg->i.xtype & _IO_XTYPE_MASK) == _IO_XTYPE_MQUEUE) { uint32_t prio; prio = mp->priority; SETIOV(&ctp->iov[0], &prio, sizeof(prio)); SETIOV(&ctp->iov[1], mp->data, mp->nbytes); if(resmgr_msgreplyv(ctp, ctp->iov, 2) == -1) { return errno; } } else { SETIOV(&ctp->iov[0], mp->data, mp->nbytes); if(resmgr_msgreplyv(ctp, ctp->iov, 1) == -1) { return errno; } } // Remove the msg if(mp != &dummy) { if ((dev->waiting_msg[0] = mp->next) == NULL) dev->waiting_msg[1] = NULL; MemchunkFree(memchunk, mp); } --dev->mq_attr.mq_curmsgs; // Keep stat info up-to-date. We overload st_size to be messages waiting. dev->attr.nbytes = dev->mq_attr.mq_curmsgs; // Since we removed a msg we may need to wake someone waiting for a msg. if(wp = dev->waiting_write) { // Unlink and free wait entry rcvid = wp->rcvid; dev->waiting_write = wp->next; MemchunkFree(memchunk, wp); --dev->mq_attr.mq_sendwait; // Process the message resmgr_msg_again(ctp, rcvid); } if((n = dev->mq_attr.mq_maxmsg - dev->mq_attr.mq_curmsgs) != 0 && IOFUNC_NOTIFY_OUTPUT_CHECK(dev->notify, n)) { iofunc_notify_trigger(dev->notify, n, IOFUNC_NOTIFY_OUTPUT); } return _RESMGR_NOREPLY; }