Compare commits

...
11 Commits
ci ... dfu
Author SHA1 Message Date
Martijn de Vos 6d8ef87cc0 Integrated USB/TCP stack from T8030 2024-01-16 21:54:09 +01:00
Martijn de Vos a0698a741e Worked on DFU mode 2024-01-13 19:30:49 +01:00
Martijn de Vos adaea1d394 Merge pull request #122 from devos50/gpio
Generalized GPIO logic
2024-01-13 13:58:25 +01:00
Martijn de Vos 7d55fc7991 Generalized GPIO logic
As preparation for the emulation of DFU mode
2024-01-13 13:56:30 +01:00
Martijn de Vos d8e7109d35 Merge pull request #121 from thebreaddev/ipod_touch_2g
fix FPE and allow running any code
2024-01-12 16:38:26 +01:00
BreadDEV 93dbb7ad69 fix floating point exception
used code from https://github.com/devos50/qemu-ios/commit/8acdcfc48ad19ee6dfb30d7be3abcb6110cb2f25
it was on ipod_touch_1g branch but not on 2g
2024-01-12 21:38:03 +07:00
BreadDEV f7f46cc0b3 boot args modification to disable code signature check
i added "amfi_allow_any_signature=1" boot arg so you can run .app that was fakesigned with ldid -S
2024-01-11 18:16:12 +07:00
Martijn de Vos 32e2ae008a Merge pull request #109 from devos50/vol_buttons
Implemented support for volume up/down buttons
2024-01-01 21:01:44 +01:00
Martijn de Vos cde16baff0 Implemented support for volume up/down buttons
It's not doing much as the audio device is not working yet.
2024-01-01 20:59:53 +01:00
Martijn de Vos 38cebf5d0b Merge pull request #108 from ChaseKnowlden/enable-cocoa
Enable cocoa on Apple Silicon Macs
2024-01-01 10:37:27 +01:00
ChaseKnowlden c87aa5415a Enable cocoa on Apple Silicon Macs 2023-12-31 19:42:53 -05:00
19 changed files with 823 additions and 932 deletions

No files matched your search

+1 -1
View File
@@ -27,7 +27,7 @@ cd build
../configure --target-list=arm-softmmu --extra-cflags=-I/usr/local/opt/openssl@3/include --extra-ldflags='-L/usr/local/opt/openssl@3/lib -lcrypto'
# On Apple Silicon Macs
../configure --enable-sdl --disable-cocoa --target-list=arm-softmmu --disable-capstone --disable-pie --disable-slirp --extra-cflags=-I/opt/homebrew/opt/openssl@3/include --extra-ldflags='-L/opt/homebrew/opt/openssl@3/lib -lcrypto'
../configure --enable-sdl --target-list=arm-softmmu --disable-capstone --disable-pie --disable-slirp --extra-cflags=-I/opt/homebrew/opt/openssl@3/include --extra-ldflags='-L/opt/homebrew/opt/openssl@3/lib -lcrypto'
# On Microsoft Windows (with MINGW64)
../configure --enable-sdl --disable-cocoa --target-list=arm-softmmu --disable-capstone --disable-slirp --disable-pie --extra-cflags=-I/mingw64/include/openssl --extra-ldflags='-L/mingw64/lib -lcrypto' --disable-stack-protector --disable-werror
+59 -30
View File
@@ -174,52 +174,64 @@ static inline qemu_irq s5l8900_get_irq(IPodTouchMachineState *s, int n)
return s->irq[n / S5L8720_VIC_SIZE][n % S5L8720_VIC_SIZE];
}
static uint32_t s5l8720_usb_hwcfg[] = {
0,
0x7a8f60d0,
0x082000e8,
0x01f08024
};
static void ipod_touch_key_event(void *opaque, int keycode)
{
bool do_irq = false;
int gpio_group = 0, gpio_selector = 0;
IPodTouchMultitouchState *s = (IPodTouchMultitouchState *)opaque;
if(keycode == 25 || keycode == 153) {
if(keycode == KEY_P_DOWN || keycode == KEY_P_UP) {
// power button
gpio_group = GPIO_BUTTON_POWER_IRQ / NUM_GPIO_PINS;
gpio_selector = GPIO_BUTTON_POWER_IRQ % NUM_GPIO_PINS;
if(keycode == 25 && (s->gpio_state->gpio_state & (1 << (GPIO_BUTTON_POWER & 0xf))) == 0) {
s->gpio_state->gpio_state |= (1 << (GPIO_BUTTON_POWER & 0xf));
do_irq = true;
if(keycode == KEY_P_DOWN && gpio_is_off(s->gpio_state->gpio_state, GPIO_BUTTON_POWER)) {
gpio_set_on(s->gpio_state->gpio_state, GPIO_BUTTON_POWER);
}
else if(keycode == 153) {
s->gpio_state->gpio_state &= ~(1 << (GPIO_BUTTON_POWER & 0xf));
do_irq = true;
else if(keycode == KEY_P_UP) {
gpio_set_off(s->gpio_state->gpio_state, GPIO_BUTTON_POWER);
}
}
else if(keycode == 35 || keycode == 163) {
else if(keycode == KEY_H_DOWN || keycode == KEY_H_UP) {
// home button
gpio_group = GPIO_BUTTON_HOME_IRQ / NUM_GPIO_PINS;
gpio_selector = GPIO_BUTTON_HOME_IRQ % NUM_GPIO_PINS;
if(keycode == 35 && (s->gpio_state->gpio_state & (1 << (GPIO_BUTTON_HOME & 0xf))) == 0) {
s->gpio_state->gpio_state |= (1 << (GPIO_BUTTON_HOME & 0xf));
do_irq = true;
if(keycode == KEY_H_DOWN && gpio_is_off(s->gpio_state->gpio_state, GPIO_BUTTON_HOME)) {
gpio_set_on(s->gpio_state->gpio_state, GPIO_BUTTON_HOME);
}
else if(keycode == 163) {
s->gpio_state->gpio_state &= ~(1 << (GPIO_BUTTON_HOME & 0xf));
do_irq = true;
else if(keycode == KEY_H_UP) {
gpio_set_off(s->gpio_state->gpio_state, GPIO_BUTTON_HOME);
}
}
else if(keycode == KEY_MIN_DOWN || keycode == KEY_MIN_UP) {
// volume down button
gpio_group = GPIO_BUTTON_VOLDOWN_IRQ / NUM_GPIO_PINS;
gpio_selector = GPIO_BUTTON_VOLDOWN_IRQ % NUM_GPIO_PINS;
if(keycode == KEY_MIN_DOWN && gpio_is_off(s->gpio_state->gpio_state, GPIO_BUTTON_VOLDOWN)) {
gpio_set_on(s->gpio_state->gpio_state, GPIO_BUTTON_VOLDOWN);
}
else if(keycode == KEY_MIN_UP) {
gpio_set_off(s->gpio_state->gpio_state, GPIO_BUTTON_VOLDOWN);
}
}
else if(keycode == KEY_PLUS_DOWN || keycode == KEY_PLUS_UP) {
// volume down button
gpio_group = GPIO_BUTTON_VOLUP_IRQ / NUM_GPIO_PINS;
gpio_selector = GPIO_BUTTON_VOLUP_IRQ % NUM_GPIO_PINS;
if(keycode == KEY_PLUS_DOWN && gpio_is_off(s->gpio_state->gpio_state, GPIO_BUTTON_VOLUP)) {
gpio_set_on(s->gpio_state->gpio_state, GPIO_BUTTON_VOLUP);
}
else if(keycode == KEY_PLUS_UP) {
gpio_set_off(s->gpio_state->gpio_state, GPIO_BUTTON_VOLUP);
}
}
if(do_irq) {
s->sysic->gpio_int_status[gpio_group] |= (1 << gpio_selector);
qemu_irq_raise(s->sysic->gpio_irqs[gpio_group]);
}
s->sysic->gpio_int_status[gpio_group] |= (1 << gpio_selector);
qemu_irq_raise(s->sysic->gpio_irqs[gpio_group]);
}
static void ipod_touch_machine_init(MachineState *machine)
@@ -384,10 +396,23 @@ static void ipod_touch_machine_init(MachineState *machine)
memory_region_add_subregion(sysmem, UNKNOWN1_MEM_BASE, &unknown1_state->iomem);
// init USB OTG
dev = ipod_touch_init_usb_otg(s5l8900_get_irq(nms, S5L8720_USB_OTG_IRQ), s5l8720_usb_hwcfg);
synopsys_usb_state *usb_otg = S5L8900USBOTG(dev);
nms->usb_otg = usb_otg;
memory_region_add_subregion(sysmem, USBOTG_MEM_BASE, &nms->usb_otg->iomem);
dev = qdev_new("dwc2-usb");
DWC2State *dwc2 = DWC2_USB(dev);
nms->dwc2 = dwc2;
memory_region_add_subregion(sysmem, USBOTG_MEM_BASE, &dwc2->container);
// TODO add IRQ etc
memory_region_init(&nms->usb_dma_container_mr, OBJECT(dev), "appleusb.dma-container-mr", UINT32_MAX);
object_property_add_const_link(OBJECT(nms->dwc2), "dma-mr", OBJECT(&nms->usb_dma_container_mr));
busdev = SYS_BUS_DEVICE(dev);
sysbus_realize(busdev, &error_fatal);
// create the TCP host and connect the busses
dev = qdev_new(TYPE_USB_TCP_HOST);
busdev = SYS_BUS_DEVICE(dev);
sysbus_realize(busdev, &error_fatal);
BusState *bus = QLIST_FIRST(&DEVICE(busdev)->child_bus);
qdev_realize(DEVICE(nms->dwc2->device), bus, &error_fatal);
// init two pl080 DMAC0 devices
dev = qdev_new("pl080");
@@ -507,6 +532,10 @@ static void ipod_touch_machine_init(MachineState *machine)
qemu_register_reset(ipod_touch_cpu_reset, nms);
qemu_add_kbd_event_handler(ipod_touch_key_event, spi4_state->mt);
// toggle DFU
gpio_set_on(nms->gpio_state->gpio_state, GPIO_FORCE_DFU);
nms->usb_phys_state->is_cable_connected = true;
}
static void ipod_touch_machine_class_init(ObjectClass *klass, void *data)
+1 -1
View File
@@ -24,7 +24,7 @@ static void dump_registers(IPodTouchFMSSState *s) {
static void read_nand_pages(IPodTouchFMSSState *s)
{
// boot args
const char *boot_args = "kextlog=0xfff debug=0x8 cpus=1 rd=disk0s1 serial=1 pmu-debug=0x1 io=0xffff8fff debug-usb=0xffffffff"; // if not const then overwritten
const char *boot_args = "kextlog=0xfff debug=0x8 cpus=1 rd=disk0s1 serial=1 pmu-debug=0x1 io=0xffff8fff debug-usb=0xffffffff amfi_allow_any_signature=1"; // if not const then overwritten
cpu_physical_memory_write(0x0ff2a584, boot_args, strlen(boot_args));
// patch iBoot - we want to inject the bluetooth MAC address which is located as sub-node of uart1 and not uart3 in the device tree...
+28 -4
View File
@@ -2,9 +2,11 @@
static void s5l8900_gpio_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
{
//fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
printf("%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
IPodTouchGPIOState *s = (struct IPodTouchGPIOState *) opaque;
// TODO this should be implemented at one point
switch(addr) {
default:
break;
@@ -13,12 +15,14 @@ static void s5l8900_gpio_write(void *opaque, hwaddr addr, uint64_t value, unsign
static uint64_t s5l8900_gpio_read(void *opaque, hwaddr addr, unsigned size)
{
fprintf(stderr, "%s: read from location 0x%08x\n", __func__, addr);
printf("%s: read from location 0x%08x\n", __func__, addr);
IPodTouchGPIOState *s = (struct IPodTouchGPIOState *) opaque;
switch(addr) {
case 0x184: // TODO: This offset only makes sure that the GPIO triggers associated with the home/power button work correctly!!
return s->gpio_state;
case 0x4:
return 0;
case 0x24 ... 0x184:
return s->gpio_state[GPIOADDR2PAD(addr)];
default:
break;
}
@@ -26,6 +30,26 @@ static uint64_t s5l8900_gpio_read(void *opaque, hwaddr addr, unsigned size)
return 0;
}
bool gpio_is_on(uint32_t *state, uint32_t gpio)
{
return (state[GPIO2PAD(gpio)] & (1 << GPIO2PIN(gpio)));
}
bool gpio_is_off(uint32_t *state, uint32_t gpio)
{
return !gpio_is_on(state, gpio);
}
void gpio_set_on(uint32_t *state, uint32_t gpio)
{
state[GPIO2PAD(gpio)] |= (1 << GPIO2PIN(gpio));
}
void gpio_set_off(uint32_t *state, uint32_t gpio)
{
state[GPIO2PAD(gpio)] &= ~(1 << GPIO2PIN(gpio));
}
static const MemoryRegionOps gpio_ops = {
.read = s5l8900_gpio_read,
.write = s5l8900_gpio_write,
+2 -2
View File
@@ -311,8 +311,8 @@ static MTFrame *get_frame(IPodTouchMultitouchState *s, uint8_t event, float x, f
// compute the velocity
int diff_x = (int)((x - s->prev_touch_x) * MT_INTERNAL_SENSOR_SURFACE_WIDTH);
int diff_y = (int)((x - s->prev_touch_y) * MT_INTERNAL_SENSOR_SURFACE_HEIGHT);
frame->finger_data.velX = diff_x / (elapsed_ns - s->last_frame_timestamp) * 1000;
frame->finger_data.velY = diff_y / (elapsed_ns - s->last_frame_timestamp) * 1000;
frame->finger_data.velX = diff_x / (elapsed_ns + 1 - s->last_frame_timestamp) * 1000;
frame->finger_data.velY = diff_y / (elapsed_ns + 1 - s->last_frame_timestamp) * 1000;
frame->finger_data.x = (int)(x * MT_INTERNAL_SENSOR_SURFACE_WIDTH);
frame->finger_data.y = (int)(y * MT_INTERNAL_SENSOR_SURFACE_HEIGHT);
-616
View File
@@ -1,616 +0,0 @@
/*
* Synopsys DesignWareCore for USB OTG.
*
* Copyright (c) 2011 Richard Ian Taylor.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "hw/platform-bus.h"
#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/arm/ipod_touch_usb_otg.h"
static inline size_t synopsys_usb_tx_fifo_start(synopsys_usb_state *_state, uint32_t _fifo)
{
if(_fifo == 0)
return _state->gnptxfsiz >> 16;
else
return _state->dptxfsiz[_fifo-1] >> 16;
}
static inline size_t synopsys_usb_tx_fifo_size(synopsys_usb_state *_state, uint32_t _fifo)
{
if(_fifo == 0)
return _state->gnptxfsiz & 0xFFFF;
else
return _state->dptxfsiz[_fifo-1] & 0xFFFF;
}
static void synopsys_usb_update_irq(synopsys_usb_state *_state)
{
_state->daintsts = 0;
_state->gintsts &=~ (GINTMSK_OEP | GINTMSK_INEP | GINTMSK_OTG);
if(_state->gotgint)
_state->gintsts |= GINTMSK_OTG;
int i;
for(i = 0; i < USB_NUM_ENDPOINTS; i++)
{
if(_state->out_eps[i].interrupt_status & _state->doepmsk)
{
_state->daintsts |= 1 << (i+DAINT_OUT_SHIFT);
if(_state->daintmsk & (1 << (i+DAINT_OUT_SHIFT)))
_state->gintsts |= GINTMSK_OEP;
}
if(_state->in_eps[i].interrupt_status & _state->diepmsk)
{
_state->daintsts |= 1 << (i+DAINT_IN_SHIFT);
if(_state->daintmsk & (1 << (i+DAINT_IN_SHIFT)))
_state->gintsts |= GINTMSK_INEP;
}
}
if((_state->pcgcctl & 3) == 0 && _state->gintmsk & _state->gintsts)
{
//printf("USB: IRQ triggered 0x%08x & 0x%08x.\n", _state->gintsts, _state->gintmsk);
qemu_irq_raise(_state->irq);
}
else
qemu_irq_lower(_state->irq);
}
static void synopsys_usb_update_ep(synopsys_usb_state *_state, synopsys_usb_ep_state *_ep)
{
if(_ep->control & USB_EPCON_SETNAK)
{
_ep->control |= USB_EPCON_NAKSTS;
_ep->interrupt_status |= USB_EPINT_INEPNakEff;
_ep->control &=~ USB_EPCON_SETNAK;
}
if(_ep->control & USB_EPCON_DISABLE)
{
_ep->interrupt_status |= USB_EPINT_EPDisbld;
_ep->control &=~ (USB_EPCON_DISABLE | USB_EPCON_ENABLE);
}
}
static void synopsys_usb_update_in_ep(synopsys_usb_state *_state, uint8_t _ep)
{
synopsys_usb_ep_state *eps = &_state->in_eps[_ep];
synopsys_usb_update_ep(_state, eps);
if(eps->control & USB_EPCON_ENABLE)
;//printf("USB: IN transfer queued on %d.\n", _ep);
}
static void synopsys_usb_update_out_ep(synopsys_usb_state *_state, uint8_t _ep)
{
synopsys_usb_ep_state *eps = &_state->out_eps[_ep];
synopsys_usb_update_ep(_state, eps);
if(eps->control & USB_EPCON_ENABLE)
;//printf("USB: OUT transfer queued on %d.\n", _ep);
}
static uint32_t synopsys_usb_in_ep_read(synopsys_usb_state *_state, uint8_t _ep, hwaddr _addr)
{
if(_ep >= USB_NUM_ENDPOINTS)
{
hw_error("usb_synopsys: Tried to read from disabled EP %d.\n", _ep);
return 0;
}
switch (_addr)
{
case 0x00:
return _state->in_eps[_ep].control;
case 0x08:
return _state->in_eps[_ep].interrupt_status;
case 0x10:
return _state->in_eps[_ep].tx_size;
case 0x14:
return _state->in_eps[_ep].dma_address;
case 0x1C:
return _state->in_eps[_ep].dma_buffer;
default:
hw_error("usb_synopsys: bad ep read offset 0x" HWADDR_FMT_plx "\n", _addr);
break;
}
return 0;
}
static uint32_t synopsys_usb_out_ep_read(synopsys_usb_state *_state, int _ep, hwaddr _addr)
{
if(_ep >= USB_NUM_ENDPOINTS)
{
hw_error("usb_synopsys: Tried to read from disabled EP %d.\n", _ep);
return 0;
}
switch (_addr)
{
case 0x00:
return _state->out_eps[_ep].control;
case 0x08:
return _state->out_eps[_ep].interrupt_status;
case 0x10:
return _state->out_eps[_ep].tx_size;
case 0x14:
return _state->out_eps[_ep].dma_address;
case 0x1C:
return _state->out_eps[_ep].dma_buffer;
default:
hw_error("usb_synopsys: bad ep read offset 0x" HWADDR_FMT_plx "\n", _addr);
break;
}
return 0;
}
static uint64_t synopsys_usb_read(void *opaque, hwaddr _addr, unsigned size)
{
synopsys_usb_state *state = (synopsys_usb_state *)opaque;
//printf("USB: Read 0x%08x.\n", _addr);
switch(_addr)
{
case PCGCCTL:
return state->pcgcctl;
case GOTGCTL:
return state->gotgctl;
case GOTGINT:
return state->gotgint;
case GRSTCTL:
return state->grstctl;
case GHWCFG1:
return state->ghwcfg1;
case GHWCFG2:
return state->ghwcfg2;
case GHWCFG3:
return state->ghwcfg3;
case GHWCFG4:
return state->ghwcfg4;
case GAHBCFG:
return state->gahbcfg;
case GUSBCFG:
return state->gusbcfg;
case GINTMSK:
return state->gintmsk;
case GINTSTS:
return state->gintsts;
case DIEPMSK:
return state->diepmsk;
case DOEPMSK:
return state->doepmsk;
case DAINTMSK:
return state->daintmsk;
case DAINTSTS:
return state->daintsts;
case DCTL:
return state->dctl;
case DCFG:
return state->dcfg;
case DSTS:
return state->dsts;
case GRXSTSR:
case GRXSTSP:
return 0; // TODO: Do something about this?
case GNPTXFSTS:
return 0xFFFFFFFF;
case GRXFSIZ:
return state->grxfsiz;
case GNPTXFSIZ:
return state->gnptxfsiz;
case DIEPTXF(1) ... DIEPTXF(USB_NUM_FIFOS+1):
_addr -= DIEPTXF(1);
_addr >>= 2;
return state->dptxfsiz[_addr];
case USB_INREGS ... (USB_INREGS + USB_EPREGS_SIZE - 4):
_addr -= USB_INREGS;
return synopsys_usb_in_ep_read(state, _addr >> 5, _addr & 0x1f);
case USB_OUTREGS ... (USB_OUTREGS + USB_EPREGS_SIZE - 4):
_addr -= USB_OUTREGS;
return synopsys_usb_out_ep_read(state, _addr >> 5, _addr & 0x1f);
case USB_FIFO_START ... USB_FIFO_END-4:
_addr -= USB_FIFO_START;
return *((uint32_t*)(&state->fifos[_addr]));
default:
hw_error("USB: Unhandled read address 0x%08x!\n", _addr);
}
return 0;
}
static void synopsys_usb_in_ep_write(synopsys_usb_state *_state, int _ep, hwaddr _addr, uint32_t _val)
{
if(_ep >= USB_NUM_ENDPOINTS)
{
hw_error("usb_synopsys: Wrote to disabled EP %d.\n", _ep);
return;
}
switch (_addr)
{
case 0x00:
_state->in_eps[_ep].control = _val;
synopsys_usb_update_in_ep(_state, _ep);
return;
case 0x08:
_state->in_eps[_ep].interrupt_status &=~ _val;
synopsys_usb_update_irq(_state);
return;
case 0x10:
_state->in_eps[_ep].tx_size = _val;
return;
case 0x14:
_state->in_eps[_ep].dma_address = _val;
return;
case 0x1C:
_state->in_eps[_ep].dma_buffer = _val;
return;
default:
hw_error("usb_synopsys: bad ep write offset 0x" HWADDR_FMT_plx "\n", _addr);
break;
}
}
static void synopsys_usb_out_ep_write(synopsys_usb_state *_state, int _ep, hwaddr _addr, uint32_t _val)
{
if(_ep >= USB_NUM_ENDPOINTS)
{
hw_error("usb_synopsys: Wrote to disabled EP %d.\n", _ep);
return;
}
switch (_addr)
{
case 0x00:
_state->out_eps[_ep].control = _val;
synopsys_usb_update_out_ep(_state, _ep);
return;
case 0x08:
_state->out_eps[_ep].interrupt_status &=~ _val;
synopsys_usb_update_irq(_state);
return;
case 0x10:
_state->out_eps[_ep].tx_size = _val;
return;
case 0x14:
_state->out_eps[_ep].dma_address = _val;
return;
case 0x1C:
_state->out_eps[_ep].dma_buffer = _val;
return;
default:
hw_error("usb_synopsys: bad ep write offset 0x" HWADDR_FMT_plx "\n", _addr);
break;
}
}
static void synopsys_usb_write(void *opaque, hwaddr _addr, uint64_t _val, unsigned size)
{
synopsys_usb_state *state = (synopsys_usb_state *)opaque;
//printf("USB: Write 0x%08x to 0x%08x.\n", _val, _addr);
switch(_addr)
{
case PCGCCTL:
state->pcgcctl = _val;
synopsys_usb_update_irq(state);
return;
case GOTGCTL:
state->gotgctl = _val;
break;
case GOTGINT:
state->gotgint &=~ _val;
synopsys_usb_update_irq(state);
return;
case GRSTCTL:
if(_val & GRSTCTL_CORESOFTRESET)
{
state->grstctl = GRSTCTL_CORESOFTRESET;
// Do reset stuff
// if(state->server_host)
// {
// tcp_usb_cleanup(&state->tcp_state);
// tcp_usb_init(&state->tcp_state, synopsys_usb_tcp_callback, NULL, state);
// printf("Connecting to USB server at %s:%d...\n",
// state->server_host, state->server_port);
// int ret = tcp_usb_connect(&state->tcp_state, state->server_host, state->server_port);
// if(ret < 0)
// hw_error("Failed to connect to USB server (%d).\n", ret);
// printf("Connected to USB server.\n");
// }
state->grstctl &= ~GRSTCTL_CORESOFTRESET;
state->grstctl |= GRSTCTL_AHBIDLE;
state->gintsts |= GINTMSK_RESET;
synopsys_usb_update_irq(state);
}
else if(_val == 0)
state->grstctl = _val;
return;
case GINTMSK:
state->gintmsk = _val;
synopsys_usb_update_irq(state);
break;
case GINTSTS:
state->gintsts &=~ _val;
synopsys_usb_update_irq(state);
return;
case DOEPMSK:
state->doepmsk = _val;
synopsys_usb_update_irq(state);
return;
case DIEPMSK:
state->diepmsk = _val;
synopsys_usb_update_irq(state);
return;
case DAINTMSK:
state->daintmsk = _val;
synopsys_usb_update_irq(state);
return;
case DAINTSTS:
state->daintsts &=~ _val;
synopsys_usb_update_irq(state);
return;
case GAHBCFG:
state->gahbcfg = _val;
return;
case GUSBCFG:
state->gusbcfg = _val;
return;
case DCTL:
if((_val & DCTL_SGNPINNAK) != (state->dctl & DCTL_SGNPINNAK)
&& (_val & DCTL_SGNPINNAK))
{
state->gintsts |= GINTMSK_GINNAKEFF;
_val &=~ DCTL_SGNPINNAK;
}
if((_val & DCTL_SGOUTNAK) != (state->dctl & DCTL_SGOUTNAK)
&& (_val & DCTL_SGOUTNAK))
{
state->gintsts |= GINTMSK_GOUTNAKEFF;
_val &=~ DCTL_SGOUTNAK;
}
state->dctl = _val;
synopsys_usb_update_irq(state);
return;
case DCFG:
//printf("USB: dcfg = 0x%08x.\n", _val);
state->dcfg = _val;
return;
case GRXFSIZ:
state->grxfsiz = _val;
return;
case GNPTXFSIZ:
state->gnptxfsiz = _val;
return;
case DIEPTXF(1) ... DIEPTXF(USB_NUM_FIFOS+1):
_addr -= DIEPTXF(1);
_addr >>= 2;
state->dptxfsiz[_addr] = _val;
return;
case USB_INREGS ... (USB_INREGS + USB_EPREGS_SIZE - 4):
_addr -= USB_INREGS;
synopsys_usb_in_ep_write(state, _addr >> 5, _addr & 0x1f, _val);
return;
case USB_OUTREGS ... (USB_OUTREGS + USB_EPREGS_SIZE - 4):
_addr -= USB_OUTREGS;
synopsys_usb_out_ep_write(state, _addr >> 5, _addr & 0x1f, _val);
return;
case USB_FIFO_START ... USB_FIFO_END-4:
_addr -= USB_FIFO_START;
*((uint32_t*)(&state->fifos[_addr])) = _val;
return;
default:
hw_error("USB: Unhandled write address 0x%08x!\n", _addr);
}
}
static const MemoryRegionOps usb_otg_ops = {
.read = synopsys_usb_read,
.write = synopsys_usb_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void s5l8900_usb_otg_reset(DeviceState *d)
{
synopsys_usb_state *state = S5L8900USBOTG(d);
printf("USB: cfg = 0x%08x, 0x%08x, 0x%08x, 0x%08x.\n",
state->ghwcfg1,
state->ghwcfg2,
state->ghwcfg3,
state->ghwcfg4);
state->pcgcctl = 3;
state->gahbcfg = 0;
state->gusbcfg = 0;
state->dctl = 0;
state->dcfg = 0;
state->dsts = 0;
state->gotgctl = 0;
state->gotgint = 0;
state->gintmsk = 0;
state->gintsts = 0;
state->daintmsk = 0;
state->daintsts = 0;
state->diepmsk = 0;
state->doepmsk = 0;
state->grxfsiz = 0x100;
state->gnptxfsiz = (0x100 << 16) | 0x100;
uint32_t counter = 0x200;
int i;
for(i = 0; i < USB_NUM_FIFOS; i++)
{
state->dptxfsiz[i] = (counter << 16) | 0x100;
counter += 0x100;
}
for(i = 0; i < USB_NUM_ENDPOINTS; i++)
{
synopsys_usb_ep_state *in = &state->in_eps[i];
in->control = 0;
in->dma_address = 0;
in->fifo = 0;
in->tx_size = 0;
synopsys_usb_ep_state *out = &state->out_eps[i];
out->control = 0;
out->dma_address = 0;
out->fifo = 0;
out->tx_size = 0;
}
synopsys_usb_update_irq(state);
}
static void s5l8900_usb_otg_init1(Object *obj)
{
DeviceState *dev = DEVICE(obj);
synopsys_usb_state *s = S5L8900USBOTG(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &usb_otg_ops, s, "usb_otg", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
sysbus_init_irq(sbd, &s->irq);
}
// Helper for adding to a machine
DeviceState *ipod_touch_init_usb_otg(qemu_irq _irq, uint32_t _hwcfg[4])
{
DeviceState *dev = qdev_new(TYPE_S5L8900USBOTG);
synopsys_usb_state *state = S5L8900USBOTG(dev);
state->ghwcfg1 = _hwcfg[0];
state->ghwcfg2 = _hwcfg[1];
state->ghwcfg3 = _hwcfg[2];
state->ghwcfg4 = _hwcfg[3];
SysBusDevice *sdev = SYS_BUS_DEVICE(dev);
sysbus_connect_irq(sdev, 0, _irq);
return dev;
}
static void s5l8900_usb_otg_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = s5l8900_usb_otg_reset;
}
static const TypeInfo s5l8900_usb_otg_info = {
.name = TYPE_S5L8900USBOTG,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(synopsys_usb_state),
.instance_init = s5l8900_usb_otg_init1,
.class_init = s5l8900_usb_otg_class_init,
};
static void s5l8900_usb_otg_register_types(void)
{
type_register_static(&s5l8900_usb_otg_info);
}
type_init(s5l8900_usb_otg_register_types)
+2
View File
@@ -16,6 +16,8 @@ static uint64_t ipod_touch_usb_phys_read(void *opaque, hwaddr addr, unsigned siz
return s->usb_unknown1;
case REG_OPHYTUNE:
return s->usb_ophytune;
case REG_CABLE:
return s->is_cable_connected;
default:
return 0x0;
//hw_error("%s: read invalid location 0x%08x\n", __func__, addr);
+1 -1
View File
@@ -65,7 +65,7 @@ arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmuv3.c'))
arm_ss.add(when: 'CONFIG_FSL_IMX6UL', if_true: files('fsl-imx6ul.c', 'mcimx6ul-evk.c'))
arm_ss.add(when: 'CONFIG_NRF51_SOC', if_true: files('nrf51_soc.c'))
arm_ss.add(when: 'CONFIG_XEN', if_true: files('xen_arm.c'))
arm_ss.add(when: 'CONFIG_IPOD_TOUCH_2G', if_true: files('ipod_touch_2g.c', 'ipod_touch_clock.c', 'ipod_touch_chipid.c', 'ipod_touch_gpio.c', 'ipod_touch_sysic.c', 'ipod_touch_timer.c', 'ipod_touch_usb_otg.c', 'ipod_touch_usb_phys.c', 'ipod_touch_spi.c', 'ipod_touch_nor_spi.c', 'ipod_touch_sha1.c', 'ipod_touch_aes.c', 'ipod_touch_pke.c', 'ipod_touch_pcf50633_pmu.c', 'ipod_touch_unknown1.c', 'ipod_touch_lcd.c', 'ipod_touch_mipi_dsi.c', 'ipod_touch_fmss.c', 'ipod_touch_mbx.c', 'ipod_touch_cd3272_mikey.c', 'ipod_touch_lis302dl.c', 'ipod_touch_multitouch.c', 'ipod_touch_scaler_csc.c', 'ipod_touch_sdio.c', 'ipod_touch_tvout.c'))
arm_ss.add(when: 'CONFIG_IPOD_TOUCH_2G', if_true: files('ipod_touch_2g.c', 'ipod_touch_clock.c', 'ipod_touch_chipid.c', 'ipod_touch_gpio.c', 'ipod_touch_sysic.c', 'ipod_touch_timer.c', 'ipod_touch_usb_phys.c', 'ipod_touch_spi.c', 'ipod_touch_nor_spi.c', 'ipod_touch_sha1.c', 'ipod_touch_aes.c', 'ipod_touch_pke.c', 'ipod_touch_pcf50633_pmu.c', 'ipod_touch_unknown1.c', 'ipod_touch_lcd.c', 'ipod_touch_mipi_dsi.c', 'ipod_touch_fmss.c', 'ipod_touch_mbx.c', 'ipod_touch_cd3272_mikey.c', 'ipod_touch_lis302dl.c', 'ipod_touch_multitouch.c', 'ipod_touch_scaler_csc.c', 'ipod_touch_sdio.c', 'ipod_touch_tvout.c'))
system_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c'))
system_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4_boards.c'))
+5
View File
@@ -137,3 +137,8 @@ config USB_DWC3
config XLNX_USB_SUBSYS
bool
select USB_DWC3
config USB_TCP
bool
default y
depends on USB
+84
View File
@@ -1368,6 +1368,9 @@ static void dwc2_realize(DeviceState *dev, Error **errp)
&dev->mem_reentrancy_guard);
sysbus_init_irq(sbd, &s->irq);
s->device = DWC2_USB_DEVICE(qdev_new(TYPE_DWC2_USB_DEVICE));
s->device->dwc2 = s;
}
static void dwc2_init(Object *obj)
@@ -1387,6 +1390,56 @@ static void dwc2_init(Object *obj)
memory_region_add_subregion(&s->container, 0x1000, &s->fifos);
}
static void dwc2_usb_device_realize(USBDevice *dev, Error **errp)
{
dev->speed = USB_SPEED_HIGH;
dev->speedmask = USB_SPEED_MASK_HIGH;
dev->flags |= (1 << USB_DEV_FLAG_IS_HOST);
dev->auto_attach = false;
}
static void dwc2_usb_device_handle_attach(USBDevice *dev)
{
DWC2DeviceState *udev = DWC2_USB_DEVICE(dev);
DWC2State *s = udev->dwc2;
/* not in host mode */
assert(!s->uport.dev);
s->gotgctl |= GOTGCTL_BSESVLD | GOTGCTL_CONID_B;
dwc2_lower_global_irq(s, GINTSTS_CURMODE_HOST);
dwc2_raise_global_irq(s, GINTSTS_CONIDSTSCHNG);
}
static void dwc2_usb_device_handle_detach(USBDevice *dev)
{
DWC2DeviceState *udev = DWC2_USB_DEVICE(dev);
DWC2State *s = udev->dwc2;
s->gotgctl &= ~(GOTGCTL_BSESVLD | GOTGCTL_CONID_B);
dwc2_raise_global_irq(s, GINTSTS_CURMODE_HOST | GINTSTS_CONIDSTSCHNG);
}
static void dwc2_usb_device_handle_reset(USBDevice *dev)
{
DWC2DeviceState *udev = DWC2_USB_DEVICE(dev);
DWC2State *s = udev->dwc2;
s->dcfg &= ~DCFG_DEVADDR_MASK;
for (int i = 1; i < DWC2_NB_EP; i++) {
s->diepctl(i) &= ~DXEPCTL_USBACTEP;
s->doepctl(i) &= ~DXEPCTL_USBACTEP;
}
dwc2_raise_global_irq(s, GINTSTS_USBRST);
}
static void dwc2_usb_device_cancel_packet(USBDevice *dev, USBPacket *p)
{
qemu_log_mask(LOG_UNIMP, "%s\n", __func__);
}
static const VMStateDescription vmstate_dwc2_state_packet = {
.name = "dwc2/packet",
.version_id = 1,
@@ -1448,6 +1501,29 @@ static Property dwc2_usb_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
static void dwc2_usb_device_class_initfn_common(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
USBDeviceClass *uc = USB_DEVICE_CLASS(klass);
uc->realize = dwc2_usb_device_realize;
uc->product_desc = "DWC2 USB Device";
uc->unrealize = NULL;
uc->cancel_packet = dwc2_usb_device_cancel_packet;
uc->handle_attach = dwc2_usb_device_handle_attach;
//uc->handle_detach = dwc2_usb_device_handle_detach;
uc->handle_reset = dwc2_usb_device_handle_reset;
uc->handle_data = NULL;
uc->handle_control = NULL;
//uc->handle_packet = dwc2_usb_device_handle_packet;
uc->flush_ep_queue = NULL;
uc->ep_stopped = NULL;
uc->alloc_streams = NULL;
uc->free_streams = NULL;
uc->usb_desc = NULL;
set_bit(DEVICE_CATEGORY_USB, dc->categories);
}
static void dwc2_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -1462,6 +1538,13 @@ static void dwc2_class_init(ObjectClass *klass, void *data)
dwc2_reset_exit, &c->parent_phases);
}
static const TypeInfo dwc2_usb_device_type_info = {
.name = TYPE_DWC2_USB_DEVICE,
.parent = TYPE_USB_DEVICE,
.instance_size = sizeof(DWC2DeviceState),
.class_init = dwc2_usb_device_class_initfn_common,
};
static const TypeInfo dwc2_usb_type_info = {
.name = TYPE_DWC2_USB,
.parent = TYPE_SYS_BUS_DEVICE,
@@ -1473,6 +1556,7 @@ static const TypeInfo dwc2_usb_type_info = {
static void dwc2_usb_register_types(void)
{
type_register_static(&dwc2_usb_device_type_info);
type_register_static(&dwc2_usb_type_info);
}
+49
View File
@@ -30,8 +30,10 @@
#define DWC2_NB_CHAN 8 /* Number of host channels */
#define DWC2_MAX_XFER_SIZE 65536 /* Max transfer size expected in HCTSIZ */
#define DWC2_NB_EP 16 /* Number of device endpoints */
typedef struct DWC2Packet DWC2Packet;
typedef struct DWC2DeviceState DWC2DeviceState;
typedef struct DWC2State DWC2State;
typedef struct DWC2Class DWC2Class;
@@ -57,12 +59,18 @@ struct DWC2Packet {
bool needs_service;
};
struct DWC2DeviceState {
USBDevice parent_obj;
DWC2State *dwc2;
};
struct DWC2State {
/*< private >*/
SysBusDevice parent_obj;
/*< public >*/
USBBus bus;
DWC2DeviceState *device;
qemu_irq irq;
MemoryRegion *dma_mr;
AddressSpace dma_as;
@@ -141,6 +149,44 @@ struct DWC2State {
#define hcdma(_ch) hreg1[((_ch) << 3) + 5] /* 514, 534, ... */
#define hcdmab(_ch) hreg1[((_ch) << 3) + 7] /* 51c, 53c, ... */
union {
#define DWC2_DREG_SIZE 0x38
uint32_t dreg[DWC2_DREG_SIZE / sizeof(uint32_t)];
struct {
uint32_t dcfg; /* 800 */
uint32_t dctl; /* 804 */
uint32_t dsts; /* 808 */
uint32_t rsvd2; /* 80c */
uint32_t diepmsk; /* 810 */
uint32_t doepmsk; /* 814 */
uint32_t daint; /* 818 */
uint32_t daintmsk; /* 81c */
uint32_t dtknqr1; /* 820 */
uint32_t dtknqr2; /* 824 */
uint32_t dvbusdis; /* 828 */
uint32_t dvbuspulse; /* 82c */
uint32_t dtknqr3; /* 830 */
uint32_t dtknqr4; /* 834 */
};
};
#define DWC2_DIEPREG_SIZE (0x20 * DWC2_NB_EP)
uint32_t diepreg[DWC2_DIEPREG_SIZE / sizeof(uint32_t)];
#define diepctl(_ch) diepreg[((_ch) << 3) + 0] /* 900, 920, ... */
#define diepint(_ch) diepreg[((_ch) << 3) + 2] /* 908, 928, ... */
#define dieptsiz(_ch) diepreg[((_ch) << 3) + 4] /* 910, 930, ... */
#define diepdma(_ch) diepreg[((_ch) << 3) + 5] /* 914, 934, ... */
#define dtxfsts(_ch) diepreg[((_ch) << 3) + 6] /* 918, 938, ... */
#define DWC2_DOEPREG_SIZE (0x20 * DWC2_NB_EP)
uint32_t doepreg[DWC2_DIEPREG_SIZE / sizeof(uint32_t)];
#define doepctl(_ch) doepreg[((_ch) << 3) + 0] /* b00, b20, ... */
#define doepint(_ch) doepreg[((_ch) << 3) + 2] /* b08, b28, ... */
#define doeptsiz(_ch) doepreg[((_ch) << 3) + 4] /* b10, b30, ... */
#define doepdma(_ch) doepreg[((_ch) << 3) + 5] /* b14, b34, ... */
union {
#define DWC2_PCGREG_SIZE 0x08
uint32_t pcgreg[DWC2_PCGREG_SIZE / sizeof(uint32_t)];
@@ -180,6 +226,9 @@ struct DWC2Class {
/*< public >*/
};
#define TYPE_DWC2_USB_DEVICE "dwc2-usb-device"
OBJECT_DECLARE_TYPE(DWC2DeviceState, USBDeviceClass, DWC2_USB_DEVICE)
#define TYPE_DWC2_USB "dwc2-usb"
OBJECT_DECLARE_TYPE(DWC2State, DWC2Class, DWC2_USB)
+457
View File
@@ -0,0 +1,457 @@
#include "qemu/osdep.h"
#include "qom/object.h"
#include "qemu/lockable.h"
#include "hw/usb.h"
#include "tcp-usb.h"
#include "hw/usb/hcd-tcp.h"
#include "qemu/cutils.h"
#include "hw/qdev-properties.h"
#include "qemu/main-loop.h"
#include "qemu/coroutine.h"
#include "io/channel.h"
#include "io/channel-util.h"
#include "qapi/error.h"
#include "sysemu/iothread.h"
#include "qemu/error-report.h"
#include "migration/blocker.h"
//#define DEBUG_HCD_TCP
#ifdef DEBUG_HCD_TCP
#define DPRINTF(fmt, ...) \
do { fprintf(stderr, "hcd-tcp: " fmt , ## __VA_ARGS__); } while (0)
#else
#define DPRINTF(fmt, ...) do {} while(0)
#endif
static void usb_tcp_host_closed(USBTCPHostState *s)
{
DPRINTF("%s\n", __func__);
if (s->ioc) {
qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
qio_channel_close(s->ioc, NULL);
object_unref(OBJECT(s->ioc));
s->ioc = NULL;
}
s->closed = true;
migrate_del_blocker(s->migration_blocker);
}
static ssize_t tcp_usb_read(QIOChannel *ioc, void *buf, size_t len)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
bool iolock = qemu_mutex_iothread_locked();
bool iothread = qemu_in_iothread();
ssize_t ret = -1;
Error *err = NULL;
/*
* Dont use in IOThread out of co-routine context as
* it will block IOThread.
*/
assert(qemu_in_coroutine() || !iothread);
if (iolock && !iothread && !qemu_in_coroutine()) {
qemu_mutex_unlock_iothread();
}
ret = qio_channel_readv_full_all_eof(ioc, &iov, 1, NULL, 0, &err);
if (iolock && !iothread && !qemu_in_coroutine()) {
qemu_mutex_lock_iothread();
}
if (err) {
error_report_err(err);
}
return (ret <= 0) ? ret : iov.iov_len;
}
static bool tcp_usb_write(QIOChannel *ioc, void *buf, ssize_t len)
{
struct iovec iov = { .iov_base = buf, .iov_len = len };
bool iolock = qemu_mutex_iothread_locked();
bool iothread = qemu_in_iothread();
bool ret = false;
Error *err = NULL;
/*
* Dont use in IOThread out of co-routine context as
* it will block IOThread.
*/
assert(qemu_in_coroutine() || !iothread);
if (iolock && !iothread && !qemu_in_coroutine()) {
qemu_mutex_unlock_iothread();
}
if (!qio_channel_writev_full_all(ioc, &iov, 1, NULL, 0, 0, &err)) {
ret = true;
}
if (iolock && !iothread && !qemu_in_coroutine()) {
qemu_mutex_lock_iothread();
}
if (err) {
error_report_err(err);
}
return ret;
}
static USBPort *usb_tcp_host_find_active_port(USBTCPHostState *s)
{
for (int i = 0; i < G_N_ELEMENTS(s->uports) - 1; i++) {
if (s->uports[i].dev->attached) {
return &s->uports[i];
}
}
return &s->uports[0];
}
static void coroutine_fn usb_tcp_host_respond_packet_co(void *opaque)
{
USBTCPPacket *pkt = (USBTCPPacket *)opaque;
USBTCPHostState *s = USB_TCP_HOST(pkt->s);
USBPacket *p = &pkt->p;
tcp_usb_header_t hdr = { 0 };
tcp_usb_response_header resp = { 0 };
g_autofree void *buffer = NULL;
USBPort *uport = usb_tcp_host_find_active_port(s);
WITH_QEMU_LOCK_GUARD(&s->write_mutex) {
if (!s->closed) {
hdr.type = TCP_USB_RESPONSE;
resp.addr = uport->dev->addr;
resp.pid = p->pid;
resp.ep = p->ep->nr;
resp.id = p->id;
resp.status = p->status;
resp.length = p->iov.size;
if (resp.length > p->actual_length) {
resp.length = p->actual_length;
}
if (p->pid == USB_TOKEN_IN && p->status != USB_RET_ASYNC) {
buffer = g_malloc(resp.length);
iov_to_buf(p->iov.iov, p->iov.niov, 0, buffer, resp.length);
}
if (!tcp_usb_write(s->ioc, &hdr, sizeof(hdr))) {
usb_tcp_host_closed(s);
return;
}
if (!tcp_usb_write(s->ioc, &resp, sizeof(resp))) {
usb_tcp_host_closed(s);
return;
}
if (buffer) {
if (!tcp_usb_write(s->ioc, buffer, resp.length)) {
usb_tcp_host_closed(s);
return;
}
}
}
}
if (!usb_packet_is_inflight(p)) {
if (pkt->buffer) {
g_free(pkt->buffer);
}
usb_packet_cleanup(p);
g_free(pkt);
}
}
static void usb_tcp_host_respond_packet(USBTCPHostState *s, USBTCPPacket *pkt)
{
Coroutine *co = NULL;
co = qemu_coroutine_create(usb_tcp_host_respond_packet_co, pkt);
qemu_coroutine_enter(co);
}
static void coroutine_fn usb_tcp_host_msg_loop_co(void *opaque)
{
USBTCPHostState *s = USB_TCP_HOST(opaque);
USBPort *uport = usb_tcp_host_find_active_port(s);
QIOChannel *ioc = s->ioc;
for(;;) {
tcp_usb_header_t hdr = { 0 };
if (unlikely((tcp_usb_read(ioc, &hdr, sizeof(hdr)) != sizeof(hdr)))) {
usb_tcp_host_closed(s);
return;
}
switch (hdr.type) {
case TCP_USB_REQUEST: {
/* fprintf(stderr, "%s: TCP_USB_REQUEST\n", __func__); */
tcp_usb_request_header pkt_hdr = {0};
g_autofree void *buffer = NULL;
g_autofree USBTCPPacket *pkt = (USBTCPPacket *) g_malloc0(sizeof(USBTCPPacket));
USBEndpoint *ep = NULL;
if (unlikely(tcp_usb_read(ioc, &pkt_hdr, sizeof(pkt_hdr)) != sizeof(pkt_hdr))) {
usb_tcp_host_closed(s);
return;
}
#if 0
DPRINTF("%s: TCP_USB_REQUEST pid: 0x%x ep: %d id: 0x%lx\n", __func__, pkt_hdr.pid, pkt_hdr.ep, pkt_hdr.id);
#endif
ep = usb_ep_get(uport->dev, pkt_hdr.pid, pkt_hdr.ep);
if (ep == NULL) {
DPRINTF("%s: TCP_USB_REQUEST unknown EP\n", __func__);
usb_tcp_host_closed(s);
return;
}
usb_packet_init(&pkt->p);
usb_packet_setup(&pkt->p, pkt_hdr.pid, ep, pkt_hdr.stream, pkt_hdr.id, pkt_hdr.short_not_ok, pkt_hdr.int_req);
if (pkt_hdr.length > 0) {
buffer = g_malloc0(pkt_hdr.length);
if (pkt_hdr.pid != USB_TOKEN_IN) {
if (unlikely(tcp_usb_read(s->ioc, buffer, pkt_hdr.length) != pkt_hdr.length)) {
usb_tcp_host_closed(s);
usb_packet_cleanup(&pkt->p);
return;
}
/* qemu_hexdump(stderr, __func__, buffer, pkt_hdr.length); */
}
usb_packet_addbuf(&pkt->p, buffer, pkt_hdr.length);
pkt->buffer = buffer;
g_steal_pointer(&buffer);
}
if (pkt_hdr.addr != uport->dev->addr) {
/*
* fprintf(stderr,
* "%s: USB_RET_NODEV: pkt_hdr.addr != uport->dev->addr: %d != %d\n",
* __func__, pkt_hdr.addr, uport->dev->addr);
*/
/* Can't enforce this check because dwc2 address transition time is slow */
}
pkt->dev = ep->dev;
pkt->s = s;
pkt->addr = pkt_hdr.addr;
assert(qemu_mutex_iothread_locked());
usb_handle_packet(pkt->dev, &pkt->p);
usb_tcp_host_respond_packet(s, pkt);
g_steal_pointer(&pkt);
break;
}
case TCP_USB_RESPONSE:
fprintf(stderr, "%s: unexpected TCP_USB_RESPONSE\n", __func__);
usb_tcp_host_closed(s);
return;
case TCP_USB_CANCEL: {
/* DPRINTF("%s: TCP_USB_CANCEL\n", __func__); */
tcp_usb_cancel_header pkt_hdr = {0};
USBTCPPacket *pkt = NULL;
USBPacket *p = NULL;
if (unlikely(tcp_usb_read(ioc, &pkt_hdr, sizeof(pkt_hdr)) != sizeof(pkt_hdr))) {
usb_tcp_host_closed(s);
return;
}
#if 1
DPRINTF("%s: TCP_USB_CANCEL pid: 0x%x ep: %d\n", __func__, pkt_hdr.pid, pkt_hdr.ep);
#endif
if (pkt_hdr.addr != uport->dev->addr) {
/*
* fprintf(stderr,
* "%s: USB_RET_NODEV: pkt_hdr.addr != uport->dev->addr: %d != %d\n",
* __func__, pkt_hdr.addr, uport->dev->addr);
*/
/* Can't enforce this check because dwc2 address transition time is slow */
}
assert(qemu_mutex_iothread_locked());
p = usb_ep_find_packet_by_id(uport->dev, pkt_hdr.pid,
pkt_hdr.ep, pkt_hdr.id);
if (p) {
pkt = container_of(p, USBTCPPacket, p);
usb_cancel_packet(&pkt->p);
DPRINTF("%s: TCP_USB_CANCEL: packet"
" pid: 0x%x ep: %d id: 0x%lx len: 0x%x\n",
__func__, pkt_hdr.pid, pkt_hdr.ep, pkt_hdr.id, p->actual_length);
usb_tcp_host_respond_packet(s, pkt);
} else {
warn_report("%s: TCP_USB_CANCEL: packet"
" pid: 0x%x ep: %d id: 0x%lx not found",
__func__, pkt_hdr.pid, pkt_hdr.ep, pkt_hdr.id);
}
break;
}
case TCP_USB_RESET:
/* fprintf(stderr, "%s: TCP_USB_RESET\n", __func__); */
DPRINTF("%s: TCP_USB_RESET\n", __func__);
assert(qemu_mutex_iothread_locked());
usb_device_reset(uport->dev);
break;;
default:
g_assert_not_reached();
break;
}
}
return;
}
static void usb_tcp_host_attach(USBPort *uport)
{
struct sockaddr_un server_addr;
USBTCPHostState *s = USB_TCP_HOST(uport->opaque);
int sock = -1;
Coroutine *co = NULL;
QIOChannel *ioc = NULL;
int ret;
Error *err = NULL;
if (uport->index >= G_N_ELEMENTS(s->uports) - 1) {
error_report("%s: attached to unused port\n", __func__);
return;
}
if (usb_tcp_host_find_active_port(s) != uport) {
error_report("%s: Attaching to 2 proxy ports at the same time. "
"This port might not be able to receive packets.\n",
__func__);
return;
}
if (!uport->dev || !uport->dev->attached) {
return;
}
sock = socket(AF_UNIX, SOCK_STREAM, 0);
if (socket < 0) {
error_report("%s: cannot open socket", __func__);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sun_family = AF_UNIX;
strncpy(server_addr.sun_path, socket_path, sizeof(server_addr.sun_path));
server_addr.sun_path[sizeof(server_addr.sun_path) - 1] = '\0';
ret = connect(sock, (const struct sockaddr *) &server_addr, sizeof(server_addr));
if (ret < 0) {
error_report("%s: failed to connect to server: %d\n", __func__, ret);
close(sock);
return;
}
ioc = qio_channel_new_fd(sock, &err);
if (!ioc) {
error_report_err(err);
close(sock);
return;
}
qio_channel_set_blocking(ioc, false, NULL);
s->closed = 0;
s->ioc = ioc;
migrate_add_blocker(s->migration_blocker, NULL);
co = qemu_coroutine_create(usb_tcp_host_msg_loop_co, s);
qemu_coroutine_enter(co);
}
static void usb_tcp_host_detach(USBPort *uport)
{
USBTCPHostState *s = USB_TCP_HOST(uport->opaque);
usb_tcp_host_closed(s);
}
static void usb_tcp_host_async_packet_complete(USBPort *port, USBPacket *p)
{
USBTCPHostState *s = USB_TCP_HOST(port->opaque);
usb_tcp_host_respond_packet(s, container_of(p, USBTCPPacket, p));
}
static USBBusOps usb_tcp_bus_ops = { };
static USBPortOps usb_tcp_host_port_ops = {
.attach = usb_tcp_host_attach,
.detach = usb_tcp_host_detach,
.child_detach = NULL,
.wakeup = NULL,
.complete = usb_tcp_host_async_packet_complete,
};
static void usb_tcp_host_realize(DeviceState *dev, Error **errp)
{
USBTCPHostState *s = USB_TCP_HOST(dev);
usb_bus_new(&s->bus, sizeof(s->bus), &usb_tcp_bus_ops, dev);
for (int i = 0; i < G_N_ELEMENTS(s->uports); i++) {
usb_register_port(&s->bus, &s->uports[i], s, i, &usb_tcp_host_port_ops,
USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL |
USB_SPEED_MASK_HIGH);
}
s->closed = 1;
qemu_co_mutex_init(&s->write_mutex);
}
static void usb_tcp_host_unrealize(DeviceState *dev)
{
USBTCPHostState *s = USB_TCP_HOST(dev);
if (s->ioc) {
qio_channel_shutdown(s->ioc, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
qio_channel_close(s->ioc, NULL);
s->ioc = NULL;
}
s->closed = 1;
s->stopped = 1;
}
static void usb_tcp_host_init(Object *obj)
{
USBTCPHostState *s = USB_TCP_HOST(obj);
s->closed = 1;
error_setg(&s->migration_blocker, "%s does not support migration "
"while connected", TYPE_USB_TCP_HOST);
}
static Property usb_tcp_host_properties[] = {
DEFINE_PROP_END_OF_LIST(),
};
static void usb_tcp_host_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->realize = usb_tcp_host_realize;
dc->unrealize = usb_tcp_host_unrealize;
dc->desc = "QEMU USB Passthrough Host Controller";
device_class_set_props(dc, usb_tcp_host_properties);
set_bit(DEVICE_CATEGORY_USB, dc->categories);
}
static const TypeInfo usb_tcp_host_type_info = {
.name = TYPE_USB_TCP_HOST,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(USBTCPHostState),
.class_init = usb_tcp_host_class_init,
.instance_init = usb_tcp_host_init,
};
static void usb_tcp_host_register_types(void)
{
type_register_static(&usb_tcp_host_type_info);
}
type_init(usb_tcp_host_register_types)
+2
View File
@@ -11,6 +11,8 @@ system_ss.add(when: 'CONFIG_USB', if_true: files(
'pcap.c',
))
system_ss.add(when: 'CONFIG_USB_TCP', if_true: files('hcd-tcp.c'))
# usb host adapters
system_ss.add(when: 'CONFIG_USB_UHCI', if_true: files('hcd-uhci.c'))
system_ss.add(when: 'CONFIG_USB_OHCI', if_true: files('hcd-ohci.c'))
+48
View File
@@ -0,0 +1,48 @@
#ifndef HW_USB_TCP_USB_H
#define HW_USB_TCP_USB_H
#include "qemu/osdep.h"
#include "hw/usb.h"
static const char *socket_path = "/tmp/usbqemu";
enum {
TCP_USB_REQUEST = (1 << 0),
TCP_USB_RESPONSE = (1 << 1),
TCP_USB_RESET = (1 << 2),
TCP_USB_CANCEL = (1 << 3)
};
typedef struct QEMU_PACKED tcp_usb_header {
uint8_t type;
} tcp_usb_header_t;
typedef struct QEMU_PACKED tcp_usb_request_header {
uint8_t addr;
int pid;
uint8_t ep;
unsigned int stream;
uint64_t id;
uint8_t short_not_ok;
uint8_t int_req;
uint16_t length;
} tcp_usb_request_header;
typedef struct QEMU_PACKED tcp_usb_response_header {
uint8_t addr;
int pid;
uint8_t ep;
uint64_t id;
uint32_t status;
uint16_t length;
} tcp_usb_response_header;
typedef struct QEMU_PACKED tcp_usb_cancel_header {
uint8_t addr;
int pid;
uint8_t ep;
uint64_t id;
} tcp_usb_cancel_header;
#endif //HW_USB_TCP_USB_H
+23 -2
View File
@@ -9,12 +9,13 @@
#include "cpu.h"
#include "hw/dma/pl080.h"
#include "hw/i2c/ipod_touch_i2c.h"
#include "hw/usb/hcd-dwc2.h"
#include "hw/usb/hcd-tcp.h"
#include "hw/arm/ipod_touch_timer.h"
#include "hw/arm/ipod_touch_clock.h"
#include "hw/arm/ipod_touch_chipid.h"
#include "hw/arm/ipod_touch_gpio.h"
#include "hw/arm/ipod_touch_sysic.h"
#include "hw/arm/ipod_touch_usb_otg.h"
#include "hw/arm/ipod_touch_usb_phys.h"
#include "hw/arm/ipod_touch_spi.h"
#include "hw/arm/ipod_touch_sha1.h"
@@ -57,6 +58,25 @@
#define S5L8900_GPIO_G3_IRQ 0x03
#define S5L8900_GPIO_G4_IRQ 0x02
// key codes
#define KEY_UP (1 << 7)
#define KEY_P 25
#define KEY_P_DOWN KEY_P
#define KEY_P_UP (KEY_P_DOWN | KEY_UP)
#define KEY_H 35
#define KEY_H_DOWN KEY_H
#define KEY_H_UP (KEY_H_DOWN | KEY_UP)
#define KEY_MIN 12
#define KEY_MIN_DOWN KEY_MIN
#define KEY_MIN_UP (KEY_MIN_DOWN | KEY_UP)
#define KEY_PLUS 13
#define KEY_PLUS_DOWN KEY_PLUS
#define KEY_PLUS_UP (KEY_PLUS_DOWN | KEY_UP)
const int S5L8900_GPIO_IRQS[5] = { S5L8900_GPIO_G0_IRQ, S5L8900_GPIO_G1_IRQ, S5L8900_GPIO_G2_IRQ, S5L8900_GPIO_G3_IRQ, S5L8900_GPIO_G4_IRQ };
#define IT2G_CPREG_VAR_NAME(name) cpreg_##name
@@ -135,7 +155,8 @@ typedef struct {
IPodTouchChipIDState *chipid_state;
IPodTouchGPIOState *gpio_state;
IPodTouchSYSICState *sysic;
synopsys_usb_state *usb_otg;
MemoryRegion usb_dma_container_mr;
DWC2State *dwc2;
IPodTouchUSBPhysState *usb_phys_state;
IPodTouchSHA1State *sha1_state;
IPodTouchAESState *aes_state;
+21 -5
View File
@@ -10,19 +10,35 @@
#define TYPE_IPOD_TOUCH_GPIO "ipodtouch.gpio"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchGPIOState, IPOD_TOUCH_GPIO)
#define GPIO_BUTTON_POWER 0xC02
#define GPIO_BUTTON_HOME 0xC01
#define GPIO_BUTTON_VOLUP 0x902
#define GPIO_FORCE_DFU 0xB03
#define GPIO_BUTTON_VOLDOWN 0xC00
#define GPIO_BUTTON_HOME 0xC01
#define GPIO_BUTTON_POWER 0xC02
#define GPIO_DFU_STATUS 0xC03
#define GPIO_BUTTON_POWER_IRQ 0x7A
#define GPIO_BUTTON_HOME_IRQ 0x79
#define GPIO_BUTTON_POWER_IRQ 0x7A
#define GPIO_BUTTON_HOME_IRQ 0x79
#define GPIO_BUTTON_VOLUP_IRQ 0x78
#define GPIO_BUTTON_VOLDOWN_IRQ 0x62
#define NUM_GPIO_PADS 0xC
#define NUM_GPIO_PINS 0x20
#define GPIO2PIN(gpio) ((gpio) & 7)
#define GPIO2PAD(gpio) (((gpio) >> 8) & 0xFF)
#define GPIOADDR2PAD(addr) (addr - 0x4) / 0x20
typedef struct IPodTouchGPIOState
{
SysBusDevice parent_obj;
MemoryRegion iomem;
uint32_t gpio_state;
uint32_t gpio_state[NUM_GPIO_PADS];
} IPodTouchGPIOState;
bool gpio_is_on(uint32_t *state, uint32_t gpio);
bool gpio_is_off(uint32_t *state, uint32_t gpio);
void gpio_set_on(uint32_t *state, uint32_t gpio);
void gpio_set_off(uint32_t *state, uint32_t gpio);
#endif
-267
View File
@@ -1,267 +0,0 @@
#ifndef HW_ARM_IPOD_TOUCH_USB_OTG_H
#define HW_ARM_IPOD_TOUCH_USB_OTG_H
#include "hw/irq.h"
#include "hw/usb.h"
#define DEVICE_NAME "usb_synopsys"
#define TYPE_S5L8900USBOTG "s5l8900usbotg"
OBJECT_DECLARE_SIMPLE_TYPE(synopsys_usb_state, S5L8900USBOTG)
// Maximums supported by OIB
#define USB_NUM_ENDPOINTS 8
#define USB_NUM_FIFOS 16
#define RX_FIFO_DEPTH 0x1C0
#define TX_FIFO_DEPTH 0x1C0
#define TX_FIFO_STARTADDR 0x200
#define PERIODIC_TX_FIFO_STARTADDR 0x21B
#define PERIODIC_TX_FIFO_DEPTH 0x100
// Registers
#define GOTGCTL 0x0
#define GOTGINT 0x4
#define GAHBCFG 0x8
#define GUSBCFG 0xC
#define GRSTCTL 0x10
#define GINTSTS 0x14
#define GINTMSK 0x18
#define GRXSTSR 0x1C
#define GRXSTSP 0x20
#define GRXFSIZ 0x24
#define GNPTXFSIZ 0x28
#define GNPTXFSTS 0x2C
#define GHWCFG1 0x44
#define GHWCFG2 0x48
#define GHWCFG3 0x4C
#define GHWCFG4 0x50
#define DIEPTXF(x) (0x100 + (4*(x)))
#define DCFG 0x800
#define DCTL 0x804
#define DSTS 0x808
#define DIEPMSK 0x810
#define DOEPMSK 0x814
#define DAINTSTS 0x818
#define DAINTMSK 0x81C
#define DTKNQR1 0x820
#define DTKNQR2 0x824
#define DTKNQR3 0x830
#define DTKNQR4 0x834
#define USB_INREGS 0x900
#define USB_OUTREGS 0xB00
#define USB_EPREGS_SIZE 0x200
#define USB_FIFO_START 0x1000
#define USB_FIFO_SIZE (0x100*(USB_NUM_FIFOS+1))
#define USB_FIFO_END (USB_FIFO_START+USB_FIFO_SIZE)
#define PCGCCTL 0xE00
#define PCGCCTL_ONOFF_MASK 3 // bits 0, 1
#define PCGCCTL_ON 0
#define PCGCCTL_OFF 1
#define GOTGCTL_BSESSIONVALID (1 << 19)
#define GOTGCTL_SESSIONREQUEST (1 << 1)
#define GAHBCFG_DMAEN (1 << 5)
#define GAHBCFG_BSTLEN_SINGLE (0 << 1)
#define GAHBCFG_BSTLEN_INCR (1 << 1)
#define GAHBCFG_BSTLEN_INCR4 (3 << 1)
#define GAHBCFG_BSTLEN_INCR8 (5 << 1)
#define GAHBCFG_BSTLEN_INCR16 (7 << 1)
#define GAHBCFG_MASKINT 0x1
#define GUSBCFG_TURNAROUND_MASK 0xF
#define GUSBCFG_TURNAROUND_SHIFT 10
#define GUSBCFG_HNPENABLE (1 << 9)
#define GUSBCFG_SRPENABLE (1 << 8)
#define GUSBCFG_PHYIF16BIT (1 << 3)
#define USB_UNKNOWNREG1_START 0x1708
#define GHWCFG2_TKNDEPTH_SHIFT 26
#define GHWCFG2_TKNDEPTH_MASK 0xF
#define GHWCFG2_NUM_ENDPOINTS_SHIFT 10
#define GHWCFG2_NUM_ENDPOINTS_MASK 0xf
#define GHWCFG4_DED_FIFO_EN (1 << 25)
#define GRSTCTL_AHBIDLE (1 << 31)
#define GRSTCTL_TXFFLUSH (1 << 5)
#define GRSTCTL_TXFFNUM_SHIFT 6
#define GRSTCTL_TXFFNUM_MASK 0x1f
#define GRSTCTL_CORESOFTRESET 0x1
#define GRSTCTL_TKNFLUSH 3
#define GINTMSK_NONE 0x0
#define GINTMSK_OTG (1 << 2)
#define GINTMSK_SOF (1 << 3)
#define GINTMSK_GINNAKEFF (1 << 6)
#define GINTMSK_GOUTNAKEFF (1 << 7)
#define GINTMSK_SUSPEND (1 << 11)
#define GINTMSK_RESET (1 << 12)
#define GINTMSK_ENUMDONE (1 << 13)
#define GINTMSK_EPMIS (1 << 17)
#define GINTMSK_INEP (1 << 18)
#define GINTMSK_OEP (1 << 19)
#define GINTMSK_DISCONNECT (1 << 29)
#define GINTMSK_RESUME (1 << 31)
#define GOTGINT_SESENDDET (1 << 2)
#define FIFO_DEPTH_SHIFT 16
#define GNPTXFSTS_GET_TXQSPCAVAIL(x) GET_BITS(x, 16, 8)
#define GHWCFG4_DED_FIFO_EN (1 << 25)
#define DAINT_ALL 0xFFFFFFFF
#define DAINT_NONE 0
#define DAINT_OUT_SHIFT 16
#define DAINT_IN_SHIFT 0
#define DCTL_SFTDISCONNECT 0x2
#define DCTL_PROGRAMDONE (1 << 11)
#define DCTL_CGOUTNAK (1 << 10)
#define DCTL_SGOUTNAK (1 << 9)
#define DCTL_CGNPINNAK (1 << 8)
#define DCTL_SGNPINNAK (1 << 7)
#define DSTS_GET_SPEED(x) GET_BITS(x, 1, 2)
#define DCFG_NZSTSOUTHSHK (1 << 2)
#define DCFG_EPMSCNT (1 << 18)
#define DCFG_HISPEED 0x0
#define DCFG_FULLSPEED 0x1
#define DCFG_DEVICEADDR_UNSHIFTED_MASK 0x7F
#define DCFG_DEVICEADDR_SHIFT 4
#define DCFG_DEVICEADDRMSK (DCFG_DEVICEADDR_UNSHIFTED_MASK << DCFG_DEVICEADDR_SHIFT)
#define DCFG_ACTIVE_EP_COUNT_MASK 0x1f
#define DCFG_ACTIVE_EP_COUNT_SHIFT 18
#define DOEPTSIZ0_SUPCNT_MASK 0x3
#define DOEPTSIZ0_SUPCNT_SHIFT 29
#define DOEPTSIZ0_PKTCNT_MASK 0x1
#define DEPTSIZ0_XFERSIZ_MASK 0x7F
#define DIEPTSIZ_MC_MASK 0x3
#define DIEPTSIZ_MC_SHIFT 29
#define DEPTSIZ_PKTCNT_MASK 0x3FF
#define DEPTSIZ_PKTCNT_SHIFT 19
#define DEPTSIZ_XFERSIZ_MASK 0x1FFFF
// ENDPOINT_DIRECTIONS register has two bits per endpoint. 0, 1 for endpoint 0. 1, 2 for end point 1, etc.
#define USB_EP_DIRECTION(ep) (USBDirection)(2-((GET_REG(USB + GHWCFG1) >> ((ep) * 2)) & 0x3))
#define USB_ENDPOINT_DIRECTIONS_BIDIR 0
#define USB_ENDPOINT_DIRECTIONS_IN 1
#define USB_ENDPOINT_DIRECTIONS_OUT 2
#define USB_START_DELAYUS 10000
#define USB_SFTDISCONNECT_DELAYUS 4000
#define USB_ONOFFSTART_DELAYUS 100
#define USB_RESETWAITFINISH_DELAYUS 1000
#define USB_SFTCONNECT_DELAYUS 250
#define USB_PROGRAMDONE_DELAYUS 10
#define USB_EPCON_ENABLE (1 << 31)
#define USB_EPCON_DISABLE (1 << 30)
#define USB_EPCON_SETD0PID (1 << 28)
#define USB_EPCON_SETNAK (1 << 27)
#define USB_EPCON_CLEARNAK (1 << 26)
#define USB_EPCON_TXFNUM_MASK 0xf
#define USB_EPCON_TXFNUM_SHIFT 22
#define USB_EPCON_STALL (1 << 21)
#define USB_EPCON_TYPE_MASK 0x3
#define USB_EPCON_TYPE_SHIFT 18
#define USB_EPCON_NAKSTS (1 << 17)
#define USB_EPCON_ACTIVE (1 << 15)
#define USB_EPCON_NEXTEP_MASK 0xF
#define USB_EPCON_NEXTEP_SHIFT 11
#define USB_EPCON_MPS_MASK 0x7FF
#define USB_EPINT_INEPNakEff 0x40
#define USB_EPINT_INTknEPMis 0x20
#define USB_EPINT_INTknTXFEmp 0x10
#define USB_EPINT_TimeOUT 0x8
#define USB_EPINT_AHBErr 0x4
#define USB_EPINT_EPDisbld 0x2
#define USB_EPINT_XferCompl 0x1
#define USB_EPINT_Back2BackSetup (1 << 6)
#define USB_EPINT_OUTTknEPDis 0x10
#define USB_EPINT_SetUp 0x8
#define USB_EPINT_EpDisbld 0x1
#define USB_EPINT_NONE 0
#define USB_EPINT_ALL 0xFFFFFFFF
#define USB_2_0 0x0200
#define USB_HIGHSPEED 0
#define USB_FULLSPEED 1
#define USB_LOWSPEED 2
#define USB_FULLSPEED_48_MHZ 3
#define USB_CONTROLEP 0
typedef struct _synopsys_usb_ep_state
{
uint32_t control;
uint32_t tx_size;
uint32_t fifo;
uint32_t interrupt_status;
hwaddr dma_address;
hwaddr dma_buffer;
} synopsys_usb_ep_state;
typedef struct synopsys_usb_state
{
SysBusDevice busdev;
MemoryRegion iomem;
qemu_irq irq;
char *server_host;
uint32_t server_port;
//tcp_usb_state_t tcp_state;
uint32_t pcgcctl;
uint32_t ghwcfg1;
uint32_t ghwcfg2;
uint32_t ghwcfg3;
uint32_t ghwcfg4;
uint32_t gahbcfg;
uint32_t gusbcfg;
uint32_t grxfsiz;
uint32_t gnptxfsiz;
uint32_t gotgctl;
uint32_t gotgint;
uint32_t grstctl;
uint32_t gintmsk;
uint32_t gintsts;
uint32_t dptxfsiz[USB_NUM_FIFOS];
uint32_t dctl;
uint32_t dcfg;
uint32_t dsts;
uint32_t daintmsk;
uint32_t daintsts;
uint32_t diepmsk;
uint32_t doepmsk;
synopsys_usb_ep_state in_eps[USB_NUM_ENDPOINTS];
synopsys_usb_ep_state out_eps[USB_NUM_ENDPOINTS];
uint8_t fifos[0x100 * (USB_NUM_FIFOS+1)];
} synopsys_usb_state;
DeviceState *ipod_touch_init_usb_otg(qemu_irq _irq, uint32_t _hwcfg[4]);
#endif
+5 -3
View File
@@ -8,11 +8,12 @@
#define TYPE_IPOD_TOUCH_USB_PHYS "ipodtouch.usbphys"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchUSBPhysState, IPOD_TOUCH_USB_PHYS)
#define REG_OPHYPWR 0x0
#define REG_OPHYCLK 0x4
#define REG_ORSTCON 0x8
#define REG_OPHYPWR 0x0
#define REG_OPHYCLK 0x4
#define REG_ORSTCON 0x8
#define REG_UNKNOWN1 0x1C
#define REG_OPHYTUNE 0x20
#define REG_CABLE 0x28
typedef struct IPodTouchUSBPhysState {
SysBusDevice busdev;
@@ -23,6 +24,7 @@ typedef struct IPodTouchUSBPhysState {
uint32_t usb_orstcon;
uint32_t usb_unknown1;
uint32_t usb_ophytune;
bool is_cable_connected;
} IPodTouchUSBPhysState;
#endif
+35
View File
@@ -0,0 +1,35 @@
#ifndef HW_USB_HCD_TCP_H
#define HW_USB_HCD_TCP_H
#include "qemu/osdep.h"
#include "hw/sysbus.h"
#include "qom/object.h"
#include "hw/usb.h"
#include "io/channel.h"
#include "qemu/coroutine.h"
#include "qapi/error.h"
#define TYPE_USB_TCP_HOST "usb-tcp-host"
OBJECT_DECLARE_SIMPLE_TYPE(USBTCPHostState, USB_TCP_HOST)
typedef struct USBTCPPacket {
USBPacket p;
void *buffer;
USBDevice *dev;
USBTCPHostState *s;
uint8_t addr;
} USBTCPPacket;
struct USBTCPHostState {
SysBusDevice parent_obj;
USBBus bus;
USBPort uports[3];
QIOChannel *ioc;
CoMutex write_mutex;
Error *migration_blocker;
bool closed;
bool stopped;
};
#endif /* HW_USB_HCD_TCP_H */