1 /*
2 * u_uac.h - Utility definitions for UAC function
3 *
4 * Copyright (C) 2016 Ruslan Bilovol <ruslan.bilovol@gmail.com>
5 * Copyright (C) 2017 Julian Scheel <julian@juss.de>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 */
11
12 #ifndef __U_UAC_H
13 #define __U_UAC_H
14
15 #include <linux/usb/composite.h>
16 #include "u_audio.h"
17
18 #define UAC_DEF_CCHMASK 0x3
19 #define UAC_DEF_CSRATE 48000
20 #define UAC_DEF_CSSIZE 2
21 #define UAC_DEF_CFU 0
22 #define UAC_DEF_PCHMASK 0x3
23 #define UAC_DEF_PSRATE 48000
24 #define UAC_DEF_PSSIZE 2
25 #define UAC_DEF_PFU 0
26 #define UAC_DEF_REQ_NUM 2
27
28 #define UAC1_OUT_EP_MAX_PACKET_SIZE 200
29
30 #define EPIN_EN(_opts) ((_opts)->p_chmask != 0)
31 #define EPOUT_EN(_opts) ((_opts)->c_chmask != 0)
32 #define EPIN_FU(_opts) ((_opts)->p_feature_unit != 0)
33 #define EPOUT_FU(_opts) ((_opts)->c_feature_unit != 0)
34
35 struct f_uac_opts {
36 struct usb_function_instance func_inst;
37 int c_chmask;
38 int c_srate[UAC_MAX_RATES];
39 int c_srate_active;
40 int c_ssize;
41 int c_feature_unit;
42 int p_chmask;
43 int p_srate[UAC_MAX_RATES];
44 int p_srate_active;
45 int p_ssize;
46 int p_feature_unit;
47 int req_number;
48 unsigned bound:1;
49
50 struct mutex lock;
51 int refcnt;
52 };
53
54 #define UAC_ATTRIBUTE(name) \
55 static ssize_t f_uac_opts_##name##_show( \
56 struct config_item *item, \
57 char *page) \
58 { \
59 struct f_uac_opts *opts = to_f_uac_opts(item); \
60 int result; \
61 \
62 mutex_lock(&opts->lock); \
63 result = sprintf(page, "%u\n", opts->name); \
64 mutex_unlock(&opts->lock); \
65 \
66 return result; \
67 } \
68 \
69 static ssize_t f_uac_opts_##name##_store( \
70 struct config_item *item, \
71 const char *page, size_t len) \
72 { \
73 struct f_uac_opts *opts = to_f_uac_opts(item); \
74 int ret; \
75 u32 num; \
76 \
77 mutex_lock(&opts->lock); \
78 if (opts->refcnt) { \
79 ret = -EBUSY; \
80 goto end; \
81 } \
82 \
83 ret = kstrtou32(page, 0, &num); \
84 if (ret) \
85 goto end; \
86 \
87 opts->name = num; \
88 ret = len; \
89 \
90 end: \
91 mutex_unlock(&opts->lock); \
92 return ret; \
93 } \
94 \
95 CONFIGFS_ATTR(f_uac_opts_, name)
96
97 #define UAC_RATE_ATTRIBUTE(name) \
98 static ssize_t f_uac_opts_##name##_show(struct config_item *item, \
99 char *page) \
100 { \
101 struct f_uac_opts *opts = to_f_uac_opts(item); \
102 int result = 0; \
103 int i; \
104 \
105 mutex_lock(&opts->lock); \
106 page[0] = '\0'; \
107 for (i = 0; i < UAC_MAX_RATES; i++) { \
108 if (opts->name[i] == 0) \
109 continue; \
110 result += sprintf(page + strlen(page), "%u,", \
111 opts->name[i]); \
112 } \
113 if (strlen(page) > 0) \
114 page[strlen(page) - 1] = '\n'; \
115 mutex_unlock(&opts->lock); \
116 \
117 return result; \
118 } \
119 \
120 static ssize_t f_uac_opts_##name##_store(struct config_item *item, \
121 const char *page, size_t len) \
122 { \
123 struct f_uac_opts *opts = to_f_uac_opts(item); \
124 char *split_page = NULL; \
125 int ret = -EINVAL; \
126 char *token; \
127 u32 num; \
128 int i; \
129 \
130 mutex_lock(&opts->lock); \
131 if (opts->refcnt) { \
132 ret = -EBUSY; \
133 goto end; \
134 } \
135 \
136 i = 0; \
137 memset(opts->name, 0x00, sizeof(opts->name)); \
138 split_page = kstrdup(page, GFP_KERNEL); \
139 while ((token = strsep(&split_page, ",")) != NULL) { \
140 ret = kstrtou32(token, 0, &num); \
141 if (ret) \
142 goto end; \
143 \
144 opts->name[i++] = num; \
145 opts->name##_active = num; \
146 ret = len; \
147 }; \
148 \
149 end: \
150 kfree(split_page); \
151 mutex_unlock(&opts->lock); \
152 return ret; \
153 } \
154 \
155 CONFIGFS_ATTR(f_uac_opts_, name)
156
157 struct f_uac {
158 struct g_audio g_audio;
159 u8 ac_intf, as_in_intf, as_out_intf;
160 u8 ac_alt, as_in_alt, as_out_alt; /* needed for get_alt() */
161 int ctl_id;
162
163 struct list_head cs;
164 u8 set_cmd;
165 u8 get_cmd;
166 struct usb_audio_control *set_con;
167 struct usb_audio_control *get_con;
168 };
169
func_to_uac(struct usb_function * f)170 static inline struct f_uac *func_to_uac(struct usb_function *f)
171 {
172 return container_of(f, struct f_uac, g_audio.func);
173 }
174
175 static inline
g_audio_to_uac_opts(struct g_audio * agdev)176 struct f_uac_opts *g_audio_to_uac_opts(struct g_audio *agdev)
177 {
178 return container_of(agdev->func.fi, struct f_uac_opts, func_inst);
179 }
180
to_f_uac_opts(struct config_item * item)181 static inline struct f_uac_opts *to_f_uac_opts(struct config_item *item)
182 {
183 return container_of(to_config_group(item), struct f_uac_opts,
184 func_inst.group);
185 }
186
f_uac_attr_release(struct config_item * item)187 static inline void f_uac_attr_release(struct config_item *item)
188 {
189 struct f_uac_opts *opts = to_f_uac_opts(item);
190
191 usb_put_function_instance(&opts->func_inst);
192 }
193
194 #endif /* __U_UAC_H */
195