Revision 4c15ba9c hw/milkymist-softusb.c
b/hw/milkymist-softusb.c | ||
---|---|---|
25 | 25 |
#include "sysbus.h" |
26 | 26 |
#include "trace.h" |
27 | 27 |
#include "console.h" |
28 |
#include "usb.h"
|
|
28 |
#include "hid.h"
|
|
29 | 29 |
#include "qemu-error.h" |
30 | 30 |
|
31 | 31 |
enum { |
... | ... | |
46 | 46 |
|
47 | 47 |
struct MilkymistSoftUsbState { |
48 | 48 |
SysBusDevice busdev; |
49 |
USBBus usbbus; |
|
50 |
USBPort usbport[2]; |
|
51 |
USBDevice *usbdev; |
|
49 |
HIDState hid_kbd; |
|
50 |
HIDState hid_mouse; |
|
52 | 51 |
|
53 | 52 |
qemu_irq irq; |
54 | 53 |
|
... | ... | |
62 | 61 |
uint32_t regs[R_MAX]; |
63 | 62 |
|
64 | 63 |
/* mouse state */ |
65 |
int mouse_dx; |
|
66 |
int mouse_dy; |
|
67 |
int mouse_dz; |
|
68 |
uint8_t mouse_buttons_state; |
|
64 |
uint8_t mouse_hid_buffer[4]; |
|
69 | 65 |
|
70 | 66 |
/* keyboard state */ |
71 |
uint8_t kbd_usb_buffer[8];
|
|
67 |
uint8_t kbd_hid_buffer[8];
|
|
72 | 68 |
}; |
73 | 69 |
typedef struct MilkymistSoftUsbState MilkymistSoftUsbState; |
74 | 70 |
|
... | ... | |
177 | 173 |
static void softusb_mouse_changed(MilkymistSoftUsbState *s) |
178 | 174 |
{ |
179 | 175 |
uint8_t m; |
180 |
uint8_t buf[4]; |
|
181 |
|
|
182 |
buf[0] = s->mouse_buttons_state; |
|
183 |
buf[1] = s->mouse_dx; |
|
184 |
buf[2] = s->mouse_dy; |
|
185 |
buf[3] = s->mouse_dz; |
|
186 | 176 |
|
187 | 177 |
softusb_read_dmem(s, COMLOC_MEVT_PRODUCE, &m, 1); |
188 | 178 |
trace_milkymist_softusb_mevt(m); |
189 |
softusb_write_dmem(s, COMLOC_MEVT_BASE + 4 * m, buf, 4);
|
|
179 |
softusb_write_dmem(s, COMLOC_MEVT_BASE + 4 * m, s->mouse_hid_buffer, 4);
|
|
190 | 180 |
m = (m + 1) & 0xf; |
191 | 181 |
softusb_write_dmem(s, COMLOC_MEVT_PRODUCE, &m, 1); |
192 | 182 |
|
... | ... | |
200 | 190 |
|
201 | 191 |
softusb_read_dmem(s, COMLOC_KEVT_PRODUCE, &m, 1); |
202 | 192 |
trace_milkymist_softusb_kevt(m); |
203 |
softusb_write_dmem(s, COMLOC_KEVT_BASE + 8 * m, s->kbd_usb_buffer, 8);
|
|
193 |
softusb_write_dmem(s, COMLOC_KEVT_BASE + 8 * m, s->kbd_hid_buffer, 8);
|
|
204 | 194 |
m = (m + 1) & 0x7; |
205 | 195 |
softusb_write_dmem(s, COMLOC_KEVT_PRODUCE, &m, 1); |
206 | 196 |
|
... | ... | |
208 | 198 |
qemu_irq_pulse(s->irq); |
209 | 199 |
} |
210 | 200 |
|
211 |
static void softusb_mouse_event(void *opaque, |
|
212 |
int dx, int dy, int dz, int buttons_state) |
|
201 |
static void softusb_kbd_hid_datain(HIDState *hs) |
|
213 | 202 |
{ |
214 |
MilkymistSoftUsbState *s = opaque; |
|
203 |
MilkymistSoftUsbState *s = container_of(hs, MilkymistSoftUsbState, hid_kbd); |
|
204 |
int len; |
|
215 | 205 |
|
216 | 206 |
/* if device is in reset, do nothing */ |
217 | 207 |
if (s->regs[R_CTRL] & CTRL_RESET) { |
218 | 208 |
return; |
219 | 209 |
} |
220 | 210 |
|
221 |
trace_milkymist_softusb_mouse_event(dx, dy, dz, buttons_state);
|
|
211 |
len = hid_keyboard_poll(hs, s->kbd_hid_buffer, sizeof(s->kbd_hid_buffer));
|
|
222 | 212 |
|
223 |
s->mouse_dx = dx; |
|
224 |
s->mouse_dy = dy; |
|
225 |
s->mouse_dz = dz; |
|
226 |
s->mouse_buttons_state = buttons_state; |
|
227 |
|
|
228 |
softusb_mouse_changed(s); |
|
213 |
if (len == 8) { |
|
214 |
softusb_kbd_changed(s); |
|
215 |
} |
|
229 | 216 |
} |
230 | 217 |
|
231 |
static void softusb_usbdev_datain(void *opaque)
|
|
218 |
static void softusb_mouse_hid_datain(HIDState *hs)
|
|
232 | 219 |
{ |
233 |
MilkymistSoftUsbState *s = opaque; |
|
234 |
|
|
235 |
USBPacket p; |
|
236 |
|
|
237 |
usb_packet_init(&p); |
|
238 |
usb_packet_setup(&p, USB_TOKEN_IN, 0, 1); |
|
239 |
usb_packet_addbuf(&p, s->kbd_usb_buffer, sizeof(s->kbd_usb_buffer)); |
|
240 |
s->usbdev->info->handle_data(s->usbdev, &p); |
|
241 |
usb_packet_cleanup(&p); |
|
242 |
|
|
243 |
softusb_kbd_changed(s); |
|
244 |
} |
|
220 |
MilkymistSoftUsbState *s = |
|
221 |
container_of(hs, MilkymistSoftUsbState, hid_mouse); |
|
222 |
int len; |
|
245 | 223 |
|
246 |
static void softusb_attach(USBPort *port) |
|
247 |
{ |
|
248 |
} |
|
224 |
/* if device is in reset, do nothing */ |
|
225 |
if (s->regs[R_CTRL] & CTRL_RESET) { |
|
226 |
return; |
|
227 |
} |
|
249 | 228 |
|
250 |
static void softusb_detach(USBPort *port) |
|
251 |
{ |
|
252 |
} |
|
229 |
len = hid_pointer_poll(hs, s->mouse_hid_buffer, |
|
230 |
sizeof(s->mouse_hid_buffer)); |
|
253 | 231 |
|
254 |
static void softusb_child_detach(USBPort *port, USBDevice *child) |
|
255 |
{ |
|
232 |
if (len == 4) { |
|
233 |
softusb_mouse_changed(s); |
|
234 |
} |
|
256 | 235 |
} |
257 | 236 |
|
258 |
static USBPortOps softusb_ops = { |
|
259 |
.attach = softusb_attach, |
|
260 |
.detach = softusb_detach, |
|
261 |
.child_detach = softusb_child_detach, |
|
262 |
}; |
|
263 |
|
|
264 |
static USBBusOps softusb_bus_ops = { |
|
265 |
}; |
|
266 |
|
|
267 | 237 |
static void milkymist_softusb_reset(DeviceState *d) |
268 | 238 |
{ |
269 | 239 |
MilkymistSoftUsbState *s = |
... | ... | |
273 | 243 |
for (i = 0; i < R_MAX; i++) { |
274 | 244 |
s->regs[i] = 0; |
275 | 245 |
} |
276 |
s->mouse_dx = 0;
|
|
277 |
s->mouse_dy = 0;
|
|
278 |
s->mouse_dz = 0; |
|
279 |
s->mouse_buttons_state = 0;
|
|
280 |
memset(s->kbd_usb_buffer, 0, sizeof(s->kbd_usb_buffer));
|
|
246 |
memset(s->kbd_hid_buffer, 0, sizeof(s->kbd_hid_buffer));
|
|
247 |
memset(s->mouse_hid_buffer, 0, sizeof(s->mouse_hid_buffer));
|
|
248 |
|
|
249 |
hid_reset(&s->hid_kbd);
|
|
250 |
hid_reset(&s->hid_mouse);
|
|
281 | 251 |
|
282 | 252 |
/* defaults */ |
283 | 253 |
s->regs[R_CTRL] = CTRL_RESET; |
... | ... | |
304 | 274 |
cpu_register_physical_memory(s->dmem_base, s->dmem_size, |
305 | 275 |
dmem_ram | IO_MEM_RAM); |
306 | 276 |
|
307 |
qemu_add_mouse_event_handler(softusb_mouse_event, s, 0, "Milkymist Mouse"); |
|
308 |
|
|
309 |
/* create our usb bus */ |
|
310 |
usb_bus_new(&s->usbbus, &softusb_bus_ops, NULL); |
|
311 |
|
|
312 |
/* our two ports */ |
|
313 |
/* FIXME: claim to support full speed devices. qemu mouse and keyboard |
|
314 |
* report themselves as full speed devices. */ |
|
315 |
usb_register_port(&s->usbbus, &s->usbport[0], NULL, 0, &softusb_ops, |
|
316 |
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); |
|
317 |
usb_register_port(&s->usbbus, &s->usbport[1], NULL, 1, &softusb_ops, |
|
318 |
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL); |
|
319 |
|
|
320 |
/* and finally create an usb keyboard */ |
|
321 |
s->usbdev = usb_create_simple(&s->usbbus, "usb-kbd"); |
|
322 |
usb_hid_datain_cb(s->usbdev, s, softusb_usbdev_datain); |
|
323 |
s->usbdev->info->handle_reset(s->usbdev); |
|
277 |
hid_init(&s->hid_kbd, HID_KEYBOARD, softusb_kbd_hid_datain); |
|
278 |
hid_init(&s->hid_mouse, HID_MOUSE, softusb_mouse_hid_datain); |
|
324 | 279 |
|
325 | 280 |
return 0; |
326 | 281 |
} |
... | ... | |
332 | 287 |
.minimum_version_id_old = 1, |
333 | 288 |
.fields = (VMStateField[]) { |
334 | 289 |
VMSTATE_UINT32_ARRAY(regs, MilkymistSoftUsbState, R_MAX), |
335 |
VMSTATE_INT32(mouse_dx, MilkymistSoftUsbState), |
|
336 |
VMSTATE_INT32(mouse_dy, MilkymistSoftUsbState), |
|
337 |
VMSTATE_INT32(mouse_dz, MilkymistSoftUsbState), |
|
338 |
VMSTATE_UINT8(mouse_buttons_state, MilkymistSoftUsbState), |
|
339 |
VMSTATE_BUFFER(kbd_usb_buffer, MilkymistSoftUsbState), |
|
290 |
VMSTATE_HID_KEYBOARD_DEVICE(hid_kbd, MilkymistSoftUsbState), |
|
291 |
VMSTATE_HID_POINTER_DEVICE(hid_mouse, MilkymistSoftUsbState), |
|
292 |
VMSTATE_BUFFER(kbd_hid_buffer, MilkymistSoftUsbState), |
|
293 |
VMSTATE_BUFFER(mouse_hid_buffer, MilkymistSoftUsbState), |
|
340 | 294 |
VMSTATE_END_OF_LIST() |
341 | 295 |
} |
342 | 296 |
}; |
Also available in: Unified diff