⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xenfb.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
static void xenfb_detach_dom(struct xenfb *xenfb){	xenfb_unbind(&xenfb->fb);	xenfb_unbind(&xenfb->kbd);	if (xenfb->pixels) {		munmap(xenfb->pixels, xenfb->fb_len);		xenfb->pixels = NULL;	}}/* Remove the backend area in xenbus since the framebuffer really is   going away. */void xenfb_shutdown(struct xenfb *xenfb){	fprintf(stderr, "FB: Shutting down backend\n");	xs_rm(xenfb->xsh, XBT_NULL, xenfb->fb.nodename);	xs_rm(xenfb->xsh, XBT_NULL, xenfb->kbd.nodename);	xenfb_detach_dom(xenfb);	if (xenfb->xc >= 0)		xc_interface_close(xenfb->xc);	if (xenfb->evt_xch >= 0)		xc_evtchn_close(xenfb->evt_xch);	if (xenfb->xsh)		xs_daemon_close(xenfb->xsh);	free(xenfb);}static int xenfb_configure_fb(struct xenfb *xenfb, size_t fb_len_lim,			      int width, int height, int depth,			      size_t fb_len, int offset, int row_stride){	size_t mfn_sz = sizeof(*((struct xenfb_page *)0)->pd);	size_t pd_len = sizeof(((struct xenfb_page *)0)->pd) / mfn_sz;	size_t fb_pages = pd_len * XC_PAGE_SIZE / mfn_sz;	size_t fb_len_max = fb_pages * XC_PAGE_SIZE;	int max_width, max_height;	if (fb_len_lim > fb_len_max) {		fprintf(stderr,			"FB: fb size limit %zu exceeds %zu, corrected\n",			fb_len_lim, fb_len_max);		fb_len_lim = fb_len_max;	}	if (fb_len_lim && fb_len > fb_len_lim) {		fprintf(stderr,			"FB: frontend fb size %zu limited to %zu\n",			fb_len, fb_len_lim);		fb_len = fb_len_lim;	}	if (depth != 8 && depth != 16 && depth != 24 && depth != 32) {		fprintf(stderr,			"FB: can't handle frontend fb depth %d\n",			depth);		return -1;	}	if (row_stride < 0 || row_stride > fb_len) {		fprintf(stderr,			"FB: invalid frontend stride %d\n", row_stride);		return -1;	}	max_width = row_stride / (depth / 8);	if (width < 0 || width > max_width) {		fprintf(stderr,			"FB: invalid frontend width %d limited to %d\n",			width, max_width);		width = max_width;	}	if (offset < 0 || offset >= fb_len) {		fprintf(stderr,			"FB: invalid frontend offset %d (max %zu)\n",			offset, fb_len - 1);		return -1;	}	max_height = (fb_len - offset) / row_stride;	if (height < 0 || height > max_height) {		fprintf(stderr,			"FB: invalid frontend height %d limited to %d\n",			height, max_height);		height = max_height;	}	xenfb->fb_len = fb_len;	xenfb->row_stride = row_stride;	xenfb->depth = depth;	xenfb->width = width;	xenfb->height = height;	xenfb->offset = offset;	fprintf(stderr, "Framebuffer %dx%dx%d offset %d stride %d\n",		width, height, depth, offset, row_stride);	return 0;}static void xenfb_on_fb_event(struct xenfb *xenfb){	uint32_t prod, cons;	struct xenfb_page *page = xenfb->fb.page;	prod = page->out_prod;	if (prod == page->out_cons)		return;	xen_rmb();		/* ensure we see ring contents up to prod */	for (cons = page->out_cons; cons != prod; cons++) {		union xenfb_out_event *event = &XENFB_OUT_RING_REF(page, cons);		int x, y, w, h;		switch (event->type) {		case XENFB_TYPE_UPDATE:			x = MAX(event->update.x, 0);			y = MAX(event->update.y, 0);			w = MIN(event->update.width, xenfb->width - x);			h = MIN(event->update.height, xenfb->height - y);			if (w < 0 || h < 0) {				fprintf(stderr, "%s bogus update ignored\n",					xenfb->fb.nodename);				break;			}			if (x != event->update.x || y != event->update.y			    || w != event->update.width			    || h != event->update.height) {				fprintf(stderr, "%s bogus update clipped\n",					xenfb->fb.nodename);			}			xenfb_guest_copy(xenfb, x, y, w, h);			break;		case XENFB_TYPE_RESIZE:			if (xenfb_configure_fb(xenfb, xenfb->fb_len,					       event->resize.width,					       event->resize.height,					       event->resize.depth,					       xenfb->fb_len,					       event->resize.offset,					       event->resize.stride) < 0)				break;			if (xenfb->ds->dpy_resize_shared)			    dpy_resize_shared(xenfb->ds, xenfb->width, xenfb->height, xenfb->depth, xenfb->row_stride, xenfb->pixels + xenfb->offset);			else			    dpy_resize(xenfb->ds, xenfb->width, xenfb->height);			xenfb_invalidate(xenfb);			break;		}	}	xen_mb();		/* ensure we're done with ring contents */	page->out_cons = cons;	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);}static int xenfb_queue_full(struct xenfb *xenfb){	struct xenfb_page *page = xenfb->fb.page;	uint32_t cons, prod;	prod = page->in_prod;	cons = page->in_cons;	return prod - cons == XENFB_IN_RING_LEN;}static void xenfb_send_event(struct xenfb *xenfb, union xenfb_in_event *event){	uint32_t prod;	struct xenfb_page *page = xenfb->fb.page;	prod = page->in_prod;	/* caller ensures !xenfb_queue_full() */	xen_mb();                   /* ensure ring space available */	XENFB_IN_RING_REF(page, prod) = *event;	xen_wmb();                  /* ensure ring contents visible */	page->in_prod = prod + 1;	xc_evtchn_notify(xenfb->evt_xch, xenfb->fb.port);}static void xenfb_send_refresh_period(struct xenfb *xenfb, int period){	union xenfb_in_event event;	memset(&event, 0, sizeof(event));	event.type = XENFB_TYPE_REFRESH_PERIOD;	event.refresh_period.period = period;	xenfb_send_event(xenfb, &event);}static void xenfb_on_kbd_event(struct xenfb *xenfb){	struct xenkbd_page *page = xenfb->kbd.page;	/* We don't understand any keyboard events, so just ignore them. */	if (page->out_prod == page->out_cons)		return;	page->out_cons = page->out_prod;	xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);}static int xenfb_on_state_change(struct xenfb_device *dev){	enum xenbus_state state;	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);	switch (state) {	case XenbusStateUnknown:		/* There was an error reading the frontend state.  The		   domain has probably gone away; in any case, there's		   not much point in us continuing. */		return -1;	case XenbusStateInitialising:	case XenbusStateInitWait:	case XenbusStateInitialised:	case XenbusStateConnected:		break;	case XenbusStateClosing:		xenfb_unbind(dev);		xenfb_switch_state(dev, state);		break;	case XenbusStateClosed:		xenfb_switch_state(dev, state);	}	return 0;}/* Send an event to the keyboard frontend driver */static int xenfb_kbd_event(struct xenfb *xenfb,			   union xenkbd_in_event *event){	uint32_t prod;	struct xenkbd_page *page = xenfb->kbd.page;	if (xenfb->kbd.state != XenbusStateConnected)		return 0;	prod = page->in_prod;	if (prod - page->in_cons == XENKBD_IN_RING_LEN) {		errno = EAGAIN;		return -1;	}	xen_mb();		/* ensure ring space available */	XENKBD_IN_RING_REF(page, prod) = *event;	xen_wmb();		/* ensure ring contents visible */	page->in_prod = prod + 1;	return xc_evtchn_notify(xenfb->evt_xch, xenfb->kbd.port);}/* Send a keyboard (or mouse button) event */static int xenfb_send_key(struct xenfb *xenfb, bool down, int keycode){	union xenkbd_in_event event;	memset(&event, 0, XENKBD_IN_EVENT_SIZE);	event.type = XENKBD_TYPE_KEY;	event.key.pressed = down ? 1 : 0;	event.key.keycode = keycode;	return xenfb_kbd_event(xenfb, &event);}/* Send a relative mouse movement event */static int xenfb_send_motion(struct xenfb *xenfb,			     int rel_x, int rel_y, int rel_z){	union xenkbd_in_event event;	memset(&event, 0, XENKBD_IN_EVENT_SIZE);	event.type = XENKBD_TYPE_MOTION;	event.motion.rel_x = rel_x;	event.motion.rel_y = rel_y;	event.motion.rel_z = rel_z;	return xenfb_kbd_event(xenfb, &event);}/* Send an absolute mouse movement event */static int xenfb_send_position(struct xenfb *xenfb,			       int abs_x, int abs_y, int rel_z){	union xenkbd_in_event event;	memset(&event, 0, XENKBD_IN_EVENT_SIZE);	event.type = XENKBD_TYPE_POS;	event.pos.abs_x = abs_x;	event.pos.abs_y = abs_y;	event.pos.rel_z = rel_z;	return xenfb_kbd_event(xenfb, &event);}/* Process events from the frontend event channel */static void xenfb_dispatch_channel(void *opaque){	struct xenfb *xenfb = (struct xenfb *)opaque;	evtchn_port_t port;	port = xc_evtchn_pending(xenfb->evt_xch);	if (port == -1) {		xenfb_shutdown(xenfb);		exit(1);	}	if (port == xenfb->fb.port)		xenfb_on_fb_event(xenfb);	else if (port == xenfb->kbd.port)		xenfb_on_kbd_event(xenfb);	if (xc_evtchn_unmask(xenfb->evt_xch, port) == -1) {		xenfb_shutdown(xenfb);		exit(1);	}}/* Process ongoing events from the frontend devices */static void xenfb_dispatch_store(void *opaque){	struct xenfb *xenfb = (struct xenfb *)opaque;	unsigned dummy;	char **vec;	int r;	vec = xs_read_watch(xenfb->xsh, &dummy);	free(vec);	r = xenfb_on_state_change(&xenfb->fb);	if (r == 0)		r = xenfb_on_state_change(&xenfb->kbd);	if (r < 0) {		xenfb_shutdown(xenfb);		exit(1);	}}/**************************************************************** * * Functions for processing frontend config * ****************************************************************//* Process the frontend framebuffer config */static int xenfb_read_frontend_fb_config(struct xenfb *xenfb) {	struct xenfb_page *fb_page;	int val;	int videoram;        if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "feature-update",                            "%d", &val) < 0)                val = 0;        if (!val) {                fprintf(stderr, "feature-update not supported\n");                errno = ENOTSUP;                return -1;        }        if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.otherend, "protocol", "%63s",                            xenfb->protocol) < 0)                xenfb->protocol[0] = '\0';        xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "request-update", "1");        xenfb->refresh_period = -1;        if (xenfb_xs_scanf1(xenfb->xsh, xenfb->fb.nodename, "videoram", "%d",                            &videoram) < 0)                videoram = 0;	fb_page = xenfb->fb.page;	if (xenfb_configure_fb(xenfb, videoram * 1024 * 1024U,			       fb_page->width, fb_page->height, fb_page->depth,			       fb_page->mem_length, 0, fb_page->line_length)	    < 0) {		errno = EINVAL;		return -1;	}        if (xenfb_map_fb(xenfb, xenfb->fb.otherend_id) < 0)		return -1;        /* Indicate we have the frame buffer resize feature */        xenfb_xs_printf(xenfb->xsh, xenfb->fb.nodename, "feature-resize", "1");        /* Tell kbd pointer the screen geometry */        xenfb_xs_printf(xenfb->xsh, xenfb->kbd.nodename, "width", "%d", xenfb->width);        xenfb_xs_printf(xenfb->xsh, xenfb->kbd.nodename, "height", "%d", xenfb->height);        if (xenfb_switch_state(&xenfb->fb, XenbusStateConnected))                return -1;        if (xenfb_switch_state(&xenfb->kbd, XenbusStateConnected))                return -1;	return 0;}/* Process the frontend keyboard config */static int xenfb_read_frontend_kbd_config(struct xenfb *xenfb){	int val;	if (xenfb_xs_scanf1(xenfb->xsh, xenfb->kbd.otherend, "request-abs-pointer",			    "%d", &val) < 0)		val = 0;	xenfb->abs_pointer_wanted = val;	return 0;}/**************************************************************** * * Functions for frontend/backend state machine * ****************************************************************//* Register a watch against a frontend device, and setup * QEMU event loop to poll the xenstore FD for notification */static int xenfb_wait_for_frontend(struct xenfb_device *dev, IOHandler *handler){        fprintf(stderr, "Doing frontend watch on %s\n", dev->otherend);	if (!xs_watch(dev->xenfb->xsh, dev->otherend, "")) {		fprintf(stderr, "Watch for dev failed\n");		return -1;	}	if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler, NULL, dev) < 0)		return -1;	return 0;}/* Register a watch against a backend device, and setup * QEMU event loop to poll the xenstore FD for notification */static int xenfb_wait_for_backend(struct xenfb_device *dev, IOHandler *handler){	fprintf(stderr, "Doing backend watch on %s\n", dev->nodename);	if (!xs_watch(dev->xenfb->xsh, dev->nodename, "")) {		fprintf(stderr, "Watch for dev failed\n");		return -1;	}	if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler, NULL, dev) < 0)		return -1;	return 0;}/* Callback invoked while waiting for KBD backend to change * to the created state */static void xenfb_backend_created_kbd(void *opaque){	struct xenfb_device *dev = (struct xenfb_device *)opaque;	int ret = xenfb_backend_created(dev);	if (ret < 0) {		xenfb_shutdown(dev->xenfb);		exit(1);	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -