?? vl.c
字號:
prev = cursor; cursor = cursor->next; } if (cursor == NULL) // does not exist or list empty return; else if (prev == NULL) { // entry is head qemu_put_mouse_event_head = cursor->next; if (qemu_put_mouse_event_current == entry) qemu_put_mouse_event_current = cursor->next; qemu_free(entry->qemu_put_mouse_event_name); qemu_free(entry); return; } prev->next = entry->next; if (qemu_put_mouse_event_current == entry) qemu_put_mouse_event_current = prev; qemu_free(entry->qemu_put_mouse_event_name); qemu_free(entry);}void kbd_put_keycode(int keycode){ if (qemu_put_kbd_event) { qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode); }}void kbd_mouse_event(int dx, int dy, int dz, int buttons_state){ QEMUPutMouseEvent *mouse_event; void *mouse_event_opaque; int width; if (!qemu_put_mouse_event_current) { return; } mouse_event = qemu_put_mouse_event_current->qemu_put_mouse_event; mouse_event_opaque = qemu_put_mouse_event_current->qemu_put_mouse_event_opaque; if (mouse_event) { if (graphic_rotate) { if (qemu_put_mouse_event_current->qemu_put_mouse_event_absolute) width = 0x7fff; else width = graphic_width; mouse_event(mouse_event_opaque, width - dy, dx, dz, buttons_state); } else mouse_event(mouse_event_opaque, dx, dy, dz, buttons_state); }}int kbd_mouse_is_absolute(void){ if (!qemu_put_mouse_event_current) return 0; return qemu_put_mouse_event_current->qemu_put_mouse_event_absolute;}void do_info_mice(void){ QEMUPutMouseEntry *cursor; int index = 0; if (!qemu_put_mouse_event_head) { term_printf("No mouse devices connected\n"); return; } term_printf("Mouse devices available:\n"); cursor = qemu_put_mouse_event_head; while (cursor != NULL) { term_printf("%c Mouse #%d: %s\n", (cursor == qemu_put_mouse_event_current ? '*' : ' '), index, cursor->qemu_put_mouse_event_name); index++; cursor = cursor->next; }}void do_mouse_set(int index){ QEMUPutMouseEntry *cursor; int i = 0; if (!qemu_put_mouse_event_head) { term_printf("No mouse devices connected\n"); return; } cursor = qemu_put_mouse_event_head; while (cursor != NULL && index != i) { i++; cursor = cursor->next; } if (cursor != NULL) qemu_put_mouse_event_current = cursor; else term_printf("Mouse at given index not found\n");}/* compute with 96 bit intermediate result: (a*b)/c */uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c){ union { uint64_t ll; struct {#ifdef WORDS_BIGENDIAN uint32_t high, low;#else uint32_t low, high;#endif } l; } u, res; uint64_t rl, rh; u.ll = a; rl = (uint64_t)u.l.low * (uint64_t)b; rh = (uint64_t)u.l.high * (uint64_t)b; rh += (rl >> 32); res.l.high = rh / c; res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c; return res.ll;}/***********************************************************//* real time host monotonic timer */#define QEMU_TIMER_BASE 1000000000LL#ifdef WIN32static int64_t clock_freq;static void init_get_clock(void){ LARGE_INTEGER freq; int ret; ret = QueryPerformanceFrequency(&freq); if (ret == 0) { fprintf(stderr, "Could not calibrate ticks\n"); exit(1); } clock_freq = freq.QuadPart;}static int64_t get_clock(void){ LARGE_INTEGER ti; QueryPerformanceCounter(&ti); return muldiv64(ti.QuadPart, QEMU_TIMER_BASE, clock_freq);}#elsestatic int use_rt_clock;static void init_get_clock(void){ use_rt_clock = 0;#if defined(__linux__) { struct timespec ts; if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) { use_rt_clock = 1; } }#endif}static int64_t get_clock(void){#if defined(__linux__) if (use_rt_clock) { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); return ts.tv_sec * 1000000000LL + ts.tv_nsec; } else#endif { /* XXX: using gettimeofday leads to problems if the date changes, so it should be avoided. */ struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000000LL + (tv.tv_usec * 1000); }}#endif/***********************************************************//* guest cycle counter */static int64_t cpu_ticks_prev;static int64_t cpu_ticks_offset;static int64_t cpu_clock_offset;static int cpu_ticks_enabled;/* return the host CPU cycle counter and handle stop/restart */int64_t cpu_get_ticks(void){ if (!cpu_ticks_enabled) { return cpu_ticks_offset; } else { int64_t ticks; ticks = cpu_get_real_ticks(); if (cpu_ticks_prev > ticks) { /* Note: non increasing ticks may happen if the host uses software suspend */ cpu_ticks_offset += cpu_ticks_prev - ticks; } cpu_ticks_prev = ticks; return ticks + cpu_ticks_offset; }}/* return the host CPU monotonic timer and handle stop/restart */static int64_t cpu_get_clock(void){ int64_t ti; if (!cpu_ticks_enabled) { return cpu_clock_offset; } else { ti = get_clock(); return ti + cpu_clock_offset; }}/* enable cpu_get_ticks() */void cpu_enable_ticks(void){ if (!cpu_ticks_enabled) { cpu_ticks_offset -= cpu_get_real_ticks(); cpu_clock_offset -= get_clock(); cpu_ticks_enabled = 1; }}/* disable cpu_get_ticks() : the clock is stopped. You must not call cpu_get_ticks() after that. */void cpu_disable_ticks(void){ if (cpu_ticks_enabled) { cpu_ticks_offset = cpu_get_ticks(); cpu_clock_offset = cpu_get_clock(); cpu_ticks_enabled = 0; }}/***********************************************************//* timers */#define QEMU_TIMER_REALTIME 0#define QEMU_TIMER_VIRTUAL 1struct QEMUClock { int type; /* XXX: add frequency */};struct QEMUTimer { QEMUClock *clock; int64_t expire_time; QEMUTimerCB *cb; void *opaque; struct QEMUTimer *next;};struct qemu_alarm_timer { char const *name; unsigned int flags; int (*start)(struct qemu_alarm_timer *t); void (*stop)(struct qemu_alarm_timer *t); void (*rearm)(struct qemu_alarm_timer *t); void *priv;};#define ALARM_FLAG_DYNTICKS 0x1#define ALARM_FLAG_EXPIRED 0x2static inline int alarm_has_dynticks(struct qemu_alarm_timer *t){ return t->flags & ALARM_FLAG_DYNTICKS;}static void qemu_rearm_alarm_timer(struct qemu_alarm_timer *t){ if (!alarm_has_dynticks(t)) return; t->rearm(t);}/* TODO: MIN_TIMER_REARM_US should be optimized */#define MIN_TIMER_REARM_US 250static struct qemu_alarm_timer *alarm_timer;#ifdef _WIN32struct qemu_alarm_win32 { MMRESULT timerId; HANDLE host_alarm; unsigned int period;} alarm_win32_data = {0, NULL, -1};static int win32_start_timer(struct qemu_alarm_timer *t);static void win32_stop_timer(struct qemu_alarm_timer *t);static void win32_rearm_timer(struct qemu_alarm_timer *t);#elsestatic int unix_start_timer(struct qemu_alarm_timer *t);static void unix_stop_timer(struct qemu_alarm_timer *t);#ifdef __linux__static int dynticks_start_timer(struct qemu_alarm_timer *t);static void dynticks_stop_timer(struct qemu_alarm_timer *t);static void dynticks_rearm_timer(struct qemu_alarm_timer *t);static int hpet_start_timer(struct qemu_alarm_timer *t);static void hpet_stop_timer(struct qemu_alarm_timer *t);static int rtc_start_timer(struct qemu_alarm_timer *t);static void rtc_stop_timer(struct qemu_alarm_timer *t);#endif /* __linux__ */#endif /* _WIN32 */static struct qemu_alarm_timer alarm_timers[] = {#ifndef _WIN32#ifdef __linux__ {"dynticks", ALARM_FLAG_DYNTICKS, dynticks_start_timer, dynticks_stop_timer, dynticks_rearm_timer, NULL}, /* HPET - if available - is preferred */ {"hpet", 0, hpet_start_timer, hpet_stop_timer, NULL, NULL}, /* ...otherwise try RTC */ {"rtc", 0, rtc_start_timer, rtc_stop_timer, NULL, NULL},#endif {"unix", 0, unix_start_timer, unix_stop_timer, NULL, NULL},#else {"dynticks", ALARM_FLAG_DYNTICKS, win32_start_timer, win32_stop_timer, win32_rearm_timer, &alarm_win32_data}, {"win32", 0, win32_start_timer, win32_stop_timer, NULL, &alarm_win32_data},#endif {NULL, }};static void show_available_alarms(){ int i; printf("Available alarm timers, in order of precedence:\n"); for (i = 0; alarm_timers[i].name; i++) printf("%s\n", alarm_timers[i].name);}static void configure_alarms(char const *opt){ int i; int cur = 0; int count = (sizeof(alarm_timers) / sizeof(*alarm_timers)) - 1; char *arg; char *name; if (!strcmp(opt, "help")) { show_available_alarms(); exit(0); } arg = strdup(opt); /* Reorder the array */ name = strtok(arg, ","); while (name) { struct qemu_alarm_timer tmp; for (i = 0; i < count && alarm_timers[i].name; i++) { if (!strcmp(alarm_timers[i].name, name)) break; } if (i == count) { fprintf(stderr, "Unknown clock %s\n", name); goto next; } if (i < cur) /* Ignore */ goto next; /* Swap */ tmp = alarm_timers[i]; alarm_timers[i] = alarm_timers[cur]; alarm_timers[cur] = tmp; cur++;next: name = strtok(NULL, ","); } free(arg); if (cur) { /* Disable remaining timers */ for (i = cur; i < count; i++) alarm_timers[i].name = NULL; } /* debug */ show_available_alarms();}QEMUClock *rt_clock;QEMUClock *vm_clock;static QEMUTimer *active_timers[2];static QEMUClock *qemu_new_clock(int type){ QEMUClock *clock; clock = qemu_mallocz(sizeof(QEMUClock)); if (!clock) return NULL; clock->type = type; return clock;}QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque){ QEMUTimer *ts; ts = qemu_mallocz(sizeof(QEMUTimer)); ts->clock = clock; ts->cb = cb; ts->opaque = opaque; return ts;}void qemu_free_timer(QEMUTimer *ts){ qemu_free(ts);}/* stop a timer, but do not dealloc it */void qemu_del_timer(QEMUTimer *ts){ QEMUTimer **pt, *t; /* NOTE: this code must be signal safe because qemu_timer_expired() can be called from a signal. */ pt = &active_timers[ts->clock->type]; for(;;) { t = *pt; if (!t) break; if (t == ts) { *pt = t->next; break; } pt = &t->next; }}/* modify the current timer so that it will be fired when current_time >= expire_time. The corresponding callback will be called. */void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time){ QEMUTimer **pt, *t; qemu_del_timer(ts); /* add the timer in the sorted list */ /* NOTE: this code must be signal safe because qemu_timer_expired() can be called from a signal. */ pt = &active_timers[ts->clock->type]; for(;;) { t = *pt; if (!t) break; if (t->expire_time > expire_time) break; pt = &t->next; } ts->expire_time = expire_time; ts->next = *pt; *pt = ts; /* Rearm if necessary */ if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0 && pt == &active_timers[ts->clock->type]) qemu_rearm_alarm_timer(alarm_timer);}int qemu_timer_pending(QEMUTimer *ts){ QEMUTimer *t; for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) { if (t == ts) return 1; } return 0;}static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time){ if (!timer_head) return 0; return (timer_head->expire_time <= current_time);}static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time){ QEMUTimer *ts; for(;;) { ts = *ptimer_head; if (!ts || ts->expire_time > current_time) break; /* remove timer from the list before calling the callback */ *ptimer_head = ts->next;
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -