Several fixes and changes

This commit is contained in:
Martijn de Vos committed 2023-07-08 16:43:02 +02:00
1 parent 9a2d42ca33
commit 6c4f881436
18 files changed
+861 -56

No files matched your search

+26 -11
View File
@@ -88,7 +88,6 @@ static void ipod_touch_memory_setup(MachineState *machine, MemoryRegion *sysmem,
allocate_ram(sysmem, "iboot", IBOOT_MEM_BASE, 0x100000);
allocate_ram(sysmem, "llb", 0x22000000, 0x100000);
allocate_ram(sysmem, "sram1", SRAM1_MEM_BASE, 0x100000);
allocate_ram(sysmem, "mbx2", MBX2_MEM_BASE, 0x1000);
allocate_ram(sysmem, "tvout1", TVOUT1_MEM_BASE, 0x1000);
allocate_ram(sysmem, "tvout2", TVOUT2_MEM_BASE, 0x1000);
allocate_ram(sysmem, "tvout3", TVOUT3_MEM_BASE, 0x1000);
@@ -260,7 +259,9 @@ static void ipod_touch_machine_init(MachineState *machine)
sysbus_create_simple("ipodtouch.spi", SPI3_MEM_BASE, s5l8900_get_irq(nms, S5L8720_SPI3_IRQ));
set_spi_base(4);
sysbus_create_simple("ipodtouch.spi", SPI4_MEM_BASE, s5l8900_get_irq(nms, S5L8720_SPI4_IRQ));
dev = sysbus_create_simple("ipodtouch.spi", SPI4_MEM_BASE, s5l8900_get_irq(nms, S5L8720_SPI4_IRQ));
IPodTouchSPIState *spi4_state = IPOD_TOUCH_SPI(dev);
nms->spi4_state = spi4_state;
// init the chip ID module
dev = qdev_new("ipodtouch.chipid");
@@ -283,7 +284,7 @@ static void ipod_touch_machine_init(MachineState *machine)
dev = qdev_new("pl080");
PL080State *pl080_1 = PL080(dev);
object_property_set_link(OBJECT(dev), "downstream", OBJECT(sysmem), &error_fatal);
memory_region_add_subregion(sysmem, DMAC0_MEM_BASE, &pl080_1->iomem);
memory_region_add_subregion(sysmem, DMAC0_MEM_BASE, &pl080_1->iomem1);
busdev = SYS_BUS_DEVICE(dev);
sysbus_realize(busdev, &error_fatal);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_DMAC0_IRQ));
@@ -291,10 +292,11 @@ static void ipod_touch_machine_init(MachineState *machine)
dev = qdev_new("pl080");
PL080State *pl080_2 = PL080(dev);
object_property_set_link(OBJECT(dev), "downstream", OBJECT(sysmem), &error_fatal);
memory_region_add_subregion(sysmem, DMAC1_MEM_BASE, &pl080_2->iomem);
memory_region_add_subregion(sysmem, DMAC1_0_MEM_BASE, &pl080_2->iomem1);
memory_region_add_subregion(sysmem, DMAC1_1_MEM_BASE, &pl080_2->iomem2);
busdev = SYS_BUS_DEVICE(dev);
sysbus_realize(busdev, &error_fatal);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_DMAC0_IRQ));
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_DMAC1_IRQ));
// Init I2C0
dev = qdev_new("ipodtouch.i2c");
@@ -302,11 +304,12 @@ static void ipod_touch_machine_init(MachineState *machine)
i2c_state->base = 0;
nms->i2c0_state = i2c_state;
busdev = SYS_BUS_DEVICE(dev);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_I2C0_IRQ));
memory_region_add_subregion(sysmem, I2C0_MEM_BASE, &i2c_state->iomem);
sysbus_realize(busdev, &error_fatal);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_I2C0_IRQ));
// init the PMU
i2c_slave_create_simple(i2c_state->bus, "pcf50633", 0x73);
I2CSlave * pmu = i2c_slave_create_simple(i2c_state->bus, "pcf50633", 0x73);
// init the accelerometer
I2CSlave *accelerometer = i2c_slave_create_simple(i2c_state->bus, "lis302dl", 0x1D);
@@ -317,19 +320,21 @@ static void ipod_touch_machine_init(MachineState *machine)
nms->i2c1_state = i2c_state;
i2c_state->base = 1;
busdev = SYS_BUS_DEVICE(dev);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_I2C1_IRQ));
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 Mikey
i2c_slave_create_simple(i2c_state->bus, "cd3272mikey", 0x39);
I2CSlave *cd327mikey = i2c_slave_create_simple(i2c_state->bus, "cd3272mikey", 0x39);
// init the FMSS flash controller
dev = qdev_new("ipodtouch.fmss");
IPodTouchFMSSState *fmss_state = IPOD_TOUCH_FMSS(dev);
nms->fmss_state = fmss_state;
busdev = SYS_BUS_DEVICE(dev);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_FMSS_IRQ));
memory_region_add_subregion(sysmem, FMSS_MEM_BASE, &fmss_state->iomem);
sysbus_realize(busdev, &error_fatal);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_FMSS_IRQ));
// init the chip ID module
dev = qdev_new("ipodtouch.usbphys");
@@ -348,10 +353,20 @@ static void ipod_touch_machine_init(MachineState *machine)
// init LCD
dev = qdev_new("ipodtouch.lcd");
IPodTouchLCDState *lcd_state = IPOD_TOUCH_LCD(dev);
lcd_state->sysmem = sysmem;
nms->lcd_state = lcd_state;
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_LCD_IRQ));
busdev = SYS_BUS_DEVICE(dev);
memory_region_add_subregion(sysmem, DISPLAY_MEM_BASE, &lcd_state->iomem);
sysbus_realize(busdev, &error_fatal);
sysbus_connect_irq(busdev, 0, s5l8900_get_irq(nms, S5L8720_LCD_IRQ));
// init scaler / CSC
dev = qdev_new("ipodtouch.scalercsc");
IPodTouchScalerCSCState *scaler_csc_state = IPOD_TOUCH_SCALER_CSC(dev);
nms->scaler_csc_state = scaler_csc_state;
busdev = SYS_BUS_DEVICE(dev);
memory_region_add_subregion(sysmem, SCALER_CSC_MEM_BASE, &scaler_csc_state->iomem);
sysbus_realize(busdev, &error_fatal);
// init SHA1 engine
dev = qdev_new("ipodtouch.sha1");
+19 -3
View File
@@ -23,9 +23,13 @@ static void ipod_touch_aes_write(void *opaque, hwaddr offset, uint64_t value, un
uint8_t *buf;
// fprintf(stderr, "%s: offset 0x%08x value 0x%08x\n", __FUNCTION__, offset, value);
uint32_t *data = malloc(sizeof(uint16_t) * 9);
switch(offset) {
case AES_GO:
// PATCH OUT
// in iBoot, we also patch the length check after LZSS compression since that can lead to issues
inbuf = (uint8_t *)malloc(aesop->insize);
cpu_physical_memory_read((aesop->inaddr), inbuf, aesop->insize);
@@ -62,14 +66,26 @@ static void ipod_touch_aes_write(void *opaque, hwaddr offset, uint64_t value, un
};
for(int i = 0; i < aesop->insize; i++) { buf[i] = key[i]; }
}
else if(aesop->gid_encryption_count == 2) { // kernelcache
else if(aesop->gid_encryption_count == 2) { // apple logo
// very ugly - we patch out here the LZSS check
data[0] = 0x0; // NOP
cpu_physical_memory_write(0x0ff119f0, (uint8_t *)data, 4);
char key[] = {
0x64, 0x23, 0x8f, 0xb0, 0x32, 0x91, 0x42, 0x25, 0x22, 0xb5, 0xdd, 0x28, 0x3f, 0xc3, 0x89, 0x5c, // IV
0x85, 0x9f, 0xd4, 0xd3, 0x82, 0xb8, 0x38, 0x51, 0x56, 0xfc, 0x58, 0x1a, 0x7f, 0x1d, 0x97, 0x22, // key
};
for(int i = 0; i < aesop->insize; i++) { buf[i] = key[i]; }
}
else if(aesop->gid_encryption_count == 3) { // kernelcache
char key[] = {
0xa1, 0x91, 0x29, 0x12, 0x90, 0xd4, 0x87, 0xff, 0x07, 0x31, 0x96, 0x9c, 0x5f, 0xc8, 0xd9, 0x18, // IV
0x0e, 0x4d, 0x23, 0xfa, 0x67, 0x59, 0x99, 0xd5, 0x95, 0x9d, 0xd1, 0x0c, 0x8d, 0xd7, 0x3d, 0x20, // key
};
for(int i = 0; i < aesop->insize; i++) { buf[i] = key[i]; }
}
else if(aesop->gid_encryption_count == 3) { // device tree
else if(aesop->gid_encryption_count == 4) { // device tree
char key[] = {
0xcc, 0xff, 0x63, 0x4e, 0xe1, 0x27, 0x35, 0xf0, 0x19, 0x16, 0xc4, 0xa6, 0xb2, 0x0f, 0xf1, 0x45, // IV
0xe1, 0x7b, 0xcd, 0x56, 0x8d, 0xf1, 0xcd, 0xdc, 0x8f, 0xec, 0xbf, 0x54, 0x87, 0xd5, 0xc3, 0xce, // key
@@ -83,7 +99,7 @@ static void ipod_touch_aes_write(void *opaque, hwaddr offset, uint64_t value, un
AES_cbc_encrypt(inbuf, buf, aesop->insize, &aesop->decryptKey, (uint8_t *)aesop->ivec, AES_DECRYPT);
}
if(aesop->outaddr != 0x220100ac && aesop->outaddr != 0x0bf08468) { // TODO very ugly hack - for the RSA key decryption, it seems that doing nothing results in the correct decryption key??
if(aesop->outaddr != 0x220100ac && aesop->outaddr != 0x0bf08468 && aesop->outaddr != 0x0fb9bcdc) { // TODO very ugly hack - for the RSA key decryption, it seems that doing nothing results in the correct decryption key??
// BUG: after decrypting the kernel, we update the Adler CRC code and number of expected bytes.
if(aesop->outaddr == 0x0b000020) {
uint32_t *cast_buf = (uint32_t *)buf;
+1 -2
View File
@@ -83,14 +83,13 @@ static void read_nand_pages(IPodTouchFMSSState *s)
cpu_physical_memory_read(s->reg_pages_in_addr + page_ind, &page_nr, 0x4);
cpu_physical_memory_read(s->reg_pages_out_addr + page_ind, &page_out_addr, 0x4);
printf("Will read page %d into address 0x%08x and spare into address 0x%08x\n", page_nr, page_out_addr, s->reg_page_spare_out_addr);
//printf("Will read page %d into address 0x%08x and spare into address 0x%08x\n", page_nr, page_out_addr, s->reg_page_spare_out_addr);
// prepare the page
char filename[200];
sprintf(filename, "/Users/martijndevos/Documents/generate_nand_it2g/nand/%d.page", page_nr);
struct stat st = {0};
if (stat(filename, &st) == -1) {
printf("Will preparing empty page %d", page_nr);
// page storage does not exist - initialize an empty buffer
memset(s->page_buffer, 0, NAND_BYTES_PER_PAGE);
memset(s->page_spare_buffer, 0, NAND_BYTES_PER_SPARE);
+126 -2
View File
@@ -1,4 +1,7 @@
#include "hw/arm/ipod_touch_lcd.h"
#include "ui/pixel_ops.h"
#include "ui/console.h"
#include "hw/display/framebuffer.h"
static uint64_t ipod_touch_lcd_read(void *opaque, hwaddr addr, unsigned size)
{
@@ -9,6 +12,16 @@ static uint64_t ipod_touch_lcd_read(void *opaque, hwaddr addr, unsigned size)
{
case 0x0:
return 2;
case 0x4:
return s->lcd_con;
case 0x20:
return s->w1_display_depth_info;
case 0x24:
return s->w1_framebuffer_base;
case 0x28:
return s->w1_hspan;
case 0x30:
return s->w1_display_resolution_info;
case 0x1b10:
return 2;
default:
@@ -21,7 +34,95 @@ 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;
// fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
fprintf(stderr, "%s: writing 0x%08x to 0x%08x\n", __func__, val, addr);
switch(addr) {
case 0x4:
s->lcd_con = val;
break;
case 0x20:
s->w1_display_depth_info = val;
break;
case 0x24:
s->w1_framebuffer_base = val;
break;
case 0x28:
s->w1_hspan = val;
break;
case 0x30:
s->w1_display_resolution_info = val;
break;
case 0xC:
qemu_irq_lower(s->irq);
break;
}
}
static void lcd_invalidate(void *opaque)
{
IPodTouchLCDState *s = opaque;
s->invalidate = 1;
}
static void draw_line32_32(void *opaque, uint8_t *d, const uint8_t *s, int width, int deststep)
{
uint8_t r, g, b;
do {
//v = lduw_le_p((void *) s);
//printf("V: %d\n", *s);
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);
s += 4;
d += 4;
} while (-- width != 0);
}
static void lcd_refresh(void *opaque)
{
//fprintf(stderr, "%s: refreshing LCD screen\n", __func__);
IPodTouchLCDState *lcd = (IPodTouchLCDState *) opaque;
DisplaySurface *surface = qemu_console_surface(lcd->con);
drawfn draw_line;
int src_width, dest_width;
int height, first, last;
int width, linesize;
if (!lcd || !lcd->con || !surface_bits_per_pixel(surface))
return;
dest_width = 4;
draw_line = draw_line32_32;
/* Resolution */
first = last = 0;
width = 320;
height = 480;
lcd->invalidate = 1;
src_width = 4 * width;
linesize = surface_stride(surface);
if(lcd->invalidate) {
framebuffer_update_memory_section(&lcd->fbsection, lcd->sysmem, lcd->w1_framebuffer_base, height, 4 * width);
}
framebuffer_update_display(surface, &lcd->fbsection,
width, height,
src_width, /* Length of source line, in bytes. */
linesize, /* Bytes between adjacent horizontal output pixels. */
dest_width, /* Bytes between adjacent vertical output pixels. */
lcd->invalidate,
draw_line, NULL,
&first, &last);
if (first >= 0) {
dpy_gfx_update(lcd->con, 0, first, width, last - first + 1);
}
lcd->invalidate = 0;
}
static const MemoryRegionOps lcd_ops = {
@@ -30,9 +131,32 @@ static const MemoryRegionOps lcd_ops = {
.endianness = DEVICE_NATIVE_ENDIAN,
};
static const GraphicHwOps gfx_ops = {
.invalidate = lcd_invalidate,
.gfx_update = lcd_refresh,
};
static void refresh_timer_tick(void *opaque)
{
IPodTouchLCDState *s = (IPodTouchLCDState *)opaque;
//qemu_irq_raise(s->irq);
//timer_mod(s->refresh_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / LCD_REFRESH_RATE_FREQUENCY);
}
static void ipod_touch_lcd_realize(DeviceState *dev, Error **errp)
{
IPodTouchLCDState *s = IPOD_TOUCH_LCD(dev);
s->con = graphic_console_init(dev, 0, &gfx_ops, s);
qemu_console_resize(s->con, 320, 480);
// add mouse handler
//qemu_add_mouse_event_handler(ipod_touch_lcd_mouse_event, s, 1, "iPod Touch Touchscreen");
// initialize the refresh timer
s->refresh_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, refresh_timer_tick, s);
timer_mod(s->refresh_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / LCD_REFRESH_RATE_FREQUENCY);
}
static void ipod_touch_lcd_init(Object *obj)
-1
View File
@@ -12,7 +12,6 @@ static uint64_t ipod_touch_mipi_dsi_read(void *opaque, hwaddr addr, unsigned siz
case REG_INTSRC:
return rDSIM_INTSRC_RxDatDone;
case REG_RXFIFO:
return 0;
if(!s->return_panel_id) {
s->return_panel_id = true;
// TODO this should be rewritten as a proper queue!
+415
View File
@@ -0,0 +1,415 @@
#include "hw/arm/ipod_touch_multitouch.h"
static void prepare_interface_version_response(IPodTouchMultitouchState *s) {
memset(s->out_buffer + 1, 0, 15);
// set the interface version
s->out_buffer[2] = MT_INTERFACE_VERSION;
// set the max packet size
s->out_buffer[3] = (MT_MAX_PACKET_SIZE & 0xFF);
s->out_buffer[4] = (MT_MAX_PACKET_SIZE >> 8) & 0xFF;
// compute and set the checksum
uint32_t checksum = 0;
for(int i = 0; i < 14; i++) {
checksum += s->out_buffer[i];
}
s->out_buffer[14] = (checksum & 0xFF);
s->out_buffer[15] = (checksum >> 8) & 0xFF;
}
static void prepare_cmd_status_response(IPodTouchMultitouchState *s) {
memset(s->out_buffer + 1, 0, 15);
// TODO we should probably set some CMD status here
// compute and set the checksum
uint32_t checksum = 0;
for(int i = 0; i < 14; i++) {
checksum += s->out_buffer[i];
}
s->out_buffer[14] = (checksum & 0xFF);
s->out_buffer[15] = (checksum >> 8) & 0xFF;
}
static void prepare_report_info_response(IPodTouchMultitouchState *s, uint8_t report_id) {
memset(s->out_buffer + 1, 0, 15);
// set the error
s->out_buffer[2] = 0;
// set the report length
uint32_t report_length = 0;
if(report_id == MT_REPORT_UNKNOWN1) {
report_length = MT_REPORT_UNKNOWN1_SIZE;
}
else if(report_id == MT_REPORT_FAMILY_ID) {
report_length = MT_REPORT_FAMILY_ID_SIZE;
}
else if(report_id == MT_REPORT_SENSOR_INFO) {
report_length = MT_REPORT_SENSOR_INFO_SIZE;
}
else if(report_id == MT_REPORT_SENSOR_REGION_DESC) {
report_length = MT_REPORT_SENSOR_REGION_DESC_SIZE;
}
else if(report_id == MT_REPORT_SENSOR_REGION_PARAM) {
report_length = MT_REPORT_SENSOR_REGION_PARAM_SIZE;
}
else if(report_id == MT_REPORT_SENSOR_DIMENSIONS) {
report_length = MT_REPORT_SENSOR_DIMENSIONS_SIZE;
}
else {
hw_error("Unknown report ID 0x%02x\n", report_id);
}
s->out_buffer[3] = (report_length & 0xFF);
s->out_buffer[4] = (report_length >> 8) & 0xFF;
// compute and set the checksum
uint32_t checksum = 0;
for(int i = 0; i < 14; i++) {
checksum += s->out_buffer[i];
}
s->out_buffer[14] = (checksum & 0xFF);
s->out_buffer[15] = (checksum >> 8) & 0xFF;
}
static void prepare_short_control_response(IPodTouchMultitouchState *s, uint8_t report_id) {
memset(s->out_buffer + 1, 0, 15);
if(report_id == MT_REPORT_FAMILY_ID) {
s->out_buffer[3] = MT_FAMILY_ID;
}
else if(report_id == MT_REPORT_SENSOR_INFO) {
s->out_buffer[3] = MT_ENDIANNESS;
s->out_buffer[4] = MT_SENSOR_ROWS;
s->out_buffer[5] = MT_SENSOR_COLUMNS;
s->out_buffer[6] = (MT_BCD_VERSION & 0xFF);
s->out_buffer[7] = (MT_BCD_VERSION >> 8) & 0xFF;
}
else if(report_id == MT_REPORT_SENSOR_REGION_DESC) {
s->out_buffer[3] = MT_SENSOR_REGION_DESC;
}
else if(report_id == MT_REPORT_SENSOR_REGION_PARAM) {
s->out_buffer[3] = MT_SENSOR_REGION_PARAM;
}
else if(report_id == MT_REPORT_SENSOR_DIMENSIONS) {
uint32_t *ob_int32 = (uint32_t *)&s->out_buffer[3];
ob_int32[0] = MT_SENSOR_SURFACE_WIDTH;
ob_int32[1] = MT_SENSOR_SURFACE_HEIGHT;
}
else {
hw_error("Unknown report ID 0x%02x\n", report_id);
}
// compute and set the checksum
uint32_t checksum = 0;
for(int i = 0; i < 14; i++) {
checksum += s->out_buffer[i];
}
s->out_buffer[14] = (checksum & 0xFF);
s->out_buffer[15] = (checksum >> 8) & 0xFF;
}
static uint32_t ipod_touch_multitouch_transfer(SSIPeripheral *dev, uint32_t value)
{
IPodTouchMultitouchState *s = IPOD_TOUCH_MULTITOUCH(dev);
//printf("<MULTITOUCH> Got value: 0x%02x\n", value);
if(s->cur_cmd == 0) {
//printf("Starting command 0x%02x\n", value);
// we're currently not in a command - start a new command
s->cur_cmd = value;
s->out_buffer = malloc(0x100);
s->out_buffer[0] = value; // the response header
s->buf_ind = 0;
s->in_buffer = malloc(0x100);
s->in_buffer_ind = 0;
if(value == 0x18) { // filler packet??
s->buf_size = 2;
s->out_buffer[1] = 0xE1;
}
else if(value == 0x1A) { // HBPP ACK
s->buf_size = 2;
if(s->hbpp_atn_ack_response[0] == 0 && s->hbpp_atn_ack_response[1] == 0) {
// return the default ACK response
s->out_buffer[0] = 0x4B;
s->out_buffer[1] = 0xC1;
}
else {
s->out_buffer[0] = s->hbpp_atn_ack_response[0];
s->out_buffer[1] = s->hbpp_atn_ack_response[1];
}
}
else if(value == 0x1C) { // read register
s->buf_size = 8;
memset(s->out_buffer, 0, 8); // just return zeros
}
else if(value == 0x1D) { // execute
s->buf_size = 12;
memset(s->out_buffer, 0, 12); // just return zeros
}
else if(value == 0x1F) { // calibration
s->buf_size = 2;
s->out_buffer[1] = 0x0;
}
else if(value == 0x1E) { // write register
s->buf_size = 16;
memset(s->out_buffer, 0, 16); // just return zeros
}
else if(value == 0x1F) { // calibration
s->buf_size = 2;
s->out_buffer[1] = 0x0;
}
else if(value == MT_CMD_HBPP_DATA_PACKET) {
s->buf_size = 20; // should be enough initially, until we get the packet length
memset(s->out_buffer + 1, 0, 20 - 1); // just return zeros
}
else if(value == 0x47) { // unknown command, probably used to clear the interrupt
s->buf_size = 2;
}
else if(value == MT_CMD_GET_CMD_STATUS) {
s->buf_size = 16;
prepare_cmd_status_response(s);
}
else if(value == MT_CMD_GET_INTERFACE_VERSION) {
s->buf_size = 16;
prepare_interface_version_response(s);
}
else if(value == MT_CMD_GET_REPORT_INFO) {
s->buf_size = 16;
}
else if(value == MT_CMD_SHORT_CONTROL_WRITE) {
s->buf_size = 16;
}
else if(value == MT_CMD_SHORT_CONTROL_READ) {
s->buf_size = 16;
}
else if(value == MT_CMD_FRAME_READ) {
printf("Will read frame!\n");
s->buf_size = sizeof(MTFrame);
free(s->out_buffer);
s->out_buffer = (uint8_t *) s->next_frame;
}
else {
hw_error("Unknown command 0x%02x!", value);
}
}
s->in_buffer[s->in_buffer_ind] = value;
s->in_buffer_ind++;
if(s->cur_cmd == MT_CMD_HBPP_DATA_PACKET && s->in_buffer_ind == 10) {
// verify the header checksum
uint32_t checksum = 0;
for(int i = 2; i < 8; i++) {
checksum += s->in_buffer[i];
}
if(checksum != (s->in_buffer[8] << 8 | s->in_buffer[9])) {
hw_error("HBPP data header checksum doesn't match!");
}
uint32_t data_len = (s->in_buffer[2] << 10) | (s->in_buffer[3] << 2) + 5;
// extend the lengths of the in/out buffers
free(s->in_buffer);
s->in_buffer = malloc(data_len + 0x10);
free(s->out_buffer);
s->out_buffer = malloc(data_len);
memset(s->out_buffer, 0, data_len);
s->buf_size = data_len;
s->buf_ind = 0;
}
else if(s->cur_cmd == MT_CMD_GET_REPORT_INFO && s->in_buffer_ind == 2) {
prepare_report_info_response(s, s->in_buffer[1]);
}
else if(s->cur_cmd == MT_CMD_SHORT_CONTROL_WRITE && s->in_buffer_ind == 16) {
// TODO we should persist the report here!
}
else if(s->cur_cmd == MT_CMD_SHORT_CONTROL_READ && s->in_buffer_ind == 2) {
prepare_short_control_response(s, s->in_buffer[1]);
}
// TODO process register writes!
uint8_t ret_val = s->out_buffer[s->buf_ind];
s->buf_ind++;
//printf("<MULTITOUCH> Got value: 0x%02x, returning 0x%02x (index: %d, buffer length: %d)\n", value, ret_val, s->buf_ind, s->buf_size);
if(s->buf_ind == s->buf_size) {
//printf("Finished command 0x%02x\n", s->cur_cmd);
if(s->cur_cmd == 0x1E) {
// make sure we return a success status on the next HBPP ACK
s->hbpp_atn_ack_response[0] = 0x4A;
s->hbpp_atn_ack_response[1] = 0xD1;
}
// we're done with the command
s->cur_cmd = 0;
s->buf_size = 0;
//free(s->out_buffer);
//free(s->in_buffer);
}
return ret_val;
}
static MTFrame *get_frame(IPodTouchMultitouchState *s, uint8_t event, float x, float y, uint16_t radius1, uint16_t radius2, uint16_t radius3, uint16_t contactDensity) {
MTFrame *frame = calloc(sizeof(MTFrame), sizeof(uint8_t *));
uint16_t data_len = sizeof(MTFrameHeader) + sizeof(FingerData) + 2;
/// create the frame length packet
frame->frame_length.cmd = MT_CMD_FRAME_READ;
frame->frame_length.length1 = (data_len & 0xFF);
frame->frame_length.length2 = (data_len >> 8) & 0xFF;
uint16_t checksum = 0;
for(int i = 0; i < 14; i++) {
checksum += ((uint8_t *) &frame->frame_length)[i];
}
frame->frame_length.checksum1 = (checksum & 0xFF);
frame->frame_length.checksum2 = (checksum >> 8) & 0xFF;
// create the frame packet
frame->frame_packet.cmd = MT_CMD_FRAME_READ;
frame->frame_packet.length1 = (data_len & 0xFF);
frame->frame_packet.length2 = (data_len >> 8) & 0xFF;
checksum = 0;
for(int i = 0; i < 4; i++) {
checksum += ((uint8_t *) &frame->frame_length)[i];
}
// the first five bytes have to sum up to 0.
frame->frame_packet.checksum_pad = 0xFF - (checksum & 0xFF) + 1;
frame->frame_packet.header.type = MT_FRAME_TYPE_PATH;
frame->frame_packet.header.frameNum = s->frame_counter;
frame->frame_packet.header.headerLen = sizeof(MTFrameHeader);
uint64_t elapsed_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) / 1000000;
frame->frame_packet.header.timestamp = elapsed_ns;
frame->frame_packet.header.numFingers = 1;
frame->frame_packet.header.fingerDataLen = sizeof(FingerData);
// create the finger data
frame->finger_data.id = 1;
frame->finger_data.event = event;
frame->finger_data.unk_2 = 2;
frame->finger_data.unk_3 = 1;
// 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.x = (int)(x * MT_INTERNAL_SENSOR_SURFACE_WIDTH);
frame->finger_data.y = (int)(y * MT_INTERNAL_SENSOR_SURFACE_HEIGHT);
frame->finger_data.radius1 = radius1;
frame->finger_data.radius2 = radius2;
frame->finger_data.radius3 = radius3;
frame->finger_data.angle = 19317;
frame->finger_data.contactDensity = contactDensity; // seems to be a medium press
// compute the checksum over the frame data.
checksum = 0;
for(int i = 0; i < data_len - 2; i++) {
checksum += ((uint8_t *) &frame->frame_packet.header)[i];
}
frame->checksum1 = (checksum & 0xFF);
frame->checksum2 = (checksum >> 8) & 0xFF;
s->last_frame_timestamp = elapsed_ns;
s->frame_counter += 1;
return frame;
}
static void ipod_touch_multitouch_inform_frame_ready(IPodTouchMultitouchState *s) {
s->sysic->gpio_int_status[4] |= (1 << 27); // the multitouch interrupt bit is in group 4 (32 interrupts per group), and the 27th of the 4th group
qemu_irq_raise(s->sysic->gpio_irqs[4]);
}
void ipod_touch_multitouch_on_touch(IPodTouchMultitouchState *s) {
s->touch_down = true;
s->next_frame = get_frame(s, MT_EVENT_TOUCH_START, s->touch_x, s->touch_y, 100, 660, 580, 150);
ipod_touch_multitouch_inform_frame_ready(s);
timer_mod(s->touch_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / 10);
}
void ipod_touch_multitouch_on_release(IPodTouchMultitouchState *s) {
s->next_frame = get_frame(s, MT_EVENT_TOUCH_ENDED, s->touch_x, s->touch_y, 0, 0, 0, 0);
s->touch_down = false;
ipod_touch_multitouch_inform_frame_ready(s);
timer_del(s->touch_timer);
timer_mod(s->touch_end_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / 10);
}
static void touch_timer_tick(void *opaque)
{
IPodTouchMultitouchState *s = (IPodTouchMultitouchState *)opaque;
s->next_frame = get_frame(s, MT_EVENT_TOUCH_MOVED, s->touch_x, s->touch_y, 100, 660, 580, 150);
ipod_touch_multitouch_inform_frame_ready(s);
if(s->touch_down) {
// reschedule the timer
timer_mod(s->touch_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + NANOSECONDS_PER_SECOND / 10);
}
}
static void touch_end_timer_tick(void *opaque)
{
IPodTouchMultitouchState *s = (IPodTouchMultitouchState *)opaque;
s->next_frame = get_frame(s, MT_EVENT_TOUCH_FULL_END, s->touch_x, s->touch_y, 0, 0, 0, 0);
s->touch_down = false;
ipod_touch_multitouch_inform_frame_ready(s);
}
static void ipod_touch_multitouch_realize(SSIPeripheral *d, Error **errp)
{
IPodTouchMultitouchState *s = IPOD_TOUCH_MULTITOUCH(d);
memset(s->hbpp_atn_ack_response, 0, 2);
s->touch_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, touch_timer_tick, s);
s->touch_end_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, touch_end_timer_tick, s);
s->prev_touch_x = 0;
s->prev_touch_y = 0;
s->last_frame_timestamp = 0;
}
static void ipod_touch_multitouch_class_init(ObjectClass *klass, void *data)
{
SSIPeripheralClass *k = SSI_PERIPHERAL_CLASS(klass);
k->realize = ipod_touch_multitouch_realize;
k->transfer = ipod_touch_multitouch_transfer;
}
static const TypeInfo ipod_touch_multitouch_type_info = {
.name = TYPE_IPOD_TOUCH_MULTITOUCH,
.parent = TYPE_SSI_PERIPHERAL,
.instance_size = sizeof(IPodTouchMultitouchState),
.class_init = ipod_touch_multitouch_class_init,
};
static void ipod_touch_multitouch_register_types(void)
{
type_register_static(&ipod_touch_multitouch_type_info);
}
type_init(ipod_touch_multitouch_register_types)
-1
View File
@@ -13,7 +13,6 @@ static uint32_t ipod_touch_nor_spi_transfer(SSIPeripheral *dev, uint32_t value)
{
IPodTouchNORSPIState *s = IPOD_TOUCH_NOR_SPI(dev);
printf("NOR SPI received value 0x%08x\n", value);
if(value == NOR_GET_JEDECID) {
printf("RECEIVED JEDCID VALUE\n");
}
+2 -22
View File
@@ -71,7 +71,6 @@ static void ipod_touch_pke_write(void *opaque, hwaddr offset, uint64_t value, un
s->num_started = 0;
break;
case 0x10:
printf("Seg sign: %d\n", value);
break;
case REG_PKE_SEG_START ... (REG_PKE_SEG_START + 1024):
{
@@ -83,22 +82,6 @@ static void ipod_touch_pke_write(void *opaque, hwaddr offset, uint64_t value, un
{
s->num_started++;
if(s->num_started == 5) {
printf("Base: 0x");
uint32_t *cast = (uint32_t *)(&s->segments[s->segment_size]); // segment 1
for(int i = (s->segment_size / 4 - 1); i >= 0; i--) {
printf("%08x", cast[i]);
}
printf("\n");
printf("Mod: 0x");
cast = (uint32_t *)s->segments; // segment 0
for(int i = (s->segment_size / 4 - 1); i >= 0; i--) {
printf("%08x", cast[i]);
}
printf("\n\n");
}
if(s->num_started == 5) { // TODO this is arbitrary!
@@ -112,8 +95,8 @@ static void ipod_touch_pke_write(void *opaque, hwaddr offset, uint64_t value, un
BIGNUM *res = BN_new();
BN_CTX *ctx = BN_CTX_new();
BN_mod_exp(res, base_bn, exp_bn, mod_bn, ctx);
BN_print(BIO_new_fp(stdout, BIO_NOCLOSE), res);
printf("\n\n");
// BN_print(BIO_new_fp(stdout, BIO_NOCLOSE), res);
// printf("\n\n");
char *res_hex = datahex(BN_bn2hex(res));
@@ -124,14 +107,11 @@ static void ipod_touch_pke_write(void *opaque, hwaddr offset, uint64_t value, un
break;
}
case REG_PKE_SEG_SIZE:
printf("Setting size: %d\n", value);
s->seg_size_reg = value;
uint32_t size_bit = (s->seg_size_reg >> 6);
if(size_bit == 0) { s->segment_size = 256; }
else if(size_bit == 1) { s->segment_size = 128; }
else { }
printf("Segment size: %d\n", s->segment_size);
break;
case REG_PKE_SWRESET:
s->num_started = 0;
+54
View File
@@ -0,0 +1,54 @@
#include "hw/arm/ipod_touch_scaler_csc.h"
static uint64_t ipod_touch_scaler_csc_read(void *opaque, hwaddr addr, unsigned size)
{
//fprintf(stderr, "%s: offset = 0x%08x\n", __func__, addr);
switch (addr) {
default:
return 0;
}
return 0;
}
static void ipod_touch_scaler_csc_write(void *opaque, hwaddr addr, uint64_t data, unsigned size)
{
IPodTouchScalerCSCState *s = IPOD_TOUCH_SCALER_CSC(opaque);
//printf("%s (base %d): writing 0x%08x to 0x%08x\n", __func__, s->base, data, addr);
}
static const MemoryRegionOps ipod_touch_scaler_csc_ops = {
.read = ipod_touch_scaler_csc_read,
.write = ipod_touch_scaler_csc_write,
.endianness = DEVICE_NATIVE_ENDIAN,
};
static void ipod_touch_scaler_csc_init(Object *obj)
{
IPodTouchScalerCSCState *s = IPOD_TOUCH_SCALER_CSC(obj);
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
memory_region_init_io(&s->iomem, obj, &ipod_touch_scaler_csc_ops, s, TYPE_IPOD_TOUCH_SCALER_CSC, 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
}
static void ipod_touch_scaler_csc_class_init(ObjectClass *klass, void *data)
{
}
static const TypeInfo ipod_touch_scaler_csc_type_info = {
.name = TYPE_IPOD_TOUCH_SCALER_CSC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IPodTouchScalerCSCState),
.instance_init = ipod_touch_scaler_csc_init,
.class_init = ipod_touch_scaler_csc_class_init,
};
static void ipod_touch_scaler_csc_register_types(void)
{
type_register_static(&ipod_touch_scaler_csc_type_info);
}
type_init(ipod_touch_scaler_csc_register_types)
+6 -6
View File
@@ -280,8 +280,8 @@ static void ipod_touch_spi_realize(DeviceState *dev, struct Error **errp)
sysbus_init_mmio(sbd, &s->iomem);
s->base = base_addr;
fifo8_create(&s->tx_fifo, R_FIFO_DEPTH);
fifo8_create(&s->rx_fifo, R_FIFO_DEPTH);
fifo8_create(&s->tx_fifo, R_FIFO_TX_DEPTH);
fifo8_create(&s->rx_fifo, R_FIFO_RX_DEPTH);
// create the peripheral
IPodTouchNORSPIState *nor;
@@ -296,11 +296,11 @@ static void ipod_touch_spi_realize(DeviceState *dev, struct Error **errp)
nor = IPOD_TOUCH_NOR_SPI(dev);
s->nor = nor;
break;
case 2:
case 4:
{
// DeviceState *dev = ssi_create_peripheral(s->spi, TYPE_IPOD_TOUCH_MULTITOUCH);
// IPodTouchMultitouchState *mt = IPOD_TOUCH_MULTITOUCH(dev);
// s->mt = mt;
DeviceState *dev = ssi_create_peripheral(s->spi, TYPE_IPOD_TOUCH_MULTITOUCH);
IPodTouchMultitouchState *mt = IPOD_TOUCH_MULTITOUCH(dev);
s->mt = mt;
break;
}
}
+1 -1
View File
@@ -62,6 +62,6 @@ arm_ss.add(when: 'CONFIG_FSL_IMX7', if_true: files('fsl-imx7.c', 'mcimx7d-sabre.
arm_ss.add(when: 'CONFIG_ARM_SMMUV3', if_true: files('smmu-common.c', '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_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_block_device.c', 'ipod_touch_mbx.c', 'ipod_touch_cd3272_mikey.c', 'ipod_touch_lis302dl.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_block_device.c', 'ipod_touch_mbx.c', 'ipod_touch_cd3272_mikey.c', 'ipod_touch_lis302dl.c', 'ipod_touch_multitouch.c', 'ipod_touch_scaler_csc.c'))
hw_arch += {'arm': arm_ss}
+4 -2
View File
@@ -391,8 +391,10 @@ static void pl080_init(Object *obj)
SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
PL080State *s = PL080(obj);
memory_region_init_io(&s->iomem, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
sysbus_init_mmio(sbd, &s->iomem);
memory_region_init_io(&s->iomem1, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
sysbus_init_mmio(sbd, &s->iomem1);
memory_region_init_io(&s->iomem2, OBJECT(s), &pl080_ops, s, "pl080", 0x1000);
sysbus_init_mmio(sbd, &s->iomem2);
sysbus_init_irq(sbd, &s->irq);
sysbus_init_irq(sbd, &s->interr);
sysbus_init_irq(sbd, &s->inttc);
+6 -1
View File
@@ -25,6 +25,7 @@
#include "hw/arm/ipod_touch_fmss.h"
#include "hw/arm/ipod_touch_block_device.h"
#include "hw/arm/ipod_touch_mbx.h"
#include "hw/arm/ipod_touch_scaler_csc.h"
#define TYPE_IPOD_TOUCH "iPod-Touch"
@@ -62,6 +63,7 @@
#define SHA1_MEM_BASE 0x38000000
#define DMAC0_MEM_BASE 0x38200000
#define USBOTG_MEM_BASE 0x38400000
#define DMAC1_0_MEM_BASE 0x38700000
#define DISPLAY_MEM_BASE 0x38900000
#define FMSS_MEM_BASE 0x38A00000
#define BLOCK_DEVICE_MEM_BASE 0x38A00F00
@@ -71,12 +73,13 @@
#define VIC1_MEM_BASE 0x38E01000
#define EDGEIC_MEM_BASE 0x38E02000
#define H264_MEM_BASE 0x38F00000
#define SCALER_CSC_MEM_BASE 0x39000000
#define TVOUT1_MEM_BASE 0x39100000
#define TVOUT2_MEM_BASE 0x39200000
#define TVOUT3_MEM_BASE 0x39300000
//#define BLOCK_DEVICE_MEM_BASE 0x39400000
#define SYSIC_MEM_BASE 0x39700000
#define DMAC1_MEM_BASE 0x39900000
#define DMAC1_1_MEM_BASE 0x39900000
#define MBX1_MEM_BASE 0x3B000000
#define MBX2_MEM_BASE 0x39400000
#define SPI0_MEM_BASE 0x3C300000
@@ -117,6 +120,7 @@ typedef struct {
IPodTouchTimerState *timer1;
IPodTouchSPIState *spi0_state;
IPodTouchSPIState *spi1_state;
IPodTouchSPIState *spi4_state;
IPodTouchChipIDState *chipid_state;
IPodTouchGPIOState *gpio_state;
IPodTouchSYSICState *sysic;
@@ -132,6 +136,7 @@ typedef struct {
IPodTouchFMSSState *fmss_state;
IPodTouchBlockDeviceState *bdev_state;
IPodTouchMBXState *mbx_state;
IPodTouchScalerCSCState *scaler_csc_state;
Clock *sysclk;
char nor_path[1024];
IT2G_CPREG_VAR_DEF(REG0);
+14
View File
@@ -11,11 +11,25 @@
#define TYPE_IPOD_TOUCH_LCD "ipodtouch.lcd"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchLCDState, IPOD_TOUCH_LCD)
#define LCD_REFRESH_RATE_FREQUENCY 10
typedef struct IPodTouchLCDState
{
SysBusDevice parent_obj;
MemoryRegion *sysmem;
MemoryRegion iomem;
QemuConsole *con;
int invalidate;
MemoryRegionSection fbsection;
qemu_irq irq;
uint32_t lcd_con;
uint32_t w1_display_resolution_info;
uint32_t w1_framebuffer_base;
uint32_t w1_hspan;
uint32_t w1_display_depth_info;
QEMUTimer *refresh_timer;
} IPodTouchLCDState;
#endif
+160
View File
@@ -0,0 +1,160 @@
#ifndef IPOD_TOUCH_MULTITOUCH_H
#define IPOD_TOUCH_MULTITOUCH_H
#include "qemu/osdep.h"
#include "qemu/module.h"
#include "qemu/timer.h"
#include "qapi/error.h"
#include "hw/hw.h"
#include "hw/ssi/ssi.h"
#include "hw/arm/ipod_touch_sysic.h"
#include "hw/arm/ipod_touch_gpio.h"
#define TYPE_IPOD_TOUCH_MULTITOUCH "ipodtouch.multitouch"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchMultitouchState, IPOD_TOUCH_MULTITOUCH)
#define MT_INTERFACE_VERSION 0x1
#define MT_FAMILY_ID 81
#define MT_ENDIANNESS 0x1
#define MT_SENSOR_ROWS 15
#define MT_SENSOR_COLUMNS 10
#define MT_BCD_VERSION 51
#define MT_SENSOR_REGION_DESC 0x0
#define MT_SENSOR_REGION_PARAM 0x0
#define MT_MAX_PACKET_SIZE 0x294 // 660
#define MT_SENSOR_SURFACE_WIDTH 5000
#define MT_SENSOR_SURFACE_HEIGHT 7500
// internal surface width/height
#define MT_INTERNAL_SENSOR_SURFACE_WIDTH (9000 - MT_SENSOR_SURFACE_WIDTH) * 84 / 73
#define MT_INTERNAL_SENSOR_SURFACE_HEIGHT (13850 - MT_SENSOR_SURFACE_HEIGHT) * 84 / 73
// report IDs
#define MT_REPORT_UNKNOWN1 0x70
#define MT_REPORT_FAMILY_ID 0xD1
#define MT_REPORT_SENSOR_INFO 0xD3
#define MT_REPORT_SENSOR_REGION_DESC 0xD0
#define MT_REPORT_SENSOR_REGION_PARAM 0xA1
#define MT_REPORT_SENSOR_DIMENSIONS 0xD9
// report sizes
#define MT_REPORT_UNKNOWN1_SIZE 0x1
#define MT_REPORT_FAMILY_ID_SIZE 0x1
#define MT_REPORT_SENSOR_INFO_SIZE 0x5
#define MT_REPORT_SENSOR_REGION_DESC_SIZE 0x1
#define MT_REPORT_SENSOR_REGION_PARAM_SIZE 0x1
#define MT_REPORT_SENSOR_DIMENSIONS_SIZE 0x8
#define MT_CMD_HBPP_DATA_PACKET 0x30
#define MT_CMD_GET_CMD_STATUS 0xE1
#define MT_CMD_GET_INTERFACE_VERSION 0xE2
#define MT_CMD_GET_REPORT_INFO 0xE3
#define MT_CMD_SHORT_CONTROL_WRITE 0xE4
#define MT_CMD_SHORT_CONTROL_READ 0xE6
#define MT_CMD_FRAME_READ 0xEA
// frame types
#define MT_FRAME_TYPE_PATH 0x44
// frame event types
#define MT_EVENT_TOUCH_FULL_END 0x0
#define MT_EVENT_TOUCH_START 0x3
#define MT_EVENT_TOUCH_MOVED 0x4
#define MT_EVENT_TOUCH_ENDED 0x7
typedef struct MTFrameLengthPacket
{
uint8_t cmd;
uint8_t length1;
uint8_t length2;
uint8_t unused[11];
uint8_t checksum1;
uint8_t checksum2;
} __attribute__((__packed__)) MTFrameLengthPacket;
typedef struct MTFrameHeader
{
uint8_t type;
uint8_t frameNum;
uint8_t headerLen;
uint8_t unk_3;
uint32_t timestamp;
uint8_t unk_8;
uint8_t unk_9;
uint8_t unk_A;
uint8_t unk_B;
uint16_t unk_C;
uint16_t isImage;
uint8_t numFingers;
uint8_t fingerDataLen;
uint16_t unk_12;
uint16_t unk_14;
uint16_t unk_16;
} __attribute__((__packed__)) MTFrameHeader;
typedef struct MTFramePacket
{
uint8_t cmd;
uint8_t unused1;
uint8_t length1;
uint8_t length2;
uint8_t checksum_pad;
MTFrameHeader header;
} __attribute__((__packed__)) MTFramePacket;
typedef struct FingerData
{
uint8_t id;
uint8_t event;
uint8_t unk_2;
uint8_t unk_3;
int16_t x;
int16_t y;
int16_t velX;
int16_t velY;
uint16_t radius2;
uint16_t radius3;
uint16_t angle;
uint16_t radius1;
uint16_t contactDensity;
uint16_t unk_16;
uint16_t unk_18;
uint16_t unk_1A;
} __attribute__((__packed__)) FingerData;
typedef struct MTFrame {
MTFrameLengthPacket frame_length;
MTFramePacket frame_packet;
FingerData finger_data; // TODO we assume one finger for now
uint8_t checksum1;
uint8_t checksum2;
} __attribute__((__packed__)) MTFrame;
typedef struct IPodTouchMultitouchState {
SSIPeripheral ssidev;
uint8_t cur_cmd;
uint8_t *out_buffer;
uint8_t *in_buffer;
uint32_t buf_size;
uint32_t buf_ind;
uint32_t in_buffer_ind;
uint8_t hbpp_atn_ack_response[2];
MTFrame *next_frame;
uint32_t frame_counter;
bool touch_down;
QEMUTimer *touch_timer;
QEMUTimer *touch_end_timer;
IPodTouchSYSICState *sysic;
IPodTouchGPIOState *gpio_state;
float touch_x;
float touch_y;
float prev_touch_x;
float prev_touch_y;
uint64_t last_frame_timestamp;
} IPodTouchMultitouchState;
void ipod_touch_multitouch_on_touch(IPodTouchMultitouchState *s);
void ipod_touch_multitouch_on_release(IPodTouchMultitouchState *s);
#endif
+19
View File
@@ -0,0 +1,19 @@
#ifndef HW_ARM_IPOD_TOUCH_SCALER_CSC_H
#define HW_ARM_IPOD_TOUCH_SCALER_CSC_H
#include "qemu/osdep.h"
#include "hw/platform-bus.h"
#include "hw/hw.h"
#include "exec/hwaddr.h"
#include "exec/memory.h"
#define TYPE_IPOD_TOUCH_SCALER_CSC "ipodtouch.scalercsc"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchScalerCSCState, IPOD_TOUCH_SCALER_CSC)
typedef struct IPodTouchScalerCSCState {
SysBusDevice busdev;
MemoryRegion iomem;
} IPodTouchScalerCSCState;
#endif
+6 -3
View File
@@ -9,6 +9,7 @@
#include "hw/irq.h"
#include "hw/ssi/ssi.h"
#include "hw/arm/ipod_touch_nor_spi.h"
#include "hw/arm/ipod_touch_multitouch.h"
#define TYPE_IPOD_TOUCH_SPI "ipodtouch.spi"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchSPIState, IPOD_TOUCH_SPI)
@@ -49,7 +50,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchSPIState, IPOD_TOUCH_SPI)
#define R_WORD_DELAY 0x038
#define R_TXCNT 0x04c
#define R_FIFO_DEPTH 16
#define R_FIFO_TX_DEPTH 50000
#define R_FIFO_RX_DEPTH 16
#define REG(_s,_v) ((_s)->regs[(_v)>>2])
#define MMIO_SIZE (0x4000)
@@ -60,16 +62,17 @@ typedef struct IPodTouchSPIState {
MemoryRegion iomem;
SSIBus *spi;
IPodTouchMultitouchState *mt;
qemu_irq irq;
uint32_t last_irq;
qemu_irq cs_line;
Fifo8 rx_fifo;
Fifo8 tx_fifo;
uint32_t regs[MMIO_SIZE >> 2];
uint8_t base;
IPodTouchNORSPIState *nor;
Fifo8 rx_fifo;
Fifo8 tx_fifo;
} IPodTouchSPIState;
void set_spi_base(uint32_t base);
+2 -1
View File
@@ -49,7 +49,8 @@ OBJECT_DECLARE_SIMPLE_TYPE(PL080State, PL080)
struct PL080State {
SysBusDevice parent_obj;
MemoryRegion iomem;
MemoryRegion iomem1;
MemoryRegion iomem2;
uint8_t tc_int;
uint8_t tc_mask;
uint8_t err_int;