hw/usb: switch MTP to use new inotify APIs
The internal inotify APIs allow a lot of conditional statements to be cleared out, and provide a simpler callback for handling events. Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
888e0359bf
commit
47287c27d0
204
hw/usb/dev-mtp.c
204
hw/usb/dev-mtp.c
|
@ -11,17 +11,16 @@
|
||||||
|
|
||||||
#include "qemu/osdep.h"
|
#include "qemu/osdep.h"
|
||||||
#include "qapi/error.h"
|
#include "qapi/error.h"
|
||||||
|
#include "qemu/error-report.h"
|
||||||
#include <wchar.h>
|
#include <wchar.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
|
||||||
#include <sys/statvfs.h>
|
#include <sys/statvfs.h>
|
||||||
#ifdef CONFIG_INOTIFY1
|
|
||||||
#include <sys/inotify.h>
|
|
||||||
#include "qemu/main-loop.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "qemu-common.h"
|
#include "qemu-common.h"
|
||||||
#include "qemu/iov.h"
|
#include "qemu/iov.h"
|
||||||
|
#include "qemu/filemonitor.h"
|
||||||
#include "trace.h"
|
#include "trace.h"
|
||||||
#include "hw/usb.h"
|
#include "hw/usb.h"
|
||||||
#include "desc.h"
|
#include "desc.h"
|
||||||
|
@ -132,7 +131,6 @@ enum {
|
||||||
EP_EVENT,
|
EP_EVENT,
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifdef CONFIG_INOTIFY1
|
|
||||||
typedef struct MTPMonEntry MTPMonEntry;
|
typedef struct MTPMonEntry MTPMonEntry;
|
||||||
|
|
||||||
struct MTPMonEntry {
|
struct MTPMonEntry {
|
||||||
|
@ -141,7 +139,6 @@ struct MTPMonEntry {
|
||||||
|
|
||||||
QTAILQ_ENTRY(MTPMonEntry) next;
|
QTAILQ_ENTRY(MTPMonEntry) next;
|
||||||
};
|
};
|
||||||
#endif
|
|
||||||
|
|
||||||
struct MTPControl {
|
struct MTPControl {
|
||||||
uint16_t code;
|
uint16_t code;
|
||||||
|
@ -172,10 +169,8 @@ struct MTPObject {
|
||||||
char *name;
|
char *name;
|
||||||
char *path;
|
char *path;
|
||||||
struct stat stat;
|
struct stat stat;
|
||||||
#ifdef CONFIG_INOTIFY1
|
/* file monitor watch id */
|
||||||
/* inotify watch cookie */
|
int watchid;
|
||||||
int watchfd;
|
|
||||||
#endif
|
|
||||||
MTPObject *parent;
|
MTPObject *parent;
|
||||||
uint32_t nchildren;
|
uint32_t nchildren;
|
||||||
QLIST_HEAD(, MTPObject) children;
|
QLIST_HEAD(, MTPObject) children;
|
||||||
|
@ -198,11 +193,8 @@ struct MTPState {
|
||||||
bool readonly;
|
bool readonly;
|
||||||
|
|
||||||
QTAILQ_HEAD(, MTPObject) objects;
|
QTAILQ_HEAD(, MTPObject) objects;
|
||||||
#ifdef CONFIG_INOTIFY1
|
QFileMonitor *file_monitor;
|
||||||
/* inotify descriptor */
|
|
||||||
int inotifyfd;
|
|
||||||
QTAILQ_HEAD(, MTPMonEntry) events;
|
QTAILQ_HEAD(, MTPMonEntry) events;
|
||||||
#endif
|
|
||||||
/* Responder is expecting a write operation */
|
/* Responder is expecting a write operation */
|
||||||
bool write_pending;
|
bool write_pending;
|
||||||
struct {
|
struct {
|
||||||
|
@ -391,6 +383,7 @@ static MTPObject *usb_mtp_object_alloc(MTPState *s, uint32_t handle,
|
||||||
goto ignore;
|
goto ignore;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o->watchid = -1;
|
||||||
o->handle = handle;
|
o->handle = handle;
|
||||||
o->parent = parent;
|
o->parent = parent;
|
||||||
o->name = g_strdup(name);
|
o->name = g_strdup(name);
|
||||||
|
@ -437,6 +430,10 @@ static void usb_mtp_object_free(MTPState *s, MTPObject *o)
|
||||||
|
|
||||||
trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path);
|
trace_usb_mtp_object_free(s->dev.addr, o->handle, o->path);
|
||||||
|
|
||||||
|
if (o->watchid != -1 && s->file_monitor) {
|
||||||
|
qemu_file_monitor_remove_watch(s->file_monitor, o->path, o->watchid);
|
||||||
|
}
|
||||||
|
|
||||||
QTAILQ_REMOVE(&s->objects, o, next);
|
QTAILQ_REMOVE(&s->objects, o, next);
|
||||||
if (o->parent) {
|
if (o->parent) {
|
||||||
QLIST_REMOVE(o, list);
|
QLIST_REMOVE(o, list);
|
||||||
|
@ -488,6 +485,10 @@ static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
|
||||||
{
|
{
|
||||||
MTPObject *iter;
|
MTPObject *iter;
|
||||||
|
|
||||||
|
if (len == -1) {
|
||||||
|
len = strlen(name);
|
||||||
|
}
|
||||||
|
|
||||||
QLIST_FOREACH(iter, &parent->children, list) {
|
QLIST_FOREACH(iter, &parent->children, list) {
|
||||||
if (strncmp(iter->name, name, len) == 0) {
|
if (strncmp(iter->name, name, len) == 0) {
|
||||||
return iter;
|
return iter;
|
||||||
|
@ -497,13 +498,12 @@ static MTPObject *usb_mtp_object_lookup_name(MTPObject *parent,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_INOTIFY1
|
static MTPObject *usb_mtp_object_lookup_id(MTPState *s, int id)
|
||||||
static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd)
|
|
||||||
{
|
{
|
||||||
MTPObject *iter;
|
MTPObject *iter;
|
||||||
|
|
||||||
QTAILQ_FOREACH(iter, &s->objects, next) {
|
QTAILQ_FOREACH(iter, &s->objects, next) {
|
||||||
if (iter->watchfd == wd) {
|
if (iter->watchid == id) {
|
||||||
return iter;
|
return iter;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -511,159 +511,103 @@ static MTPObject *usb_mtp_object_lookup_wd(MTPState *s, int wd)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void inotify_watchfn(void *arg)
|
static void file_monitor_event(int id,
|
||||||
|
QFileMonitorEvent ev,
|
||||||
|
const char *name,
|
||||||
|
void *opaque)
|
||||||
{
|
{
|
||||||
MTPState *s = arg;
|
MTPState *s = opaque;
|
||||||
ssize_t bytes;
|
MTPObject *parent = usb_mtp_object_lookup_id(s, id);
|
||||||
/* From the man page: atleast one event can be read */
|
|
||||||
int pos;
|
|
||||||
char buf[sizeof(struct inotify_event) + NAME_MAX + 1];
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
bytes = read(s->inotifyfd, buf, sizeof(buf));
|
|
||||||
pos = 0;
|
|
||||||
|
|
||||||
if (bytes <= 0) {
|
|
||||||
/* Better luck next time */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TODO: Ignore initiator initiated events.
|
|
||||||
* For now we are good because the store is RO
|
|
||||||
*/
|
|
||||||
while (bytes > 0) {
|
|
||||||
char *p = buf + pos;
|
|
||||||
struct inotify_event *event = (struct inotify_event *)p;
|
|
||||||
int watchfd = 0;
|
|
||||||
uint32_t mask = event->mask & (IN_CREATE | IN_DELETE |
|
|
||||||
IN_MODIFY | IN_IGNORED);
|
|
||||||
MTPObject *parent = usb_mtp_object_lookup_wd(s, event->wd);
|
|
||||||
MTPMonEntry *entry = NULL;
|
MTPMonEntry *entry = NULL;
|
||||||
MTPObject *o;
|
MTPObject *o;
|
||||||
|
|
||||||
pos = pos + sizeof(struct inotify_event) + event->len;
|
|
||||||
bytes = bytes - pos;
|
|
||||||
|
|
||||||
if (!parent) {
|
if (!parent) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mask) {
|
switch (ev) {
|
||||||
case IN_CREATE:
|
case QFILE_MONITOR_EVENT_CREATED:
|
||||||
if (usb_mtp_object_lookup_name
|
if (usb_mtp_object_lookup_name(parent, name, -1)) {
|
||||||
(parent, event->name, event->len)) {
|
|
||||||
/* Duplicate create event */
|
/* Duplicate create event */
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
entry = g_new0(MTPMonEntry, 1);
|
entry = g_new0(MTPMonEntry, 1);
|
||||||
entry->handle = s->next_handle;
|
entry->handle = s->next_handle;
|
||||||
entry->event = EVT_OBJ_ADDED;
|
entry->event = EVT_OBJ_ADDED;
|
||||||
o = usb_mtp_add_child(s, parent, event->name);
|
o = usb_mtp_add_child(s, parent, name);
|
||||||
if (!o) {
|
if (!o) {
|
||||||
g_free(entry);
|
g_free(entry);
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
o->watchfd = watchfd;
|
trace_usb_mtp_file_monitor_event(s->dev.addr, name, "Obj Added");
|
||||||
trace_usb_mtp_inotify_event(s->dev.addr, event->name,
|
|
||||||
event->mask, "Obj Added");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IN_DELETE:
|
case QFILE_MONITOR_EVENT_DELETED:
|
||||||
/*
|
/*
|
||||||
* The kernel issues a IN_IGNORED event
|
* The kernel issues a IN_IGNORED event
|
||||||
* when a dir containing a watchpoint is
|
* when a dir containing a watchpoint is
|
||||||
* deleted, so we don't have to delete the
|
* deleted, so we don't have to delete the
|
||||||
* watchpoint
|
* watchpoint
|
||||||
*/
|
*/
|
||||||
o = usb_mtp_object_lookup_name(parent, event->name, event->len);
|
o = usb_mtp_object_lookup_name(parent, name, -1);
|
||||||
if (!o) {
|
if (!o) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
entry = g_new0(MTPMonEntry, 1);
|
entry = g_new0(MTPMonEntry, 1);
|
||||||
entry->handle = o->handle;
|
entry->handle = o->handle;
|
||||||
entry->event = EVT_OBJ_REMOVED;
|
entry->event = EVT_OBJ_REMOVED;
|
||||||
trace_usb_mtp_inotify_event(s->dev.addr, o->path,
|
trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Deleted");
|
||||||
event->mask, "Obj Deleted");
|
|
||||||
usb_mtp_object_free(s, o);
|
usb_mtp_object_free(s, o);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IN_MODIFY:
|
case QFILE_MONITOR_EVENT_MODIFIED:
|
||||||
o = usb_mtp_object_lookup_name(parent, event->name, event->len);
|
o = usb_mtp_object_lookup_name(parent, name, -1);
|
||||||
if (!o) {
|
if (!o) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
entry = g_new0(MTPMonEntry, 1);
|
entry = g_new0(MTPMonEntry, 1);
|
||||||
entry->handle = o->handle;
|
entry->handle = o->handle;
|
||||||
entry->event = EVT_OBJ_INFO_CHANGED;
|
entry->event = EVT_OBJ_INFO_CHANGED;
|
||||||
trace_usb_mtp_inotify_event(s->dev.addr, o->path,
|
trace_usb_mtp_file_monitor_event(s->dev.addr, o->path, "Obj Modified");
|
||||||
event->mask, "Obj Modified");
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IN_IGNORED:
|
case QFILE_MONITOR_EVENT_IGNORED:
|
||||||
trace_usb_mtp_inotify_event(s->dev.addr, parent->path,
|
trace_usb_mtp_file_monitor_event(s->dev.addr, parent->path,
|
||||||
event->mask, "Obj parent dir ignored");
|
"Obj parent dir ignored");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case QFILE_MONITOR_EVENT_ATTRIBUTES:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "usb-mtp: failed to parse inotify event\n");
|
g_assert_not_reached();
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry) {
|
if (entry) {
|
||||||
QTAILQ_INSERT_HEAD(&s->events, entry, next);
|
QTAILQ_INSERT_HEAD(&s->events, entry, next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int usb_mtp_inotify_init(MTPState *s)
|
static void usb_mtp_file_monitor_cleanup(MTPState *s)
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
|
|
||||||
fd = inotify_init1(IN_NONBLOCK);
|
|
||||||
if (fd == -1) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QTAILQ_INIT(&s->events);
|
|
||||||
s->inotifyfd = fd;
|
|
||||||
|
|
||||||
qemu_set_fd_handler(fd, inotify_watchfn, NULL, s);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void usb_mtp_inotify_cleanup(MTPState *s)
|
|
||||||
{
|
{
|
||||||
MTPMonEntry *e, *p;
|
MTPMonEntry *e, *p;
|
||||||
|
|
||||||
if (!s->inotifyfd) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
qemu_set_fd_handler(s->inotifyfd, NULL, NULL, s);
|
|
||||||
close(s->inotifyfd);
|
|
||||||
|
|
||||||
QTAILQ_FOREACH_SAFE(e, &s->events, next, p) {
|
QTAILQ_FOREACH_SAFE(e, &s->events, next, p) {
|
||||||
QTAILQ_REMOVE(&s->events, e, next);
|
QTAILQ_REMOVE(&s->events, e, next);
|
||||||
g_free(e);
|
g_free(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qemu_file_monitor_free(s->file_monitor);
|
||||||
|
s->file_monitor = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_mtp_add_watch(int inotifyfd, const char *path)
|
|
||||||
{
|
|
||||||
uint32_t mask = IN_CREATE | IN_DELETE | IN_MODIFY;
|
|
||||||
|
|
||||||
return inotify_add_watch(inotifyfd, path, mask);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
|
static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
|
||||||
{
|
{
|
||||||
struct dirent *entry;
|
struct dirent *entry;
|
||||||
DIR *dir;
|
DIR *dir;
|
||||||
int fd;
|
int fd;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
if (o->have_children) {
|
if (o->have_children) {
|
||||||
return;
|
return;
|
||||||
|
@ -679,16 +623,21 @@ static void usb_mtp_object_readdir(MTPState *s, MTPObject *o)
|
||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#ifdef CONFIG_INOTIFY1
|
|
||||||
int watchfd = usb_mtp_add_watch(s->inotifyfd, o->path);
|
if (s->file_monitor) {
|
||||||
if (watchfd == -1) {
|
int id = qemu_file_monitor_add_watch(s->file_monitor, o->path, NULL,
|
||||||
fprintf(stderr, "usb-mtp: failed to add watch for %s\n", o->path);
|
file_monitor_event, s, &err);
|
||||||
|
if (id == -1) {
|
||||||
|
error_report("usb-mtp: failed to add watch for %s: %s", o->path,
|
||||||
|
error_get_pretty(err));
|
||||||
|
error_free(err);
|
||||||
} else {
|
} else {
|
||||||
trace_usb_mtp_inotify_event(s->dev.addr, o->path,
|
trace_usb_mtp_file_monitor_event(s->dev.addr, o->path,
|
||||||
0, "Watch Added");
|
"Watch Added");
|
||||||
o->watchfd = watchfd;
|
o->watchid = id;
|
||||||
}
|
}
|
||||||
#endif
|
}
|
||||||
|
|
||||||
while ((entry = readdir(dir)) != NULL) {
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
usb_mtp_add_child(s, o, entry->d_name);
|
usb_mtp_add_child(s, o, entry->d_name);
|
||||||
}
|
}
|
||||||
|
@ -1196,13 +1145,11 @@ enum {
|
||||||
/* Assumes that children, if any, have been already freed */
|
/* Assumes that children, if any, have been already freed */
|
||||||
static void usb_mtp_object_free_one(MTPState *s, MTPObject *o)
|
static void usb_mtp_object_free_one(MTPState *s, MTPObject *o)
|
||||||
{
|
{
|
||||||
#ifndef CONFIG_INOTIFY1
|
|
||||||
assert(o->nchildren == 0);
|
assert(o->nchildren == 0);
|
||||||
QTAILQ_REMOVE(&s->objects, o, next);
|
QTAILQ_REMOVE(&s->objects, o, next);
|
||||||
g_free(o->name);
|
g_free(o->name);
|
||||||
g_free(o->path);
|
g_free(o->path);
|
||||||
g_free(o);
|
g_free(o);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
|
static int usb_mtp_deletefn(MTPState *s, MTPObject *o, uint32_t trans)
|
||||||
|
@ -1301,6 +1248,7 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
|
||||||
MTPData *data_in = NULL;
|
MTPData *data_in = NULL;
|
||||||
MTPObject *o = NULL;
|
MTPObject *o = NULL;
|
||||||
uint32_t nres = 0, res0 = 0;
|
uint32_t nres = 0, res0 = 0;
|
||||||
|
Error *err = NULL;
|
||||||
|
|
||||||
/* sanity checks */
|
/* sanity checks */
|
||||||
if (c->code >= CMD_CLOSE_SESSION && s->session == 0) {
|
if (c->code >= CMD_CLOSE_SESSION && s->session == 0) {
|
||||||
|
@ -1328,19 +1276,21 @@ static void usb_mtp_command(MTPState *s, MTPControl *c)
|
||||||
trace_usb_mtp_op_open_session(s->dev.addr);
|
trace_usb_mtp_op_open_session(s->dev.addr);
|
||||||
s->session = c->argv[0];
|
s->session = c->argv[0];
|
||||||
usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root);
|
usb_mtp_object_alloc(s, s->next_handle++, NULL, s->root);
|
||||||
#ifdef CONFIG_INOTIFY1
|
|
||||||
if (usb_mtp_inotify_init(s)) {
|
s->file_monitor = qemu_file_monitor_new(&err);
|
||||||
fprintf(stderr, "usb-mtp: file monitoring init failed\n");
|
if (err) {
|
||||||
|
error_report("usb-mtp: file monitoring init failed: %s",
|
||||||
|
error_get_pretty(err));
|
||||||
|
error_free(err);
|
||||||
|
} else {
|
||||||
|
QTAILQ_INIT(&s->events);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
case CMD_CLOSE_SESSION:
|
case CMD_CLOSE_SESSION:
|
||||||
trace_usb_mtp_op_close_session(s->dev.addr);
|
trace_usb_mtp_op_close_session(s->dev.addr);
|
||||||
s->session = 0;
|
s->session = 0;
|
||||||
s->next_handle = 0;
|
s->next_handle = 0;
|
||||||
#ifdef CONFIG_INOTIFY1
|
usb_mtp_file_monitor_cleanup(s);
|
||||||
usb_mtp_inotify_cleanup(s);
|
|
||||||
#endif
|
|
||||||
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
|
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
|
||||||
assert(QTAILQ_EMPTY(&s->objects));
|
assert(QTAILQ_EMPTY(&s->objects));
|
||||||
break;
|
break;
|
||||||
|
@ -1553,9 +1503,7 @@ static void usb_mtp_handle_reset(USBDevice *dev)
|
||||||
|
|
||||||
trace_usb_mtp_reset(s->dev.addr);
|
trace_usb_mtp_reset(s->dev.addr);
|
||||||
|
|
||||||
#ifdef CONFIG_INOTIFY1
|
usb_mtp_file_monitor_cleanup(s);
|
||||||
usb_mtp_inotify_cleanup(s);
|
|
||||||
#endif
|
|
||||||
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
|
usb_mtp_object_free(s, QTAILQ_FIRST(&s->objects));
|
||||||
s->session = 0;
|
s->session = 0;
|
||||||
usb_mtp_data_free(s->data_in);
|
usb_mtp_data_free(s->data_in);
|
||||||
|
@ -2026,7 +1974,6 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EP_EVENT:
|
case EP_EVENT:
|
||||||
#ifdef CONFIG_INOTIFY1
|
|
||||||
if (!QTAILQ_EMPTY(&s->events)) {
|
if (!QTAILQ_EMPTY(&s->events)) {
|
||||||
struct MTPMonEntry *e = QTAILQ_LAST(&s->events);
|
struct MTPMonEntry *e = QTAILQ_LAST(&s->events);
|
||||||
uint32_t handle;
|
uint32_t handle;
|
||||||
|
@ -2050,7 +1997,6 @@ static void usb_mtp_handle_data(USBDevice *dev, USBPacket *p)
|
||||||
g_free(e);
|
g_free(e);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
p->status = USB_RET_NAK;
|
p->status = USB_RET_NAK;
|
||||||
return;
|
return;
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -237,7 +237,7 @@ usb_mtp_op_unknown(int dev, uint32_t code) "dev %d, command code 0x%x"
|
||||||
usb_mtp_object_alloc(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
|
usb_mtp_object_alloc(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
|
||||||
usb_mtp_object_free(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
|
usb_mtp_object_free(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
|
||||||
usb_mtp_add_child(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
|
usb_mtp_add_child(int dev, uint32_t handle, const char *path) "dev %d, handle 0x%x, path %s"
|
||||||
usb_mtp_inotify_event(int dev, const char *path, uint32_t mask, const char *s) "dev %d, path %s mask 0x%x event %s"
|
usb_mtp_file_monitor_event(int dev, const char *path, const char *s) "dev %d, path %s event %s"
|
||||||
|
|
||||||
# hw/usb/host-libusb.c
|
# hw/usb/host-libusb.c
|
||||||
usb_host_open_started(int bus, int addr) "dev %d:%d"
|
usb_host_open_started(int bus, int addr) "dev %d:%d"
|
||||||
|
|
Loading…
Reference in a new issue