linux-hardened/include/linux/usb/gadget_configfs.h
Sebastian Andrzej Siewior 88af8bbe4e usb: gadget: the start of the configfs interface
|# modprobe dummy_hcd num=2
|# modprobe libcomposite

|# lsmod
|Module                  Size  Used by
|libcomposite           31648  0
|dummy_hcd              19871  0

|# mkdir /sys/kernel/config/usb_gadget/oha
|# cd /sys/kernel/config/usb_gadget/oha
|# mkdir configs/def.1
|# mkdir configs/def.2
|# mkdir functions/acm.ttyS1
|# mkdir strings/0x1
|mkdir: cannot create directory `strings/0x1': Invalid argument
|# mkdir strings/0x409
|# mkdir strings/1033
|mkdir: cannot create directory `strings/1033': File exists
|# mkdir strings/1032
|# mkdir configs/def.1/strings/0x409
|# mkdir configs/def.2/strings/0x409

|#find . -ls
|   975    0 drwxr-xr-x   5 root     root            0 Dec 23 17:40 .
|   978    0 drwxr-xr-x   4 root     root            0 Dec 23 17:43 ./strings
|  4100    0 drwxr-xr-x   2 root     root            0 Dec 23 17:43 ./strings/1032
|   995    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./strings/1032/serialnumber
|   996    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./strings/1032/product
|   997    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./strings/1032/manufacturer
|  2002    0 drwxr-xr-x   2 root     root            0 Dec 23 17:41 ./strings/0x409
|   998    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./strings/0x409/serialnumber
|   999    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./strings/0x409/product
|  1000    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./strings/0x409/manufacturer
|   977    0 drwxr-xr-x   4 root     root            0 Dec 23 17:41 ./configs
|  4081    0 drwxr-xr-x   3 root     root            0 Dec 23 17:41 ./configs/def.2
|  4082    0 drwxr-xr-x   3 root     root            0 Dec 23 17:42 ./configs/def.2/strings
|  2016    0 drwxr-xr-x   2 root     root            0 Dec 23 17:42 ./configs/def.2/strings/0x409
|  1001    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./configs/def.2/strings/0x409/configuration
|  1002    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./configs/def.2/bmAttributes
|  1003    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./configs/def.2/MaxPower
|   979    0 drwxr-xr-x   3 root     root            0 Dec 23 17:42 ./configs/def.1
|   980    0 drwxr-xr-x   3 root     root            0 Dec 23 17:42 ./configs/def.1/strings
|  5122    0 drwxr-xr-x   2 root     root            0 Dec 23 17:42 ./configs/def.1/strings/0x409
|  1004    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./configs/def.1/strings/0x409/configuration
|  1005    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./configs/def.1/bmAttributes
|  1006    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./configs/def.1/MaxPower
|   976    0 drwxr-xr-x   3 root     root            0 Dec 23 17:41 ./functions
|   981    0 drwxr-xr-x   2 root     root            0 Dec 23 17:41 ./functions/acm.ttyS1
|  1007    0 -r--r--r--   1 root     root         4096 Dec 23 17:43 ./functions/acm.ttyS1/port_num
|  1008    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./UDC
|  1009    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./bcdUSB
|  1010    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./bcdDevice
|  1011    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./idProduct
|  1012    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./idVendor
|  1013    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./bMaxPacketSize0
|  1014    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./bDeviceProtocol
|  1015    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./bDeviceSubClass
|  1016    0 -rw-r--r--   1 root     root         4096 Dec 23 17:43 ./bDeviceClass

|# cat functions/acm.ttyS1/port_num
|0
|# ls -lah /dev/ttyGS*
|crw-rw---T 1 root dialout 252, 0 Dec 23 17:41 /dev/ttyGS0
|
|# echo 0x1234 > idProduct
|# echo 0xabcd > idVendor
|# echo 1122 > strings/0x409/serialnumber
|# echo "The manufacturer" > strings/0x409/manufacturer
|# echo 1 > strings/1032/manufacturer
|# echo 1sa > strings/1032/product
|# echo tada > strings/1032/serialnumber
|echo "Primary configuration" > configs/def.1/strings/0x409/configuration
|# echo "Secondary configuration" > configs/def.2/strings/0x409/configuration
|# ln -s functions/acm.ttyS1 configs/def.1/
|# ln -s functions/acm.ttyS1 configs/def.2/
|find configs/def.1/ -ls
|   979    0 drwxr-xr-x   3 root     root            0 Dec 23 17:49 configs/def.1/
|  6264    0 lrwxrwxrwx   1 root     root            0 Dec 23 17:48 configs/def.1/acm.ttyS1 -> ../../../../usb_gadget/oha/functions/acm.ttyS1
|   980    0 drwxr-xr-x   3 root     root            0 Dec 23 17:42 configs/def.1/strings
|  5122    0 drwxr-xr-x   2 root     root            0 Dec 23 17:49 configs/def.1/strings/0x409
|  6284    0 -rw-r--r--   1 root     root         4096 Dec 23 17:47 configs/def.1/strings/0x409/configuration
|  6285    0 -rw-r--r--   1 root     root         4096 Dec 23 17:49 configs/def.1/bmAttributes
|  6286    0 -rw-r--r--   1 root     root         4096 Dec 23 17:49 configs/def.1/MaxPower
|
|echo 120 > configs/def.1/MaxPower
|
|# ls -lh /sys/class/udc/
|total 0
|lrwxrwxrwx 1 root root 0 Dec 23 17:50 dummy_udc.0 -> ../../devices/platform/dummy_udc.0/udc/dummy_udc.0
|lrwxrwxrwx 1 root root 0 Dec 23 17:50 dummy_udc.1 -> ../../devices/platform/dummy_udc.1/udc/dummy_udc.1
|# echo dummy_udc.0 > UDC
|# lsusb
|Bus 001 Device 002: ID abcd:1234 Unknown
|
|lsusb -d abcd:1234 -v
|Device Descriptor:
…
|  idVendor           0xabcd Unknown
|  idProduct          0x1234
|  bcdDevice            3.06
|  iManufacturer           1 The manufacturer
|  iProduct                2
|  iSerial                 3 1122
|  bNumConfigurations      2
…
|echo "" > UDC

v5…v6
- wired up strings with usb_gstrings_attach()
- add UDC attribe. Write "udc-name" will bind the gadget. Write an empty
  string (it should contain \n since 0 bytes write get optimzed away)
  will unbind the UDC from the gadget. The name of available UDCs can be
  obtained from /sys/class/udc/

v4…v5
- string rework. This will add a strings folder incl. language code like
    strings/409/manufacturer
  as suggested by Alan.
- rebased ontop reworked functions.c which has usb_function_instance
  which is used prior after "mkdir acm.instance" and can be directly
  used for configuration via configfs.

v3…v4
 - moved functions from the root folde down to the gadget as suggested
   by Michał
 - configs have now their own configs folder as suggested by Michał.
   The folder is still name.bConfigurationValue where name becomes the
   sConfiguration. Is this usefull should we just stilc
   configs/bConfigurationValue/ ?
 - added configfs support to the ACM function. The port_num attribute is
   exported by f_acm. An argument has been added to the USB alloc
   function to distinguish between "old" (use facm_configure() to
   configure and configfs interface (expose a config_node).
   The port_num is currently a dumb counter. It will
   require some function re-work to make it work.

scheduled for v5:
- sym linking function into config.

v2…v3
- replaced one ifndef by ifdef as suggested by Micahał
- strstr()/strchr() function_make as suggested by Micahł
- replace [iSerialNumber|iProduct|iManufacturer] with
  [sSerialNumber|sProduct|sManufacturer] as suggested by Alan
- added creation of config descriptors

v1…v2
- moved gadgets from configfs' root directory into /udcs/ within our
  "usb_gadget" folder. Requested by Andrzej & Michał
- use a dot as a delimiter between function's name and its instance's name
  as suggested by Michał
- renamed all config_item_type, configfs_group_operations, make_group,
  drop_item as suggested by suggested by Andrzej to remain consisten
  within this file and within other configfs users
- Since configfs.c and functions.c are now part of the udc-core module,
  the module itself is now called udc. Also added a tiny ifdef around
  init code becuase udc-core is subsys init and this is too early for
  configfs in the built-in case. In the module case, we can only have
  one init function.

Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Felipe Balbi <balbi@ti.com>
2013-04-03 14:43:32 +03:00

110 lines
3.2 KiB
C

#ifndef __GADGET_CONFIGFS__
#define __GADGET_CONFIGFS__
#include <linux/configfs.h>
int check_user_usb_string(const char *name,
struct usb_gadget_strings *stringtab_dev);
#define GS_STRINGS_W(__struct, __name) \
static ssize_t __struct##_##__name##_store(struct __struct *gs, \
const char *page, size_t len) \
{ \
int ret; \
\
ret = usb_string_copy(page, &gs->__name); \
if (ret) \
return ret; \
return len; \
}
#define GS_STRINGS_R(__struct, __name) \
static ssize_t __struct##_##__name##_show(struct __struct *gs, \
char *page) \
{ \
return sprintf(page, "%s\n", gs->__name ?: ""); \
}
#define GS_STRING_ITEM_ATTR(struct_name, name) \
static struct struct_name##_attribute struct_name##_##name = \
__CONFIGFS_ATTR(name, S_IRUGO | S_IWUSR, \
struct_name##_##name##_show, \
struct_name##_##name##_store)
#define GS_STRINGS_RW(struct_name, _name) \
GS_STRINGS_R(struct_name, _name) \
GS_STRINGS_W(struct_name, _name) \
GS_STRING_ITEM_ATTR(struct_name, _name)
#define USB_CONFIG_STRING_RW_OPS(struct_in) \
CONFIGFS_ATTR_OPS(struct_in); \
\
static struct configfs_item_operations struct_in##_langid_item_ops = { \
.release = struct_in##_attr_release, \
.show_attribute = struct_in##_attr_show, \
.store_attribute = struct_in##_attr_store, \
}; \
\
static struct config_item_type struct_in##_langid_type = { \
.ct_item_ops = &struct_in##_langid_item_ops, \
.ct_attrs = struct_in##_langid_attrs, \
.ct_owner = THIS_MODULE, \
}
#define USB_CONFIG_STRINGS_LANG(struct_in, struct_member) \
static struct config_group *struct_in##_strings_make( \
struct config_group *group, \
const char *name) \
{ \
struct struct_member *gi; \
struct struct_in *gs; \
struct struct_in *new; \
int langs = 0; \
int ret; \
\
new = kzalloc(sizeof(*new), GFP_KERNEL); \
if (!new) \
return ERR_PTR(-ENOMEM); \
\
ret = check_user_usb_string(name, &new->stringtab_dev); \
if (ret) \
goto err; \
config_group_init_type_name(&new->group, name, \
&struct_in##_langid_type); \
\
gi = container_of(group, struct struct_member, strings_group); \
ret = -EEXIST; \
list_for_each_entry(gs, &gi->string_list, list) { \
if (gs->stringtab_dev.language == new->stringtab_dev.language) \
goto err; \
langs++; \
} \
ret = -EOVERFLOW; \
if (langs >= MAX_USB_STRING_LANGS) \
goto err; \
\
list_add_tail(&new->list, &gi->string_list); \
return &new->group; \
err: \
kfree(new); \
return ERR_PTR(ret); \
} \
\
static void struct_in##_strings_drop( \
struct config_group *group, \
struct config_item *item) \
{ \
config_item_put(item); \
} \
\
static struct configfs_group_operations struct_in##_strings_ops = { \
.make_group = &struct_in##_strings_make, \
.drop_item = &struct_in##_strings_drop, \
}; \
\
static struct config_item_type struct_in##_strings_type = { \
.ct_group_ops = &struct_in##_strings_ops, \
.ct_owner = THIS_MODULE, \
}
#endif