1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
|
/*
* Copyright (C) 2014 Samsung Electronics
*
* Krzysztof Opasiak <k.opasiak@samsung.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/**
* @file gadget-ffs.c
* @example gadget-ffs.c
* This is an example of how to create gadget with FunctionFS based functions
* in two ways. After executing this program gadget will not be enabled
* because ffs instances should be mounted and both descriptors and strings
* should be written to ep0.
* For more details about FunctionFS please refer to FunctionFS documentation
* in linux kernel repository.
*/
#include <errno.h>
#include <stdio.h>
#include <linux/usb/ch9.h>
#include <usbg/usbg.h>
#define VENDOR 0x1d6b
#define PRODUCT 0x0104
int main(void)
{
usbg_state *s;
usbg_gadget *g;
usbg_config *c;
usbg_function *f_ffs1, *f_ffs2;
int ret = -EINVAL;
int usbg_ret;
usbg_gadget_attrs g_attrs = {
.bcdUSB = 0x0200,
.bDeviceClass = USB_CLASS_PER_INTERFACE,
.bDeviceSubClass = 0x00,
.bDeviceProtocol = 0x00,
.bMaxPacketSize0 = 64, /* Max allowed ep0 packet size */
.idVendor = VENDOR,
.idProduct = PRODUCT,
.bcdDevice = 0x0001, /* Verson of device */
};
usbg_gadget_strs g_strs = {
.str_ser = "0123456789", /* Serial number */
.str_mnf = "Foo Inc.", /* Manufacturer */
.str_prd = "Bar Gadget" /* Product string */
};
usbg_config_strs c_strs = {
.configuration = "2xFFS"
};
usbg_function_attrs f_attrs = {
.attrs.ffs = {
.dev_name = "my_awesome_dev_name",
},
};
usbg_ret = usbg_init("/sys/kernel/config", &s);
if (usbg_ret != USBG_SUCCESS) {
fprintf(stderr, "Error on USB gadget init\n");
fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
usbg_strerror(usbg_ret));
goto out1;
}
usbg_ret = usbg_create_gadget(s, "g1", &g_attrs, &g_strs, &g);
if (usbg_ret != USBG_SUCCESS) {
fprintf(stderr, "Error on create gadget\n");
fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
usbg_strerror(usbg_ret));
goto out2;
}
usbg_ret = usbg_create_function(g, F_FFS, "my_dev_name", NULL, &f_ffs1);
if (usbg_ret != USBG_SUCCESS) {
fprintf(stderr, "Error creating ffs1 function\n");
fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
usbg_strerror(usbg_ret));
goto out2;
}
/* When NULL is passed as instance name, dev_name take from f_attrs
is used as instance name for this function */
usbg_ret = usbg_create_function(g, F_FFS, NULL, &f_attrs, &f_ffs2);
if (usbg_ret != USBG_SUCCESS) {
fprintf(stderr, "Error creating ffs2 function\n");
fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
usbg_strerror(usbg_ret));
goto out2;
}
/* NULL can be passed to use kernel defaults */
usbg_ret = usbg_create_config(g, 1, "The only one", NULL, &c_strs, &c);
if (usbg_ret != USBG_SUCCESS) {
fprintf(stderr, "Error creating config\n");
fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
usbg_strerror(usbg_ret));
goto out2;
}
usbg_ret = usbg_add_config_function(c, "some_name_here", f_ffs1);
if (usbg_ret != USBG_SUCCESS) {
fprintf(stderr, "Error adding ffs1\n");
fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
usbg_strerror(usbg_ret));
goto out2;
}
usbg_ret = usbg_add_config_function(c, "some_name_here_too", f_ffs2);
if (usbg_ret != USBG_SUCCESS) {
fprintf(stderr, "Error adding ffs2\n");
fprintf(stderr, "Error: %s : %s\n", usbg_error_name(usbg_ret),
usbg_strerror(usbg_ret));
goto out2;
}
fprintf(stdout, "2xFFS gadget has been created.\n"
"Enable it after preparing your functions.\n");
/*
* Here we end up with two created ffs instances but they are not
* fully operational. Now we have to do step by step:
* 1) Mount both instances:
* $ mount my_dev_name -t functionfs /path/to/mount/dir1
* $ mount my_awesome_dev_name -t functionfs /path/to/mount/dir2
*
* 2) Run ffs daemons for both instances:
* $ my-ffs-daemon /path/to/mount/dir1
* $ my-ffs-daemon /path/to/mount/dir2
*
* 3) Enable your gadget:
* $ echo "my_udc_name" > /sys/kernel/config/usb_gadget/g1/UDC
*/
ret = 0;
out2:
usbg_cleanup(s);
out1:
return ret;
}
|