Skip to content

Commit

Permalink
vdp: vdpusb-proxy...
Browse files Browse the repository at this point in the history
  • Loading branch information
Sheph committed Jan 5, 2017
1 parent 8147efa commit a47db0a
Show file tree
Hide file tree
Showing 7 changed files with 249 additions and 5 deletions.
146 changes: 142 additions & 4 deletions apps/vdpusb-proxy/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,14 @@
#include <errno.h>
#include <assert.h>
#include <signal.h>
#include <poll.h>

struct proxy_device;

static int done = 0;
static struct vdp_usb_device* vdp_devs[5];
static struct proxy_device* proxy_devs[5];
static int vdp_busnum = -1;

struct proxy_device
{
Expand All @@ -48,61 +50,74 @@ struct proxy_device

static void proxy_gadget_ep_enable(struct vdp_usb_gadget_ep* ep, int value)
{
printf("ep enable\n");
}

static void proxy_gadget_ep_enqueue(struct vdp_usb_gadget_ep* ep, struct vdp_usb_gadget_request* request)
{
printf("ep enqueue\n");
request->status = vdp_usb_urb_status_completed;
request->complete(request);
request->destroy(request);
}

static void proxy_gadget_ep_dequeue(struct vdp_usb_gadget_ep* ep, struct vdp_usb_gadget_request* request)
{
printf("ep dequeue\n");
request->status = vdp_usb_urb_status_unlinked;
request->complete(request);
request->destroy(request);
}

static vdp_usb_urb_status proxy_gadget_ep_clear_stall(struct vdp_usb_gadget_ep* ep)
{
printf("ep clear stall\n");
return vdp_usb_urb_status_completed;
}

static void proxy_gadget_ep_destroy(struct vdp_usb_gadget_ep* ep)
{
printf("ep destroy\n");
}

static void proxy_gadget_interface_enable(struct vdp_usb_gadget_interface* interface, int value)
{
printf("interface enable\n");
}

static void proxy_gadget_interface_destroy(struct vdp_usb_gadget_interface* interface)
{
printf("interface destroy\n");
}

static void proxy_gadget_config_enable(struct vdp_usb_gadget_config* config, int value)
{
printf("config enable\n");
}

static void proxy_gadget_config_destroy(struct vdp_usb_gadget_config* config)
{
printf("config destroy\n");
}

static void proxy_gadget_reset(struct vdp_usb_gadget* gadget, int start)
{
printf("gadget reset\n");
}

static void proxy_gadget_power(struct vdp_usb_gadget* gadget, int on)
{
printf("gadget power\n");
}

static void proxy_gadget_set_address(struct vdp_usb_gadget* gadget, vdp_u32 address)
{
printf("gadget set_address\n");
}

static void proxy_gadget_destroy(struct vdp_usb_gadget* gadget)
{
printf("gadget destroy\n");
}

static struct vdp_usb_gadget_ep* create_proxy_gadget_ep(const struct libusb_endpoint_descriptor* desc,
Expand Down Expand Up @@ -415,6 +430,10 @@ static int hotplug_callback_attach(libusb_context* ctx, libusb_device* dev, libu
int i;
vdp_usb_result vdp_res;

if (libusb_get_bus_number(dev) == vdp_busnum) {
return 0;
}

printf("device attached: %d:%d\n",
libusb_get_bus_number(dev), libusb_get_port_number(dev));

Expand Down Expand Up @@ -453,6 +472,10 @@ static int hotplug_callback_detach(libusb_context* ctx, libusb_device* dev, libu
{
int i;

if (libusb_get_bus_number(dev) == vdp_busnum) {
return 0;
}

printf("device detached: %d:%d\n",
libusb_get_bus_number(dev), libusb_get_port_number(dev));

Expand Down Expand Up @@ -519,6 +542,7 @@ int main(int argc, char* argv[])
res = 1;
goto out3;
}
vdp_busnum = vdp_usb_device_get_busnum(vdp_devs[i]);
}

if (!libusb_has_capability(LIBUSB_CAP_HAS_HOTPLUG)) {
Expand Down Expand Up @@ -561,12 +585,126 @@ int main(int argc, char* argv[])
libusb_free_device_list(devs, 1);
}

while (1) {
res = libusb_handle_events(NULL);
if (res != 0) {
printf("libusb_handle_events() failed: %s\n", libusb_error_name(res));
while (!done) {
fd_set read_fds, write_fds;
const struct libusb_pollfd** libusb_fds;
struct timeval tv, zero_tv;
int have_tv, i, max_fd = 0;
int have_libusb_events = 0;

zero_tv.tv_sec = 0;
zero_tv.tv_usec = 0;

FD_ZERO(&read_fds);
FD_ZERO(&write_fds);

libusb_fds = libusb_get_pollfds(NULL);
if (!libusb_fds) {
printf("libusb_get_pollfds() failed\n");
break;
}

have_tv = libusb_get_next_timeout(NULL, &tv);
if (have_tv < 0) {
printf("libusb_get_next_timeout() failed\n");
libusb_free_pollfds(libusb_fds);
break;
}

for (i = 0; i < sizeof(proxy_devs)/sizeof(proxy_devs[0]); ++i) {
vdp_fd fd = -1;

if (!proxy_devs[i]) {
continue;
}

vdp_usb_device_wait_event(vdp_devs[i], &fd);

FD_SET(fd, &read_fds);
if (fd > max_fd) {
max_fd = fd;
}
}

for (i = 0; libusb_fds[i]; ++i) {
if (libusb_fds[i]->events & POLLIN) {
FD_SET(libusb_fds[i]->fd, &read_fds);
if (libusb_fds[i]->fd > max_fd) {
max_fd = libusb_fds[i]->fd;
}
} else if (libusb_fds[i]->events & POLLOUT) {
FD_SET(libusb_fds[i]->fd, &write_fds);
if (libusb_fds[i]->fd > max_fd) {
max_fd = libusb_fds[i]->fd;
}
}
}

assert(max_fd > 0);

res = select(max_fd + 1, &read_fds, &write_fds, NULL, (have_tv ? &tv : NULL));

if (res < 0) {
printf("select error: %s\n", strerror(errno));
libusb_free_pollfds(libusb_fds);
break;
}

if (res == 0) {
have_libusb_events = 1;
} else {
for (i = 0; libusb_fds[i]; ++i) {
if (libusb_fds[i]->events & POLLIN) {
if (FD_ISSET(libusb_fds[i]->fd, &read_fds)) {
have_libusb_events = 1;
break;
}
} else if (libusb_fds[i]->events & POLLOUT) {
if (FD_ISSET(libusb_fds[i]->fd, &write_fds)) {
have_libusb_events = 1;
break;
}
}
}
}

libusb_free_pollfds(libusb_fds);

for (i = 0; i < sizeof(proxy_devs)/sizeof(proxy_devs[0]); ++i) {
vdp_fd fd = -1;

if (!proxy_devs[i]) {
continue;
}

vdp_usb_device_wait_event(vdp_devs[i], &fd);

if (FD_ISSET(fd, &read_fds)) {
struct vdp_usb_event event;

vdp_res = vdp_usb_device_get_event(vdp_devs[i], &event);

if (vdp_res != vdp_usb_success) {
printf("failed to get event: %s\n", vdp_usb_result_to_str(vdp_res));
i = 0;
break;
}

vdp_usb_gadget_event(proxy_devs[i]->gadget, &event);
}
}

if (i == 0) {
break;
}

if (have_libusb_events) {
res = libusb_handle_events_timeout_completed(NULL, &zero_tv, NULL);
if (res != 0) {
printf("libusb_handle_events_timeout_completed() failed: %s\n", libusb_error_name(res));
break;
}
}
}

for (i = 0; i < sizeof(proxy_devs)/sizeof(proxy_devs[0]); ++i) {
Expand Down
3 changes: 3 additions & 0 deletions include/vdp/usb.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,9 @@ vdp_usb_result vdp_usb_device_attach(struct vdp_usb_device* device);
*/
vdp_usb_result vdp_usb_device_detach(struct vdp_usb_device* device);

int vdp_usb_device_get_busnum(struct vdp_usb_device* device);
int vdp_usb_device_get_portnum(struct vdp_usb_device* device);

/*
* @}
*/
Expand Down
17 changes: 17 additions & 0 deletions include/vdphci-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
#define _VDPHCI_COMMON_H_

#include <linux/types.h>
#include <linux/ioctl.h>

#ifdef __cplusplus
extern "C" {
Expand All @@ -47,6 +48,22 @@ extern "C" {
*/
#define VDPHCI_DEVICE_PREFIX "vdphcidev"

/*
* Device control codes magic.
*/
#define VDPHCI_IOC_MAGIC 'V'

/*
* Get info.
*/
struct vdphci_info
{
int busnum;
int portnum;
};

#define VDPHCI_IOC_GET_INFO _IOR(VDPHCI_IOC_MAGIC, 0, struct vdphci_info)

/*
* HEvent related. HEvents are sent by HCD to device.
*/
Expand Down
48 changes: 47 additions & 1 deletion modules/vdphci/vdphci_device.c
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,51 @@ static unsigned int vdphci_device_poll(struct file* file, struct poll_table_stru
return ret;
}

static long vdphci_device_ioctl(struct file* file, unsigned int cmd, unsigned long arg)
{
struct vdphci_device* device = file->private_data;
int ret = 0;
union
{
struct vdphci_info info;
} value;

if (_IOC_TYPE(cmd) != VDPHCI_IOC_MAGIC) {
return -ENOTTY;
}

if (_IOC_DIR(cmd) & _IOC_READ) {
ret = !access_ok(VERIFY_WRITE, (void __user*)arg, _IOC_SIZE(cmd));
}

if (_IOC_DIR(cmd) & _IOC_WRITE) {
ret = ret || !access_ok(VERIFY_READ, (void __user*)arg, _IOC_SIZE(cmd));
}

if (ret != 0) {
return -EFAULT;
}

ret = 0;

switch (cmd) {
case VDPHCI_IOC_GET_INFO:
value.info.busnum = vdphci_hcd_to_usb_hcd(device->parent_hcd)->self.busnum;
value.info.portnum = device->port->number;
if (copy_to_user((struct vdphci_info __user*)arg,
&value.info,
sizeof(value.info)) != 0) {
ret = -EFAULT;
}
break;
default:
ret = -ENOTTY;
break;
}

return ret;
}

static struct file_operations vdphci_device_ops =
{
.owner = THIS_MODULE,
Expand All @@ -881,7 +926,8 @@ static struct file_operations vdphci_device_ops =
.release = vdphci_device_release,
.write = vdphci_device_write,
.read = vdphci_device_read,
.poll = vdphci_device_poll
.poll = vdphci_device_poll,
.unlocked_ioctl = vdphci_device_ioctl
};

int vdphci_device_init(struct vdphci_hcd* parent_hcd, struct vdphci_port* port, dev_t devno, struct vdphci_device* device)
Expand Down
3 changes: 3 additions & 0 deletions modules/vdphci/vdphci_hcd.c
Original file line number Diff line number Diff line change
Expand Up @@ -818,13 +818,16 @@ int vdphci_hcd_add(struct device* controller,
if (ret != 0) {
usb_put_hcd(*hcd);
*hcd = 0;
} else {
print_info("%s/%d added\n", (*hcd)->self.bus_name, (*hcd)->self.busnum);
}

return ret;
}

void vdphci_hcd_remove(struct usb_hcd* hcd)
{
print_info("%s/%d removed\n", hcd->self.bus_name, hcd->self.busnum);
usb_remove_hcd(hcd);
usb_put_hcd(hcd);
}
Expand Down
Loading

0 comments on commit a47db0a

Please sign in to comment.