2013-12-03 15:15:31 +01:00
/*
* u_fs . h
*
* Utility definitions for the FunctionFS
*
* Copyright ( c ) 2013 Samsung Electronics Co . , Ltd .
* http : //www.samsung.com
*
* Author : Andrzej Pietrasiewicz < andrzej . p @ samsung . com >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
# ifndef U_FFS_H
# define U_FFS_H
# include <linux/usb/composite.h>
2013-12-03 15:15:32 +01:00
# include <linux/list.h>
# include <linux/mutex.h>
2013-12-03 15:15:31 +01:00
2013-12-03 15:15:33 +01:00
# ifdef VERBOSE_DEBUG
# ifndef pr_vdebug
# define pr_vdebug pr_debug
# endif /* pr_vdebug */
# define ffs_dump_mem(prefix, ptr, len) \
print_hex_dump_bytes ( pr_fmt ( prefix " : " ) , DUMP_PREFIX_NONE , ptr , len )
# else
# ifndef pr_vdebug
# define pr_vdebug(...) do { } while (0)
# endif /* pr_vdebug */
# define ffs_dump_mem(prefix, ptr, len) do { } while (0)
# endif /* VERBOSE_DEBUG */
# define ENTER() pr_vdebug("%s()\n", __func__)
2013-12-03 15:15:36 +01:00
struct f_fs_opts ;
2013-12-03 15:15:33 +01:00
2013-12-03 15:15:31 +01:00
struct ffs_dev {
const char * name ;
2013-12-03 15:15:36 +01:00
bool name_allocated ;
2013-12-03 15:15:31 +01:00
bool mounted ;
bool desc_ready ;
2013-12-03 15:15:32 +01:00
bool single ;
2013-12-03 15:15:31 +01:00
struct ffs_data * ffs_data ;
2013-12-03 15:15:36 +01:00
struct f_fs_opts * opts ;
2013-12-03 15:15:32 +01:00
struct list_head entry ;
int ( * ffs_ready_callback ) ( struct ffs_data * ffs ) ;
void ( * ffs_closed_callback ) ( struct ffs_data * ffs ) ;
2013-12-03 15:15:33 +01:00
void * ( * ffs_acquire_dev_callback ) ( struct ffs_dev * dev ) ;
void ( * ffs_release_dev_callback ) ( struct ffs_dev * dev ) ;
2013-12-03 15:15:31 +01:00
} ;
2013-12-03 15:15:32 +01:00
extern struct mutex ffs_lock ;
static inline void ffs_dev_lock ( void )
{
mutex_lock ( & ffs_lock ) ;
}
static inline void ffs_dev_unlock ( void )
{
mutex_unlock ( & ffs_lock ) ;
}
int ffs_name_dev ( struct ffs_dev * dev , const char * name ) ;
int ffs_single_dev ( struct ffs_dev * dev ) ;
2013-12-03 15:15:33 +01:00
struct ffs_epfile ;
struct ffs_function ;
enum ffs_state {
/*
* Waiting for descriptors and strings .
*
* In this state no open ( 2 ) , read ( 2 ) or write ( 2 ) on epfiles
* may succeed ( which should not be the problem as there
* should be no such files opened in the first place ) .
*/
FFS_READ_DESCRIPTORS ,
FFS_READ_STRINGS ,
/*
* We ' ve got descriptors and strings . We are or have called
* functionfs_ready_callback ( ) . functionfs_bind ( ) may have
* been called but we don ' t know .
*
* This is the only state in which operations on epfiles may
* succeed .
*/
FFS_ACTIVE ,
/*
* All endpoints have been closed . This state is also set if
* we encounter an unrecoverable error . The only
* unrecoverable error is situation when after reading strings
* from user space we fail to initialise epfiles or
* functionfs_ready_callback ( ) returns with error ( < 0 ) .
*
* In this state no open ( 2 ) , read ( 2 ) or write ( 2 ) ( both on ep0
* as well as epfile ) may succeed ( at this point epfiles are
* unlinked and all closed so this is not a problem ; ep0 is
* also closed but ep0 file exists and so open ( 2 ) on ep0 must
* fail ) .
*/
FFS_CLOSING
} ;
enum ffs_setup_state {
/* There is no setup request pending. */
FFS_NO_SETUP ,
/*
* User has read events and there was a setup request event
* there . The next read / write on ep0 will handle the
* request .
*/
FFS_SETUP_PENDING ,
/*
* There was event pending but before user space handled it
* some other event was introduced which canceled existing
* setup . If this state is set read / write on ep0 return
* - EIDRM . This state is only set when adding event .
*/
2014-02-10 10:42:40 +01:00
FFS_SETUP_CANCELLED
2013-12-03 15:15:33 +01:00
} ;
struct ffs_data {
struct usb_gadget * gadget ;
/*
* Protect access read / write operations , only one read / write
* at a time . As a consequence protects ep0req and company .
* While setup request is being processed ( queued ) this is
* held .
*/
struct mutex mutex ;
/*
* Protect access to endpoint related structures ( basically
* usb_ep_queue ( ) , usb_ep_dequeue ( ) , etc . calls ) except for
* endpoint zero .
*/
spinlock_t eps_lock ;
/*
* XXX REVISIT do we need our own request ? Since we are not
* handling setup requests immediately user space may be so
* slow that another setup will be sent to the gadget but this
* time not to us but another function and then there could be
* a race . Is that the case ? Or maybe we can use cdev - > req
* after all , maybe we just need some spinlock for that ?
*/
struct usb_request * ep0req ; /* P: mutex */
struct completion ep0req_completion ; /* P: mutex */
/* reference counter */
atomic_t ref ;
/* how many files are opened (EP0 and others) */
atomic_t opened ;
/* EP0 state */
enum ffs_state state ;
/*
* Possible transitions :
2014-02-10 10:42:40 +01:00
* + FFS_NO_SETUP - > FFS_SETUP_PENDING - - P : ev . waitq . lock
2013-12-03 15:15:33 +01:00
* happens only in ep0 read which is P : mutex
2014-02-10 10:42:40 +01:00
* + FFS_SETUP_PENDING - > FFS_NO_SETUP - - P : ev . waitq . lock
2013-12-03 15:15:33 +01:00
* happens only in ep0 i / o which is P : mutex
2014-02-10 10:42:40 +01:00
* + FFS_SETUP_PENDING - > FFS_SETUP_CANCELLED - - P : ev . waitq . lock
* + FFS_SETUP_CANCELLED - > FFS_NO_SETUP - - cmpxchg
2014-02-10 10:42:41 +01:00
*
* This field should never be accessed directly and instead
* ffs_setup_state_clear_cancelled function should be used .
2013-12-03 15:15:33 +01:00
*/
enum ffs_setup_state setup_state ;
/* Events & such. */
struct {
u8 types [ 4 ] ;
unsigned short count ;
/* XXX REVISIT need to update it in some places, or do we? */
unsigned short can_stall ;
struct usb_ctrlrequest setup ;
wait_queue_head_t waitq ;
} ev ; /* the whole structure, P: ev.waitq.lock */
/* Flags */
unsigned long flags ;
# define FFS_FL_CALL_CLOSED_CALLBACK 0
# define FFS_FL_BOUND 1
/* Active function */
struct ffs_function * func ;
/*
* Device name , write once when file system is mounted .
* Intended for user to read if she wants .
*/
const char * dev_name ;
/* Private data for our user (ie. gadget). Managed by user. */
void * private_data ;
/* filled by __ffs_data_got_descs() */
/*
2014-02-28 16:50:23 +05:30
* raw_descs is what you kfree , real_descs points inside of raw_descs ,
* where full speed , high speed and super speed descriptors start .
* real_descs_length is the length of all those descriptors .
2013-12-03 15:15:33 +01:00
*/
2014-02-28 16:50:23 +05:30
const void * raw_descs_data ;
2013-12-03 15:15:33 +01:00
const void * raw_descs ;
2014-02-28 16:50:23 +05:30
unsigned raw_descs_length ;
2013-12-03 15:15:33 +01:00
unsigned fs_descs_count ;
unsigned hs_descs_count ;
2014-02-28 16:50:22 +05:30
unsigned ss_descs_count ;
2013-12-03 15:15:33 +01:00
unsigned short strings_count ;
unsigned short interfaces_count ;
unsigned short eps_count ;
unsigned short _pad1 ;
/* filled by __ffs_data_got_strings() */
/* ids in stringtabs are set in functionfs_bind() */
const void * raw_strings ;
struct usb_gadget_strings * * stringtabs ;
/*
* File system ' s super block , write once when file system is
* mounted .
*/
struct super_block * sb ;
/* File permissions, written once when fs is mounted */
struct ffs_file_perms {
umode_t mode ;
kuid_t uid ;
kgid_t gid ;
} file_perms ;
/*
* The endpoint files , filled by ffs_epfiles_create ( ) ,
* destroyed by ffs_epfiles_destroy ( ) .
*/
struct ffs_epfile * epfiles ;
} ;
struct f_fs_opts {
struct usb_function_instance func_inst ;
struct ffs_dev * dev ;
unsigned refcnt ;
bool no_configfs ;
} ;
static inline struct f_fs_opts * to_f_fs_opts ( struct usb_function_instance * fi )
{
return container_of ( fi , struct f_fs_opts , func_inst ) ;
}
2013-12-03 15:15:31 +01:00
# endif /* U_FFS_H */