On 12/26/2016 08:08 AM, Nobuo Iwata wrote: > Refactoring to the daemon to reuse common portion for new application > side daemon. It's divided into two portions. > > usbipd.c : common code for both device and application side daemon. > usbipd_dev.c : device-side specific code extracted from usbipd.c. > > To do so, host driver dependent headers and declaration (i.e. static > struct usbip_host_driver *driver;) are moved from usbipd.c to > usbipd_dev.c. > > usbipd_driver_ops is introduced to call device-side specific driver > operations from usbipd.c. It will also be used for application-side > specific driver operation in succeeding patch. > usbipd_driver_<somethig>()s are wrappers for the operations. > > usbipd_recv_pdu_op is introduced to share recv_pdu() routine. > > In diagram below, usbipd EXISTING-1 is the device-side daemon and NEW-1 > is the application side daemon. > > EXISTING) - invites devices from application(vhci)-side > +------+ +------------------+ > device--+ STUB | | application/VHCI | > +------+ +------------------+ > (server) (client) > 1) # usbipd ... start daemon > = = = > 2) # usbip list --local > 3) # usbip bind > <--- list bound devices --- 4) # usbip list --remote > <--- import a device ------ 5) # usbip attach > = = = > X disconnected 6) # usbip detach > 7) usbip unbind > > NEW) - dedicates devices from device(stub)-side > +------+ +------------------+ > device--+ STUB | | application/VHCI | > +------+ +------------------+ > (client) (server) > 1) # usbipa ... start daemon > = = = > 2) # usbip list --local > 3) # usbip connect --- export a device ------> > = = = > 4) # usbip disconnect --- un-export a device ---> > > Bind and unbind are done in connect and disconnect internally. > (...) > +extern struct usbipd_recv_pdu_op usbipd_recv_pdu_ops[]; > + > +struct usbipd_driver_ops { > + void (*init)(void); > + int (*set)(int type); > + int (*open)(void); > + void (*close)(void); > + int (*refresh_device_list)(void); > +}; > + > +extern struct usbipd_driver_ops usbipd_driver_ops; > + > +static inline void usbipd_driver_init(void) > +{ > + if (usbipd_driver_ops.init) > + (*(usbipd_driver_ops.init))(); > +} This function can be dropped if you add one more define below: > + > +#define USBIPD_DRIVER_TYPE_HOST 0 > +#define USBIPD_DRIVER_TYPE_DEVICE 1 #define USBIPD_DRIVER_TYPE_DEFAULT USBIPD_DRIVER_TYPE_HOST Then instead of calling usbipd_driver_init() You may simply call: usbipd_driver_set(USBIPD_DRIVER_TYPE_DEFAULT) > + > +static inline void usbipd_driver_set(int type) > +{ > + if (usbipd_driver_ops.set) > + (*(usbipd_driver_ops.set))(type); > +} > + > +static inline int usbipd_driver_open(void) > +{ > + if (usbipd_driver_ops.open) > + return (*(usbipd_driver_ops.open))(); > + return 0; > +} > + > +static inline void usbipd_driver_close(void) > +{ > + if (usbipd_driver_ops.close) > + (*(usbipd_driver_ops.close))(); > +} > + > +static inline int usbipd_refresh_device_list(void) > +{ > + if (usbipd_driver_ops.refresh_device_list) > + return (*(usbipd_driver_ops.refresh_device_list))(); > + return 0; > +} > + > +#endif /* __USBIPD_H */ > diff --git a/tools/usb/usbip/src/usbipd_dev.c b/tools/usb/usbip/src/usbipd_dev.c > new file mode 100644 > index 0000000..0d59edd > --- /dev/null > +++ b/tools/usb/usbip/src/usbipd_dev.c > @@ -0,0 +1,230 @@ > +/* > + * Copyright (C) 2011 matt mooney <mfm@xxxxxxxxxxxxx> > + * 2005-2007 Takahiro Hirofuchi > + * Copyright (C) 2015-2016 Nobuo Iwata <nobuo.iwata@xxxxxxxxxxxxxxx> > + * > + * This program is free software: you can redistribute it and/or modify > + * it under the terms of the GNU General Public License as published by > + * the Free Software Foundation, either version 2 of the License, or > + * (at your option) any later version. > + * > + * This program 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 General Public License for more details. > + * > + * You should have received a copy of the GNU General Public License > + * along with this program. If not, see <http://www.gnu.org/licenses/>. > + */ > + > +#ifdef HAVE_CONFIG_H > +#include "../config.h" > +#endif > + > +#define _GNU_SOURCE > +#include <errno.h> > +#include <unistd.h> > +#include <netdb.h> > +#include <string.h> > +#include <stdlib.h> > +#include <sys/types.h> > +#include <sys/stat.h> > +#include <arpa/inet.h> > +#include <sys/socket.h> > +#include <netinet/in.h> > + > +#include "usbip_host_driver.h" > +#include "usbip_host_common.h" > +#include "usbip_device_driver.h" > +#include "usbip_common.h" > +#include "usbip_network.h" > +#include "usbipd.h" > +#include "list.h" > + > +char *usbip_progname = "usbipd"; > +char *usbip_default_pid_file = "/var/run/usbipd"; > + > +static struct usbip_host_driver *driver; > + > +static void driver_init(void) > +{ > + driver = &host_driver; > +} > + > +static int driver_set(int type) > +{ > + switch (type) { > + case USBIPD_DRIVER_TYPE_HOST: > + driver = &host_driver; > + break; > + case USBIPD_DRIVER_TYPE_DEVICE: > + driver = &device_driver; > + break; > + default: > + err("unknown driver type to set %d", type); > + return -1; > + } > + return 0; > +} > + > +static int driver_open(void) > +{ > + return usbip_driver_open(driver); > +} > + > +static void driver_close(void) > +{ > + usbip_driver_close(driver); > +} > + > +static int refresh_device_list(void) > +{ > + return usbip_refresh_device_list(driver); > +} > + > +struct usbipd_driver_ops usbipd_driver_ops = { > + .init = driver_init, > + .set = driver_set, > + .open = driver_open, > + .close = driver_close, > + .refresh_device_list = refresh_device_list, > +}; > + > +static int recv_request_import(int sockfd) > +{ > + struct op_import_request req; > + struct usbip_exported_device *edev; > + struct usbip_usb_device pdu_udev; > + struct list_head *i; > + int found = 0; > + int error = 0; > + int rc; > + > + memset(&req, 0, sizeof(req)); > + > + rc = usbip_net_recv(sockfd, &req, sizeof(req)); > + if (rc < 0) { > + dbg("usbip_net_recv failed: import request"); > + return -1; > + } > + PACK_OP_IMPORT_REQUEST(0, &req); > + > + list_for_each(i, &driver->edev_list) { Using i as a list node name souds a little bit weird at least for me... I know that it's not your fault because it was like that but please rename it to node or sth like this. > + edev = list_entry(i, struct usbip_exported_device, node); > + if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { > + info("found requested device: %s", req.busid); > + found = 1; > + break; > + } > + } > + > + if (found) { > + /* export device needs a TCP/IP socket descriptor */ > + rc = usbip_export_device(edev, sockfd); > + if (rc < 0) > + error = 1; > + } else { > + info("requested device not found: %s", req.busid); > + error = 1; > + } > + > + rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, > + (!error ? ST_OK : ST_NA)); > + if (rc < 0) { > + dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT); > + return -1; > + } > + > + if (error) { > + dbg("import request busid %s: failed", req.busid); > + return -1; > + } > + > + memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); > + usbip_net_pack_usb_device(1, &pdu_udev); > + > + rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev)); > + if (rc < 0) { > + dbg("usbip_net_send failed: devinfo"); > + return -1; > + } > + > + dbg("import request busid %s: complete", req.busid); > + > + return 0; > +} > + > +static int send_reply_devlist(int connfd) > +{ > + struct usbip_exported_device *edev; > + struct usbip_usb_device pdu_udev; > + struct usbip_usb_interface pdu_uinf; > + struct op_devlist_reply reply; > + struct list_head *j; > + int rc, i; > + > + reply.ndev = driver->ndevs; > + info("importable devices: %d", reply.ndev); > + > + rc = usbip_net_send_op_common(connfd, OP_REP_DEVLIST, ST_OK); > + if (rc < 0) { > + dbg("usbip_net_send_op_common failed: %#0x", OP_REP_DEVLIST); > + return -1; > + } > + PACK_OP_DEVLIST_REPLY(1, &reply); > + > + rc = usbip_net_send(connfd, &reply, sizeof(reply)); > + if (rc < 0) { > + dbg("usbip_net_send failed: %#0x", OP_REP_DEVLIST); > + return -1; > + } > + > + list_for_each(j, &driver->edev_list) { > + edev = list_entry(j, struct usbip_exported_device, node); The same as above s/j/node... > + dump_usb_device(&edev->udev); > + memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); > + usbip_net_pack_usb_device(1, &pdu_udev); > + > + rc = usbip_net_send(connfd, &pdu_udev, sizeof(pdu_udev)); > + if (rc < 0) { > + dbg("usbip_net_send failed: pdu_udev"); > + return -1; > + } > + > + for (i = 0; i < edev->udev.bNumInterfaces; i++) { > + dump_usb_interface(&edev->uinf[i]); > + memcpy(&pdu_uinf, &edev->uinf[i], sizeof(pdu_uinf)); > + usbip_net_pack_usb_interface(1, &pdu_uinf); > + > + rc = usbip_net_send(connfd, &pdu_uinf, > + sizeof(pdu_uinf)); > + if (rc < 0) { > + err("usbip_net_send failed: pdu_uinf"); > + return -1; > + } > + } > + } > + > + return 0; > +} > + > +static int recv_request_devlist(int connfd) > +{ > + int rc; > + > + rc = send_reply_devlist(connfd); > + if (rc < 0) { > + dbg("send_reply_devlist failed"); > + return -1; > + } > + > + return 0; > +} > + > +struct usbipd_recv_pdu_op usbipd_recv_pdu_ops[] = { > + {OP_REQ_DEVLIST, recv_request_devlist}, > + {OP_REQ_IMPORT, recv_request_import}, > + {OP_REQ_DEVINFO, NULL}, > + {OP_REQ_CRYPKEY, NULL}, > + {OP_UNSPEC, NULL} > +}; > -- Krzysztof Opasiak Samsung R&D Institute Poland Samsung Electronics -- To unsubscribe from this list: send the line "unsubscribe linux-usb" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html