Compare commits
19
Commits
dfu
...
dfu_s5l8720
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fd6f1e0ed9 | ||
|
|
aa88deb054 | ||
|
|
328815631b | ||
|
|
c5998ab084 | ||
|
|
1c586e8a0c | ||
|
|
7022646c4d | ||
|
|
fa0981b602 | ||
|
|
0cb390e281 | ||
|
|
0d8014f8db | ||
|
|
e241f91a5b | ||
|
|
4400b861c8 | ||
|
|
cae1b51a78 | ||
|
|
a99e51abfa | ||
|
|
ce74809f11 | ||
|
|
ceb93afd79 | ||
|
|
bad3d0cc90 | ||
|
|
82b95a84a3 | ||
|
|
28f87fc7d6 | ||
|
|
973b5a90ef |
No files matched your search
+19
@@ -2,6 +2,18 @@
|
||||
|
||||
This file contains the instructions on how to run the iPod Touch 2G emulator using QEMU.
|
||||
Note that this is an experimental release and the functionality of the device is still limited.
|
||||
Linux compatibility is currently unstable. Efforts are underway to improve it.
|
||||
|
||||
### Getting the Source Code
|
||||
|
||||
Clone the repository using the following commands:
|
||||
|
||||
```
|
||||
git clone https://github.com/devos50/qemu-ios.git
|
||||
cd qemu-ios
|
||||
```
|
||||
|
||||
Now you can proceed with the rest of the instructions for building and running the emulator.
|
||||
|
||||
### Building QEMU
|
||||
|
||||
@@ -14,6 +26,9 @@ brew install glib ninja pixman pkg-config sdl2
|
||||
# On Linux (Ubuntu)
|
||||
sudo apt install make ninja-build pkg-config libssl-dev libsdl2-dev libpixman-1-dev libpixman-1-0 libglib2.0-dev
|
||||
|
||||
# On Linux (Arch)
|
||||
sudo pacman -S --needed make ninja pkgconf openssl sdl2 pixman glib2
|
||||
|
||||
# On Windows (MSYS2/mingw64)
|
||||
pacman -S base-devel mingw-w64-x86_64-toolchain git python ninja mingw-w64-x86_64-glib2 mingw-w64-x86_64-pixman python-setuptools mingw-w64-x86_64-SDL2
|
||||
|
||||
@@ -23,12 +38,16 @@ Compile QEMU by running the following commands from the root directory:
|
||||
```
|
||||
mkdir build
|
||||
cd build
|
||||
|
||||
# On Intel Macs
|
||||
../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 --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 Linux
|
||||
../configure --enable-sdl --disable-cocoa --target-list=arm-softmmu --disable-capstone --disable-slirp --extra-cflags=-I/usr/include/openssl --extra-ldflags='-lcrypto' --disable-werror --enable-pie
|
||||
|
||||
# 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
|
||||
|
||||
|
||||
+15
-2
@@ -96,7 +96,7 @@ static void ipod_touch_memory_setup(MachineState *machine, MemoryRegion *sysmem,
|
||||
|
||||
// load the bootrom (vrom)
|
||||
uint8_t *file_data = NULL;
|
||||
unsigned long fsize;
|
||||
gsize fsize;
|
||||
if (g_file_get_contents(nms->bootrom_path, (char **)&file_data, &fsize, NULL)) {
|
||||
allocate_ram(sysmem, "vrom", 0x0, 0x20000);
|
||||
address_space_rw(nsas, VROM_MEM_BASE, MEMTXATTRS_UNSPECIFIED, (uint8_t *)file_data, fsize, 1);
|
||||
@@ -236,6 +236,7 @@ static void ipod_touch_key_event(void *opaque, int keycode)
|
||||
gpio_set_off(s->gpio_state->gpio_state, GPIO_BUTTON_VOLUP);
|
||||
}
|
||||
}
|
||||
else return;
|
||||
|
||||
s->sysic->gpio_int_status[gpio_group] |= (1 << gpio_selector);
|
||||
qemu_irq_raise(s->sysic->gpio_irqs[gpio_group]);
|
||||
@@ -406,7 +407,9 @@ static void ipod_touch_machine_init(MachineState *machine)
|
||||
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;
|
||||
busdev = SYS_BUS_DEVICE(dev);
|
||||
memory_region_add_subregion(sysmem, USBOTG_MEM_BASE, &nms->usb_otg->iomem);
|
||||
sysbus_realize(busdev, &error_fatal);
|
||||
|
||||
// init two pl080 DMAC0 devices
|
||||
dev = qdev_new("pl080");
|
||||
@@ -442,6 +445,9 @@ static void ipod_touch_machine_init(MachineState *machine)
|
||||
// init the accelerometer
|
||||
I2CSlave *accelerometer = i2c_slave_create_simple(i2c_state->bus, "lis302dl", 0x1D);
|
||||
|
||||
// init the audio codec (disabled because unused)
|
||||
// I2CSlave *audio_codec = i2c_slave_create_simple(i2c_state->bus, "cs42l58", 0x4A);
|
||||
|
||||
// Init I2C1
|
||||
dev = qdev_new("ipodtouch.i2c");
|
||||
i2c_state = IPOD_TOUCH_I2C(dev);
|
||||
@@ -451,6 +457,9 @@ static void ipod_touch_machine_init(MachineState *machine)
|
||||
memory_region_add_subregion(sysmem, I2C1_MEM_BASE, &i2c_state->iomem);
|
||||
sysbus_realize(busdev, &error_fatal);
|
||||
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_I2C1_IRQ));
|
||||
|
||||
// Init the light sensor
|
||||
I2CSlave *isl29003dl = i2c_slave_create_simple(i2c_state->bus, "isl29003dl", 0x44);
|
||||
|
||||
// init the Mikey
|
||||
I2CSlave *cd327mikey = i2c_slave_create_simple(i2c_state->bus, "cd3272mikey", 0x39);
|
||||
@@ -526,6 +535,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)
|
||||
@@ -551,4 +564,4 @@ static void ipod_touch_machine_types(void)
|
||||
type_register_static(&ipod_touch_machine_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_machine_types)
|
||||
type_init(ipod_touch_machine_types)
|
||||
@@ -0,0 +1,54 @@
|
||||
#include "hw/arm/ipod_touch_cs42l58.h"
|
||||
|
||||
static int cs42l58_event(I2CSlave *i2c, enum i2c_event event)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t cs42l58_recv(I2CSlave *i2c)
|
||||
{
|
||||
CS42L58State *s = CS42L58(i2c);
|
||||
printf("Reading stereo codec register %d\n", s->cmd);
|
||||
|
||||
switch(s->cmd) {
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int cs42l58_send(I2CSlave *i2c, uint8_t data)
|
||||
{
|
||||
CS42L58State *s = CS42L58(i2c);
|
||||
s->cmd = data;
|
||||
printf("Writing stereo codec register %d\n", s->cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cs42l58_init(Object *obj)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static void cs42l58_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
||||
|
||||
k->event = cs42l58_event;
|
||||
k->recv = cs42l58_recv;
|
||||
k->send = cs42l58_send;
|
||||
}
|
||||
|
||||
static const TypeInfo cs42l58_info = {
|
||||
.name = TYPE_CS42L58,
|
||||
.parent = TYPE_I2C_SLAVE,
|
||||
.instance_init = cs42l58_init,
|
||||
.instance_size = sizeof(CS42L58State),
|
||||
.class_init = cs42l58_class_init,
|
||||
};
|
||||
|
||||
static void cs42l58_register_types(void)
|
||||
{
|
||||
type_register_static(&cs42l58_info);
|
||||
}
|
||||
|
||||
type_init(cs42l58_register_types)
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "hw/arm/ipod_touch_fmss.h"
|
||||
|
||||
uint64_t temp_storage[512];
|
||||
|
||||
static uint8_t find_bit_index(uint8_t num) {
|
||||
int index = 0;
|
||||
while (num > 1) {
|
||||
@@ -24,7 +26,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 amfi_allow_any_signature=1"; // 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 -v zalloc_debug"; // 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...
|
||||
@@ -45,7 +47,7 @@ static void read_nand_pages(IPodTouchFMSSState *s)
|
||||
|
||||
if(cs > 3) {
|
||||
printf("CS %d invalid! (original CS: %d, reading page %d)\n", cs, og_cs, page_nr);
|
||||
dump_registers(s);
|
||||
//dump_registers(s);
|
||||
hw_error("CS %d invalid!", cs);
|
||||
}
|
||||
|
||||
@@ -86,7 +88,7 @@ static void read_nand_pages(IPodTouchFMSSState *s)
|
||||
|
||||
static uint64_t ipod_touch_fmss_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: read from location 0x%08x\n", __func__, addr);
|
||||
//fprintf(stderr, "%s: read from location 0x%08lx\n", __func__, addr);
|
||||
|
||||
IPodTouchFMSSState *s = (IPodTouchFMSSState *)opaque;
|
||||
switch(addr)
|
||||
@@ -101,8 +103,10 @@ static uint64_t ipod_touch_fmss_read(void *opaque, hwaddr addr, unsigned size)
|
||||
return (0x1 << 30);
|
||||
case 0xD00:
|
||||
return 42;
|
||||
case 0x00000C30:
|
||||
return 0x1;
|
||||
default:
|
||||
// hw_error("%s: read invalid location 0x%08x.\n", __func__, addr);
|
||||
printf("%s: read invalid location 0x%08x.\n", __func__, addr);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@@ -111,7 +115,7 @@ static uint64_t ipod_touch_fmss_read(void *opaque, hwaddr addr, unsigned size)
|
||||
static void ipod_touch_fmss_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
IPodTouchFMSSState *s = (IPodTouchFMSSState *)opaque;
|
||||
//printf("%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
|
||||
//printf("%s: writing 0x%08lx to 0x%08lx\n", __func__, val, addr);
|
||||
|
||||
switch(addr) {
|
||||
case 0xC00:
|
||||
@@ -146,8 +150,11 @@ static void ipod_touch_fmss_write(void *opaque, hwaddr addr, uint64_t val, unsig
|
||||
break;
|
||||
case 0xD38:
|
||||
if(s->reg_csgenrc == 0xa01) { read_nand_pages(s); }
|
||||
else { printf("NAND write not suported yet!\n"); }
|
||||
|
||||
else { /*printf("NAND write %ld addr %ld\n", val, addr); temp_storage[addr] = val;*//*cpu_physical_memory_write(addr, val, sizeof(val)); */}
|
||||
break;
|
||||
default:
|
||||
//printf("%s unknown write %lx to %lx\n", __func__, val, addr);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
#include "hw/arm/ipod_touch_isl29003dl.h"
|
||||
|
||||
static int isl29003dl_event(I2CSlave *i2c, enum i2c_event event)
|
||||
{
|
||||
ISL29003DLState *s = ISL29003DL(i2c);
|
||||
|
||||
printf("%s Got event %d\n", __func__, event);
|
||||
|
||||
if (event == I2C_START_SEND)
|
||||
s->ready = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t isl29003dl_recv(I2CSlave *i2c)
|
||||
{
|
||||
ISL29003DLState *s = ISL29003DL(i2c);
|
||||
printf("Reading lightsensor register %d\n", s->cmd);
|
||||
|
||||
int res = 0;
|
||||
|
||||
switch(s->cmd) {
|
||||
case LIGHTSENSOR_COMMAND:
|
||||
res = s->command;
|
||||
break;
|
||||
case LIGHTSENSOR_CONTROL:
|
||||
res = s->ctrl;
|
||||
break;
|
||||
case LIGHTSENSOR_LSB_SENSOR:
|
||||
res = s->lsb_sensor;
|
||||
break;
|
||||
case LIGHTSENSOR_MSB_SENSOR:
|
||||
res = s->msb_sensor;
|
||||
break;
|
||||
default:
|
||||
res = 0;
|
||||
printf("%s unknown register %d\n", __func__, s->cmd);
|
||||
}
|
||||
|
||||
s->cmd += 1;
|
||||
return res;
|
||||
}
|
||||
|
||||
static int isl29003dl_send(I2CSlave *i2c, uint8_t data)
|
||||
{
|
||||
ISL29003DLState *s = ISL29003DL(i2c);
|
||||
|
||||
if (s->ready)
|
||||
{
|
||||
s->curreg = data;
|
||||
s->ready = 0;
|
||||
printf("%s Lightsensor ready\n", __func__);
|
||||
}
|
||||
else
|
||||
{
|
||||
switch(s->curreg++)
|
||||
{
|
||||
case LIGHTSENSOR_COMMAND:
|
||||
s->command = data;
|
||||
if ((s->command >> 7) == 1)
|
||||
{
|
||||
s->lsb_sensor = 0xE;
|
||||
s->msb_sensor = 0xE << 4;
|
||||
s->it_hi = 0xF;
|
||||
s->it_lo = 0x0;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
printf("%s unknown register %d\n", __func__, s->curreg-1);
|
||||
}
|
||||
}
|
||||
printf("Writing lightsensor data %d\n", s->cmd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void isl29003dl_init(Object *obj)
|
||||
{
|
||||
}
|
||||
|
||||
static void isl29003dl_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
I2CSlaveClass *k = I2C_SLAVE_CLASS(klass);
|
||||
|
||||
k->event = isl29003dl_event;
|
||||
k->recv = isl29003dl_recv;
|
||||
k->send = isl29003dl_send;
|
||||
}
|
||||
|
||||
static const TypeInfo isl29003dl_info = {
|
||||
.name = TYPE_ISL29003DL,
|
||||
.parent = TYPE_I2C_SLAVE,
|
||||
.instance_init = isl29003dl_init,
|
||||
.instance_size = sizeof(ISL29003DLState),
|
||||
.class_init = isl29003dl_class_init,
|
||||
};
|
||||
|
||||
static void isl29003dl_register_types(void)
|
||||
{
|
||||
type_register_static(&isl29003dl_info);
|
||||
}
|
||||
|
||||
type_init(isl29003dl_register_types)
|
||||
+25
-11
@@ -3,9 +3,11 @@
|
||||
#include "ui/console.h"
|
||||
#include "hw/display/framebuffer.h"
|
||||
|
||||
int lcd_brightness = 255;
|
||||
|
||||
static uint64_t ipod_touch_lcd_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//printf("%s: read from location 0x%08x\n", __func__, addr);
|
||||
// printf("%s: read from location 0x%08x\n", __func__, addr);
|
||||
|
||||
IPodTouchLCDState *s = (IPodTouchLCDState *)opaque;
|
||||
switch(addr)
|
||||
@@ -26,8 +28,10 @@ static uint64_t ipod_touch_lcd_read(void *opaque, hwaddr addr, unsigned size)
|
||||
return s->w1_display_resolution_info;
|
||||
case 0x1b10:
|
||||
return 2;
|
||||
case 0x1b14:
|
||||
return 0x3;
|
||||
default:
|
||||
// hw_error("%s: read invalid location 0x%08x.\n", __func__, addr);
|
||||
printf("%s: read invalid location 0x%08x.\n", __func__, addr);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@@ -36,15 +40,16 @@ static uint64_t ipod_touch_lcd_read(void *opaque, hwaddr addr, unsigned size)
|
||||
static void ipod_touch_lcd_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
IPodTouchLCDState *s = (IPodTouchLCDState *)opaque;
|
||||
//printf("%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
|
||||
// printf("%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
|
||||
|
||||
switch(addr) {
|
||||
case 0x4:
|
||||
s->lcd_con = val;
|
||||
break;
|
||||
case 0xC:
|
||||
s->unknown1 = val;
|
||||
s->render = val;
|
||||
qemu_irq_lower(s->irq);
|
||||
// qemu_irq_raise(s->irq);
|
||||
break;
|
||||
case 0x20:
|
||||
s->w1_display_depth_info = val;
|
||||
@@ -61,6 +66,11 @@ static void ipod_touch_lcd_write(void *opaque, hwaddr addr, uint64_t val, unsign
|
||||
}
|
||||
}
|
||||
|
||||
void lcd_changebrightness(int brightness)
|
||||
{
|
||||
lcd_brightness = brightness & 0xFF;
|
||||
}
|
||||
|
||||
static void lcd_invalidate(void *opaque)
|
||||
{
|
||||
IPodTouchLCDState *s = opaque;
|
||||
@@ -69,6 +79,7 @@ static void lcd_invalidate(void *opaque)
|
||||
|
||||
static void draw_line32_32(void *opaque, uint8_t *d, const uint8_t *s, int width, int deststep)
|
||||
{
|
||||
// IPodTouchLCDState *lcd = (IPodTouchLCDState *) opaque;
|
||||
uint8_t r, g, b;
|
||||
|
||||
do {
|
||||
@@ -77,8 +88,8 @@ static void draw_line32_32(void *opaque, uint8_t *d, const uint8_t *s, int width
|
||||
b = s[0];
|
||||
g = s[1];
|
||||
r = s[2];
|
||||
//printf("R: %d, G: %d, B: %d\n", r, g, b);
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(r, g, b);
|
||||
// printf("R: %d, G: %d, B: %d, A: %d\n", r, g, b, lcd_brightness);
|
||||
((uint32_t *) d)[0] = rgb_to_pixel32(round((float)r * ((float)lcd_brightness / 255.0f)), round((float)g * ((float)lcd_brightness / 255.0f)), round((float)b * ((float)lcd_brightness / 255.0f)));
|
||||
s += 4;
|
||||
d += 4;
|
||||
} while (-- width != 0);
|
||||
@@ -86,7 +97,7 @@ static void draw_line32_32(void *opaque, uint8_t *d, const uint8_t *s, int width
|
||||
|
||||
static void lcd_refresh(void *opaque)
|
||||
{
|
||||
//fprintf(stderr, "%s: refreshing LCD screen\n", __func__);
|
||||
// printf("%s: refreshing LCD screen\n", __func__);
|
||||
|
||||
IPodTouchLCDState *lcd = (IPodTouchLCDState *) opaque;
|
||||
DisplaySurface *surface = qemu_console_surface(lcd->con);
|
||||
@@ -141,7 +152,7 @@ static const GraphicHwOps gfx_ops = {
|
||||
|
||||
static void ipod_touch_lcd_mouse_event(void *opaque, int x, int y, int z, int buttons_state)
|
||||
{
|
||||
//printf("CLICKY %d %d %d %d\n", x, y, z, buttons_state);
|
||||
// printf("x %d y %d z %d state %d\n", x, y, z, buttons_state);
|
||||
|
||||
// convert x and y to fractional numbers
|
||||
float fx = x / pow(2, 15);
|
||||
@@ -165,9 +176,12 @@ static void refresh_timer_tick(void *opaque)
|
||||
{
|
||||
IPodTouchLCDState *s = (IPodTouchLCDState *)opaque;
|
||||
|
||||
qemu_irq_raise(s->irq);
|
||||
if (s->render == 0x1)
|
||||
qemu_irq_raise(s->irq);
|
||||
else if (s->render == 0xFF)
|
||||
qemu_irq_lower(s->irq);
|
||||
|
||||
timer_mod(s->refresh_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / LCD_REFRESH_RATE_FREQUENCY);
|
||||
timer_mod(s->refresh_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / 60);//LCD_REFRESH_RATE_FREQUENCY);
|
||||
}
|
||||
|
||||
static void ipod_touch_lcd_realize(DeviceState *dev, Error **errp)
|
||||
@@ -215,4 +229,4 @@ static void ipod_touch_machine_types(void)
|
||||
type_register_static(&ipod_touch_lcd_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_machine_types)
|
||||
type_init(ipod_touch_machine_types)
|
||||
@@ -12,8 +12,21 @@ static uint8_t lis302dl_recv(I2CSlave *i2c)
|
||||
|
||||
switch(s->cmd) {
|
||||
case ACCEL_WHOAMI:
|
||||
return ACCEL_WHOAMI_VALUE; // whoami value
|
||||
return ACCEL_WHOAMI_VALUE;
|
||||
case ACCEL_OUT_X:
|
||||
return s->ctrl_reg1 == 1 ? s->out_x : 0;
|
||||
case ACCEL_OUT_Y:
|
||||
return s->ctrl_reg1 << 1 == 1 ? s->out_y : 0;
|
||||
case ACCEL_OUT_Z:
|
||||
return s->ctrl_reg1 << 2 == 1 ? s->out_z : 0;
|
||||
case ACCEL_CTRL_REG1:
|
||||
return s->ctrl_reg1;
|
||||
case ACCEL_CTRL_REG2:
|
||||
return s->ctrl_reg2;
|
||||
case ACCEL_CTRL_REG3:
|
||||
return s->ctrl_reg3;
|
||||
default:
|
||||
printf("%s Unknown register %d\n", __func__, s->cmd);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -52,4 +65,4 @@ static void lis302dl_register_types(void)
|
||||
type_register_static(&lis302dl_info);
|
||||
}
|
||||
|
||||
type_init(lis302dl_register_types)
|
||||
type_init(lis302dl_register_types)
|
||||
+21
-5
@@ -9,7 +9,9 @@ static uint32_t reverse_byte_order(uint32_t value) {
|
||||
|
||||
static uint64_t ipod_touch_mbx1_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
printf("%s: read from location 0x%08x\n", __func__, addr);
|
||||
IPodTouchMBXState *s = (IPodTouchMBXState *)opaque;
|
||||
if (addr != 0x1020)
|
||||
printf("%s: read from location 0x%08x\n", __func__, addr);
|
||||
switch(addr)
|
||||
{
|
||||
case 0x12c:
|
||||
@@ -17,7 +19,7 @@ static uint64_t ipod_touch_mbx1_read(void *opaque, hwaddr addr, unsigned size)
|
||||
case 0xf00:
|
||||
return (2 << 0x10) | (1 << 0x18); // seems to be some kind of identifier
|
||||
case 0x1020:
|
||||
return 0x10000;
|
||||
return s->addr != 0x0 ? s->addr : 0x10000;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -28,10 +30,19 @@ static void ipod_touch_mbx1_write(void *opaque, hwaddr addr, uint64_t val, unsig
|
||||
{
|
||||
IPodTouchMBXState *s = (IPodTouchMBXState *)opaque;
|
||||
fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case 0x1020:
|
||||
s->addr = val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void patch_kernel()
|
||||
static void patch_kernel(bool alreadypatched)
|
||||
{
|
||||
if (alreadypatched) return;
|
||||
alreadypatched = 1;
|
||||
// patch the loading of the AppleBCM4325 driver
|
||||
char *bcm4325_vars = "test";
|
||||
|
||||
@@ -91,11 +102,16 @@ static void patch_kernel()
|
||||
|
||||
static uint64_t ipod_touch_mbx2_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
IPodTouchMBXState *s = (IPodTouchMBXState *)opaque;
|
||||
printf("%s: read from location 0x%08x\n", __func__, addr);
|
||||
switch(addr)
|
||||
{
|
||||
case 0xC:
|
||||
patch_kernel();
|
||||
patch_kernel(s->alreadypatched);
|
||||
break;
|
||||
case 0x4:
|
||||
return 0xFF;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -149,4 +165,4 @@ static void ipod_touch_mbx_register_types(void)
|
||||
type_register_static(&ipod_touch_mbx_type_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_mbx_register_types)
|
||||
type_init(ipod_touch_mbx_register_types)
|
||||
@@ -2,7 +2,8 @@
|
||||
|
||||
static uint64_t ipod_touch_mipi_dsi_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
fprintf(stderr, "%s: read from location 0x%08x\n", __func__, addr);
|
||||
if (addr != 0x00000)
|
||||
fprintf(stderr, "%s: read from location 0x%08lx\n", __func__, addr);
|
||||
|
||||
IPodTouchMIPIDSIState *s = (IPodTouchMIPIDSIState *)opaque;
|
||||
switch(addr)
|
||||
@@ -24,7 +25,7 @@ static uint64_t ipod_touch_mipi_dsi_read(void *opaque, hwaddr addr, unsigned siz
|
||||
case REG_FIFOCTRL:
|
||||
return rDSIM_FIFOCTRL_EmptyHSfr;
|
||||
default:
|
||||
// hw_error("%s: read invalid location 0x%08x.\n", __func__, addr);
|
||||
printf("%s: read invalid location 0x%08lx.\n", __func__, addr);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
@@ -33,13 +34,16 @@ static uint64_t ipod_touch_mipi_dsi_read(void *opaque, hwaddr addr, unsigned siz
|
||||
static void ipod_touch_mipi_dsi_write(void *opaque, hwaddr addr, uint64_t val, unsigned size)
|
||||
{
|
||||
IPodTouchMIPIDSIState *s = (IPodTouchMIPIDSIState *)opaque;
|
||||
fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
|
||||
fprintf(stderr, "%s: writing 0x%08lx to 0x%08lx\n", __func__, val, addr);
|
||||
|
||||
switch(addr)
|
||||
{
|
||||
case REG_PKTHDR:
|
||||
s->pkthdr_reg = val;
|
||||
break;
|
||||
case 0x00000008:
|
||||
if (val == 0)
|
||||
printf("turning off screen\n");
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -89,4 +93,4 @@ static void ipod_touch_machine_types(void)
|
||||
type_register_static(&ipod_touch_mipi_dsi_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_machine_types)
|
||||
type_init(ipod_touch_machine_types)
|
||||
@@ -199,7 +199,7 @@ static uint32_t ipod_touch_multitouch_transfer(SSIPeripheral *dev, uint32_t valu
|
||||
s->out_buffer = (uint8_t *) s->next_frame;
|
||||
}
|
||||
else {
|
||||
hw_error("Unknown command 0x%02x!", value);
|
||||
printf("%s Unknown command 0x%02x!\n", __func__, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
static void initialize_nor(IPodTouchNORSPIState *s)
|
||||
{
|
||||
unsigned long fsize;
|
||||
gsize fsize;
|
||||
if (g_file_get_contents(s->nor_path, (char **)&s->nor_data, &fsize, NULL)) {
|
||||
s->nor_initialized = true;
|
||||
}
|
||||
@@ -67,8 +67,8 @@ static uint32_t ipod_touch_nor_spi_transfer(SSIPeripheral *dev, uint32_t value)
|
||||
s->out_buf[2] = 0x02;
|
||||
}
|
||||
else {
|
||||
printf("Unknown command %d!\n", value);
|
||||
hw_error("Unknown command 0x%02x!", value);
|
||||
printf("%s Unknown command 0x%02x!\n", __func__, value);
|
||||
// hw_error("Unknown command 0x%02x!", value);
|
||||
}
|
||||
|
||||
return 0x0;
|
||||
|
||||
@@ -1,7 +1,21 @@
|
||||
#include "hw/arm/ipod_touch_pcf50633_pmu.h"
|
||||
#include "hw/arm/ipod_touch_lcd.h"
|
||||
|
||||
static int pcf50633_event(I2CSlave *i2c, enum i2c_event event)
|
||||
{
|
||||
Pcf50633State *s = PCF50633(i2c);
|
||||
// printf("%s Event %d\n", __func__, s->cmd);
|
||||
|
||||
if (event == I2C_START_SEND)
|
||||
{
|
||||
// printf("%s start send %d\n", __func__, s->cmd);
|
||||
}
|
||||
else if (event == I2C_FINISH)
|
||||
{
|
||||
s->ready = 1;
|
||||
// printf("%s end send %d\n", __func__, s->cmd);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -27,10 +41,10 @@ static uint8_t pcf50633_recv(I2CSlave *i2c)
|
||||
|
||||
switch(s->cmd) {
|
||||
case PMU_MBCS1:
|
||||
res = 0; // battery power source
|
||||
res = 1; // battery power source
|
||||
break;
|
||||
case PMU_ADCC1:
|
||||
res = 0; // battery charge voltage
|
||||
res = 3; // battery charge voltage
|
||||
break;
|
||||
case PMU_RTCSC: // seconds
|
||||
res = int_to_bcd(tm.tm_sec);
|
||||
@@ -70,7 +84,22 @@ static uint8_t pcf50633_recv(I2CSlave *i2c)
|
||||
static int pcf50633_send(I2CSlave *i2c, uint8_t data)
|
||||
{
|
||||
Pcf50633State *s = PCF50633(i2c);
|
||||
s->cmd = data;
|
||||
if (s->ready)
|
||||
{
|
||||
s->curreg = data;
|
||||
s->ready = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
s->cmd = data;
|
||||
}
|
||||
|
||||
printf("Writing PMU register cmd %d reg %d\n", s->cmd, s->curreg);
|
||||
switch(s->curreg) {
|
||||
case PMU_DSBL1:
|
||||
lcd_changebrightness(s->cmd);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -101,4 +130,4 @@ static void pcf50633_register_types(void)
|
||||
type_register_static(&pcf50633_info);
|
||||
}
|
||||
|
||||
type_init(pcf50633_register_types)
|
||||
type_init(pcf50633_register_types)
|
||||
@@ -12,7 +12,7 @@ void sdio_exec_cmd(IPodTouchSDIOState *s)
|
||||
uint32_t cmd_type = s->cmd & 0x3f;
|
||||
uint32_t addr = (s->arg >> 9) & 0x1ffff;
|
||||
uint32_t func = (s->arg >> 28) & 0x7;
|
||||
//printf("SDIO CMD: %d, ADDR: %d, FUNC: %d\n", cmd_type, addr, func);
|
||||
printf("SDIO CMD: %d, ADDR: %d, FUNC: %d\n", cmd_type, addr, func);
|
||||
if(cmd_type == 0x3) {
|
||||
// RCA request - ignore
|
||||
}
|
||||
@@ -52,7 +52,7 @@ void sdio_exec_cmd(IPodTouchSDIOState *s)
|
||||
// CMD53 - block transfer
|
||||
addr = addr & 0x7fff;
|
||||
bool is_write = (s->arg >> 31) != 0;
|
||||
printf("SDIO: Executing cmd53 with block size %d and %d blocks (reg address: 0x%08x, destination address: 0x%08x, write? %d)\n", s->blklen, s->numblk, addr, s->baddr, is_write);
|
||||
printf("SDIO: Executing cmd53 func %x with block size %d and %d blocks (reg address: 0x%08x, destination address: 0x%08x, write? %d)\n", func, s->blklen, s->numblk, addr, s->baddr, is_write);
|
||||
|
||||
if(is_write) {
|
||||
if(func == 0x1) {
|
||||
@@ -61,7 +61,7 @@ void sdio_exec_cmd(IPodTouchSDIOState *s)
|
||||
else if(func == 0x2) {
|
||||
// this is a BCM4325 command - add a frame to the queue and schedule the IRQ request to indicate that the command has been completed
|
||||
BCM4325FrameHeaderPacket *frame_header = calloc(sizeof(BCM4325FrameHeaderPacket), sizeof(uint8_t *));
|
||||
uint16_t length = 14;
|
||||
uint16_t length = s->blklen * s->numblk;
|
||||
frame_header->frame_length = length;
|
||||
frame_header->checksum = length ^ 0xffff;
|
||||
g_queue_push_tail(s->rx_fifo, frame_header);
|
||||
@@ -83,6 +83,9 @@ void sdio_exec_cmd(IPodTouchSDIOState *s)
|
||||
if(!frame_header) {
|
||||
// create an empty frame
|
||||
frame_header = calloc(sizeof(BCM4325FrameHeaderPacket), sizeof(uint8_t *));
|
||||
|
||||
frame_header->frame_length = s->blklen * s->numblk;
|
||||
frame_header->checksum = (s->blklen * s->numblk) ^ 0xffff;
|
||||
}
|
||||
cpu_physical_memory_write(s->baddr, frame_header, sizeof(BCM4325FrameHeaderPacket));
|
||||
}
|
||||
@@ -101,7 +104,7 @@ void sdio_exec_cmd(IPodTouchSDIOState *s)
|
||||
|
||||
static void ipod_touch_sdio_write(void *opaque, hwaddr addr, uint64_t value, unsigned size)
|
||||
{
|
||||
//printf("%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
printf("%s: writing 0x%08x to 0x%08x\n", __func__, value, addr);
|
||||
|
||||
IPodTouchSDIOState *s = (struct IPodTouchSDIOState *) opaque;
|
||||
|
||||
@@ -146,7 +149,7 @@ static void ipod_touch_sdio_write(void *opaque, hwaddr addr, uint64_t value, uns
|
||||
|
||||
static uint64_t ipod_touch_sdio_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//printf("%s: offset = 0x%08x\n", __func__, addr);
|
||||
printf("%s: offset = 0x%08x\n", __func__, addr);
|
||||
|
||||
IPodTouchSDIOState *s = (struct IPodTouchSDIOState *) opaque;
|
||||
|
||||
@@ -164,11 +167,11 @@ static uint64_t ipod_touch_sdio_read(void *opaque, hwaddr addr, unsigned size)
|
||||
case SDIO_RESP0:
|
||||
return s->resp0;
|
||||
case SDIO_RESP1:
|
||||
return s->resp1;
|
||||
return s->resp1 == 0 ? 0x7465 : s->resp1;
|
||||
case SDIO_RESP2:
|
||||
return s->resp2;
|
||||
return s->resp2 == 0 ? 0x7374 : s->resp2;
|
||||
case SDIO_RESP3:
|
||||
return s->resp3;
|
||||
return s->resp3 == 0 ? 0xFFFF : s->resp3;
|
||||
case SDIO_CSR:
|
||||
return s->csr;
|
||||
case SDIO_IRQ:
|
||||
@@ -249,4 +252,4 @@ static void ipod_touch_sdio_register_types(void)
|
||||
type_register_static(&ipod_touch_sdio_type_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_sdio_register_types)
|
||||
type_init(ipod_touch_sdio_register_types)
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "hw/arm/ipod_touch_sha1.h"
|
||||
|
||||
static uint64_t swapLong(void *X) {
|
||||
uint64_t x = (uint64_t) X;
|
||||
static uint64_t swapLong(uint64_t x) {
|
||||
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
|
||||
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
|
||||
x = (x & 0x00FF00FF00FF00FF) << 8 | (x & 0xFF00FF00FF00FF00) >> 8;
|
||||
@@ -150,4 +149,4 @@ static void ipod_touch_machine_types(void)
|
||||
type_register_static(&ipod_touch_sha1_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_machine_types)
|
||||
type_init(ipod_touch_machine_types)
|
||||
@@ -93,7 +93,7 @@ static uint64_t s5l8900_timer1_read(void *opaque, hwaddr addr, unsigned size)
|
||||
case TIMER_TICKSLOW:
|
||||
return s->ticks_low;
|
||||
case TIMER_IRQSTAT:
|
||||
return ~0; // s->irqstat;
|
||||
return s->irqstat; // ~0; // s->irqstat;
|
||||
case TIMER_IRQLATCH:
|
||||
return 0xffffffff;
|
||||
|
||||
@@ -140,4 +140,4 @@ static void ipod_touch_machine_types(void)
|
||||
type_register_static(&ipod_touch_timer_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_machine_types)
|
||||
type_init(ipod_touch_machine_types)
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
static uint64_t ipod_touch_unknown1_read(void *opaque, hwaddr addr, unsigned size)
|
||||
{
|
||||
//fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
|
||||
fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
|
||||
|
||||
switch (addr) {
|
||||
case 0x140:
|
||||
@@ -53,4 +53,4 @@ static void ipod_touch_unknown1_register_types(void)
|
||||
type_register_static(&ipod_touch_unknown1_type_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_unknown1_register_types)
|
||||
type_init(ipod_touch_unknown1_register_types)
|
||||
+176
-15
@@ -95,7 +95,7 @@ static void synopsys_usb_update_in_ep(synopsys_usb_state *_state, uint8_t _ep)
|
||||
synopsys_usb_update_ep(_state, eps);
|
||||
|
||||
if(eps->control & USB_EPCON_ENABLE)
|
||||
;//printf("USB: IN transfer queued on %d.\n", _ep);
|
||||
;printf("USB: IN transfer queued on %d.\n", _ep);
|
||||
}
|
||||
|
||||
static void synopsys_usb_update_out_ep(synopsys_usb_state *_state, uint8_t _ep)
|
||||
@@ -107,6 +107,157 @@ static void synopsys_usb_update_out_ep(synopsys_usb_state *_state, uint8_t _ep)
|
||||
;//printf("USB: OUT transfer queued on %d.\n", _ep);
|
||||
}
|
||||
|
||||
static int synopsys_usb_tcp_callback(tcp_usb_state_t *_state, void *_arg, tcp_usb_header_t *_hdr, char *_buffer)
|
||||
{
|
||||
synopsys_usb_state *state = _arg;
|
||||
|
||||
_hdr->addr = (state->dcfg & DCFG_DEVICEADDRMSK) >> DCFG_DEVICEADDR_SHIFT;
|
||||
|
||||
if(_hdr->flags & tcp_usb_reset)
|
||||
{
|
||||
state->gintsts |= GINTMSK_RESET;
|
||||
synopsys_usb_update_irq(state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(_hdr->flags & tcp_usb_enumdone)
|
||||
{
|
||||
state->gintsts |= GINTMSK_ENUMDONE;
|
||||
}
|
||||
|
||||
int ret;
|
||||
uint8_t ep = _hdr->ep & 0x7f;
|
||||
if(_hdr->ep & USB_DIR_IN)
|
||||
{
|
||||
synopsys_usb_ep_state *eps = &state->in_eps[ep];
|
||||
|
||||
if(eps->control & USB_EPCON_STALL)
|
||||
{
|
||||
eps->control &=~ USB_EPCON_STALL; // Should this be EP0 only
|
||||
//printf("USB: Stall.\n");
|
||||
ret = USB_RET_STALL;
|
||||
}
|
||||
else if(eps->control & USB_EPCON_ENABLE)
|
||||
{
|
||||
// Do IN transfer!
|
||||
eps->control &=~ USB_EPCON_ENABLE;
|
||||
|
||||
size_t sz = eps->tx_size & DEPTSIZ_XFERSIZ_MASK;
|
||||
size_t amtDone = sz;
|
||||
if(amtDone > _hdr->length)
|
||||
amtDone = _hdr->length;
|
||||
|
||||
if(eps->fifo >= USB_NUM_FIFOS)
|
||||
hw_error("usb_synopsys: USB transfer on non-existant FIFO %d!\n", eps->fifo);
|
||||
|
||||
size_t txfz = synopsys_usb_tx_fifo_size(state, eps->fifo);
|
||||
if(amtDone > txfz)
|
||||
amtDone = txfz;
|
||||
|
||||
size_t txfs = synopsys_usb_tx_fifo_start(state, eps->fifo);
|
||||
if(txfs + txfz > sizeof(state->fifos))
|
||||
hw_error("usb_synopsys: USB transfer would overflow FIFO buffer!\n");
|
||||
|
||||
printf("USB: Starting IN transfer on EP %d (%d bytes)...\n", ep, amtDone);
|
||||
|
||||
if(amtDone > 0)
|
||||
{
|
||||
if(eps->dma_address)
|
||||
{
|
||||
cpu_physical_memory_read(eps->dma_address, &state->fifos[txfs], amtDone);
|
||||
eps->dma_address += amtDone;
|
||||
}
|
||||
|
||||
memcpy(_buffer, (char*)&state->fifos[txfs], amtDone);
|
||||
}
|
||||
|
||||
printf("USB: IN transfer complete!\n");
|
||||
|
||||
eps->tx_size = (eps->tx_size &~ DEPTSIZ_XFERSIZ_MASK)
|
||||
| ((sz-amtDone) & DEPTSIZ_XFERSIZ_MASK);
|
||||
eps->interrupt_status |= USB_EPINT_XferCompl;
|
||||
|
||||
ret = amtDone;
|
||||
}
|
||||
else
|
||||
ret = USB_RET_NAK;
|
||||
}
|
||||
else // OUT
|
||||
{
|
||||
synopsys_usb_ep_state *eps = &state->out_eps[ep];
|
||||
|
||||
printf("EPS control: %d\n", eps->control);
|
||||
|
||||
if(eps->control & USB_EPCON_STALL)
|
||||
{
|
||||
eps->control &=~ USB_EPCON_STALL; // Should this be EP0 only
|
||||
//printf("USB: Stall.\n");
|
||||
ret = USB_RET_STALL;
|
||||
}
|
||||
else if(eps->control & USB_EPCON_ENABLE)
|
||||
{
|
||||
// Do OUT transfer!
|
||||
eps->control &=~ USB_EPCON_ENABLE;
|
||||
|
||||
size_t sz = eps->tx_size & DEPTSIZ_XFERSIZ_MASK;
|
||||
size_t amtDone = sz;
|
||||
if(amtDone > _hdr->length)
|
||||
amtDone = _hdr->length;
|
||||
|
||||
size_t rxfz = state->grxfsiz;
|
||||
if(amtDone > rxfz)
|
||||
amtDone = rxfz;
|
||||
|
||||
if(rxfz > sizeof(state->fifos))
|
||||
hw_error("usb_synopsys: USB transfer would overflow FIFO buffer!\n");
|
||||
|
||||
printf("USB: Starting OUT transfer on EP %d (%d)...\n", ep, amtDone);
|
||||
|
||||
if(amtDone > 0)
|
||||
{
|
||||
memcpy((char*)state->fifos, _buffer, amtDone);
|
||||
|
||||
if(eps->dma_address)
|
||||
{
|
||||
printf("USB: DMA copying to 0x%08x.\n", eps->dma_address);
|
||||
cpu_physical_memory_write(eps->dma_address, state->fifos, amtDone);
|
||||
eps->dma_address += amtDone;
|
||||
}
|
||||
}
|
||||
|
||||
printf("USB: OUT transfer complete!\n");
|
||||
|
||||
if(_hdr->flags & tcp_usb_setup)
|
||||
{
|
||||
/*
|
||||
printf("USB: Setup %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
state->fifos[0],
|
||||
state->fifos[1],
|
||||
state->fifos[2],
|
||||
state->fifos[3],
|
||||
state->fifos[4],
|
||||
state->fifos[5],
|
||||
state->fifos[6],
|
||||
state->fifos[7]);
|
||||
*/
|
||||
eps->interrupt_status |= USB_EPINT_SetUp;
|
||||
}
|
||||
else
|
||||
eps->interrupt_status |= USB_EPINT_XferCompl;
|
||||
|
||||
eps->tx_size = (eps->tx_size &~ DEPTSIZ_XFERSIZ_MASK)
|
||||
| ((sz-amtDone) & DEPTSIZ_XFERSIZ_MASK);
|
||||
|
||||
ret = amtDone;
|
||||
}
|
||||
else
|
||||
ret = USB_RET_NAK;
|
||||
}
|
||||
|
||||
synopsys_usb_update_irq(state);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t synopsys_usb_in_ep_read(synopsys_usb_state *_state, uint8_t _ep, hwaddr _addr)
|
||||
{
|
||||
if(_ep >= USB_NUM_ENDPOINTS)
|
||||
@@ -283,6 +434,10 @@ static void synopsys_usb_in_ep_write(synopsys_usb_state *_state, int _ep, hwaddr
|
||||
return;
|
||||
}
|
||||
|
||||
if (_addr == 0x10) {
|
||||
printf("USB: Setting TX size of EP %d to %d.\n", _ep, _val);
|
||||
}
|
||||
|
||||
switch (_addr)
|
||||
{
|
||||
case 0x00:
|
||||
@@ -355,7 +510,7 @@ static void synopsys_usb_write(void *opaque, hwaddr _addr, uint64_t _val, unsign
|
||||
{
|
||||
synopsys_usb_state *state = (synopsys_usb_state *)opaque;
|
||||
|
||||
//printf("USB: Write 0x%08x to 0x%08x.\n", _val, _addr);
|
||||
printf("USB: Write 0x%08x to 0x%08x.\n", _val, _addr);
|
||||
|
||||
switch(_addr)
|
||||
{
|
||||
@@ -379,20 +534,22 @@ static void synopsys_usb_write(void *opaque, hwaddr _addr, uint64_t _val, unsign
|
||||
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);
|
||||
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);
|
||||
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");
|
||||
// }
|
||||
int ret = tcp_usb_connect(&state->tcp_state, state->server_host, state->server_port);
|
||||
if(ret < 0) {
|
||||
printf("Failed to connect to USB server (%d).\n", ret);
|
||||
}
|
||||
else {
|
||||
printf("Connected to USB server.\n");
|
||||
}
|
||||
}
|
||||
|
||||
state->grstctl &= ~GRSTCTL_CORESOFTRESET;
|
||||
state->grstctl |= GRSTCTL_AHBIDLE;
|
||||
@@ -517,6 +674,7 @@ static void s5l8900_usb_otg_reset(DeviceState *d)
|
||||
state->ghwcfg4);
|
||||
|
||||
state->pcgcctl = 3;
|
||||
state->grstctl = GRSTCTL_AHBIDLE;
|
||||
|
||||
state->gahbcfg = 0;
|
||||
state->gusbcfg = 0;
|
||||
@@ -540,6 +698,9 @@ static void s5l8900_usb_otg_reset(DeviceState *d)
|
||||
state->grxfsiz = 0x100;
|
||||
state->gnptxfsiz = (0x100 << 16) | 0x100;
|
||||
|
||||
state->server_host = "localhost";
|
||||
state->server_port = 1235;
|
||||
|
||||
uint32_t counter = 0x200;
|
||||
int i;
|
||||
for(i = 0; i < USB_NUM_FIFOS; i++)
|
||||
@@ -613,4 +774,4 @@ static void s5l8900_usb_otg_register_types(void)
|
||||
type_register_static(&s5l8900_usb_otg_info);
|
||||
}
|
||||
|
||||
type_init(s5l8900_usb_otg_register_types)
|
||||
type_init(s5l8900_usb_otg_register_types)
|
||||
@@ -16,9 +16,12 @@ 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);
|
||||
//return 0x0;
|
||||
printf("%s: read invalid location 0x%08x\n", __func__, addr);
|
||||
return 0x0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,7 +48,7 @@ static void ipod_touch_usb_phys_write(void *opaque, hwaddr addr, uint64_t val, u
|
||||
return;
|
||||
|
||||
default:
|
||||
//hw_error("%s: write invalid location 0x%08x.\n", __func__, addr);
|
||||
printf("%s: write invalid location 0x%08x.\n", __func__, addr);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -83,4 +86,4 @@ static void ipod_touch_usb_phys_register_types(void)
|
||||
type_register_static(&ipod_touch_usb_phys_type_info);
|
||||
}
|
||||
|
||||
type_init(ipod_touch_usb_phys_register_types)
|
||||
type_init(ipod_touch_usb_phys_register_types)
|
||||
+1
-1
@@ -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_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', 'ipod_touch_isl29003dl.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'))
|
||||
|
||||
@@ -11,6 +11,8 @@ system_ss.add(when: 'CONFIG_USB', if_true: files(
|
||||
'pcap.c',
|
||||
))
|
||||
|
||||
system_ss.add(when: 'CONFIG_USB', if_true: files('tcp_usb.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'))
|
||||
|
||||
@@ -0,0 +1,524 @@
|
||||
/*
|
||||
* USB over TCP driver.
|
||||
*
|
||||
* 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 "hw/usb/tcp_usb.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netdb.h>
|
||||
|
||||
#define DEBUG_TCP_USB
|
||||
|
||||
void tcp_usb_init(tcp_usb_state_t *_state, tcp_usb_callback_t _cb, tcp_usb_closed_t _closed, void *_arg)
|
||||
{
|
||||
_state->data_callback = _cb;
|
||||
_state->closed_callback = _closed;
|
||||
_state->callback_arg = _arg;
|
||||
|
||||
_state->socket = -1;
|
||||
_state->closed = 1;
|
||||
|
||||
_state->state = tcp_usb_idle;
|
||||
_state->amount_done = 0;
|
||||
}
|
||||
|
||||
void tcp_usb_cleanup(tcp_usb_state_t *_state)
|
||||
{
|
||||
if(_state->socket >= 0)
|
||||
{
|
||||
close(_state->socket);
|
||||
qemu_set_fd_handler(_state->socket, NULL, NULL, NULL);
|
||||
_state->socket = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int tcp_usb_closed(tcp_usb_state_t *_state)
|
||||
{
|
||||
return _state->closed != 0;
|
||||
}
|
||||
|
||||
static void tcp_usb_do_closed(tcp_usb_state_t *_state)
|
||||
{
|
||||
if(_state->closed)
|
||||
return;
|
||||
|
||||
_state->closed = 1;
|
||||
|
||||
qemu_set_fd_handler(_state->socket, NULL, NULL, NULL);
|
||||
|
||||
if(_state->closed_callback)
|
||||
_state->closed_callback(_state, _state->callback_arg);
|
||||
}
|
||||
|
||||
#ifdef DEBUG_TCP_USB
|
||||
static void hexdump(const void *_data, size_t _amt)
|
||||
{
|
||||
char *ptr = (char*)_data;
|
||||
int i;
|
||||
for(i = 0; i < _amt; i++)
|
||||
{
|
||||
if((i%8) == 0)
|
||||
fprintf(stderr, "\t");
|
||||
|
||||
fprintf(stderr, "%02x ", (ptr[i] & 0xFF));
|
||||
|
||||
if((i%8) == 7)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
if((i%8) != 0)
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
# define debug_hexdump(title, data, amt); fprintf(stderr, title); hexdump((data), (amt));
|
||||
# define debug_printf(args...) printf(args);
|
||||
#else
|
||||
# define debug_hexdump(a, b, c)
|
||||
# define debug_printf(a...)
|
||||
#endif // DEBUG_TCP_USB
|
||||
|
||||
static void tcp_usb_callback(tcp_usb_state_t *state, int _can_read, int _can_write)
|
||||
{
|
||||
if(state->closed)
|
||||
return;
|
||||
|
||||
int ret;
|
||||
switch(state->state)
|
||||
{
|
||||
case tcp_usb_idle:
|
||||
if(!_can_read)
|
||||
return;
|
||||
|
||||
debug_printf("%s: tcp_usb_idle.\n", __func__);
|
||||
|
||||
// Receiving new request
|
||||
state->header = malloc(sizeof(*state->header));
|
||||
state->amount_done = 0;
|
||||
state->state = tcp_usb_read_request;
|
||||
|
||||
// Fall through
|
||||
case tcp_usb_read_request:
|
||||
debug_printf("%s: tcp_usb_read_request\n", __func__);
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
{
|
||||
ret = read(state->socket,
|
||||
((char*)state->header) + state->amount_done,
|
||||
sizeof(*state->header) - state->amount_done);
|
||||
if(ret == 0 && _can_read)
|
||||
{
|
||||
free(state->header);
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Error %d reading request header!\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_read = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Got Header: ", state->header, sizeof(*state->header));
|
||||
debug_printf("Length: %d\n", state->header->length);
|
||||
|
||||
if(state->header->length > 0)
|
||||
state->buffer = malloc(state->header->length);
|
||||
else
|
||||
state->buffer = NULL;
|
||||
}
|
||||
|
||||
if((state->header->ep & USB_DIR_IN) == 0 && state->header->length > 0) // OUT
|
||||
{
|
||||
ret = read(state->socket,
|
||||
((char*)state->buffer) + (state->amount_done - sizeof(*state->header)),
|
||||
state->header->length - (state->amount_done - sizeof(*state->header)));
|
||||
printf("RET: %d\n", ret);
|
||||
if(ret == 0 && _can_read)
|
||||
{
|
||||
free(state->header);
|
||||
if(state->buffer)
|
||||
free(state->buffer);
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
printf("tcp_usb: Error %d reading request data!\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_read = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header) + state->header->length)
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Read: ", state->buffer, state->header->length);
|
||||
}
|
||||
|
||||
// Transfer complete! Call callback!
|
||||
if(state->data_callback)
|
||||
{
|
||||
state->state = tcp_usb_write_response;
|
||||
state->amount_done = 0;
|
||||
|
||||
debug_printf("tcp_usb: Calling callback.\n");
|
||||
ret = state->data_callback(state, state->callback_arg, state->header, state->buffer);
|
||||
state->header->length = ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Packet received but no callback!\n");
|
||||
state->state = tcp_usb_idle;
|
||||
return;
|
||||
}
|
||||
|
||||
// Fall through
|
||||
case tcp_usb_write_response:
|
||||
debug_printf("%s: tcp_usb_write_response\n", __func__);
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
{
|
||||
ret = write(state->socket,
|
||||
((char*)state->header) + state->amount_done,
|
||||
sizeof(*state->header) - state->amount_done);
|
||||
if(ret == 0 && _can_write)
|
||||
{
|
||||
free(state->header);
|
||||
if(state->buffer)
|
||||
free(state->buffer);
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Error %d writing response header.\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_write = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Sent Header (write response): ", state->header, sizeof(*state->header));
|
||||
}
|
||||
|
||||
if((state->header->ep & USB_DIR_IN) != 0 && state->header->length > 0) // IN
|
||||
{
|
||||
ret = write(state->socket,
|
||||
((char*)state->buffer) + (state->amount_done - sizeof(*state->header)),
|
||||
state->header->length - (state->amount_done - sizeof(*state->header)));
|
||||
if(ret == 0 && _can_write)
|
||||
{
|
||||
free(state->header);
|
||||
if(state->buffer)
|
||||
free(state->buffer);
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Error %d writing response data.\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_write = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header) + state->header->length)
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Wrote: ", state->buffer, state->header->length);
|
||||
}
|
||||
|
||||
free(state->header);
|
||||
if(state->buffer)
|
||||
free(state->buffer);
|
||||
state->state = tcp_usb_idle;
|
||||
break;
|
||||
|
||||
case tcp_usb_write_request:
|
||||
debug_printf("%s: tcp_usb_write_request\n", __func__);
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
{
|
||||
ret = write(state->socket,
|
||||
((char*)state->header) + state->amount_done,
|
||||
sizeof(*state->header) - state->amount_done);
|
||||
if(ret == 0 && _can_write)
|
||||
{
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Error %d writing request header!\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_write = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Sent Header (write request): ", state->header, sizeof(*state->header));
|
||||
}
|
||||
|
||||
if((state->header->ep & USB_DIR_IN) == 0 && state->header->length > 0) // OUT
|
||||
{
|
||||
ret = write(state->socket,
|
||||
((char*)state->buffer) + (state->amount_done - sizeof(*state->header)),
|
||||
state->header->length - (state->amount_done - sizeof(*state->header)));
|
||||
if(ret == 0 && _can_write)
|
||||
{
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Error %d writing request data!\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_write = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header) + state->header->length)
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Wrote: ", state->buffer, state->header->length);
|
||||
}
|
||||
|
||||
state->state = tcp_usb_read_response;
|
||||
state->amount_done = 0;
|
||||
|
||||
// Fall through
|
||||
case tcp_usb_read_response:
|
||||
debug_printf("%s: tcp_usb_read_response\n", __func__);
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
{
|
||||
ret = read(state->socket,
|
||||
((char*)state->header) + state->amount_done,
|
||||
sizeof(*state->header) - state->amount_done);
|
||||
if(ret == 0 && _can_read)
|
||||
{
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Error %d reading response header.\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_read = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header))
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Got Header: ", state->header, sizeof(*state->header));
|
||||
}
|
||||
|
||||
if((state->header->ep & USB_DIR_IN) != 0 && state->header->length > 0) // IN
|
||||
{
|
||||
ret = read(state->socket,
|
||||
((char*)state->buffer) + (state->amount_done - sizeof(*state->header)),
|
||||
state->header->length - (state->amount_done - sizeof(*state->header)));
|
||||
if(ret == 0 && _can_read)
|
||||
{
|
||||
tcp_usb_do_closed(state);
|
||||
return;
|
||||
}
|
||||
else if(ret == EWOULDBLOCK || ret == 0 || ret == -1)
|
||||
return;
|
||||
else if(ret < 0)
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Error %d reading response data.\n", ret);
|
||||
return;
|
||||
}
|
||||
|
||||
_can_read = 0;
|
||||
state->amount_done += ret;
|
||||
|
||||
if(state->amount_done < sizeof(*state->header) + state->header->length)
|
||||
return;
|
||||
|
||||
debug_hexdump("tcp_usb: Read: ", state->buffer, state->header->length);
|
||||
}
|
||||
|
||||
state->state = tcp_usb_idle;
|
||||
|
||||
// Transfer complete! Call callback!
|
||||
if(state->data_callback)
|
||||
{
|
||||
debug_printf("tcp_usb: calling callback!\n");
|
||||
state->data_callback(state, state->callback_arg, state->header, state->buffer);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "tcp_usb: Request sent but no callback!\n");
|
||||
state->state = tcp_usb_idle;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void tcp_usb_read_callback(void *_arg)
|
||||
{
|
||||
tcp_usb_state_t *state = _arg;
|
||||
tcp_usb_callback(state, 1, 0);
|
||||
}
|
||||
|
||||
static void tcp_usb_write_callback(void *_arg)
|
||||
{
|
||||
tcp_usb_state_t *state = _arg;
|
||||
tcp_usb_callback(state, 0, 1);
|
||||
}
|
||||
|
||||
int tcp_usb_connect(tcp_usb_state_t *_state, char *_host, uint32_t _port)
|
||||
{
|
||||
_state->socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
struct hostent *hostname = gethostbyname(_host);
|
||||
|
||||
struct sockaddr_in server_addr;
|
||||
memset(&server_addr, 0, sizeof(server_addr));
|
||||
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(_port);
|
||||
memcpy(&server_addr.sin_addr.s_addr,
|
||||
hostname->h_addr, hostname->h_length);
|
||||
|
||||
int ret = connect(_state->socket, &server_addr, sizeof(server_addr));
|
||||
if(ret < 0)
|
||||
return -EIO;
|
||||
|
||||
_state->closed = 0;
|
||||
int flags = fcntl(_state->socket, F_GETFL, 0);
|
||||
fcntl(_state->socket, F_SETFL, flags | O_NONBLOCK);
|
||||
qemu_set_fd_handler(_state->socket, tcp_usb_read_callback, tcp_usb_write_callback, _state);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tcp_usb_request(tcp_usb_state_t *_state, tcp_usb_header_t *_header, const char *_data)
|
||||
{
|
||||
debug_printf("%s.\n", __func__);
|
||||
|
||||
if(_state->state != tcp_usb_idle)
|
||||
return -EBUSY;
|
||||
|
||||
debug_printf("%s starting request.\n", __func__);
|
||||
|
||||
_state->state = tcp_usb_write_request;
|
||||
_state->amount_done = 0;
|
||||
_state->buffer = (char*)_data;
|
||||
_state->header = _header;
|
||||
|
||||
tcp_usb_callback(_state, 0, 1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tcp_usb_host_init(tcp_usb_host_state_t *_state)
|
||||
{
|
||||
_state->socket = -1;
|
||||
}
|
||||
|
||||
void tcp_usb_host_cleanup(tcp_usb_host_state_t *_state)
|
||||
{
|
||||
if(_state->socket >= 0)
|
||||
{
|
||||
close(_state->socket);
|
||||
_state->socket = -1;
|
||||
}
|
||||
}
|
||||
|
||||
int tcp_usb_host_okay(tcp_usb_host_state_t *_state)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tcp_usb_host(tcp_usb_host_state_t *_state, uint32_t _port)
|
||||
{
|
||||
_state->socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if(_state->socket < 0)
|
||||
return -EIO;
|
||||
|
||||
struct linger linger;
|
||||
linger.l_onoff = 0;
|
||||
linger.l_linger = 0;
|
||||
setsockopt(_state->socket, SOL_SOCKET, SO_LINGER, (char *)&linger, sizeof(linger));
|
||||
|
||||
struct sockaddr_in server_addr;
|
||||
server_addr.sin_family = AF_INET;
|
||||
server_addr.sin_port = htons(_port);
|
||||
server_addr.sin_addr.s_addr = INADDR_ANY;
|
||||
|
||||
if(bind(_state->socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
|
||||
return -EIO;
|
||||
|
||||
listen(_state->socket, 5);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tcp_usb_accept(tcp_usb_host_state_t *_host, tcp_usb_state_t *_client)
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
size_t addr_sz = sizeof(addr);
|
||||
|
||||
debug_printf("%s: waiting on accept...\n", __func__);
|
||||
|
||||
_client->socket = accept(_host->socket, &addr, &addr_sz);
|
||||
if(_client->socket < 0)
|
||||
{
|
||||
fprintf(stderr, "%s: accept error %d.\n", __func__, errno);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
_client->closed = 0;
|
||||
int flags = fcntl(_client->socket, F_GETFL, 0);
|
||||
fcntl(_client->socket, F_SETFL, flags | O_NONBLOCK);
|
||||
qemu_set_fd_handler(_client->socket, tcp_usb_read_callback, tcp_usb_write_callback, _client);
|
||||
debug_printf("%s: USB device accepted!\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
@@ -176,4 +176,4 @@ typedef struct {
|
||||
IT2G_CPREG_VAR_DEF(REG1);
|
||||
} IPodTouchMachineState;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,19 @@
|
||||
#ifndef HW_CS42L58_H
|
||||
#define HW_CS42L58_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/i2c/i2c.h"
|
||||
#include "hw/irq.h"
|
||||
|
||||
#define TYPE_CS42L58 "cs42l58"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(CS42L58State, CS42L58)
|
||||
|
||||
typedef struct CS42L58State {
|
||||
I2CSlave i2c;
|
||||
uint32_t cmd;
|
||||
} CS42L58State;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,39 @@
|
||||
#ifndef HW_ISL29003DL_H
|
||||
#define HW_ISL29003DL_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "hw/sysbus.h"
|
||||
#include "hw/i2c/i2c.h"
|
||||
#include "hw/irq.h"
|
||||
#include "time.h"
|
||||
|
||||
#define TYPE_ISL29003DL "isl29003dl"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(ISL29003DLState, ISL29003DL)
|
||||
|
||||
#define LIGHTSENSOR_COMMAND 0x00
|
||||
#define LIGHTSENSOR_CONTROL 0x01
|
||||
#define LIGHTSENSOR_IT_HI 0x02
|
||||
#define LIGHTSENSOR_IT_LO 0x03
|
||||
#define LIGHTSENSOR_LSB_SENSOR 0x04
|
||||
#define LIGHTSENSOR_MSB_SENSOR 0x05
|
||||
#define LIGHTSENSOR_LSB_TIMER 0x06
|
||||
#define LIGHTSENSOR_MSB_TIMER 0x07
|
||||
|
||||
typedef struct ISL29003DLState {
|
||||
I2CSlave i2c;
|
||||
uint32_t cmd;
|
||||
uint32_t command;
|
||||
uint32_t ctrl;
|
||||
uint32_t curreg;
|
||||
uint32_t ready;
|
||||
uint32_t it_hi;
|
||||
uint32_t it_lo;
|
||||
uint32_t lsb_sensor;
|
||||
uint32_t msb_sensor;
|
||||
uint32_t lsb_timer;
|
||||
uint32_t msb_timer;
|
||||
} ISL29003DLState;
|
||||
|
||||
#endif
|
||||
@@ -22,6 +22,7 @@ typedef struct IPodTouchLCDState
|
||||
QemuConsole *con;
|
||||
IPodTouchMultitouchState *mt;
|
||||
int invalidate;
|
||||
uint8_t brightness;
|
||||
MemoryRegionSection fbsection;
|
||||
qemu_irq irq;
|
||||
uint32_t lcd_con;
|
||||
@@ -31,9 +32,11 @@ typedef struct IPodTouchLCDState
|
||||
uint32_t w1_hspan;
|
||||
uint32_t w1_display_depth_info;
|
||||
|
||||
uint32_t unknown1;
|
||||
uint32_t render;
|
||||
|
||||
QEMUTimer *refresh_timer;
|
||||
} IPodTouchLCDState;
|
||||
|
||||
#endif
|
||||
void lcd_changebrightness(int brightness);
|
||||
|
||||
#endif
|
||||
@@ -12,12 +12,24 @@
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(LIS302DLState, LIS302DL)
|
||||
|
||||
#define ACCEL_WHOAMI 0x0F
|
||||
#define ACCEL_OUT_X 0x29
|
||||
#define ACCEL_OUT_Y 0x2B
|
||||
#define ACCEL_OUT_Z 0x2D
|
||||
#define ACCEL_CTRL_REG1 0x20
|
||||
#define ACCEL_CTRL_REG2 0x21
|
||||
#define ACCEL_CTRL_REG3 0x22
|
||||
|
||||
#define ACCEL_WHOAMI_VALUE 0x3B
|
||||
|
||||
typedef struct LIS302DLState {
|
||||
I2CSlave i2c;
|
||||
uint32_t cmd;
|
||||
uint32_t out_x;
|
||||
uint32_t out_y;
|
||||
uint32_t out_z;
|
||||
uint16_t ctrl_reg1;
|
||||
uint16_t ctrl_reg2;
|
||||
uint16_t ctrl_reg3;
|
||||
} LIS302DLState;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -12,6 +12,8 @@ typedef struct IPodTouchMBXState {
|
||||
SysBusDevice busdev;
|
||||
MemoryRegion iomem1;
|
||||
MemoryRegion iomem2;
|
||||
uint64_t addr;
|
||||
bool alreadypatched;
|
||||
} IPodTouchMBXState;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -12,6 +12,7 @@
|
||||
#define TYPE_PCF50633 "pcf50633"
|
||||
OBJECT_DECLARE_SIMPLE_TYPE(Pcf50633State, PCF50633)
|
||||
|
||||
#define PMU_DSBL1 0x30
|
||||
#define PMU_MBCS1 0x4B
|
||||
#define PMU_ADCC1 0x57
|
||||
|
||||
@@ -27,6 +28,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(Pcf50633State, PCF50633)
|
||||
typedef struct Pcf50633State {
|
||||
I2CSlave i2c;
|
||||
uint32_t cmd;
|
||||
uint32_t ready;
|
||||
uint32_t curreg;
|
||||
} Pcf50633State;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "hw/irq.h"
|
||||
#include "hw/usb.h"
|
||||
#include "hw/usb/tcp_usb.h"
|
||||
|
||||
#define DEVICE_NAME "usb_synopsys"
|
||||
|
||||
@@ -223,7 +224,7 @@ typedef struct synopsys_usb_state
|
||||
|
||||
char *server_host;
|
||||
uint32_t server_port;
|
||||
//tcp_usb_state_t tcp_state;
|
||||
tcp_usb_state_t tcp_state;
|
||||
|
||||
uint32_t pcgcctl;
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifndef HW_TCP_USB
|
||||
#define HW_TCP_USB
|
||||
|
||||
/*
|
||||
* USB over TCP driver.
|
||||
*
|
||||
* 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 "qemu/module.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "hw/usb.h"
|
||||
#include "hw/sysbus.h"
|
||||
|
||||
enum
|
||||
{
|
||||
tcp_usb_setup = 1 << 0,
|
||||
tcp_usb_reset = 1 << 1,
|
||||
tcp_usb_enumdone = 1 << 2,
|
||||
};
|
||||
|
||||
typedef enum _tcp_usb_state_enum
|
||||
{
|
||||
tcp_usb_idle,
|
||||
|
||||
// Client
|
||||
tcp_usb_read_request,
|
||||
tcp_usb_write_response,
|
||||
|
||||
// Host
|
||||
tcp_usb_write_request,
|
||||
tcp_usb_read_response,
|
||||
|
||||
} tcp_usb_state_enum_t;
|
||||
|
||||
typedef struct _tcp_usb_header
|
||||
{
|
||||
uint8_t addr;
|
||||
uint8_t ep;
|
||||
uint8_t flags;
|
||||
int16_t length;
|
||||
|
||||
} __attribute__((packed)) tcp_usb_header_t;
|
||||
|
||||
struct _tcp_usb_state;
|
||||
typedef int (*tcp_usb_callback_t)(struct _tcp_usb_state *_status, void *_arg, tcp_usb_header_t *_hdr, char *_buffer);
|
||||
typedef void (*tcp_usb_closed_t)(struct _tcp_usb_state *_state, void *_arg);
|
||||
|
||||
typedef struct _tcp_usb_state
|
||||
{
|
||||
int socket;
|
||||
int closed;
|
||||
|
||||
tcp_usb_state_enum_t state;
|
||||
tcp_usb_header_t *header;
|
||||
char *buffer;
|
||||
size_t amount_done;
|
||||
|
||||
tcp_usb_closed_t closed_callback;
|
||||
tcp_usb_callback_t data_callback;
|
||||
void *callback_arg;
|
||||
} tcp_usb_state_t;
|
||||
|
||||
void tcp_usb_init(tcp_usb_state_t *_state, tcp_usb_callback_t _cb, tcp_usb_closed_t _closed, void *_arg);
|
||||
void tcp_usb_cleanup(tcp_usb_state_t *_state);
|
||||
|
||||
int tcp_usb_closed(tcp_usb_state_t *_state);
|
||||
|
||||
int tcp_usb_connect(tcp_usb_state_t *_state, char *_host, uint32_t _port);
|
||||
|
||||
int tcp_usb_request(tcp_usb_state_t *_state, tcp_usb_header_t *_header, const char *_data);
|
||||
|
||||
typedef struct _tcp_usb_host_state
|
||||
{
|
||||
int socket;
|
||||
|
||||
} tcp_usb_host_state_t;
|
||||
|
||||
void tcp_usb_host_init(tcp_usb_host_state_t *_state);
|
||||
void tcp_usb_host_cleanup(tcp_usb_host_state_t *_state);
|
||||
|
||||
int tcp_usb_host_okay(tcp_usb_host_state_t *_state);
|
||||
|
||||
int tcp_usb_host(tcp_usb_host_state_t *_state, uint32_t _port);
|
||||
int tcp_usb_accept(tcp_usb_host_state_t *_host, tcp_usb_state_t *_client);
|
||||
|
||||
#endif //HW_TCP_USB
|
||||
Reference in new issue
Block a user