18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015 Karol Kosik <karo9@interia.eu> 48c2ecf20Sopenharmony_ci * Copyright (C) 2015-2016 Samsung Electronics 58c2ecf20Sopenharmony_ci * Igor Kotrasinski <i.kotrasinsk@samsung.com> 68c2ecf20Sopenharmony_ci * Krzysztof Opasiak <k.opasiak@samsung.com> 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#ifndef __USBIP_VUDC_H 108c2ecf20Sopenharmony_ci#define __USBIP_VUDC_H 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 138c2ecf20Sopenharmony_ci#include <linux/usb.h> 148c2ecf20Sopenharmony_ci#include <linux/usb/gadget.h> 158c2ecf20Sopenharmony_ci#include <linux/usb/ch9.h> 168c2ecf20Sopenharmony_ci#include <linux/list.h> 178c2ecf20Sopenharmony_ci#include <linux/timer.h> 188c2ecf20Sopenharmony_ci#include <linux/time.h> 198c2ecf20Sopenharmony_ci#include <linux/sysfs.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "usbip_common.h" 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define GADGET_NAME "usbip-vudc" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistruct vep { 268c2ecf20Sopenharmony_ci struct usb_ep ep; 278c2ecf20Sopenharmony_ci unsigned type:2; /* type, as USB_ENDPOINT_XFER_* */ 288c2ecf20Sopenharmony_ci char name[8]; /* space for ep name */ 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci const struct usb_endpoint_descriptor *desc; 318c2ecf20Sopenharmony_ci struct usb_gadget *gadget; 328c2ecf20Sopenharmony_ci struct list_head req_queue; /* Request queue */ 338c2ecf20Sopenharmony_ci unsigned halted:1; 348c2ecf20Sopenharmony_ci unsigned wedged:1; 358c2ecf20Sopenharmony_ci unsigned already_seen:1; 368c2ecf20Sopenharmony_ci unsigned setup_stage:1; 378c2ecf20Sopenharmony_ci}; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistruct vrequest { 408c2ecf20Sopenharmony_ci struct usb_request req; 418c2ecf20Sopenharmony_ci struct vudc *udc; 428c2ecf20Sopenharmony_ci struct list_head req_entry; /* Request queue */ 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct urbp { 468c2ecf20Sopenharmony_ci struct urb *urb; 478c2ecf20Sopenharmony_ci struct vep *ep; 488c2ecf20Sopenharmony_ci struct list_head urb_entry; /* urb queue */ 498c2ecf20Sopenharmony_ci unsigned long seqnum; 508c2ecf20Sopenharmony_ci unsigned type:2; /* for tx, since ep type can change after */ 518c2ecf20Sopenharmony_ci unsigned new:1; 528c2ecf20Sopenharmony_ci}; 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_cistruct v_unlink { 558c2ecf20Sopenharmony_ci unsigned long seqnum; 568c2ecf20Sopenharmony_ci __u32 status; 578c2ecf20Sopenharmony_ci}; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_cienum tx_type { 608c2ecf20Sopenharmony_ci TX_UNLINK, 618c2ecf20Sopenharmony_ci TX_SUBMIT, 628c2ecf20Sopenharmony_ci}; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_cistruct tx_item { 658c2ecf20Sopenharmony_ci struct list_head tx_entry; 668c2ecf20Sopenharmony_ci enum tx_type type; 678c2ecf20Sopenharmony_ci union { 688c2ecf20Sopenharmony_ci struct urbp *s; 698c2ecf20Sopenharmony_ci struct v_unlink *u; 708c2ecf20Sopenharmony_ci }; 718c2ecf20Sopenharmony_ci}; 728c2ecf20Sopenharmony_ci 738c2ecf20Sopenharmony_cienum tr_state { 748c2ecf20Sopenharmony_ci VUDC_TR_RUNNING, 758c2ecf20Sopenharmony_ci VUDC_TR_IDLE, 768c2ecf20Sopenharmony_ci VUDC_TR_STOPPED, 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_cistruct transfer_timer { 808c2ecf20Sopenharmony_ci struct timer_list timer; 818c2ecf20Sopenharmony_ci enum tr_state state; 828c2ecf20Sopenharmony_ci unsigned long frame_start; 838c2ecf20Sopenharmony_ci int frame_limit; 848c2ecf20Sopenharmony_ci}; 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_cistruct vudc { 878c2ecf20Sopenharmony_ci struct usb_gadget gadget; 888c2ecf20Sopenharmony_ci struct usb_gadget_driver *driver; 898c2ecf20Sopenharmony_ci struct platform_device *pdev; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci struct usb_device_descriptor dev_desc; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci struct usbip_device ud; 948c2ecf20Sopenharmony_ci struct transfer_timer tr_timer; 958c2ecf20Sopenharmony_ci struct timespec64 start_time; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci struct list_head urb_queue; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci spinlock_t lock_tx; 1008c2ecf20Sopenharmony_ci struct list_head tx_queue; 1018c2ecf20Sopenharmony_ci wait_queue_head_t tx_waitq; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci spinlock_t lock; 1048c2ecf20Sopenharmony_ci struct vep *ep; 1058c2ecf20Sopenharmony_ci int address; 1068c2ecf20Sopenharmony_ci u16 devstatus; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci unsigned pullup:1; 1098c2ecf20Sopenharmony_ci unsigned connected:1; 1108c2ecf20Sopenharmony_ci unsigned desc_cached:1; 1118c2ecf20Sopenharmony_ci}; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_cistruct vudc_device { 1148c2ecf20Sopenharmony_ci struct platform_device *pdev; 1158c2ecf20Sopenharmony_ci struct list_head dev_entry; 1168c2ecf20Sopenharmony_ci}; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ciextern const struct attribute_group *vudc_groups[]; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* visible everywhere */ 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_cistatic inline struct vep *to_vep(struct usb_ep *_ep) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci return container_of(_ep, struct vep, ep); 1258c2ecf20Sopenharmony_ci} 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic inline struct vrequest *to_vrequest( 1288c2ecf20Sopenharmony_ci struct usb_request *_req) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci return container_of(_req, struct vrequest, req); 1318c2ecf20Sopenharmony_ci} 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_cistatic inline struct vudc *usb_gadget_to_vudc( 1348c2ecf20Sopenharmony_ci struct usb_gadget *_gadget) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci return container_of(_gadget, struct vudc, gadget); 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_cistatic inline struct vudc *ep_to_vudc(struct vep *ep) 1408c2ecf20Sopenharmony_ci{ 1418c2ecf20Sopenharmony_ci return container_of(ep->gadget, struct vudc, gadget); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/* vudc_sysfs.c */ 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ciint get_gadget_descs(struct vudc *udc); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci/* vudc_tx.c */ 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ciint v_tx_loop(void *data); 1518c2ecf20Sopenharmony_civoid v_enqueue_ret_unlink(struct vudc *udc, __u32 seqnum, __u32 status); 1528c2ecf20Sopenharmony_civoid v_enqueue_ret_submit(struct vudc *udc, struct urbp *urb_p); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci/* vudc_rx.c */ 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ciint v_rx_loop(void *data); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci/* vudc_transfer.c */ 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_civoid v_init_timer(struct vudc *udc); 1618c2ecf20Sopenharmony_civoid v_start_timer(struct vudc *udc); 1628c2ecf20Sopenharmony_civoid v_kick_timer(struct vudc *udc, unsigned long time); 1638c2ecf20Sopenharmony_civoid v_stop_timer(struct vudc *udc); 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci/* vudc_dev.c */ 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_cistruct urbp *alloc_urbp(void); 1688c2ecf20Sopenharmony_civoid free_urbp_and_urb(struct urbp *urb_p); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistruct vep *vudc_find_endpoint(struct vudc *udc, u8 address); 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistruct vudc_device *alloc_vudc_device(int devid); 1738c2ecf20Sopenharmony_civoid put_vudc_device(struct vudc_device *udc_dev); 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ciint vudc_probe(struct platform_device *pdev); 1768c2ecf20Sopenharmony_ciint vudc_remove(struct platform_device *pdev); 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci#endif /* __USBIP_VUDC_H */ 179