// SPDX-License-Identifier: GPL-2.0+ /* * Copyright (C) 2015 Karol Kosik * Copyright (C) 2015-2016 Samsung Electronics * Igor Kotrasinski * Krzysztof Opasiak */ #ifndef __USBIP_VUDC_H #define __USBIP_VUDC_H #include #include #include #include #include #include #include #include #include "usbip_common.h" #define GADGET_NAME "usbip-vudc" struct vep { struct usb_ep ep; unsigned type:2; /* type, as USB_ENDPOINT_XFER_* */ char name[8]; /* space for ep name */ const struct usb_endpoint_descriptor *desc; struct usb_gadget *gadget; struct list_head req_queue; /* Request queue */ unsigned halted:1; unsigned wedged:1; unsigned already_seen:1; unsigned setup_stage:1; }; struct vrequest { struct usb_request req; struct vudc *udc; struct list_head req_entry; /* Request queue */ }; struct urbp { struct urb *urb; struct vep *ep; struct list_head urb_entry; /* urb queue */ unsigned long seqnum; unsigned type:2; /* for tx, since ep type can change after */ unsigned new:1; }; struct v_unlink { unsigned long seqnum; __u32 status; }; enum tx_type { TX_UNLINK, TX_SUBMIT, }; struct tx_item { struct list_head tx_entry; enum tx_type type; union { struct urbp *s; struct v_unlink *u; }; }; enum tr_state { VUDC_TR_RUNNING, VUDC_TR_IDLE, VUDC_TR_STOPPED, }; struct transfer_timer { struct timer_list timer; enum tr_state state; unsigned long frame_start; int frame_limit; }; struct vudc { struct usb_gadget gadget; struct usb_gadget_driver *driver; struct platform_device *pdev; struct usb_device_descriptor dev_desc; struct usbip_device ud; struct transfer_timer tr_timer; struct timespec64 start_time; struct list_head urb_queue; spinlock_t lock_tx; struct list_head tx_queue; wait_queue_head_t tx_waitq; spinlock_t lock; struct vep *ep; int address; u16 devstatus; unsigned pullup:1; unsigned connected:1; unsigned desc_cached:1; }; struct vudc_device { struct platform_device *pdev; struct list_head dev_entry; }; extern const struct attribute_group vudc_attr_group; /* visible everywhere */ static inline struct vep *to_vep(struct usb_ep *_ep) { return container_of(_ep, struct vep, ep); } static inline struct vrequest *to_vrequest( struct usb_request *_req) { return container_of(_req, struct vrequest, req); } static inline struct vudc *usb_gadget_to_vudc( struct usb_gadget *_gadget) { return container_of(_gadget, struct vudc, gadget); } static inline struct vudc *ep_to_vudc(struct vep *ep) { return container_of(ep->gadget, struct vudc, gadget); } /* vudc_sysfs.c */ int get_gadget_descs(struct vudc *udc); /* vudc_tx.c */ int v_tx_loop(void *data); void v_enqueue_ret_unlink(struct vudc *udc, __u32 seqnum, __u32 status); void v_enqueue_ret_submit(struct vudc *udc, struct urbp *urb_p); /* vudc_rx.c */ int v_rx_loop(void *data); /* vudc_transfer.c */ void v_init_timer(struct vudc *udc); void v_start_timer(struct vudc *udc); void v_kick_timer(struct vudc *udc, unsigned long time); void v_stop_timer(struct vudc *udc); /* vudc_dev.c */ struct urbp *alloc_urbp(void); void free_urbp_and_urb(struct urbp *urb_p); struct vep *vudc_find_endpoint(struct vudc *udc, u8 address); struct vudc_device *alloc_vudc_device(int devid); void put_vudc_device(struct vudc_device *udc_dev); int vudc_probe(struct platform_device *pdev); int vudc_remove(struct platform_device *pdev); #endif /* __USBIP_VUDC_H */