Compare commits

...
Author SHA1 Message Date
Martijn de Vos fd6f1e0ed9 USB communication working 2025-02-19 19:33:07 +01:00
Martijn de Vos aa88deb054 Worked on USB/TCP 2025-02-04 20:33:40 +01:00
8 changed files with 818 additions and 18 deletions

No files matched your search

+6
View File
@@ -407,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");
@@ -533,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)
+175 -14
View File
@@ -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++)
+2
View File
@@ -16,6 +16,8 @@ static uint64_t ipod_touch_usb_phys_read(void *opaque, hwaddr addr, unsigned siz
return s->usb_unknown1;
case REG_OPHYTUNE:
return s->usb_ophytune;
case REG_CABLE:
return s->is_cable_connected;
default:
//return 0x0;
printf("%s: read invalid location 0x%08x\n", __func__, addr);
+2
View File
@@ -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'))
+524
View File
@@ -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;
}
+2 -1
View File
@@ -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;
+5 -3
View File
@@ -8,11 +8,12 @@
#define TYPE_IPOD_TOUCH_USB_PHYS "ipodtouch.usbphys"
OBJECT_DECLARE_SIMPLE_TYPE(IPodTouchUSBPhysState, IPOD_TOUCH_USB_PHYS)
#define REG_OPHYPWR 0x0
#define REG_OPHYCLK 0x4
#define REG_ORSTCON 0x8
#define REG_OPHYPWR 0x0
#define REG_OPHYCLK 0x4
#define REG_ORSTCON 0x8
#define REG_UNKNOWN1 0x1C
#define REG_OPHYTUNE 0x20
#define REG_CABLE 0x28
typedef struct IPodTouchUSBPhysState {
SysBusDevice busdev;
@@ -23,6 +24,7 @@ typedef struct IPodTouchUSBPhysState {
uint32_t usb_orstcon;
uint32_t usb_unknown1;
uint32_t usb_ophytune;
bool is_cable_connected;
} IPodTouchUSBPhysState;
#endif
+102
View File
@@ -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