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 * This program is free software; you can redistribute it and/or modify 9602364fdSIgor Kotrasinski * it under the terms of the GNU General Public License as published by 10602364fdSIgor Kotrasinski * the Free Software Foundation; either version 2 of the License, or 11602364fdSIgor Kotrasinski * (at your option) any later version. 12602364fdSIgor Kotrasinski * 13602364fdSIgor Kotrasinski * This program is distributed in the hope that it will be useful, 14602364fdSIgor Kotrasinski * but WITHOUT ANY WARRANTY; without even the implied warranty of 15602364fdSIgor Kotrasinski * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16602364fdSIgor Kotrasinski * GNU General Public License for more details. 17602364fdSIgor Kotrasinski * 18602364fdSIgor Kotrasinski * You should have received a copy of the GNU General Public License 19602364fdSIgor Kotrasinski * along with this program. If not, see <http://www.gnu.org/licenses/>. 20602364fdSIgor Kotrasinski */ 21602364fdSIgor Kotrasinski 22602364fdSIgor Kotrasinski #ifndef __USBIP_VUDC_H 23602364fdSIgor Kotrasinski #define __USBIP_VUDC_H 24602364fdSIgor Kotrasinski 25602364fdSIgor Kotrasinski #include <linux/platform_device.h> 26602364fdSIgor Kotrasinski #include <linux/usb.h> 27602364fdSIgor Kotrasinski #include <linux/usb/gadget.h> 28602364fdSIgor Kotrasinski #include <linux/usb/ch9.h> 29602364fdSIgor Kotrasinski #include <linux/list.h> 30602364fdSIgor Kotrasinski #include <linux/timer.h> 31602364fdSIgor Kotrasinski #include <linux/time.h> 32602364fdSIgor Kotrasinski #include <linux/sysfs.h> 33602364fdSIgor Kotrasinski 34602364fdSIgor Kotrasinski #include "usbip_common.h" 35602364fdSIgor Kotrasinski 36602364fdSIgor Kotrasinski #define GADGET_NAME "usbip-vudc" 37602364fdSIgor Kotrasinski 38602364fdSIgor Kotrasinski struct vep { 39602364fdSIgor Kotrasinski struct usb_ep ep; 40602364fdSIgor Kotrasinski unsigned type:2; /* type, as USB_ENDPOINT_XFER_* */ 41602364fdSIgor Kotrasinski char name[8]; /* space for ep name */ 42602364fdSIgor Kotrasinski 43602364fdSIgor Kotrasinski const struct usb_endpoint_descriptor *desc; 44602364fdSIgor Kotrasinski struct usb_gadget *gadget; 45602364fdSIgor Kotrasinski struct list_head req_queue; /* Request queue */ 46602364fdSIgor Kotrasinski unsigned halted:1; 47602364fdSIgor Kotrasinski unsigned wedged:1; 48602364fdSIgor Kotrasinski unsigned already_seen:1; 49602364fdSIgor Kotrasinski unsigned setup_stage:1; 50602364fdSIgor Kotrasinski }; 51602364fdSIgor Kotrasinski 52602364fdSIgor Kotrasinski struct vrequest { 53602364fdSIgor Kotrasinski struct usb_request req; 54602364fdSIgor Kotrasinski struct vudc *udc; 55602364fdSIgor Kotrasinski struct list_head req_entry; /* Request queue */ 56602364fdSIgor Kotrasinski }; 57602364fdSIgor Kotrasinski 58602364fdSIgor Kotrasinski struct urbp { 59602364fdSIgor Kotrasinski struct urb *urb; 60602364fdSIgor Kotrasinski struct vep *ep; 61602364fdSIgor Kotrasinski struct list_head urb_entry; /* urb queue */ 62602364fdSIgor Kotrasinski unsigned long seqnum; 63602364fdSIgor Kotrasinski unsigned type:2; /* for tx, since ep type can change after */ 64602364fdSIgor Kotrasinski unsigned new:1; 65602364fdSIgor Kotrasinski }; 66602364fdSIgor Kotrasinski 67602364fdSIgor Kotrasinski struct v_unlink { 68602364fdSIgor Kotrasinski unsigned long seqnum; 69602364fdSIgor Kotrasinski __u32 status; 70602364fdSIgor Kotrasinski }; 71602364fdSIgor Kotrasinski 72602364fdSIgor Kotrasinski enum tx_type { 73602364fdSIgor Kotrasinski TX_UNLINK, 74602364fdSIgor Kotrasinski TX_SUBMIT, 75602364fdSIgor Kotrasinski }; 76602364fdSIgor Kotrasinski 77602364fdSIgor Kotrasinski struct tx_item { 78602364fdSIgor Kotrasinski struct list_head tx_entry; 79602364fdSIgor Kotrasinski enum tx_type type; 80602364fdSIgor Kotrasinski union { 81602364fdSIgor Kotrasinski struct urbp *s; 82602364fdSIgor Kotrasinski struct v_unlink *u; 83602364fdSIgor Kotrasinski }; 84602364fdSIgor Kotrasinski }; 85602364fdSIgor Kotrasinski 86602364fdSIgor Kotrasinski enum tr_state { 87602364fdSIgor Kotrasinski VUDC_TR_RUNNING, 88602364fdSIgor Kotrasinski VUDC_TR_IDLE, 89602364fdSIgor Kotrasinski VUDC_TR_STOPPED, 90602364fdSIgor Kotrasinski }; 91602364fdSIgor Kotrasinski 92602364fdSIgor Kotrasinski struct transfer_timer { 93602364fdSIgor Kotrasinski struct timer_list timer; 94602364fdSIgor Kotrasinski enum tr_state state; 95602364fdSIgor Kotrasinski unsigned long frame_start; 96602364fdSIgor Kotrasinski int frame_limit; 97602364fdSIgor Kotrasinski }; 98602364fdSIgor Kotrasinski 99602364fdSIgor Kotrasinski struct vudc { 100602364fdSIgor Kotrasinski struct usb_gadget gadget; 101602364fdSIgor Kotrasinski struct usb_gadget_driver *driver; 102602364fdSIgor Kotrasinski struct platform_device *pdev; 103602364fdSIgor Kotrasinski 104602364fdSIgor Kotrasinski struct usb_device_descriptor dev_desc; 105602364fdSIgor Kotrasinski 106602364fdSIgor Kotrasinski struct usbip_device ud; 107602364fdSIgor Kotrasinski struct transfer_timer tr_timer; 108*6c51441cSArnd Bergmann struct timespec64 start_time; 109602364fdSIgor Kotrasinski 110602364fdSIgor Kotrasinski struct list_head urb_queue; 111602364fdSIgor Kotrasinski 112602364fdSIgor Kotrasinski spinlock_t lock_tx; 113602364fdSIgor Kotrasinski struct list_head tx_queue; 114602364fdSIgor Kotrasinski wait_queue_head_t tx_waitq; 115602364fdSIgor Kotrasinski 116602364fdSIgor Kotrasinski spinlock_t lock; 117602364fdSIgor Kotrasinski struct vep *ep; 118602364fdSIgor Kotrasinski int address; 119602364fdSIgor Kotrasinski u16 devstatus; 120602364fdSIgor Kotrasinski 121602364fdSIgor Kotrasinski unsigned pullup:1; 122602364fdSIgor Kotrasinski unsigned connected:1; 123602364fdSIgor Kotrasinski unsigned desc_cached:1; 124602364fdSIgor Kotrasinski }; 125602364fdSIgor Kotrasinski 126602364fdSIgor Kotrasinski struct vudc_device { 127602364fdSIgor Kotrasinski struct platform_device *pdev; 128602364fdSIgor Kotrasinski struct list_head dev_entry; 129602364fdSIgor Kotrasinski }; 130602364fdSIgor Kotrasinski 131602364fdSIgor Kotrasinski extern const struct attribute_group vudc_attr_group; 132602364fdSIgor Kotrasinski 133602364fdSIgor Kotrasinski /* visible everywhere */ 134602364fdSIgor Kotrasinski 135602364fdSIgor Kotrasinski static inline struct vep *to_vep(struct usb_ep *_ep) 136602364fdSIgor Kotrasinski { 137602364fdSIgor Kotrasinski return container_of(_ep, struct vep, ep); 138602364fdSIgor Kotrasinski } 139602364fdSIgor Kotrasinski 140602364fdSIgor Kotrasinski static inline struct vrequest *to_vrequest( 141602364fdSIgor Kotrasinski struct usb_request *_req) 142602364fdSIgor Kotrasinski { 143602364fdSIgor Kotrasinski return container_of(_req, struct vrequest, req); 144602364fdSIgor Kotrasinski } 145602364fdSIgor Kotrasinski 146602364fdSIgor Kotrasinski static inline struct vudc *usb_gadget_to_vudc( 147602364fdSIgor Kotrasinski struct usb_gadget *_gadget) 148602364fdSIgor Kotrasinski { 149602364fdSIgor Kotrasinski return container_of(_gadget, struct vudc, gadget); 150602364fdSIgor Kotrasinski } 151602364fdSIgor Kotrasinski 152602364fdSIgor Kotrasinski static inline struct vudc *ep_to_vudc(struct vep *ep) 153602364fdSIgor Kotrasinski { 154602364fdSIgor Kotrasinski return container_of(ep->gadget, struct vudc, gadget); 155602364fdSIgor Kotrasinski } 156602364fdSIgor Kotrasinski 157602364fdSIgor Kotrasinski /* vudc_sysfs.c */ 158602364fdSIgor Kotrasinski 159602364fdSIgor Kotrasinski int get_gadget_descs(struct vudc *udc); 160602364fdSIgor Kotrasinski 161602364fdSIgor Kotrasinski /* vudc_tx.c */ 162602364fdSIgor Kotrasinski 163602364fdSIgor Kotrasinski int v_tx_loop(void *data); 164602364fdSIgor Kotrasinski void v_enqueue_ret_unlink(struct vudc *udc, __u32 seqnum, __u32 status); 165602364fdSIgor Kotrasinski void v_enqueue_ret_submit(struct vudc *udc, struct urbp *urb_p); 166602364fdSIgor Kotrasinski 167602364fdSIgor Kotrasinski /* vudc_rx.c */ 168602364fdSIgor Kotrasinski 169602364fdSIgor Kotrasinski int v_rx_loop(void *data); 170602364fdSIgor Kotrasinski 171602364fdSIgor Kotrasinski /* vudc_transfer.c */ 172602364fdSIgor Kotrasinski 173602364fdSIgor Kotrasinski void v_init_timer(struct vudc *udc); 174602364fdSIgor Kotrasinski void v_start_timer(struct vudc *udc); 175602364fdSIgor Kotrasinski void v_kick_timer(struct vudc *udc, unsigned long time); 176602364fdSIgor Kotrasinski void v_stop_timer(struct vudc *udc); 177602364fdSIgor Kotrasinski 178602364fdSIgor Kotrasinski /* vudc_dev.c */ 179602364fdSIgor Kotrasinski 180602364fdSIgor Kotrasinski struct urbp *alloc_urbp(void); 181602364fdSIgor Kotrasinski void free_urbp_and_urb(struct urbp *urb_p); 182602364fdSIgor Kotrasinski 1830255cf9eSKrzysztof Opasiak struct vep *vudc_find_endpoint(struct vudc *udc, u8 address); 184602364fdSIgor Kotrasinski 185602364fdSIgor Kotrasinski struct vudc_device *alloc_vudc_device(int devid); 186602364fdSIgor Kotrasinski void put_vudc_device(struct vudc_device *udc_dev); 187602364fdSIgor Kotrasinski 188602364fdSIgor Kotrasinski int vudc_probe(struct platform_device *pdev); 189602364fdSIgor Kotrasinski int vudc_remove(struct platform_device *pdev); 190602364fdSIgor Kotrasinski 191602364fdSIgor Kotrasinski #endif /* __USBIP_VUDC_H */ 192