162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * u_fs.h 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Utility definitions for the FunctionFS 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Copyright (c) 2013 Samsung Electronics Co., Ltd. 862306a36Sopenharmony_ci * http://www.samsung.com 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.com> 1162306a36Sopenharmony_ci */ 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#ifndef U_GENERIC_H 1462306a36Sopenharmony_ci#define U_GENERIC_H 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci#include <linux/usb/composite.h> 1762306a36Sopenharmony_ci#include <linux/list.h> 1862306a36Sopenharmony_ci#include <linux/mutex.h> 1962306a36Sopenharmony_ci#include <linux/workqueue.h> 2062306a36Sopenharmony_ci#include <linux/refcount.h> 2162306a36Sopenharmony_ci#include <linux/cdev.h> 2262306a36Sopenharmony_ci#ifdef VERBOSE_DEBUG 2362306a36Sopenharmony_ci#ifndef pr_vdebug 2462306a36Sopenharmony_ci# define pr_vdebug pr_debug 2562306a36Sopenharmony_ci#endif /* pr_vdebug */ 2662306a36Sopenharmony_ci# define ffs_dump_mem(prefix, ptr, len) \ 2762306a36Sopenharmony_ci print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len) 2862306a36Sopenharmony_ci#else 2962306a36Sopenharmony_ci#ifndef pr_vdebug 3062306a36Sopenharmony_ci# define pr_vdebug(...) do { } while (0) 3162306a36Sopenharmony_ci#endif /* pr_vdebug */ 3262306a36Sopenharmony_ci# define ffs_dump_mem(prefix, ptr, len) do { } while (0) 3362306a36Sopenharmony_ci#endif /* VERBOSE_DEBUG */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define ENTER() pr_vdebug("%s()\n", __func__) 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci#define MAX_REQUEST 64 3862306a36Sopenharmony_ci#define MAX_NAMELEN 64 3962306a36Sopenharmony_ci#define FUNCTION_GENERIC "f_generic" 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct FuncNew { 4262306a36Sopenharmony_ci uint32_t nameLen; 4362306a36Sopenharmony_ci char name[MAX_NAMELEN]; 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_cistruct IoData { 4762306a36Sopenharmony_ci uint32_t aio; 4862306a36Sopenharmony_ci uint32_t read; 4962306a36Sopenharmony_ci uint32_t len; 5062306a36Sopenharmony_ci uint32_t timeout; 5162306a36Sopenharmony_ci uint64_t buf; 5262306a36Sopenharmony_ci}; 5362306a36Sopenharmony_ci 5462306a36Sopenharmony_cistruct UsbFnReqEvent { 5562306a36Sopenharmony_ci uint64_t buf; 5662306a36Sopenharmony_ci uint32_t actual; 5762306a36Sopenharmony_ci int status; 5862306a36Sopenharmony_ci}; 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_cistruct ffs_memory{ 6162306a36Sopenharmony_ci uint64_t mem; 6262306a36Sopenharmony_ci uint64_t vm_start; 6362306a36Sopenharmony_ci uint32_t size; 6462306a36Sopenharmony_ci struct list_head memlist; 6562306a36Sopenharmony_ci}; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_cistruct generic_memory{ 6862306a36Sopenharmony_ci uint32_t size; 6962306a36Sopenharmony_ci uint64_t buf; 7062306a36Sopenharmony_ci}; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci 7362306a36Sopenharmony_ci#define FUNCTIONFS_NEWFN _IOW('g', 60, struct FuncNew) 7462306a36Sopenharmony_ci#define FUNCTIONFS_DELFN _IOW('g', 61, struct FuncNew) 7562306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_GET_REQ_STATUS _IOW('g', 48, struct IoData) 7662306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_WRITE _IOW('g', 49, struct IoData) 7762306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_READ _IOW('g', 50, struct IoData) 7862306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_RW_CANCEL _IOW('g', 51, struct IoData) 7962306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_QUEUE_INIT _IO('g', 52) 8062306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_QUEUE_DEL _IO('g', 53) 8162306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_RELEASE_BUF _IOR('g', 54, struct generic_memory) 8262306a36Sopenharmony_ci#define FUNCTIONFS_ENDPOINT_GET_EP0_EVENT _IOR('g', 56, struct UsbFnReqEvent) 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistruct f_fs_opts; 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_cistruct ffs_dev { 8762306a36Sopenharmony_ci struct ffs_data *ffs_data; 8862306a36Sopenharmony_ci struct f_fs_opts *opts; 8962306a36Sopenharmony_ci struct list_head entry; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci char name[MAX_NAMELEN]; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci bool mounted; 9462306a36Sopenharmony_ci bool desc_ready; 9562306a36Sopenharmony_ci bool single; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci int (*ffs_ready_callback)(struct ffs_data *ffs); 9862306a36Sopenharmony_ci void (*ffs_closed_callback)(struct ffs_data *ffs); 9962306a36Sopenharmony_ci void *(*ffs_acquire_dev_callback)(struct ffs_dev *dev); 10062306a36Sopenharmony_ci void (*ffs_release_dev_callback)(struct ffs_dev *dev); 10162306a36Sopenharmony_ci}; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ciextern struct mutex ffs_lock_adapter; 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic inline void ffs_dev_lock(void) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci mutex_lock(&ffs_lock_adapter); 10862306a36Sopenharmony_ci} 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic inline void ffs_dev_unlock(void) 11162306a36Sopenharmony_ci{ 11262306a36Sopenharmony_ci mutex_unlock(&ffs_lock_adapter); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ciint ffs_name_dev_adapter(struct ffs_dev *dev, const char *name); 11662306a36Sopenharmony_ciint ffs_single_dev_adapter(struct ffs_dev *dev); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_cistruct ffs_epfile; 11962306a36Sopenharmony_cistruct ffs_function; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_cienum ffs_state { 12262306a36Sopenharmony_ci /* 12362306a36Sopenharmony_ci * Waiting for descriptors and strings. 12462306a36Sopenharmony_ci * 12562306a36Sopenharmony_ci * In this state no open(2), read(2) or write(2) on epfiles 12662306a36Sopenharmony_ci * may succeed (which should not be the problem as there 12762306a36Sopenharmony_ci * should be no such files opened in the first place). 12862306a36Sopenharmony_ci */ 12962306a36Sopenharmony_ci FFS_READ_DESCRIPTORS, 13062306a36Sopenharmony_ci FFS_READ_STRINGS, 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci /* 13362306a36Sopenharmony_ci * We've got descriptors and strings. We are or have called 13462306a36Sopenharmony_ci * functionfs_ready_callback(). functionfs_bind() may have 13562306a36Sopenharmony_ci * been called but we don't know. 13662306a36Sopenharmony_ci * 13762306a36Sopenharmony_ci * This is the only state in which operations on epfiles may 13862306a36Sopenharmony_ci * succeed. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci FFS_ACTIVE, 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* 14362306a36Sopenharmony_ci * Function is visible to host, but it's not functional. All 14462306a36Sopenharmony_ci * setup requests are stalled and transfers on another endpoints 14562306a36Sopenharmony_ci * are refused. All epfiles, except ep0, are deleted so there 14662306a36Sopenharmony_ci * is no way to perform any operations on them. 14762306a36Sopenharmony_ci * 14862306a36Sopenharmony_ci * This state is set after closing all functionfs files, when 14962306a36Sopenharmony_ci * mount parameter "no_disconnect=1" has been set. Function will 15062306a36Sopenharmony_ci * remain in deactivated state until filesystem is umounted or 15162306a36Sopenharmony_ci * ep0 is opened again. In the second case functionfs state will 15262306a36Sopenharmony_ci * be reset, and it will be ready for descriptors and strings 15362306a36Sopenharmony_ci * writing. 15462306a36Sopenharmony_ci * 15562306a36Sopenharmony_ci * This is useful only when functionfs is composed to gadget 15662306a36Sopenharmony_ci * with another function which can perform some critical 15762306a36Sopenharmony_ci * operations, and it's strongly desired to have this operations 15862306a36Sopenharmony_ci * completed, even after functionfs files closure. 15962306a36Sopenharmony_ci */ 16062306a36Sopenharmony_ci FFS_DEACTIVATED, 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci /* 16362306a36Sopenharmony_ci * All endpoints have been closed. This state is also set if 16462306a36Sopenharmony_ci * we encounter an unrecoverable error. The only 16562306a36Sopenharmony_ci * unrecoverable error is situation when after reading strings 16662306a36Sopenharmony_ci * from user space we fail to initialise epfiles or 16762306a36Sopenharmony_ci * functionfs_ready_callback() returns with error (<0). 16862306a36Sopenharmony_ci * 16962306a36Sopenharmony_ci * In this state no open(2), read(2) or write(2) (both on ep0 17062306a36Sopenharmony_ci * as well as epfile) may succeed (at this point epfiles are 17162306a36Sopenharmony_ci * unlinked and all closed so this is not a problem; ep0 is 17262306a36Sopenharmony_ci * also closed but ep0 file exists and so open(2) on ep0 must 17362306a36Sopenharmony_ci * fail). 17462306a36Sopenharmony_ci */ 17562306a36Sopenharmony_ci FFS_CLOSING 17662306a36Sopenharmony_ci}; 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_cienum ffs_setup_state { 17962306a36Sopenharmony_ci /* There is no setup request pending. */ 18062306a36Sopenharmony_ci FFS_NO_SETUP, 18162306a36Sopenharmony_ci /* 18262306a36Sopenharmony_ci * User has read events and there was a setup request event 18362306a36Sopenharmony_ci * there. The next read/write on ep0 will handle the 18462306a36Sopenharmony_ci * request. 18562306a36Sopenharmony_ci */ 18662306a36Sopenharmony_ci FFS_SETUP_PENDING, 18762306a36Sopenharmony_ci /* 18862306a36Sopenharmony_ci * There was event pending but before user space handled it 18962306a36Sopenharmony_ci * some other event was introduced which canceled existing 19062306a36Sopenharmony_ci * setup. If this state is set read/write on ep0 return 19162306a36Sopenharmony_ci * -EIDRM. This state is only set when adding event. 19262306a36Sopenharmony_ci */ 19362306a36Sopenharmony_ci FFS_SETUP_CANCELLED 19462306a36Sopenharmony_ci}; 19562306a36Sopenharmony_ci 19662306a36Sopenharmony_cistruct ffs_data { 19762306a36Sopenharmony_ci struct usb_gadget *gadget; 19862306a36Sopenharmony_ci struct list_head entry; 19962306a36Sopenharmony_ci struct list_head memory_list; 20062306a36Sopenharmony_ci /* 20162306a36Sopenharmony_ci * Protect access read/write operations, only one read/write 20262306a36Sopenharmony_ci * at a time. As a consequence protects ep0req and company. 20362306a36Sopenharmony_ci * While setup request is being processed (queued) this is 20462306a36Sopenharmony_ci * held. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci struct mutex mutex; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* 20962306a36Sopenharmony_ci * Protect access to endpoint related structures (basically 21062306a36Sopenharmony_ci * usb_ep_queue(), usb_ep_dequeue(), etc. calls) except for 21162306a36Sopenharmony_ci * endpoint zero. 21262306a36Sopenharmony_ci */ 21362306a36Sopenharmony_ci spinlock_t eps_lock; 21462306a36Sopenharmony_ci spinlock_t mem_lock; 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_ci /* 21762306a36Sopenharmony_ci * XXX REVISIT do we need our own request? Since we are not 21862306a36Sopenharmony_ci * handling setup requests immediately user space may be so 21962306a36Sopenharmony_ci * slow that another setup will be sent to the gadget but this 22062306a36Sopenharmony_ci * time not to us but another function and then there could be 22162306a36Sopenharmony_ci * a race. Is that the case? Or maybe we can use cdev->req 22262306a36Sopenharmony_ci * after all, maybe we just need some spinlock for that? 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_ci struct usb_request *ep0req; /* P: mutex */ 22562306a36Sopenharmony_ci struct completion ep0req_completion; /* P: mutex */ 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci /* reference counter */ 22862306a36Sopenharmony_ci refcount_t ref; 22962306a36Sopenharmony_ci /* how many files are opened (EP0 and others) */ 23062306a36Sopenharmony_ci atomic_t opened; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci /* EP0 state */ 23362306a36Sopenharmony_ci enum ffs_state state; 23462306a36Sopenharmony_ci 23562306a36Sopenharmony_ci /* 23662306a36Sopenharmony_ci * Possible transitions: 23762306a36Sopenharmony_ci * + FFS_NO_SETUP -> FFS_SETUP_PENDING -- P: ev.waitq.lock 23862306a36Sopenharmony_ci * happens only in ep0 read which is P: mutex 23962306a36Sopenharmony_ci * + FFS_SETUP_PENDING -> FFS_NO_SETUP -- P: ev.waitq.lock 24062306a36Sopenharmony_ci * happens only in ep0 i/o which is P: mutex 24162306a36Sopenharmony_ci * + FFS_SETUP_PENDING -> FFS_SETUP_CANCELLED -- P: ev.waitq.lock 24262306a36Sopenharmony_ci * + FFS_SETUP_CANCELLED -> FFS_NO_SETUP -- cmpxchg 24362306a36Sopenharmony_ci * 24462306a36Sopenharmony_ci * This field should never be accessed directly and instead 24562306a36Sopenharmony_ci * ffs_setup_state_clear_cancelled function should be used. 24662306a36Sopenharmony_ci */ 24762306a36Sopenharmony_ci enum ffs_setup_state setup_state; 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci /* Events & such. */ 25062306a36Sopenharmony_ci struct { 25162306a36Sopenharmony_ci u8 types[4]; 25262306a36Sopenharmony_ci unsigned short count; 25362306a36Sopenharmony_ci /* XXX REVISIT need to update it in some places, or do we? */ 25462306a36Sopenharmony_ci unsigned short can_stall; 25562306a36Sopenharmony_ci struct usb_ctrlrequest setup; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci wait_queue_head_t waitq; 25862306a36Sopenharmony_ci } ev; /* the whole structure, P: ev.waitq.lock */ 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci /* Flags */ 26162306a36Sopenharmony_ci unsigned long flags; 26262306a36Sopenharmony_ci#define FFS_FL_CALL_CLOSED_CALLBACK 0 26362306a36Sopenharmony_ci#define FFS_FL_BOUND 1 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci /* For waking up blocked threads when function is enabled. */ 26662306a36Sopenharmony_ci wait_queue_head_t wait; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* Active function */ 26962306a36Sopenharmony_ci struct ffs_function *func; 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci char dev_name[MAX_NAMELEN]; 27362306a36Sopenharmony_ci struct cdev cdev; 27462306a36Sopenharmony_ci dev_t devno; 27562306a36Sopenharmony_ci struct device *fn_device; 27662306a36Sopenharmony_ci 27762306a36Sopenharmony_ci struct kfifo reqEventFifo; 27862306a36Sopenharmony_ci wait_queue_head_t wait_que; 27962306a36Sopenharmony_ci /* Private data for our user (ie. gadget). Managed by user. */ 28062306a36Sopenharmony_ci void *private_data; 28162306a36Sopenharmony_ci /* filled by __ffs_data_got_descs() */ 28262306a36Sopenharmony_ci /* 28362306a36Sopenharmony_ci * raw_descs is what you kfree, real_descs points inside of raw_descs, 28462306a36Sopenharmony_ci * where full speed, high speed and super speed descriptors start. 28562306a36Sopenharmony_ci * real_descs_length is the length of all those descriptors. 28662306a36Sopenharmony_ci */ 28762306a36Sopenharmony_ci const void *raw_descs_data; 28862306a36Sopenharmony_ci const void *raw_descs; 28962306a36Sopenharmony_ci unsigned raw_descs_length; 29062306a36Sopenharmony_ci unsigned fs_descs_count; 29162306a36Sopenharmony_ci unsigned hs_descs_count; 29262306a36Sopenharmony_ci unsigned ss_descs_count; 29362306a36Sopenharmony_ci unsigned ms_os_descs_count; 29462306a36Sopenharmony_ci unsigned ms_os_descs_ext_prop_count; 29562306a36Sopenharmony_ci unsigned ms_os_descs_ext_prop_name_len; 29662306a36Sopenharmony_ci unsigned ms_os_descs_ext_prop_data_len; 29762306a36Sopenharmony_ci void *ms_os_descs_ext_prop_avail; 29862306a36Sopenharmony_ci void *ms_os_descs_ext_prop_name_avail; 29962306a36Sopenharmony_ci void *ms_os_descs_ext_prop_data_avail; 30062306a36Sopenharmony_ci 30162306a36Sopenharmony_ci unsigned user_flags; 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci#define FFS_MAX_EPS_COUNT 31 30462306a36Sopenharmony_ci u8 eps_addrmap[FFS_MAX_EPS_COUNT]; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci unsigned short strings_count; 30762306a36Sopenharmony_ci unsigned short interfaces_count; 30862306a36Sopenharmony_ci unsigned short eps_count; 30962306a36Sopenharmony_ci unsigned short _pad1; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci /* filled by __ffs_data_got_strings() */ 31262306a36Sopenharmony_ci /* ids in stringtabs are set in functionfs_bind() */ 31362306a36Sopenharmony_ci const void *raw_strings; 31462306a36Sopenharmony_ci struct usb_gadget_strings **stringtabs; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* 31762306a36Sopenharmony_ci * File system's super block, write once when file system is 31862306a36Sopenharmony_ci * mounted. 31962306a36Sopenharmony_ci */ 32062306a36Sopenharmony_ci struct super_block *sb; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci /* File permissions, written once when fs is mounted */ 32362306a36Sopenharmony_ci struct ffs_file_perms { 32462306a36Sopenharmony_ci umode_t mode; 32562306a36Sopenharmony_ci kuid_t uid; 32662306a36Sopenharmony_ci kgid_t gid; 32762306a36Sopenharmony_ci } file_perms; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci struct eventfd_ctx *ffs_eventfd; 33062306a36Sopenharmony_ci struct workqueue_struct *io_completion_wq; 33162306a36Sopenharmony_ci bool no_disconnect; 33262306a36Sopenharmony_ci struct work_struct reset_work; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci /* 33562306a36Sopenharmony_ci * The endpoint files, filled by ffs_epfiles_create(), 33662306a36Sopenharmony_ci * destroyed by ffs_epfiles_destroy(). 33762306a36Sopenharmony_ci */ 33862306a36Sopenharmony_ci struct ffs_epfile *epfiles; 33962306a36Sopenharmony_ci struct ffs_ep *eps; 34062306a36Sopenharmony_ci enum usb_device_speed speed; 34162306a36Sopenharmony_ci}; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistruct f_fs_opts { 34562306a36Sopenharmony_ci struct usb_function_instance func_inst; 34662306a36Sopenharmony_ci struct ffs_dev *dev; 34762306a36Sopenharmony_ci unsigned refcnt; 34862306a36Sopenharmony_ci bool no_configfs; 34962306a36Sopenharmony_ci}; 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic inline struct f_fs_opts *to_f_fs_opts(struct usb_function_instance *fi) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci return container_of(fi, struct f_fs_opts, func_inst); 35462306a36Sopenharmony_ci} 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci#endif /* U_GENERIC_H */