15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+ 2602364fdSIgor Kotrasinski /* 3602364fdSIgor Kotrasinski * Copyright (C) 2015 Karol Kosik <karo9@interia.eu> 4602364fdSIgor Kotrasinski * Copyright (C) 2015-2016 Samsung Electronics 5602364fdSIgor Kotrasinski * Igor Kotrasinski <i.kotrasinsk@samsung.com> 6602364fdSIgor Kotrasinski * Krzysztof Opasiak <k.opasiak@samsung.com> 7602364fdSIgor Kotrasinski */ 8602364fdSIgor Kotrasinski 9602364fdSIgor Kotrasinski #ifndef __USBIP_VUDC_H 10602364fdSIgor Kotrasinski #define __USBIP_VUDC_H 11602364fdSIgor Kotrasinski 12602364fdSIgor Kotrasinski #include <linux/platform_device.h> 13602364fdSIgor Kotrasinski #include <linux/usb.h> 14602364fdSIgor Kotrasinski #include <linux/usb/gadget.h> 15602364fdSIgor Kotrasinski #include <linux/usb/ch9.h> 16602364fdSIgor Kotrasinski #include <linux/list.h> 17602364fdSIgor Kotrasinski #include <linux/timer.h> 18602364fdSIgor Kotrasinski #include <linux/time.h> 19602364fdSIgor Kotrasinski #include <linux/sysfs.h> 20602364fdSIgor Kotrasinski 21602364fdSIgor Kotrasinski #include "usbip_common.h" 22602364fdSIgor Kotrasinski 23602364fdSIgor Kotrasinski #define GADGET_NAME "usbip-vudc" 24602364fdSIgor Kotrasinski 25602364fdSIgor Kotrasinski struct vep { 26602364fdSIgor Kotrasinski struct usb_ep ep; 27602364fdSIgor Kotrasinski unsigned type:2; /* type, as USB_ENDPOINT_XFER_* */ 28602364fdSIgor Kotrasinski char name[8]; /* space for ep name */ 29602364fdSIgor Kotrasinski 30602364fdSIgor Kotrasinski const struct usb_endpoint_descriptor *desc; 31602364fdSIgor Kotrasinski struct usb_gadget *gadget; 32602364fdSIgor Kotrasinski struct list_head req_queue; /* Request queue */ 33602364fdSIgor Kotrasinski unsigned halted:1; 34602364fdSIgor Kotrasinski unsigned wedged:1; 35602364fdSIgor Kotrasinski unsigned already_seen:1; 36602364fdSIgor Kotrasinski unsigned setup_stage:1; 37602364fdSIgor Kotrasinski }; 38602364fdSIgor Kotrasinski 39602364fdSIgor Kotrasinski struct vrequest { 40602364fdSIgor Kotrasinski struct usb_request req; 41602364fdSIgor Kotrasinski struct vudc *udc; 42602364fdSIgor Kotrasinski struct list_head req_entry; /* Request queue */ 43602364fdSIgor Kotrasinski }; 44602364fdSIgor Kotrasinski 45602364fdSIgor Kotrasinski struct urbp { 46602364fdSIgor Kotrasinski struct urb *urb; 47602364fdSIgor Kotrasinski struct vep *ep; 48602364fdSIgor Kotrasinski struct list_head urb_entry; /* urb queue */ 49602364fdSIgor Kotrasinski unsigned long seqnum; 50602364fdSIgor Kotrasinski unsigned type:2; /* for tx, since ep type can change after */ 51602364fdSIgor Kotrasinski unsigned new:1; 52602364fdSIgor Kotrasinski }; 53602364fdSIgor Kotrasinski 54602364fdSIgor Kotrasinski struct v_unlink { 55602364fdSIgor Kotrasinski unsigned long seqnum; 56602364fdSIgor Kotrasinski __u32 status; 57602364fdSIgor Kotrasinski }; 58602364fdSIgor Kotrasinski 59602364fdSIgor Kotrasinski enum tx_type { 60602364fdSIgor Kotrasinski TX_UNLINK, 61602364fdSIgor Kotrasinski TX_SUBMIT, 62602364fdSIgor Kotrasinski }; 63602364fdSIgor Kotrasinski 64602364fdSIgor Kotrasinski struct tx_item { 65602364fdSIgor Kotrasinski struct list_head tx_entry; 66602364fdSIgor Kotrasinski enum tx_type type; 67602364fdSIgor Kotrasinski union { 68602364fdSIgor Kotrasinski struct urbp *s; 69602364fdSIgor Kotrasinski struct v_unlink *u; 70602364fdSIgor Kotrasinski }; 71602364fdSIgor Kotrasinski }; 72602364fdSIgor Kotrasinski 73602364fdSIgor Kotrasinski enum tr_state { 74602364fdSIgor Kotrasinski VUDC_TR_RUNNING, 75602364fdSIgor Kotrasinski VUDC_TR_IDLE, 76602364fdSIgor Kotrasinski VUDC_TR_STOPPED, 77602364fdSIgor Kotrasinski }; 78602364fdSIgor Kotrasinski 79602364fdSIgor Kotrasinski struct transfer_timer { 80602364fdSIgor Kotrasinski struct timer_list timer; 81602364fdSIgor Kotrasinski enum tr_state state; 82602364fdSIgor Kotrasinski unsigned long frame_start; 83602364fdSIgor Kotrasinski int frame_limit; 84602364fdSIgor Kotrasinski }; 85602364fdSIgor Kotrasinski 86602364fdSIgor Kotrasinski struct vudc { 87602364fdSIgor Kotrasinski struct usb_gadget gadget; 88602364fdSIgor Kotrasinski struct usb_gadget_driver *driver; 89602364fdSIgor Kotrasinski struct platform_device *pdev; 90602364fdSIgor Kotrasinski 91602364fdSIgor Kotrasinski struct usb_device_descriptor dev_desc; 92602364fdSIgor Kotrasinski 93602364fdSIgor Kotrasinski struct usbip_device ud; 94602364fdSIgor Kotrasinski struct transfer_timer tr_timer; 956c51441cSArnd Bergmann struct timespec64 start_time; 96602364fdSIgor Kotrasinski 97602364fdSIgor Kotrasinski struct list_head urb_queue; 98602364fdSIgor Kotrasinski 99602364fdSIgor Kotrasinski spinlock_t lock_tx; 100602364fdSIgor Kotrasinski struct list_head tx_queue; 101602364fdSIgor Kotrasinski wait_queue_head_t tx_waitq; 102602364fdSIgor Kotrasinski 103602364fdSIgor Kotrasinski spinlock_t lock; 104602364fdSIgor Kotrasinski struct vep *ep; 105602364fdSIgor Kotrasinski int address; 106602364fdSIgor Kotrasinski u16 devstatus; 107602364fdSIgor Kotrasinski 108602364fdSIgor Kotrasinski unsigned pullup:1; 109602364fdSIgor Kotrasinski unsigned connected:1; 110602364fdSIgor Kotrasinski unsigned desc_cached:1; 111602364fdSIgor Kotrasinski }; 112602364fdSIgor Kotrasinski 113602364fdSIgor Kotrasinski struct vudc_device { 114602364fdSIgor Kotrasinski struct platform_device *pdev; 115602364fdSIgor Kotrasinski struct list_head dev_entry; 116602364fdSIgor Kotrasinski }; 117602364fdSIgor Kotrasinski 11891148dbaSGreg Kroah-Hartman extern const struct attribute_group *vudc_groups[]; 119602364fdSIgor Kotrasinski 120602364fdSIgor Kotrasinski /* visible everywhere */ 121602364fdSIgor Kotrasinski 122602364fdSIgor Kotrasinski static inline struct vep *to_vep(struct usb_ep *_ep) 123602364fdSIgor Kotrasinski { 124602364fdSIgor Kotrasinski return container_of(_ep, struct vep, ep); 125602364fdSIgor Kotrasinski } 126602364fdSIgor Kotrasinski 127602364fdSIgor Kotrasinski static inline struct vrequest *to_vrequest( 128602364fdSIgor Kotrasinski struct usb_request *_req) 129602364fdSIgor Kotrasinski { 130602364fdSIgor Kotrasinski return container_of(_req, struct vrequest, req); 131602364fdSIgor Kotrasinski } 132602364fdSIgor Kotrasinski 133602364fdSIgor Kotrasinski static inline struct vudc *usb_gadget_to_vudc( 134602364fdSIgor Kotrasinski struct usb_gadget *_gadget) 135602364fdSIgor Kotrasinski { 136602364fdSIgor Kotrasinski return container_of(_gadget, struct vudc, gadget); 137602364fdSIgor Kotrasinski } 138602364fdSIgor Kotrasinski 139602364fdSIgor Kotrasinski static inline struct vudc *ep_to_vudc(struct vep *ep) 140602364fdSIgor Kotrasinski { 141602364fdSIgor Kotrasinski return container_of(ep->gadget, struct vudc, gadget); 142602364fdSIgor Kotrasinski } 143602364fdSIgor Kotrasinski 144602364fdSIgor Kotrasinski /* vudc_sysfs.c */ 145602364fdSIgor Kotrasinski 146602364fdSIgor Kotrasinski int get_gadget_descs(struct vudc *udc); 147602364fdSIgor Kotrasinski 148602364fdSIgor Kotrasinski /* vudc_tx.c */ 149602364fdSIgor Kotrasinski 150602364fdSIgor Kotrasinski int v_tx_loop(void *data); 151602364fdSIgor Kotrasinski void v_enqueue_ret_unlink(struct vudc *udc, __u32 seqnum, __u32 status); 152602364fdSIgor Kotrasinski void v_enqueue_ret_submit(struct vudc *udc, struct urbp *urb_p); 153602364fdSIgor Kotrasinski 154602364fdSIgor Kotrasinski /* vudc_rx.c */ 155602364fdSIgor Kotrasinski 156602364fdSIgor Kotrasinski int v_rx_loop(void *data); 157602364fdSIgor Kotrasinski 158602364fdSIgor Kotrasinski /* vudc_transfer.c */ 159602364fdSIgor Kotrasinski 160602364fdSIgor Kotrasinski void v_init_timer(struct vudc *udc); 161602364fdSIgor Kotrasinski void v_start_timer(struct vudc *udc); 162602364fdSIgor Kotrasinski void v_kick_timer(struct vudc *udc, unsigned long time); 163602364fdSIgor Kotrasinski void v_stop_timer(struct vudc *udc); 164602364fdSIgor Kotrasinski 165602364fdSIgor Kotrasinski /* vudc_dev.c */ 166602364fdSIgor Kotrasinski 167602364fdSIgor Kotrasinski struct urbp *alloc_urbp(void); 168602364fdSIgor Kotrasinski void free_urbp_and_urb(struct urbp *urb_p); 169602364fdSIgor Kotrasinski 1700255cf9eSKrzysztof Opasiak struct vep *vudc_find_endpoint(struct vudc *udc, u8 address); 171602364fdSIgor Kotrasinski 172602364fdSIgor Kotrasinski struct vudc_device *alloc_vudc_device(int devid); 173602364fdSIgor Kotrasinski void put_vudc_device(struct vudc_device *udc_dev); 174602364fdSIgor Kotrasinski 175602364fdSIgor Kotrasinski int vudc_probe(struct platform_device *pdev); 176*b9a24821SUwe Kleine-König void vudc_remove(struct platform_device *pdev); 177602364fdSIgor Kotrasinski 178602364fdSIgor Kotrasinski #endif /* __USBIP_VUDC_H */ 179