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

📄 xenfb.c

📁 xen虚拟机源代码安装包
💻 C
📖 第 1 页 / 共 3 页
字号:
	if (ret)		return; /* Still waiting */	if (xenfb_xs_printf(dev->xenfb->xsh, dev->nodename, "feature-abs-pointer", "1")) {		xenfb_shutdown(dev->xenfb);		exit(1);	}	fprintf(stderr, "FB: Waiting for FB backend creation\n");	xenfb_wait_for_backend(&dev->xenfb->fb, xenfb_backend_created_fb);}/* Callback invoked while waiting for FB backend to change * to the created state */static void xenfb_backend_created_fb(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);	}	if (ret)		return; /* Still waiting */	fprintf(stderr, "FB: Waiting for KBD frontend initialization\n");	xenfb_wait_for_frontend(&dev->xenfb->kbd, xenfb_frontend_initialized_kbd);}/* Callback invoked while waiting for KBD frontend to change * to the initialized state */static void xenfb_frontend_initialized_kbd(void *opaque){	struct xenfb_device *dev = (struct xenfb_device *)opaque;	int ret = xenfb_frontend_initialized(dev);	if (ret < 0) {		xenfb_shutdown(dev->xenfb);		exit(1);	}	if (ret)		return; /* Still waiting */        fprintf(stderr, "FB: Waiting for FB frontend initialization\n");	xenfb_wait_for_frontend(&dev->xenfb->fb, xenfb_frontend_initialized_fb);}/* Callback invoked while waiting for FB frontend to change * to the initialized state */static void xenfb_frontend_initialized_fb(void *opaque){	struct xenfb_device *dev = (struct xenfb_device *)opaque;	int ret = xenfb_frontend_initialized(dev);	if (ret < 0) {		xenfb_shutdown(dev->xenfb);		exit(1);	}	if (ret)		return; /* Still waiting */	if (xenfb_read_frontend_fb_config(dev->xenfb)) {		xenfb_shutdown(dev->xenfb);	        exit(1);	}        fprintf(stderr, "FB: Waiting for KBD frontend connection\n");	xenfb_wait_for_frontend(&dev->xenfb->kbd, xenfb_frontend_connected_kbd);}/* Callback invoked while waiting for KBD frontend to change * to the connected state */static void xenfb_frontend_connected_kbd(void *opaque){	struct xenfb_device *dev = (struct xenfb_device *)opaque;	int ret = xenfb_frontend_connected(dev);	if (ret < 0) {		xenfb_shutdown(dev->xenfb);		exit(1);	}	if (ret)		return; /* Still waiting */	if (xenfb_read_frontend_kbd_config(dev->xenfb) < 0) {		xenfb_shutdown(dev->xenfb);	        exit(1);	}	xenfb_register_console(dev->xenfb);}/**************************************************************** * * Helper functions for checking state of frontend/backend devices * ****************************************************************//* Helper to determine if a frontend device is in Connected state */static int xenfb_frontend_connected(struct xenfb_device *dev){	unsigned int state;	unsigned int dummy;	char **vec;	vec = xs_read_watch(dev->xenfb->xsh, &dummy);	if (!vec)		return -1;	free(vec);	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);	if (!((1 <<state) & ((1 << XenbusStateUnknown) |			     (1 << XenbusStateConnected)))) {		fprintf(stderr, "FB: Carry on waiting\n");		return 1;	}	/* Don't unwatch frontend - we need to detect shutdown */	/*xs_unwatch(dev->xenfb->xsh, dev->otherend, "");*/	switch (state) {	case XenbusStateConnected:		break;	default:		return -1;	}	return 0;}/* Helper to determine if a frontend device is in Initialized state */static int xenfb_frontend_initialized(struct xenfb_device *dev){	unsigned int state;	unsigned int dummy;	char **vec;	vec = xs_read_watch(dev->xenfb->xsh, &dummy);	if (!vec)		return -1;	free(vec);	state = xenfb_read_state(dev->xenfb->xsh, dev->otherend);	if (!((1 << state) & ((1 << XenbusStateUnknown)			      | (1 << XenbusStateInitialised)#if 1 /* TODO fudging state to permit restarting; to be removed */			      | (1 << XenbusStateConnected)#endif			      ))) {		fprintf(stderr, "FB: Carry on waiting\n");		return 1;	}	xs_unwatch(dev->xenfb->xsh, dev->otherend, "");	switch (state) {#if 1	case XenbusStateConnected:                printf("Fudging state to %d\n", XenbusStateInitialised); /* FIXME */#endif        case XenbusStateInitialised:                break;        default:                return -1;        }	if (xenfb_bind(dev) < 0)		return -1;	return 0;}/* Helper to determine if a backend device is in Created state */static int xenfb_backend_created(struct xenfb_device *dev){	unsigned int state;	unsigned int dummy;	char **vec;	vec = xs_read_watch(dev->xenfb->xsh, &dummy);	if (!vec)		return -1;	free(vec);	state = xenfb_read_state(dev->xenfb->xsh, dev->nodename);	if (!((1 <<state) & ((1 << XenbusStateUnknown)			     | (1 << XenbusStateInitialising)			     | (1 << XenbusStateClosed)#if 1 /* TODO fudging state to permit restarting; to be removed */			     | (1 << XenbusStateInitWait)			     | (1 << XenbusStateConnected)			     | (1 << XenbusStateClosing)#endif			     ))) {		fprintf(stderr, "FB: Carry on waiting\n");		return 1;	}	xs_unwatch(dev->xenfb->xsh, dev->nodename, "");        switch (state) {#if 1        case XenbusStateInitWait:        case XenbusStateConnected:                printf("Fudging state to %d\n", XenbusStateInitialising); /* FIXME */#endif        case XenbusStateInitialising:        case XenbusStateClosing:        case XenbusStateClosed:                break;        default:                fprintf(stderr, "Wrong state %d\n", state);                return -1;        }        xenfb_switch_state(dev, XenbusStateInitWait);        if (xenfb_hotplug(dev) < 0)                return -1;        return 0;}/**************************************************************** *  * QEMU device model integration functions * ****************************************************************//*  * Send a key event from the client to the guest OS * QEMU gives us a raw scancode from an AT / PS/2 style keyboard. * We have to turn this into a Linux Input layer keycode. *  * Extra complexity from the fact that with extended scancodes  * (like those produced by arrow keys) this method gets called * twice, but we only want to send a single event. So we have to * track the '0xe0' scancode state & collapse the extended keys * as needed. *  * Wish we could just send scancodes straight to the guest which * already has code for dealing with this... */static void xenfb_key_event(void *opaque, int scancode){    static int extended = 0;    int down = 1;    if (scancode == 0xe0) {        extended = 1;        return;    } else if (scancode & 0x80) {        scancode &= 0x7f;        down = 0;    }    if (extended) {        scancode |= 0x80;        extended = 0;    }    xenfb_send_key(opaque, down, scancode2linux[scancode]);}/* * Send a mouse event from the client to the guest OS *  * The QEMU mouse can be in either relative, or absolute mode. * Movement is sent separately from button state, which has to * be encoded as virtual key events. We also don't actually get * given any button up/down events, so have to track changes in * the button state. */static void xenfb_mouse_event(void *opaque,			      int dx, int dy, int dz, int button_state){    int i;    struct xenfb *xenfb = opaque;    if (xenfb->abs_pointer_wanted)	    xenfb_send_position(xenfb,                                dx * (xenfb->ds->width - 1) / 0x7fff,                                dy * (xenfb->ds->height - 1) / 0x7fff,				dz);    else	    xenfb_send_motion(xenfb, dx, dy, dz);    for (i = 0 ; i < 8 ; i++) {	    int lastDown = xenfb->button_state & (1 << i);	    int down = button_state & (1 << i);	    if (down == lastDown)		    continue;	    if (xenfb_send_key(xenfb, down, BTN_LEFT+i) < 0)		    return;    }    xenfb->button_state = button_state;}/* A convenient function for munging pixels between different depths */#define BLT(SRC_T,DST_T,RSB,GSB,BSB,RDB,GDB,BDB)                        \    for (line = y ; line < (y+h) ; line++) {                            \        SRC_T *src = (SRC_T *)(xenfb->pixels                            \                               + xenfb->offset                          \                               + (line * xenfb->row_stride)             \                               + (x * xenfb->depth / 8));               \        DST_T *dst = (DST_T *)(xenfb->ds->data                                 \                               + (line * xenfb->ds->linesize)                  \                               + (x * xenfb->ds->depth / 8));                  \        int col;                                                        \        const int RSS = 32 - (RSB + GSB + BSB);                         \        const int GSS = 32 - (GSB + BSB);                               \        const int BSS = 32 - (BSB);                                     \        const uint32_t RSM = (~0U) << (32 - RSB);                       \        const uint32_t GSM = (~0U) << (32 - GSB);                       \        const uint32_t BSM = (~0U) << (32 - BSB);                       \        const int RDS = 32 - (RDB + GDB + BDB);                         \        const int GDS = 32 - (GDB + BDB);                               \        const int BDS = 32 - (BDB);                                     \        const uint32_t RDM = (~0U) << (32 - RDB);                       \        const uint32_t GDM = (~0U) << (32 - GDB);                       \        const uint32_t BDM = (~0U) << (32 - BDB);                       \        for (col = x ; col < (x+w) ; col++) {                           \            uint32_t spix = *src;                                       \            *dst = (((spix << RSS) & RSM & RDM) >> RDS) |               \                   (((spix << GSS) & GSM & GDM) >> GDS) |               \                   (((spix << BSS) & BSM & BDM) >> BDS);                \            src = (SRC_T *) ((unsigned long) src + xenfb->depth / 8);   \            dst = (DST_T *) ((unsigned long) dst + xenfb->ds->depth / 8); \        }                                                               \    }/* This copies data from the guest framebuffer region, into QEMU's copy * NB. QEMU's copy is stored in the pixel format of a) the local X  * server (SDL case) or b) the current VNC client pixel format. * When shifting between colour depths we preserve the MSB. */static void xenfb_guest_copy(struct xenfb *xenfb, int x, int y, int w, int h){    int line;    if (!xenfb->ds->shared_buf) {        if (xenfb->depth == xenfb->ds->depth) { /* Perfect match can use fast path */            for (line = y ; line < (y+h) ; line++) {                memcpy(xenfb->ds->data + (line * xenfb->ds->linesize) + (x * xenfb->ds->depth / 8),                        xenfb->pixels + xenfb->offset + (line * xenfb->row_stride) + (x * xenfb->depth / 8),                        w * xenfb->depth / 8);            }        } else { /* Mismatch requires slow pixel munging */            /* 8 bit == r:3 g:3 b:2 */            /* 16 bit == r:5 g:6 b:5 */            /* 24 bit == r:8 g:8 b:8 */            /* 32 bit == r:8 g:8 b:8 (padding:8) */            if (xenfb->depth == 8) {                if (xenfb->ds->depth == 16) {                    BLT(uint8_t, uint16_t,   3, 3, 2,   5, 6, 5);                } else if (xenfb->ds->depth == 32) {                    BLT(uint8_t, uint32_t,   3, 3, 2,   8, 8, 8);                }            } else if (xenfb->depth == 16) {                if (xenfb->ds->depth == 8) {                    BLT(uint16_t, uint8_t,   5, 6, 5,   3, 3, 2);                } else if (xenfb->ds->depth == 32) {                    BLT(uint16_t, uint32_t,  5, 6, 5,   8, 8, 8);                }            } else if (xenfb->depth == 24 || xenfb->depth == 32) {                if (xenfb->ds->depth == 8) {                    BLT(uint32_t, uint8_t,   8, 8, 8,   3, 3, 2);                } else if (xenfb->ds->depth == 16) {                    BLT(uint32_t, uint16_t,  8, 8, 8,   5, 6, 5);                } else if (xenfb->ds->depth == 32) {                    BLT(uint32_t, uint32_t,  8, 8, 8,   8, 8, 8);                }            }        }    }    dpy_update(xenfb->ds, x, y, w, h);}/* Periodic update of display, transmit the refresh interval to the frontend */static void xenfb_update(void *opaque){    struct xenfb *xenfb = opaque;    int period;    if (xenfb_queue_full(xenfb))        return;    if (xenfb->ds->idle)        period = XENFB_NO_REFRESH;    else {        period = xenfb->ds->gui_timer_interval;        if (!period)            period = GUI_REFRESH_INTERVAL;    }    /* Will have to be disabled for frontends without feature-update */    if (xenfb->refresh_period != period) {        xenfb_send_refresh_period(xenfb, period);        xenfb->refresh_period = period;    }}/* QEMU display state changed, so refresh the framebuffer copy */static void xenfb_invalidate(void *opaque){    struct xenfb *xenfb = opaque;    xenfb_guest_copy(xenfb, 0, 0, xenfb->width, xenfb->height);}/* Screen dump is not used in Xen, so no need to impl this....yet */static void xenfb_screen_dump(void *opaque, const char *name) { }/* Register a QEMU graphical console, and key/mouse handler, * connecting up their events to the frontend */static int xenfb_register_console(struct xenfb *xenfb) {	/* Register our keyboard & mouse handlers */	qemu_add_kbd_event_handler(xenfb_key_event, xenfb);	qemu_add_mouse_event_handler(xenfb_mouse_event, xenfb,  				     xenfb->abs_pointer_wanted,  				     "Xen PVFB Mouse");    	/* Tell QEMU to allocate a graphical console */	graphic_console_init(xenfb->ds,			     xenfb_update,			     xenfb_invalidate,			     xenfb_screen_dump,			     xenfb);        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);	if (qemu_set_fd_handler2(xc_evtchn_fd(xenfb->evt_xch), NULL, xenfb_dispatch_channel, NULL, xenfb) < 0)	        return -1;	if (qemu_set_fd_handler2(xs_fileno(xenfb->xsh), NULL, xenfb_dispatch_store, NULL, xenfb) < 0)		return -1;        fprintf(stderr, "Xen Framebuffer registered\n");        return 0;}/* * Local variables: *  c-indent-level: 8 *  c-basic-offset: 8 *  tab-width: 8 * End: */

⌨️ 快捷键说明

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