1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * f_midi2.c -- USB MIDI 2.0 class function driver |
4 | */ |
5 | |
6 | #include <linux/device.h> |
7 | #include <linux/kernel.h> |
8 | #include <linux/module.h> |
9 | #include <linux/slab.h> |
10 | |
11 | #include <sound/core.h> |
12 | #include <sound/control.h> |
13 | #include <sound/ump.h> |
14 | #include <sound/ump_msg.h> |
15 | #include <sound/ump_convert.h> |
16 | |
17 | #include <linux/usb/ch9.h> |
18 | #include <linux/usb/gadget.h> |
19 | #include <linux/usb/audio.h> |
20 | #include <linux/usb/midi-v2.h> |
21 | |
22 | #include "u_f.h" |
23 | #include "u_midi2.h" |
24 | |
25 | struct f_midi2; |
26 | struct f_midi2_ep; |
27 | struct f_midi2_usb_ep; |
28 | |
29 | /* Context for each USB request */ |
30 | struct f_midi2_req_ctx { |
31 | struct f_midi2_usb_ep *usb_ep; /* belonging USB EP */ |
32 | unsigned int index; /* array index: 0-31 */ |
33 | struct usb_request *req; /* assigned request */ |
34 | }; |
35 | |
36 | /* Resources for a USB Endpoint */ |
37 | struct f_midi2_usb_ep { |
38 | struct f_midi2 *card; /* belonging card */ |
39 | struct f_midi2_ep *ep; /* belonging UMP EP (optional) */ |
40 | struct usb_ep *usb_ep; /* assigned USB EP */ |
41 | void (*complete)(struct usb_ep *usb_ep, struct usb_request *req); |
42 | unsigned long free_reqs; /* bitmap for unused requests */ |
43 | unsigned int num_reqs; /* number of allocated requests */ |
44 | struct f_midi2_req_ctx *reqs; /* request context array */ |
45 | }; |
46 | |
47 | /* Resources for UMP Function Block (and USB Group Terminal Block) */ |
48 | struct f_midi2_block { |
49 | struct f_midi2_block_info info; /* FB info, copied from configfs */ |
50 | struct snd_ump_block *fb; /* assigned FB */ |
51 | unsigned int gtb_id; /* assigned GTB id */ |
52 | unsigned int string_id; /* assigned string id */ |
53 | }; |
54 | |
55 | /* Temporary buffer for altset 0 MIDI 1.0 handling */ |
56 | struct f_midi2_midi1_port { |
57 | unsigned int pending; /* pending bytes on the input buffer */ |
58 | u8 buf[32]; /* raw MIDI 1.0 byte input */ |
59 | u8 state; /* running status */ |
60 | u8 data[2]; /* rendered USB MIDI 1.0 packet data */ |
61 | }; |
62 | |
63 | /* MIDI 1.0 message states */ |
64 | enum { |
65 | STATE_INITIAL = 0, /* pseudo state */ |
66 | STATE_1PARAM, |
67 | STATE_2PARAM_1, |
68 | STATE_2PARAM_2, |
69 | STATE_SYSEX_0, |
70 | STATE_SYSEX_1, |
71 | STATE_SYSEX_2, |
72 | STATE_REAL_TIME, |
73 | STATE_FINISHED, /* pseudo state */ |
74 | }; |
75 | |
76 | /* Resources for UMP Endpoint */ |
77 | struct f_midi2_ep { |
78 | struct snd_ump_endpoint *ump; /* assigned UMP EP */ |
79 | struct f_midi2 *card; /* belonging MIDI 2.0 device */ |
80 | |
81 | struct f_midi2_ep_info info; /* UMP EP info, copied from configfs */ |
82 | unsigned int num_blks; /* number of FBs */ |
83 | struct f_midi2_block blks[SNDRV_UMP_MAX_BLOCKS]; /* UMP FBs */ |
84 | |
85 | struct f_midi2_usb_ep ep_in; /* USB MIDI EP-in */ |
86 | struct f_midi2_usb_ep ep_out; /* USB MIDI EP-out */ |
87 | |
88 | u8 in_group_to_cable[SNDRV_UMP_MAX_GROUPS]; /* map to cable; 1-based! */ |
89 | }; |
90 | |
91 | /* indices for USB strings */ |
92 | enum { |
93 | STR_IFACE = 0, |
94 | STR_GTB1 = 1, |
95 | }; |
96 | |
97 | /* 1-based GTB id to string id */ |
98 | #define gtb_to_str_id(id) (STR_GTB1 + (id) - 1) |
99 | |
100 | /* mapping from MIDI 1.0 cable to UMP group */ |
101 | struct midi1_cable_mapping { |
102 | struct f_midi2_ep *ep; |
103 | unsigned char block; |
104 | unsigned char group; |
105 | }; |
106 | |
107 | /* operation mode */ |
108 | enum { |
109 | MIDI_OP_MODE_UNSET, /* no altset set yet */ |
110 | MIDI_OP_MODE_MIDI1, /* MIDI 1.0 (altset 0) is used */ |
111 | MIDI_OP_MODE_MIDI2, /* MIDI 2.0 (altset 1) is used */ |
112 | }; |
113 | |
114 | /* Resources for MIDI 2.0 Device */ |
115 | struct f_midi2 { |
116 | struct usb_function func; |
117 | struct usb_gadget *gadget; |
118 | struct snd_card *card; |
119 | |
120 | /* MIDI 1.0 in/out USB EPs */ |
121 | struct f_midi2_usb_ep midi1_ep_in; |
122 | struct f_midi2_usb_ep midi1_ep_out; |
123 | |
124 | /* number of MIDI 1.0 I/O cables */ |
125 | unsigned int num_midi1_in; |
126 | unsigned int num_midi1_out; |
127 | |
128 | /* conversion for MIDI 1.0 EP-in */ |
129 | struct f_midi2_midi1_port midi1_port[MAX_CABLES]; |
130 | /* conversion for MIDI 1.0 EP-out */ |
131 | struct ump_cvt_to_ump midi1_ump_cvt; |
132 | /* mapping between cables and UMP groups */ |
133 | struct midi1_cable_mapping in_cable_mapping[MAX_CABLES]; |
134 | struct midi1_cable_mapping out_cable_mapping[MAX_CABLES]; |
135 | |
136 | int midi_if; /* USB MIDI interface number */ |
137 | int operation_mode; /* current operation mode */ |
138 | |
139 | spinlock_t queue_lock; |
140 | |
141 | struct f_midi2_card_info info; /* card info, copied from configfs */ |
142 | |
143 | unsigned int num_eps; |
144 | struct f_midi2_ep midi2_eps[MAX_UMP_EPS]; |
145 | |
146 | unsigned int total_blocks; /* total number of blocks of all EPs */ |
147 | struct usb_string *string_defs; |
148 | struct usb_string *strings; |
149 | }; |
150 | |
151 | #define func_to_midi2(f) container_of(f, struct f_midi2, func) |
152 | |
153 | /* get EP name string */ |
154 | static const char *ump_ep_name(const struct f_midi2_ep *ep) |
155 | { |
156 | return ep->info.ep_name ? ep->info.ep_name : "MIDI 2.0 Gadget" ; |
157 | } |
158 | |
159 | /* get EP product ID string */ |
160 | static const char *ump_product_id(const struct f_midi2_ep *ep) |
161 | { |
162 | return ep->info.product_id ? ep->info.product_id : "Unique Product ID" ; |
163 | } |
164 | |
165 | /* get FB name string */ |
166 | static const char *ump_fb_name(const struct f_midi2_block_info *info) |
167 | { |
168 | return info->name ? info->name : "MIDI 2.0 Gadget I/O" ; |
169 | } |
170 | |
171 | /* |
172 | * USB Descriptor Definitions |
173 | */ |
174 | /* GTB header descriptor */ |
175 | static struct usb_ms20_gr_trm_block_header_descriptor = { |
176 | .bLength = sizeof(gtb_header_desc), |
177 | .bDescriptorType = USB_DT_CS_GR_TRM_BLOCK, |
178 | .bDescriptorSubtype = USB_MS_GR_TRM_BLOCK_HEADER, |
179 | .wTotalLength = __cpu_to_le16(0x12), // to be filled |
180 | }; |
181 | |
182 | /* GTB descriptor template: most items are replaced dynamically */ |
183 | static struct usb_ms20_gr_trm_block_descriptor gtb_desc = { |
184 | .bLength = sizeof(gtb_desc), |
185 | .bDescriptorType = USB_DT_CS_GR_TRM_BLOCK, |
186 | .bDescriptorSubtype = USB_MS_GR_TRM_BLOCK, |
187 | .bGrpTrmBlkID = 0x01, |
188 | .bGrpTrmBlkType = USB_MS_GR_TRM_BLOCK_TYPE_BIDIRECTIONAL, |
189 | .nGroupTrm = 0x00, |
190 | .nNumGroupTrm = 1, |
191 | .iBlockItem = 0, |
192 | .bMIDIProtocol = USB_MS_MIDI_PROTO_1_0_64, |
193 | .wMaxInputBandwidth = 0, |
194 | .wMaxOutputBandwidth = 0, |
195 | }; |
196 | |
197 | DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); |
198 | DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(16); |
199 | DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); |
200 | DECLARE_USB_MS20_ENDPOINT_DESCRIPTOR(32); |
201 | |
202 | #define EP_MAX_PACKET_INT 8 |
203 | |
204 | /* Audio Control Interface */ |
205 | static struct usb_interface_descriptor midi2_audio_if_desc = { |
206 | .bLength = USB_DT_INTERFACE_SIZE, |
207 | .bDescriptorType = USB_DT_INTERFACE, |
208 | .bInterfaceNumber = 0, // to be filled |
209 | .bNumEndpoints = 0, |
210 | .bInterfaceClass = USB_CLASS_AUDIO, |
211 | .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, |
212 | .bInterfaceProtocol = 0, |
213 | .iInterface = 0, |
214 | }; |
215 | |
216 | static struct uac1_ac_header_descriptor_1 midi2_audio_class_desc = { |
217 | .bLength = 0x09, |
218 | .bDescriptorType = USB_DT_CS_INTERFACE, |
219 | .bDescriptorSubtype = 0x01, |
220 | .bcdADC = __cpu_to_le16(0x0100), |
221 | .wTotalLength = __cpu_to_le16(0x0009), |
222 | .bInCollection = 0x01, |
223 | .baInterfaceNr = { 0x01 }, // to be filled |
224 | }; |
225 | |
226 | /* MIDI 1.0 Streaming Interface (altset 0) */ |
227 | static struct usb_interface_descriptor midi2_midi1_if_desc = { |
228 | .bLength = USB_DT_INTERFACE_SIZE, |
229 | .bDescriptorType = USB_DT_INTERFACE, |
230 | .bInterfaceNumber = 0, // to be filled |
231 | .bAlternateSetting = 0, |
232 | .bNumEndpoints = 2, // to be filled |
233 | .bInterfaceClass = USB_CLASS_AUDIO, |
234 | .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, |
235 | .bInterfaceProtocol = 0, |
236 | .iInterface = 0, // to be filled |
237 | }; |
238 | |
239 | static struct usb_ms_header_descriptor midi2_midi1_class_desc = { |
240 | .bLength = 0x07, |
241 | .bDescriptorType = USB_DT_CS_INTERFACE, |
242 | .bDescriptorSubtype = USB_MS_HEADER, |
243 | .bcdMSC = __cpu_to_le16(0x0100), |
244 | .wTotalLength = __cpu_to_le16(0x41), // to be calculated |
245 | }; |
246 | |
247 | /* MIDI 1.0 EP OUT */ |
248 | static struct usb_endpoint_descriptor midi2_midi1_ep_out_desc = { |
249 | .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, |
250 | .bDescriptorType = USB_DT_ENDPOINT, |
251 | .bEndpointAddress = USB_DIR_OUT | 0, // set up dynamically |
252 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
253 | }; |
254 | |
255 | static struct usb_ss_ep_comp_descriptor midi2_midi1_ep_out_ss_comp_desc = { |
256 | .bLength = sizeof(midi2_midi1_ep_out_ss_comp_desc), |
257 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
258 | }; |
259 | |
260 | static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_out_class_desc = { |
261 | .bLength = 0x05, // to be filled |
262 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
263 | .bDescriptorSubtype = USB_MS_GENERAL, |
264 | .bNumEmbMIDIJack = 1, |
265 | .baAssocJackID = { 0x01 }, |
266 | }; |
267 | |
268 | /* MIDI 1.0 EP IN */ |
269 | static struct usb_endpoint_descriptor midi2_midi1_ep_in_desc = { |
270 | .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, |
271 | .bDescriptorType = USB_DT_ENDPOINT, |
272 | .bEndpointAddress = USB_DIR_IN | 0, // set up dynamically |
273 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
274 | }; |
275 | |
276 | static struct usb_ss_ep_comp_descriptor midi2_midi1_ep_in_ss_comp_desc = { |
277 | .bLength = sizeof(midi2_midi1_ep_in_ss_comp_desc), |
278 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
279 | }; |
280 | |
281 | static struct usb_ms_endpoint_descriptor_16 midi2_midi1_ep_in_class_desc = { |
282 | .bLength = 0x05, // to be filled |
283 | .bDescriptorType = USB_DT_CS_ENDPOINT, |
284 | .bDescriptorSubtype = USB_MS_GENERAL, |
285 | .bNumEmbMIDIJack = 1, |
286 | .baAssocJackID = { 0x03 }, |
287 | }; |
288 | |
289 | /* MIDI 2.0 Streaming Interface (altset 1) */ |
290 | static struct usb_interface_descriptor midi2_midi2_if_desc = { |
291 | .bLength = USB_DT_INTERFACE_SIZE, |
292 | .bDescriptorType = USB_DT_INTERFACE, |
293 | .bInterfaceNumber = 0, // to be filled |
294 | .bAlternateSetting = 1, |
295 | .bNumEndpoints = 2, // to be filled |
296 | .bInterfaceClass = USB_CLASS_AUDIO, |
297 | .bInterfaceSubClass = USB_SUBCLASS_MIDISTREAMING, |
298 | .bInterfaceProtocol = 0, |
299 | .iInterface = 0, // to be filled |
300 | }; |
301 | |
302 | static struct usb_ms_header_descriptor midi2_midi2_class_desc = { |
303 | .bLength = 0x07, |
304 | .bDescriptorType = USB_DT_CS_INTERFACE, |
305 | .bDescriptorSubtype = USB_MS_HEADER, |
306 | .bcdMSC = __cpu_to_le16(0x0200), |
307 | .wTotalLength = __cpu_to_le16(0x07), |
308 | }; |
309 | |
310 | /* MIDI 2.0 EP OUT */ |
311 | static struct usb_endpoint_descriptor midi2_midi2_ep_out_desc[MAX_UMP_EPS]; |
312 | |
313 | static struct usb_ss_ep_comp_descriptor midi2_midi2_ep_out_ss_comp_desc = { |
314 | .bLength = sizeof(midi2_midi1_ep_out_ss_comp_desc), |
315 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
316 | }; |
317 | |
318 | static struct usb_ms20_endpoint_descriptor_32 midi2_midi2_ep_out_class_desc[MAX_UMP_EPS]; |
319 | |
320 | /* MIDI 2.0 EP IN */ |
321 | static struct usb_endpoint_descriptor midi2_midi2_ep_in_desc[MAX_UMP_EPS]; |
322 | |
323 | static struct usb_ss_ep_comp_descriptor midi2_midi2_ep_in_ss_comp_desc = { |
324 | .bLength = sizeof(midi2_midi2_ep_in_ss_comp_desc), |
325 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
326 | }; |
327 | |
328 | static struct usb_ms20_endpoint_descriptor_32 midi2_midi2_ep_in_class_desc[MAX_UMP_EPS]; |
329 | |
330 | /* Arrays of descriptors to be created */ |
331 | static void *midi2_audio_descs[] = { |
332 | &midi2_audio_if_desc, |
333 | &midi2_audio_class_desc, |
334 | NULL |
335 | }; |
336 | |
337 | static void *midi2_midi1_descs[] = { |
338 | &midi2_midi1_if_desc, |
339 | &midi2_midi1_class_desc, |
340 | NULL |
341 | }; |
342 | |
343 | static void *midi2_midi1_ep_out_descs[] = { |
344 | &midi2_midi1_ep_out_desc, |
345 | &midi2_midi1_ep_out_class_desc, |
346 | NULL |
347 | }; |
348 | |
349 | static void *midi2_midi1_ep_in_descs[] = { |
350 | &midi2_midi1_ep_in_desc, |
351 | &midi2_midi1_ep_in_class_desc, |
352 | NULL |
353 | }; |
354 | |
355 | static void *midi2_midi1_ep_out_ss_descs[] = { |
356 | &midi2_midi1_ep_out_desc, |
357 | &midi2_midi1_ep_out_ss_comp_desc, |
358 | &midi2_midi1_ep_out_class_desc, |
359 | NULL |
360 | }; |
361 | |
362 | static void *midi2_midi1_ep_in_ss_descs[] = { |
363 | &midi2_midi1_ep_in_desc, |
364 | &midi2_midi1_ep_in_ss_comp_desc, |
365 | &midi2_midi1_ep_in_class_desc, |
366 | NULL |
367 | }; |
368 | |
369 | static void *midi2_midi2_descs[] = { |
370 | &midi2_midi2_if_desc, |
371 | &midi2_midi2_class_desc, |
372 | NULL |
373 | }; |
374 | |
375 | /* |
376 | * USB request handling |
377 | */ |
378 | |
379 | /* get an empty request for the given EP */ |
380 | static struct usb_request *get_empty_request(struct f_midi2_usb_ep *usb_ep) |
381 | { |
382 | struct usb_request *req = NULL; |
383 | unsigned long flags; |
384 | int index; |
385 | |
386 | spin_lock_irqsave(&usb_ep->card->queue_lock, flags); |
387 | if (!usb_ep->free_reqs) |
388 | goto unlock; |
389 | index = find_first_bit(addr: &usb_ep->free_reqs, size: usb_ep->num_reqs); |
390 | if (index >= usb_ep->num_reqs) |
391 | goto unlock; |
392 | req = usb_ep->reqs[index].req; |
393 | if (!req) |
394 | goto unlock; |
395 | clear_bit(nr: index, addr: &usb_ep->free_reqs); |
396 | req->length = 0; |
397 | unlock: |
398 | spin_unlock_irqrestore(lock: &usb_ep->card->queue_lock, flags); |
399 | return req; |
400 | } |
401 | |
402 | /* put the empty request back */ |
403 | static void put_empty_request(struct usb_request *req) |
404 | { |
405 | struct f_midi2_req_ctx *ctx = req->context; |
406 | unsigned long flags; |
407 | |
408 | spin_lock_irqsave(&ctx->usb_ep->card->queue_lock, flags); |
409 | set_bit(nr: ctx->index, addr: &ctx->usb_ep->free_reqs); |
410 | spin_unlock_irqrestore(lock: &ctx->usb_ep->card->queue_lock, flags); |
411 | } |
412 | |
413 | /* |
414 | * UMP v1.1 Stream message handling |
415 | */ |
416 | |
417 | /* queue a request to UMP EP; request is either queued or freed after this */ |
418 | static int queue_request_ep_raw(struct usb_request *req) |
419 | { |
420 | struct f_midi2_req_ctx *ctx = req->context; |
421 | int err; |
422 | |
423 | req->complete = ctx->usb_ep->complete; |
424 | err = usb_ep_queue(ep: ctx->usb_ep->usb_ep, req, GFP_ATOMIC); |
425 | if (err) { |
426 | put_empty_request(req); |
427 | return err; |
428 | } |
429 | return 0; |
430 | } |
431 | |
432 | /* queue a request with endianness conversion */ |
433 | static int queue_request_ep_in(struct usb_request *req) |
434 | { |
435 | /* UMP packets have to be converted to little-endian */ |
436 | cpu_to_le32_array(buf: (u32 *)req->buf, words: req->length >> 2); |
437 | return queue_request_ep_raw(req); |
438 | } |
439 | |
440 | /* reply a UMP packet via EP-in */ |
441 | static int reply_ep_in(struct f_midi2_ep *ep, const void *buf, int len) |
442 | { |
443 | struct f_midi2_usb_ep *usb_ep = &ep->ep_in; |
444 | struct usb_request *req; |
445 | |
446 | req = get_empty_request(usb_ep); |
447 | if (!req) |
448 | return -ENOSPC; |
449 | |
450 | req->length = len; |
451 | memcpy(req->buf, buf, len); |
452 | return queue_request_ep_in(req); |
453 | } |
454 | |
455 | /* reply a UMP stream EP info */ |
456 | static void reply_ump_stream_ep_info(struct f_midi2_ep *ep) |
457 | { |
458 | struct snd_ump_stream_msg_ep_info rep = { |
459 | .type = UMP_MSG_TYPE_STREAM, |
460 | .status = UMP_STREAM_MSG_STATUS_EP_INFO, |
461 | .ump_version_major = 0x01, |
462 | .ump_version_minor = 0x01, |
463 | .num_function_blocks = ep->num_blks, |
464 | .static_function_block = !!ep->card->info.static_block, |
465 | .protocol = (UMP_STREAM_MSG_EP_INFO_CAP_MIDI1 | |
466 | UMP_STREAM_MSG_EP_INFO_CAP_MIDI2) >> 8, |
467 | }; |
468 | |
469 | reply_ep_in(ep, buf: &rep, len: sizeof(rep)); |
470 | } |
471 | |
472 | /* reply a UMP EP device info */ |
473 | static void reply_ump_stream_ep_device(struct f_midi2_ep *ep) |
474 | { |
475 | struct snd_ump_stream_msg_devince_info rep = { |
476 | .type = UMP_MSG_TYPE_STREAM, |
477 | .status = UMP_STREAM_MSG_STATUS_DEVICE_INFO, |
478 | .manufacture_id = ep->info.manufacturer, |
479 | .family_lsb = ep->info.family & 0xff, |
480 | .family_msb = (ep->info.family >> 8) & 0xff, |
481 | .model_lsb = ep->info.model & 0xff, |
482 | .model_msb = (ep->info.model >> 8) & 0xff, |
483 | .sw_revision = ep->info.sw_revision, |
484 | }; |
485 | |
486 | reply_ep_in(ep, buf: &rep, len: sizeof(rep)); |
487 | } |
488 | |
489 | #define UMP_STREAM_PKT_BYTES 16 /* UMP stream packet size = 16 bytes*/ |
490 | #define UMP_STREAM_EP_STR_OFF 2 /* offset of name string for EP info */ |
491 | #define UMP_STREAM_FB_STR_OFF 3 /* offset of name string for FB info */ |
492 | |
493 | /* Helper to replay a string */ |
494 | static void reply_ump_stream_string(struct f_midi2_ep *ep, const u8 *name, |
495 | unsigned int type, unsigned int , |
496 | unsigned int start_ofs) |
497 | { |
498 | struct f_midi2_usb_ep *usb_ep = &ep->ep_in; |
499 | struct f_midi2 *midi2 = ep->card; |
500 | struct usb_request *req; |
501 | unsigned int pos; |
502 | u32 *buf; |
503 | |
504 | if (!*name) |
505 | return; |
506 | req = get_empty_request(usb_ep); |
507 | if (!req) |
508 | return; |
509 | |
510 | buf = (u32 *)req->buf; |
511 | pos = start_ofs; |
512 | for (;;) { |
513 | if (pos == start_ofs) { |
514 | memset(buf, 0, UMP_STREAM_PKT_BYTES); |
515 | buf[0] = ump_stream_compose(status: type, form: 0) | extra; |
516 | } |
517 | buf[pos / 4] |= *name++ << ((3 - (pos % 4)) * 8); |
518 | if (!*name) { |
519 | if (req->length) |
520 | buf[0] |= UMP_STREAM_MSG_FORMAT_END << 26; |
521 | req->length += UMP_STREAM_PKT_BYTES; |
522 | break; |
523 | } |
524 | if (++pos == UMP_STREAM_PKT_BYTES) { |
525 | if (!req->length) |
526 | buf[0] |= UMP_STREAM_MSG_FORMAT_START << 26; |
527 | else |
528 | buf[0] |= UMP_STREAM_MSG_FORMAT_CONTINUE << 26; |
529 | req->length += UMP_STREAM_PKT_BYTES; |
530 | if (midi2->info.req_buf_size - req->length < UMP_STREAM_PKT_BYTES) |
531 | break; |
532 | buf += 4; |
533 | pos = start_ofs; |
534 | } |
535 | } |
536 | |
537 | if (req->length) |
538 | queue_request_ep_in(req); |
539 | else |
540 | put_empty_request(req); |
541 | } |
542 | |
543 | /* Reply a UMP EP name string */ |
544 | static void reply_ump_stream_ep_name(struct f_midi2_ep *ep) |
545 | { |
546 | reply_ump_stream_string(ep, name: ump_ep_name(ep), |
547 | type: UMP_STREAM_MSG_STATUS_EP_NAME, extra: 0, |
548 | UMP_STREAM_EP_STR_OFF); |
549 | } |
550 | |
551 | /* Reply a UMP EP product ID string */ |
552 | static void reply_ump_stream_ep_pid(struct f_midi2_ep *ep) |
553 | { |
554 | reply_ump_stream_string(ep, name: ump_product_id(ep), |
555 | type: UMP_STREAM_MSG_STATUS_PRODUCT_ID, extra: 0, |
556 | UMP_STREAM_EP_STR_OFF); |
557 | } |
558 | |
559 | /* Reply a UMP EP stream config */ |
560 | static void reply_ump_stream_ep_config(struct f_midi2_ep *ep) |
561 | { |
562 | struct snd_ump_stream_msg_stream_cfg rep = { |
563 | .type = UMP_MSG_TYPE_STREAM, |
564 | .status = UMP_STREAM_MSG_STATUS_STREAM_CFG, |
565 | }; |
566 | |
567 | if ((ep->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI_MASK) == |
568 | SNDRV_UMP_EP_INFO_PROTO_MIDI2) |
569 | rep.protocol = UMP_STREAM_MSG_EP_INFO_CAP_MIDI2 >> 8; |
570 | else |
571 | rep.protocol = UMP_STREAM_MSG_EP_INFO_CAP_MIDI1 >> 8; |
572 | |
573 | reply_ep_in(ep, buf: &rep, len: sizeof(rep)); |
574 | } |
575 | |
576 | /* Reply a UMP FB info */ |
577 | static void reply_ump_stream_fb_info(struct f_midi2_ep *ep, int blk) |
578 | { |
579 | struct f_midi2_block_info *b = &ep->blks[blk].info; |
580 | struct snd_ump_stream_msg_fb_info rep = { |
581 | .type = UMP_MSG_TYPE_STREAM, |
582 | .status = UMP_STREAM_MSG_STATUS_FB_INFO, |
583 | .active = !!b->active, |
584 | .function_block_id = blk, |
585 | .ui_hint = b->ui_hint, |
586 | .midi_10 = b->is_midi1, |
587 | .direction = b->direction, |
588 | .first_group = b->first_group, |
589 | .num_groups = b->num_groups, |
590 | .midi_ci_version = b->midi_ci_version, |
591 | .sysex8_streams = b->sysex8_streams, |
592 | }; |
593 | |
594 | reply_ep_in(ep, buf: &rep, len: sizeof(rep)); |
595 | } |
596 | |
597 | /* Reply a FB name string */ |
598 | static void reply_ump_stream_fb_name(struct f_midi2_ep *ep, unsigned int blk) |
599 | { |
600 | reply_ump_stream_string(ep, name: ump_fb_name(info: &ep->blks[blk].info), |
601 | type: UMP_STREAM_MSG_STATUS_FB_NAME, extra: blk << 8, |
602 | UMP_STREAM_FB_STR_OFF); |
603 | } |
604 | |
605 | /* Process a UMP Stream message */ |
606 | static void process_ump_stream_msg(struct f_midi2_ep *ep, const u32 *data) |
607 | { |
608 | struct f_midi2 *midi2 = ep->card; |
609 | unsigned int format, status, blk; |
610 | |
611 | format = ump_stream_message_format(data: *data); |
612 | status = ump_stream_message_status(data: *data); |
613 | switch (status) { |
614 | case UMP_STREAM_MSG_STATUS_EP_DISCOVERY: |
615 | if (format) |
616 | return; // invalid |
617 | if (data[1] & UMP_STREAM_MSG_REQUEST_EP_INFO) |
618 | reply_ump_stream_ep_info(ep); |
619 | if (data[1] & UMP_STREAM_MSG_REQUEST_DEVICE_INFO) |
620 | reply_ump_stream_ep_device(ep); |
621 | if (data[1] & UMP_STREAM_MSG_REQUEST_EP_NAME) |
622 | reply_ump_stream_ep_name(ep); |
623 | if (data[1] & UMP_STREAM_MSG_REQUEST_PRODUCT_ID) |
624 | reply_ump_stream_ep_pid(ep); |
625 | if (data[1] & UMP_STREAM_MSG_REQUEST_STREAM_CFG) |
626 | reply_ump_stream_ep_config(ep); |
627 | return; |
628 | case UMP_STREAM_MSG_STATUS_STREAM_CFG_REQUEST: |
629 | if (*data & UMP_STREAM_MSG_EP_INFO_CAP_MIDI2) { |
630 | ep->info.protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI2; |
631 | DBG(midi2, "Switching Protocol to MIDI2\n" ); |
632 | } else { |
633 | ep->info.protocol = SNDRV_UMP_EP_INFO_PROTO_MIDI1; |
634 | DBG(midi2, "Switching Protocol to MIDI1\n" ); |
635 | } |
636 | snd_ump_switch_protocol(ump: ep->ump, protocol: ep->info.protocol); |
637 | reply_ump_stream_ep_config(ep); |
638 | return; |
639 | case UMP_STREAM_MSG_STATUS_FB_DISCOVERY: |
640 | if (format) |
641 | return; // invalid |
642 | blk = (*data >> 8) & 0xff; |
643 | if (blk >= ep->num_blks) |
644 | return; |
645 | if (*data & UMP_STREAM_MSG_REQUEST_FB_INFO) |
646 | reply_ump_stream_fb_info(ep, blk); |
647 | if (*data & UMP_STREAM_MSG_REQUEST_FB_NAME) |
648 | reply_ump_stream_fb_name(ep, blk); |
649 | return; |
650 | } |
651 | } |
652 | |
653 | /* Process UMP messages included in a USB request */ |
654 | static void process_ump(struct f_midi2_ep *ep, const struct usb_request *req) |
655 | { |
656 | const u32 *data = (u32 *)req->buf; |
657 | int len = req->actual >> 2; |
658 | const u32 *in_buf = ep->ump->input_buf; |
659 | |
660 | for (; len > 0; len--, data++) { |
661 | if (snd_ump_receive_ump_val(ump: ep->ump, val: *data) <= 0) |
662 | continue; |
663 | if (ump_message_type(data: *in_buf) == UMP_MSG_TYPE_STREAM) |
664 | process_ump_stream_msg(ep, data: in_buf); |
665 | } |
666 | } |
667 | |
668 | /* |
669 | * MIDI 2.0 UMP USB request handling |
670 | */ |
671 | |
672 | /* complete handler for UMP EP-out requests */ |
673 | static void f_midi2_ep_out_complete(struct usb_ep *usb_ep, |
674 | struct usb_request *req) |
675 | { |
676 | struct f_midi2_req_ctx *ctx = req->context; |
677 | struct f_midi2_ep *ep = ctx->usb_ep->ep; |
678 | struct f_midi2 *midi2 = ep->card; |
679 | int status = req->status; |
680 | |
681 | if (status) { |
682 | DBG(midi2, "%s complete error %d: %d/%d\n" , |
683 | usb_ep->name, status, req->actual, req->length); |
684 | goto error; |
685 | } |
686 | |
687 | /* convert to UMP packet in native endianness */ |
688 | le32_to_cpu_array(buf: (u32 *)req->buf, words: req->actual >> 2); |
689 | |
690 | if (midi2->info.process_ump) |
691 | process_ump(ep, req); |
692 | |
693 | snd_ump_receive(ump: ep->ump, buffer: req->buf, count: req->actual & ~3); |
694 | |
695 | if (midi2->operation_mode != MIDI_OP_MODE_MIDI2) |
696 | goto error; |
697 | |
698 | if (queue_request_ep_raw(req)) |
699 | goto error; |
700 | return; |
701 | |
702 | error: |
703 | put_empty_request(req); |
704 | } |
705 | |
706 | /* Transmit UMP packets received from user-space to the gadget */ |
707 | static void process_ump_transmit(struct f_midi2_ep *ep) |
708 | { |
709 | struct f_midi2_usb_ep *usb_ep = &ep->ep_in; |
710 | struct f_midi2 *midi2 = ep->card; |
711 | struct usb_request *req; |
712 | int len; |
713 | |
714 | if (!usb_ep->usb_ep->enabled) |
715 | return; |
716 | |
717 | for (;;) { |
718 | req = get_empty_request(usb_ep); |
719 | if (!req) |
720 | break; |
721 | len = snd_ump_transmit(ump: ep->ump, buffer: (u32 *)req->buf, |
722 | count: midi2->info.req_buf_size); |
723 | if (len <= 0) { |
724 | put_empty_request(req); |
725 | break; |
726 | } |
727 | |
728 | req->length = len; |
729 | if (queue_request_ep_in(req) < 0) |
730 | break; |
731 | } |
732 | } |
733 | |
734 | /* Complete handler for UMP EP-in requests */ |
735 | static void f_midi2_ep_in_complete(struct usb_ep *usb_ep, |
736 | struct usb_request *req) |
737 | { |
738 | struct f_midi2_req_ctx *ctx = req->context; |
739 | struct f_midi2_ep *ep = ctx->usb_ep->ep; |
740 | struct f_midi2 *midi2 = ep->card; |
741 | int status = req->status; |
742 | |
743 | put_empty_request(req); |
744 | |
745 | if (status) { |
746 | DBG(midi2, "%s complete error %d: %d/%d\n" , |
747 | usb_ep->name, status, req->actual, req->length); |
748 | return; |
749 | } |
750 | |
751 | process_ump_transmit(ep); |
752 | } |
753 | |
754 | /* |
755 | * MIDI1 (altset 0) USB request handling |
756 | */ |
757 | |
758 | /* process one MIDI byte -- copied from f_midi.c |
759 | * |
760 | * fill the packet or request if needed |
761 | * returns true if the request became empty (queued) |
762 | */ |
763 | static bool process_midi1_byte(struct f_midi2 *midi2, u8 cable, u8 b, |
764 | struct usb_request **req_p) |
765 | { |
766 | struct f_midi2_midi1_port *port = &midi2->midi1_port[cable]; |
767 | u8 p[4] = { cable << 4, 0, 0, 0 }; |
768 | int next_state = STATE_INITIAL; |
769 | struct usb_request *req = *req_p; |
770 | |
771 | switch (b) { |
772 | case 0xf8 ... 0xff: |
773 | /* System Real-Time Messages */ |
774 | p[0] |= 0x0f; |
775 | p[1] = b; |
776 | next_state = port->state; |
777 | port->state = STATE_REAL_TIME; |
778 | break; |
779 | |
780 | case 0xf7: |
781 | /* End of SysEx */ |
782 | switch (port->state) { |
783 | case STATE_SYSEX_0: |
784 | p[0] |= 0x05; |
785 | p[1] = 0xf7; |
786 | next_state = STATE_FINISHED; |
787 | break; |
788 | case STATE_SYSEX_1: |
789 | p[0] |= 0x06; |
790 | p[1] = port->data[0]; |
791 | p[2] = 0xf7; |
792 | next_state = STATE_FINISHED; |
793 | break; |
794 | case STATE_SYSEX_2: |
795 | p[0] |= 0x07; |
796 | p[1] = port->data[0]; |
797 | p[2] = port->data[1]; |
798 | p[3] = 0xf7; |
799 | next_state = STATE_FINISHED; |
800 | break; |
801 | default: |
802 | /* Ignore byte */ |
803 | next_state = port->state; |
804 | port->state = STATE_INITIAL; |
805 | } |
806 | break; |
807 | |
808 | case 0xf0 ... 0xf6: |
809 | /* System Common Messages */ |
810 | port->data[0] = port->data[1] = 0; |
811 | port->state = STATE_INITIAL; |
812 | switch (b) { |
813 | case 0xf0: |
814 | port->data[0] = b; |
815 | port->data[1] = 0; |
816 | next_state = STATE_SYSEX_1; |
817 | break; |
818 | case 0xf1: |
819 | case 0xf3: |
820 | port->data[0] = b; |
821 | next_state = STATE_1PARAM; |
822 | break; |
823 | case 0xf2: |
824 | port->data[0] = b; |
825 | next_state = STATE_2PARAM_1; |
826 | break; |
827 | case 0xf4: |
828 | case 0xf5: |
829 | next_state = STATE_INITIAL; |
830 | break; |
831 | case 0xf6: |
832 | p[0] |= 0x05; |
833 | p[1] = 0xf6; |
834 | next_state = STATE_FINISHED; |
835 | break; |
836 | } |
837 | break; |
838 | |
839 | case 0x80 ... 0xef: |
840 | /* |
841 | * Channel Voice Messages, Channel Mode Messages |
842 | * and Control Change Messages. |
843 | */ |
844 | port->data[0] = b; |
845 | port->data[1] = 0; |
846 | port->state = STATE_INITIAL; |
847 | if (b >= 0xc0 && b <= 0xdf) |
848 | next_state = STATE_1PARAM; |
849 | else |
850 | next_state = STATE_2PARAM_1; |
851 | break; |
852 | |
853 | case 0x00 ... 0x7f: |
854 | /* Message parameters */ |
855 | switch (port->state) { |
856 | case STATE_1PARAM: |
857 | if (port->data[0] < 0xf0) |
858 | p[0] |= port->data[0] >> 4; |
859 | else |
860 | p[0] |= 0x02; |
861 | |
862 | p[1] = port->data[0]; |
863 | p[2] = b; |
864 | /* This is to allow Running State Messages */ |
865 | next_state = STATE_1PARAM; |
866 | break; |
867 | case STATE_2PARAM_1: |
868 | port->data[1] = b; |
869 | next_state = STATE_2PARAM_2; |
870 | break; |
871 | case STATE_2PARAM_2: |
872 | if (port->data[0] < 0xf0) |
873 | p[0] |= port->data[0] >> 4; |
874 | else |
875 | p[0] |= 0x03; |
876 | |
877 | p[1] = port->data[0]; |
878 | p[2] = port->data[1]; |
879 | p[3] = b; |
880 | /* This is to allow Running State Messages */ |
881 | next_state = STATE_2PARAM_1; |
882 | break; |
883 | case STATE_SYSEX_0: |
884 | port->data[0] = b; |
885 | next_state = STATE_SYSEX_1; |
886 | break; |
887 | case STATE_SYSEX_1: |
888 | port->data[1] = b; |
889 | next_state = STATE_SYSEX_2; |
890 | break; |
891 | case STATE_SYSEX_2: |
892 | p[0] |= 0x04; |
893 | p[1] = port->data[0]; |
894 | p[2] = port->data[1]; |
895 | p[3] = b; |
896 | next_state = STATE_SYSEX_0; |
897 | break; |
898 | } |
899 | break; |
900 | } |
901 | |
902 | /* States where we have to write into the USB request */ |
903 | if (next_state == STATE_FINISHED || |
904 | port->state == STATE_SYSEX_2 || |
905 | port->state == STATE_1PARAM || |
906 | port->state == STATE_2PARAM_2 || |
907 | port->state == STATE_REAL_TIME) { |
908 | memcpy(req->buf + req->length, p, sizeof(p)); |
909 | req->length += sizeof(p); |
910 | |
911 | if (next_state == STATE_FINISHED) { |
912 | next_state = STATE_INITIAL; |
913 | port->data[0] = port->data[1] = 0; |
914 | } |
915 | |
916 | if (midi2->info.req_buf_size - req->length <= 4) { |
917 | queue_request_ep_raw(req); |
918 | *req_p = NULL; |
919 | return true; |
920 | } |
921 | } |
922 | |
923 | port->state = next_state; |
924 | return false; |
925 | } |
926 | |
927 | /* process all pending MIDI bytes in the internal buffer; |
928 | * returns true if the request gets empty |
929 | * returns false if all have been processed |
930 | */ |
931 | static bool process_midi1_pending_buf(struct f_midi2 *midi2, |
932 | struct usb_request **req_p) |
933 | { |
934 | unsigned int cable, c; |
935 | |
936 | for (cable = 0; cable < midi2->num_midi1_in; cable++) { |
937 | struct f_midi2_midi1_port *port = &midi2->midi1_port[cable]; |
938 | |
939 | if (!port->pending) |
940 | continue; |
941 | for (c = 0; c < port->pending; c++) { |
942 | if (process_midi1_byte(midi2, cable, b: port->buf[c], |
943 | req_p)) { |
944 | port->pending -= c; |
945 | if (port->pending) |
946 | memmove(port->buf, port->buf + c, |
947 | port->pending); |
948 | return true; |
949 | } |
950 | } |
951 | port->pending = 0; |
952 | } |
953 | |
954 | return false; |
955 | } |
956 | |
957 | /* fill the MIDI bytes onto the temporary buffer |
958 | */ |
959 | static void fill_midi1_pending_buf(struct f_midi2 *midi2, u8 cable, u8 *buf, |
960 | unsigned int size) |
961 | { |
962 | struct f_midi2_midi1_port *port = &midi2->midi1_port[cable]; |
963 | |
964 | if (port->pending + size > sizeof(port->buf)) |
965 | return; |
966 | memcpy(port->buf + port->pending, buf, size); |
967 | port->pending += size; |
968 | } |
969 | |
970 | /* try to process data given from the associated UMP stream */ |
971 | static void process_midi1_transmit(struct f_midi2 *midi2) |
972 | { |
973 | struct f_midi2_usb_ep *usb_ep = &midi2->midi1_ep_in; |
974 | struct f_midi2_ep *ep = &midi2->midi2_eps[0]; |
975 | struct usb_request *req = NULL; |
976 | /* 12 is the largest outcome (4 MIDI1 cmds) for a single UMP packet */ |
977 | unsigned char outbuf[12]; |
978 | unsigned char group, cable; |
979 | int len, size; |
980 | u32 ump; |
981 | |
982 | if (!usb_ep->usb_ep || !usb_ep->usb_ep->enabled) |
983 | return; |
984 | |
985 | for (;;) { |
986 | if (!req) { |
987 | req = get_empty_request(usb_ep); |
988 | if (!req) |
989 | break; |
990 | } |
991 | |
992 | if (process_midi1_pending_buf(midi2, req_p: &req)) |
993 | continue; |
994 | |
995 | len = snd_ump_transmit(ump: ep->ump, buffer: &ump, count: 4); |
996 | if (len <= 0) |
997 | break; |
998 | if (snd_ump_receive_ump_val(ump: ep->ump, val: ump) <= 0) |
999 | continue; |
1000 | size = snd_ump_convert_from_ump(data: ep->ump->input_buf, dst: outbuf, |
1001 | group_ret: &group); |
1002 | if (size <= 0) |
1003 | continue; |
1004 | cable = ep->in_group_to_cable[group]; |
1005 | if (!cable) |
1006 | continue; |
1007 | cable--; /* to 0-base */ |
1008 | fill_midi1_pending_buf(midi2, cable, buf: outbuf, size); |
1009 | } |
1010 | |
1011 | if (req) { |
1012 | if (req->length) |
1013 | queue_request_ep_raw(req); |
1014 | else |
1015 | put_empty_request(req); |
1016 | } |
1017 | } |
1018 | |
1019 | /* complete handler for MIDI1 EP-in requests */ |
1020 | static void f_midi2_midi1_ep_in_complete(struct usb_ep *usb_ep, |
1021 | struct usb_request *req) |
1022 | { |
1023 | struct f_midi2_req_ctx *ctx = req->context; |
1024 | struct f_midi2 *midi2 = ctx->usb_ep->card; |
1025 | int status = req->status; |
1026 | |
1027 | put_empty_request(req); |
1028 | |
1029 | if (status) { |
1030 | DBG(midi2, "%s complete error %d: %d/%d\n" , |
1031 | usb_ep->name, status, req->actual, req->length); |
1032 | return; |
1033 | } |
1034 | |
1035 | process_midi1_transmit(midi2); |
1036 | } |
1037 | |
1038 | /* complete handler for MIDI1 EP-out requests */ |
1039 | static void f_midi2_midi1_ep_out_complete(struct usb_ep *usb_ep, |
1040 | struct usb_request *req) |
1041 | { |
1042 | struct f_midi2_req_ctx *ctx = req->context; |
1043 | struct f_midi2 *midi2 = ctx->usb_ep->card; |
1044 | struct f_midi2_ep *ep; |
1045 | struct ump_cvt_to_ump *cvt = &midi2->midi1_ump_cvt; |
1046 | static const u8 midi1_packet_bytes[16] = { |
1047 | 0, 0, 2, 3, 3, 1, 2, 3, 3, 3, 3, 3, 2, 2, 3, 1 |
1048 | }; |
1049 | unsigned int group, cable, bytes, c, len; |
1050 | int status = req->status; |
1051 | const u8 *buf = req->buf; |
1052 | |
1053 | if (status) { |
1054 | DBG(midi2, "%s complete error %d: %d/%d\n" , |
1055 | usb_ep->name, status, req->actual, req->length); |
1056 | goto error; |
1057 | } |
1058 | |
1059 | len = req->actual >> 2; |
1060 | for (; len; len--, buf += 4) { |
1061 | cable = *buf >> 4; |
1062 | ep = midi2->out_cable_mapping[cable].ep; |
1063 | if (!ep) |
1064 | continue; |
1065 | group = midi2->out_cable_mapping[cable].group; |
1066 | bytes = midi1_packet_bytes[*buf & 0x0f]; |
1067 | for (c = 0; c < bytes; c++) { |
1068 | snd_ump_convert_to_ump(cvt, group, protocol: ep->info.protocol, |
1069 | c: buf[c + 1]); |
1070 | if (cvt->ump_bytes) { |
1071 | snd_ump_receive(ump: ep->ump, buffer: cvt->ump, |
1072 | count: cvt->ump_bytes); |
1073 | cvt->ump_bytes = 0; |
1074 | } |
1075 | } |
1076 | } |
1077 | |
1078 | if (midi2->operation_mode != MIDI_OP_MODE_MIDI1) |
1079 | goto error; |
1080 | |
1081 | if (queue_request_ep_raw(req)) |
1082 | goto error; |
1083 | return; |
1084 | |
1085 | error: |
1086 | put_empty_request(req); |
1087 | } |
1088 | |
1089 | /* |
1090 | * Common EP handling helpers |
1091 | */ |
1092 | |
1093 | /* Start MIDI EP */ |
1094 | static int f_midi2_start_ep(struct f_midi2_usb_ep *usb_ep, |
1095 | struct usb_function *fn) |
1096 | { |
1097 | int err; |
1098 | |
1099 | if (!usb_ep->usb_ep) |
1100 | return 0; |
1101 | |
1102 | usb_ep_disable(ep: usb_ep->usb_ep); |
1103 | err = config_ep_by_speed(g: usb_ep->card->gadget, f: fn, ep: usb_ep->usb_ep); |
1104 | if (err) |
1105 | return err; |
1106 | return usb_ep_enable(ep: usb_ep->usb_ep); |
1107 | } |
1108 | |
1109 | /* Drop pending requests */ |
1110 | static void f_midi2_drop_reqs(struct f_midi2_usb_ep *usb_ep) |
1111 | { |
1112 | int i; |
1113 | |
1114 | if (!usb_ep->usb_ep || !usb_ep->num_reqs) |
1115 | return; |
1116 | |
1117 | for (i = 0; i < usb_ep->num_reqs; i++) { |
1118 | if (!test_bit(i, &usb_ep->free_reqs) && usb_ep->reqs[i].req) { |
1119 | usb_ep_dequeue(ep: usb_ep->usb_ep, req: usb_ep->reqs[i].req); |
1120 | set_bit(nr: i, addr: &usb_ep->free_reqs); |
1121 | } |
1122 | } |
1123 | } |
1124 | |
1125 | /* Allocate requests for the given EP */ |
1126 | static int f_midi2_alloc_ep_reqs(struct f_midi2_usb_ep *usb_ep) |
1127 | { |
1128 | struct f_midi2 *midi2 = usb_ep->card; |
1129 | int i; |
1130 | |
1131 | if (!usb_ep->usb_ep) |
1132 | return 0; |
1133 | if (!usb_ep->reqs) |
1134 | return -EINVAL; |
1135 | |
1136 | for (i = 0; i < midi2->info.num_reqs; i++) { |
1137 | if (usb_ep->reqs[i].req) |
1138 | continue; |
1139 | usb_ep->reqs[i].req = alloc_ep_req(ep: usb_ep->usb_ep, |
1140 | len: midi2->info.req_buf_size); |
1141 | if (!usb_ep->reqs[i].req) |
1142 | return -ENOMEM; |
1143 | usb_ep->reqs[i].req->context = &usb_ep->reqs[i]; |
1144 | } |
1145 | return 0; |
1146 | } |
1147 | |
1148 | /* Free allocated requests */ |
1149 | static void f_midi2_free_ep_reqs(struct f_midi2_usb_ep *usb_ep) |
1150 | { |
1151 | struct f_midi2 *midi2 = usb_ep->card; |
1152 | int i; |
1153 | |
1154 | for (i = 0; i < midi2->info.num_reqs; i++) { |
1155 | if (!usb_ep->reqs[i].req) |
1156 | continue; |
1157 | free_ep_req(ep: usb_ep->usb_ep, req: usb_ep->reqs[i].req); |
1158 | usb_ep->reqs[i].req = NULL; |
1159 | } |
1160 | } |
1161 | |
1162 | /* Initialize EP */ |
1163 | static int f_midi2_init_ep(struct f_midi2 *midi2, struct f_midi2_ep *ep, |
1164 | struct f_midi2_usb_ep *usb_ep, |
1165 | void *desc, |
1166 | void (*complete)(struct usb_ep *usb_ep, |
1167 | struct usb_request *req)) |
1168 | { |
1169 | int i; |
1170 | |
1171 | usb_ep->card = midi2; |
1172 | usb_ep->ep = ep; |
1173 | usb_ep->usb_ep = usb_ep_autoconfig(midi2->gadget, desc); |
1174 | if (!usb_ep->usb_ep) |
1175 | return -ENODEV; |
1176 | usb_ep->complete = complete; |
1177 | |
1178 | usb_ep->reqs = kcalloc(n: midi2->info.num_reqs, size: sizeof(*usb_ep->reqs), |
1179 | GFP_KERNEL); |
1180 | if (!usb_ep->reqs) |
1181 | return -ENOMEM; |
1182 | for (i = 0; i < midi2->info.num_reqs; i++) { |
1183 | usb_ep->reqs[i].index = i; |
1184 | usb_ep->reqs[i].usb_ep = usb_ep; |
1185 | set_bit(nr: i, addr: &usb_ep->free_reqs); |
1186 | usb_ep->num_reqs++; |
1187 | } |
1188 | |
1189 | return 0; |
1190 | } |
1191 | |
1192 | /* Free EP */ |
1193 | static void f_midi2_free_ep(struct f_midi2_usb_ep *usb_ep) |
1194 | { |
1195 | f_midi2_drop_reqs(usb_ep); |
1196 | |
1197 | f_midi2_free_ep_reqs(usb_ep); |
1198 | |
1199 | kfree(objp: usb_ep->reqs); |
1200 | usb_ep->num_reqs = 0; |
1201 | usb_ep->free_reqs = 0; |
1202 | usb_ep->reqs = NULL; |
1203 | } |
1204 | |
1205 | /* Queue requests for EP-out at start */ |
1206 | static void f_midi2_queue_out_reqs(struct f_midi2_usb_ep *usb_ep) |
1207 | { |
1208 | int i, err; |
1209 | |
1210 | if (!usb_ep->usb_ep) |
1211 | return; |
1212 | |
1213 | for (i = 0; i < usb_ep->num_reqs; i++) { |
1214 | if (!test_bit(i, &usb_ep->free_reqs) || !usb_ep->reqs[i].req) |
1215 | continue; |
1216 | usb_ep->reqs[i].req->complete = usb_ep->complete; |
1217 | err = usb_ep_queue(ep: usb_ep->usb_ep, req: usb_ep->reqs[i].req, |
1218 | GFP_ATOMIC); |
1219 | if (!err) |
1220 | clear_bit(nr: i, addr: &usb_ep->free_reqs); |
1221 | } |
1222 | } |
1223 | |
1224 | /* |
1225 | * Gadget Function callbacks |
1226 | */ |
1227 | |
1228 | /* stop both IN and OUT EPs */ |
1229 | static void f_midi2_stop_eps(struct f_midi2_usb_ep *ep_in, |
1230 | struct f_midi2_usb_ep *ep_out) |
1231 | { |
1232 | f_midi2_drop_reqs(usb_ep: ep_in); |
1233 | f_midi2_drop_reqs(usb_ep: ep_out); |
1234 | f_midi2_free_ep_reqs(usb_ep: ep_in); |
1235 | f_midi2_free_ep_reqs(usb_ep: ep_out); |
1236 | } |
1237 | |
1238 | /* start/queue both IN and OUT EPs */ |
1239 | static int f_midi2_start_eps(struct f_midi2_usb_ep *ep_in, |
1240 | struct f_midi2_usb_ep *ep_out, |
1241 | struct usb_function *fn) |
1242 | { |
1243 | int err; |
1244 | |
1245 | err = f_midi2_start_ep(usb_ep: ep_in, fn); |
1246 | if (err) |
1247 | return err; |
1248 | err = f_midi2_start_ep(usb_ep: ep_out, fn); |
1249 | if (err) |
1250 | return err; |
1251 | |
1252 | err = f_midi2_alloc_ep_reqs(usb_ep: ep_in); |
1253 | if (err) |
1254 | return err; |
1255 | err = f_midi2_alloc_ep_reqs(usb_ep: ep_out); |
1256 | if (err) |
1257 | return err; |
1258 | |
1259 | f_midi2_queue_out_reqs(usb_ep: ep_out); |
1260 | return 0; |
1261 | } |
1262 | |
1263 | /* gadget function set_alt callback */ |
1264 | static int f_midi2_set_alt(struct usb_function *fn, unsigned int intf, |
1265 | unsigned int alt) |
1266 | { |
1267 | struct f_midi2 *midi2 = func_to_midi2(fn); |
1268 | struct f_midi2_ep *ep; |
1269 | int i, op_mode, err; |
1270 | |
1271 | if (intf != midi2->midi_if || alt > 1) |
1272 | return 0; |
1273 | |
1274 | if (alt == 0) |
1275 | op_mode = MIDI_OP_MODE_MIDI1; |
1276 | else if (alt == 1) |
1277 | op_mode = MIDI_OP_MODE_MIDI2; |
1278 | else |
1279 | op_mode = MIDI_OP_MODE_UNSET; |
1280 | |
1281 | if (midi2->operation_mode == op_mode) |
1282 | return 0; |
1283 | |
1284 | midi2->operation_mode = op_mode; |
1285 | |
1286 | if (op_mode != MIDI_OP_MODE_MIDI1) |
1287 | f_midi2_stop_eps(ep_in: &midi2->midi1_ep_in, ep_out: &midi2->midi1_ep_out); |
1288 | |
1289 | if (op_mode != MIDI_OP_MODE_MIDI2) { |
1290 | for (i = 0; i < midi2->num_eps; i++) { |
1291 | ep = &midi2->midi2_eps[i]; |
1292 | f_midi2_stop_eps(ep_in: &ep->ep_in, ep_out: &ep->ep_out); |
1293 | } |
1294 | } |
1295 | |
1296 | if (op_mode == MIDI_OP_MODE_MIDI1) |
1297 | return f_midi2_start_eps(ep_in: &midi2->midi1_ep_in, |
1298 | ep_out: &midi2->midi1_ep_out, fn); |
1299 | |
1300 | if (op_mode == MIDI_OP_MODE_MIDI2) { |
1301 | for (i = 0; i < midi2->num_eps; i++) { |
1302 | ep = &midi2->midi2_eps[i]; |
1303 | |
1304 | err = f_midi2_start_eps(ep_in: &ep->ep_in, ep_out: &ep->ep_out, fn); |
1305 | if (err) |
1306 | return err; |
1307 | } |
1308 | } |
1309 | |
1310 | return 0; |
1311 | } |
1312 | |
1313 | /* gadget function get_alt callback */ |
1314 | static int f_midi2_get_alt(struct usb_function *fn, unsigned int intf) |
1315 | { |
1316 | struct f_midi2 *midi2 = func_to_midi2(fn); |
1317 | |
1318 | if (intf == midi2->midi_if && |
1319 | midi2->operation_mode == MIDI_OP_MODE_MIDI2) |
1320 | return 1; |
1321 | return 0; |
1322 | } |
1323 | |
1324 | /* convert UMP direction to USB MIDI 2.0 direction */ |
1325 | static unsigned int ump_to_usb_dir(unsigned int ump_dir) |
1326 | { |
1327 | switch (ump_dir) { |
1328 | case SNDRV_UMP_DIR_INPUT: |
1329 | return USB_MS_GR_TRM_BLOCK_TYPE_INPUT_ONLY; |
1330 | case SNDRV_UMP_DIR_OUTPUT: |
1331 | return USB_MS_GR_TRM_BLOCK_TYPE_OUTPUT_ONLY; |
1332 | default: |
1333 | return USB_MS_GR_TRM_BLOCK_TYPE_BIDIRECTIONAL; |
1334 | } |
1335 | } |
1336 | |
1337 | /* assign GTB descriptors (for the given request) */ |
1338 | static void assign_block_descriptors(struct f_midi2 *midi2, |
1339 | struct usb_request *req, |
1340 | int max_len) |
1341 | { |
1342 | struct usb_ms20_gr_trm_block_header_descriptor ; |
1343 | struct usb_ms20_gr_trm_block_descriptor *desc; |
1344 | struct f_midi2_block_info *b; |
1345 | struct f_midi2_ep *ep; |
1346 | int i, blk, len; |
1347 | char *data; |
1348 | |
1349 | len = sizeof(gtb_header_desc) + sizeof(gtb_desc) * midi2->total_blocks; |
1350 | if (WARN_ON(len > midi2->info.req_buf_size)) |
1351 | return; |
1352 | |
1353 | header = gtb_header_desc; |
1354 | header.wTotalLength = cpu_to_le16(len); |
1355 | if (max_len < len) { |
1356 | len = min_t(int, len, sizeof(header)); |
1357 | memcpy(req->buf, &header, len); |
1358 | req->length = len; |
1359 | req->zero = len < max_len; |
1360 | return; |
1361 | } |
1362 | |
1363 | memcpy(req->buf, &header, sizeof(header)); |
1364 | data = req->buf + sizeof(header); |
1365 | for (i = 0; i < midi2->num_eps; i++) { |
1366 | ep = &midi2->midi2_eps[i]; |
1367 | for (blk = 0; blk < ep->num_blks; blk++) { |
1368 | b = &ep->blks[blk].info; |
1369 | desc = (struct usb_ms20_gr_trm_block_descriptor *)data; |
1370 | |
1371 | *desc = gtb_desc; |
1372 | desc->bGrpTrmBlkID = ep->blks[blk].gtb_id; |
1373 | desc->bGrpTrmBlkType = ump_to_usb_dir(ump_dir: b->direction); |
1374 | desc->nGroupTrm = b->first_group; |
1375 | desc->nNumGroupTrm = b->num_groups; |
1376 | desc->iBlockItem = ep->blks[blk].string_id; |
1377 | |
1378 | if (ep->info.protocol & SNDRV_UMP_EP_INFO_PROTO_MIDI2) |
1379 | desc->bMIDIProtocol = USB_MS_MIDI_PROTO_2_0; |
1380 | else |
1381 | desc->bMIDIProtocol = USB_MS_MIDI_PROTO_1_0_128; |
1382 | |
1383 | if (b->is_midi1 == 2) { |
1384 | desc->wMaxInputBandwidth = cpu_to_le16(1); |
1385 | desc->wMaxOutputBandwidth = cpu_to_le16(1); |
1386 | } |
1387 | |
1388 | data += sizeof(*desc); |
1389 | } |
1390 | } |
1391 | |
1392 | req->length = len; |
1393 | req->zero = len < max_len; |
1394 | } |
1395 | |
1396 | /* gadget function setup callback: handle GTB requests */ |
1397 | static int f_midi2_setup(struct usb_function *fn, |
1398 | const struct usb_ctrlrequest *ctrl) |
1399 | { |
1400 | struct f_midi2 *midi2 = func_to_midi2(fn); |
1401 | struct usb_composite_dev *cdev = fn->config->cdev; |
1402 | struct usb_request *req = cdev->req; |
1403 | u16 value, length; |
1404 | |
1405 | if ((ctrl->bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD || |
1406 | ctrl->bRequest != USB_REQ_GET_DESCRIPTOR) |
1407 | return -EOPNOTSUPP; |
1408 | |
1409 | value = le16_to_cpu(ctrl->wValue); |
1410 | length = le16_to_cpu(ctrl->wLength); |
1411 | |
1412 | if ((value >> 8) != USB_DT_CS_GR_TRM_BLOCK) |
1413 | return -EOPNOTSUPP; |
1414 | |
1415 | /* handle only altset 1 */ |
1416 | if ((value & 0xff) != 1) |
1417 | return -EOPNOTSUPP; |
1418 | |
1419 | assign_block_descriptors(midi2, req, max_len: length); |
1420 | return usb_ep_queue(ep: cdev->gadget->ep0, req, GFP_ATOMIC); |
1421 | } |
1422 | |
1423 | /* gadget function disable callback */ |
1424 | static void f_midi2_disable(struct usb_function *fn) |
1425 | { |
1426 | struct f_midi2 *midi2 = func_to_midi2(fn); |
1427 | |
1428 | midi2->operation_mode = MIDI_OP_MODE_UNSET; |
1429 | } |
1430 | |
1431 | /* |
1432 | * ALSA UMP ops: most of them are NOPs, only trigger for write is needed |
1433 | */ |
1434 | static int f_midi2_ump_open(struct snd_ump_endpoint *ump, int dir) |
1435 | { |
1436 | return 0; |
1437 | } |
1438 | |
1439 | static void f_midi2_ump_close(struct snd_ump_endpoint *ump, int dir) |
1440 | { |
1441 | } |
1442 | |
1443 | static void f_midi2_ump_trigger(struct snd_ump_endpoint *ump, int dir, int up) |
1444 | { |
1445 | struct f_midi2_ep *ep = ump->private_data; |
1446 | struct f_midi2 *midi2 = ep->card; |
1447 | |
1448 | if (up && dir == SNDRV_RAWMIDI_STREAM_OUTPUT) { |
1449 | switch (midi2->operation_mode) { |
1450 | case MIDI_OP_MODE_MIDI1: |
1451 | process_midi1_transmit(midi2); |
1452 | break; |
1453 | case MIDI_OP_MODE_MIDI2: |
1454 | process_ump_transmit(ep); |
1455 | break; |
1456 | } |
1457 | } |
1458 | } |
1459 | |
1460 | static void f_midi2_ump_drain(struct snd_ump_endpoint *ump, int dir) |
1461 | { |
1462 | } |
1463 | |
1464 | static const struct snd_ump_ops f_midi2_ump_ops = { |
1465 | .open = f_midi2_ump_open, |
1466 | .close = f_midi2_ump_close, |
1467 | .trigger = f_midi2_ump_trigger, |
1468 | .drain = f_midi2_ump_drain, |
1469 | }; |
1470 | |
1471 | /* |
1472 | * "Operation Mode" control element |
1473 | */ |
1474 | static int f_midi2_operation_mode_info(struct snd_kcontrol *kcontrol, |
1475 | struct snd_ctl_elem_info *uinfo) |
1476 | { |
1477 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
1478 | uinfo->count = 1; |
1479 | uinfo->value.integer.min = MIDI_OP_MODE_UNSET; |
1480 | uinfo->value.integer.max = MIDI_OP_MODE_MIDI2; |
1481 | return 0; |
1482 | } |
1483 | |
1484 | static int f_midi2_operation_mode_get(struct snd_kcontrol *kcontrol, |
1485 | struct snd_ctl_elem_value *ucontrol) |
1486 | { |
1487 | struct f_midi2 *midi2 = snd_kcontrol_chip(kcontrol); |
1488 | |
1489 | ucontrol->value.integer.value[0] = midi2->operation_mode; |
1490 | return 0; |
1491 | } |
1492 | |
1493 | static const struct snd_kcontrol_new operation_mode_ctl = { |
1494 | .iface = SNDRV_CTL_ELEM_IFACE_RAWMIDI, |
1495 | .name = "Operation Mode" , |
1496 | .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, |
1497 | .info = f_midi2_operation_mode_info, |
1498 | .get = f_midi2_operation_mode_get, |
1499 | }; |
1500 | |
1501 | /* |
1502 | * ALSA UMP instance creation / deletion |
1503 | */ |
1504 | static void f_midi2_free_card(struct f_midi2 *midi2) |
1505 | { |
1506 | if (midi2->card) { |
1507 | snd_card_free_when_closed(card: midi2->card); |
1508 | midi2->card = NULL; |
1509 | } |
1510 | } |
1511 | |
1512 | /* use a reverse direction for the gadget host */ |
1513 | static int reverse_dir(int dir) |
1514 | { |
1515 | if (!dir || dir == SNDRV_UMP_DIR_BIDIRECTION) |
1516 | return dir; |
1517 | return (dir == SNDRV_UMP_DIR_OUTPUT) ? |
1518 | SNDRV_UMP_DIR_INPUT : SNDRV_UMP_DIR_OUTPUT; |
1519 | } |
1520 | |
1521 | static int f_midi2_create_card(struct f_midi2 *midi2) |
1522 | { |
1523 | struct snd_card *card; |
1524 | struct snd_ump_endpoint *ump; |
1525 | struct f_midi2_ep *ep; |
1526 | int i, id, blk, err; |
1527 | __be32 sw; |
1528 | |
1529 | err = snd_card_new(parent: &midi2->gadget->dev, idx: -1, NULL, THIS_MODULE, extra_size: 0, |
1530 | card_ret: &card); |
1531 | if (err < 0) |
1532 | return err; |
1533 | midi2->card = card; |
1534 | |
1535 | strcpy(p: card->driver, q: "f_midi2" ); |
1536 | strcpy(p: card->shortname, q: "MIDI 2.0 Gadget" ); |
1537 | strcpy(p: card->longname, q: "MIDI 2.0 Gadget" ); |
1538 | |
1539 | id = 0; |
1540 | for (i = 0; i < midi2->num_eps; i++) { |
1541 | ep = &midi2->midi2_eps[i]; |
1542 | err = snd_ump_endpoint_new(card, id: "MIDI 2.0 Gadget" , device: id, |
1543 | output: 1, input: 1, ump_ret: &ump); |
1544 | if (err < 0) |
1545 | goto error; |
1546 | id++; |
1547 | |
1548 | ep->ump = ump; |
1549 | ump->no_process_stream = true; |
1550 | ump->private_data = ep; |
1551 | ump->ops = &f_midi2_ump_ops; |
1552 | if (midi2->info.static_block) |
1553 | ump->info.flags |= SNDRV_UMP_EP_INFO_STATIC_BLOCKS; |
1554 | ump->info.protocol_caps = (ep->info.protocol_caps & 3) << 8; |
1555 | ump->info.protocol = (ep->info.protocol & 3) << 8; |
1556 | ump->info.version = 0x0101; |
1557 | ump->info.family_id = ep->info.family; |
1558 | ump->info.model_id = ep->info.model; |
1559 | ump->info.manufacturer_id = ep->info.manufacturer & 0xffffff; |
1560 | sw = cpu_to_be32(ep->info.sw_revision); |
1561 | memcpy(ump->info.sw_revision, &sw, 4); |
1562 | |
1563 | strscpy(ump->info.name, ump_ep_name(ep), |
1564 | sizeof(ump->info.name)); |
1565 | strscpy(ump->info.product_id, ump_product_id(ep), |
1566 | sizeof(ump->info.product_id)); |
1567 | strscpy(ump->core.name, ump->info.name, sizeof(ump->core.name)); |
1568 | |
1569 | for (blk = 0; blk < ep->num_blks; blk++) { |
1570 | const struct f_midi2_block_info *b = &ep->blks[blk].info; |
1571 | struct snd_ump_block *fb; |
1572 | |
1573 | err = snd_ump_block_new(ump, blk, |
1574 | direction: reverse_dir(dir: b->direction), |
1575 | first_group: b->first_group, num_groups: b->num_groups, |
1576 | blk_ret: &ep->blks[blk].fb); |
1577 | if (err < 0) |
1578 | goto error; |
1579 | fb = ep->blks[blk].fb; |
1580 | fb->info.active = !!b->active; |
1581 | fb->info.midi_ci_version = b->midi_ci_version; |
1582 | fb->info.ui_hint = reverse_dir(dir: b->ui_hint); |
1583 | fb->info.sysex8_streams = b->sysex8_streams; |
1584 | fb->info.flags |= b->is_midi1; |
1585 | strscpy(fb->info.name, ump_fb_name(b), |
1586 | sizeof(fb->info.name)); |
1587 | } |
1588 | } |
1589 | |
1590 | for (i = 0; i < midi2->num_eps; i++) { |
1591 | err = snd_ump_attach_legacy_rawmidi(ump: midi2->midi2_eps[i].ump, |
1592 | id: "Legacy MIDI" , device: id); |
1593 | if (err < 0) |
1594 | goto error; |
1595 | id++; |
1596 | } |
1597 | |
1598 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &operation_mode_ctl, private_data: midi2)); |
1599 | if (err < 0) |
1600 | goto error; |
1601 | |
1602 | err = snd_card_register(card); |
1603 | if (err < 0) |
1604 | goto error; |
1605 | |
1606 | return 0; |
1607 | |
1608 | error: |
1609 | f_midi2_free_card(midi2); |
1610 | return err; |
1611 | } |
1612 | |
1613 | /* |
1614 | * Creation of USB descriptors |
1615 | */ |
1616 | struct f_midi2_usb_config { |
1617 | struct usb_descriptor_header **list; |
1618 | unsigned int size; |
1619 | unsigned int alloc; |
1620 | |
1621 | /* MIDI 1.0 jacks */ |
1622 | unsigned char jack_in, jack_out, jack_id; |
1623 | struct usb_midi_in_jack_descriptor jack_ins[MAX_CABLES]; |
1624 | struct usb_midi_out_jack_descriptor_1 jack_outs[MAX_CABLES]; |
1625 | }; |
1626 | |
1627 | static int append_config(struct f_midi2_usb_config *config, void *d) |
1628 | { |
1629 | unsigned int size; |
1630 | void *buf; |
1631 | |
1632 | if (config->size + 2 >= config->alloc) { |
1633 | size = config->size + 16; |
1634 | buf = krealloc(objp: config->list, new_size: size * sizeof(void *), GFP_KERNEL); |
1635 | if (!buf) |
1636 | return -ENOMEM; |
1637 | config->list = buf; |
1638 | config->alloc = size; |
1639 | } |
1640 | |
1641 | config->list[config->size] = d; |
1642 | config->size++; |
1643 | config->list[config->size] = NULL; |
1644 | return 0; |
1645 | } |
1646 | |
1647 | static int append_configs(struct f_midi2_usb_config *config, void **d) |
1648 | { |
1649 | int err; |
1650 | |
1651 | for (; *d; d++) { |
1652 | err = append_config(config, d: *d); |
1653 | if (err) |
1654 | return err; |
1655 | } |
1656 | return 0; |
1657 | } |
1658 | |
1659 | static int append_midi1_in_jack(struct f_midi2 *midi2, |
1660 | struct f_midi2_usb_config *config, |
1661 | struct midi1_cable_mapping *map, |
1662 | unsigned int type) |
1663 | { |
1664 | struct usb_midi_in_jack_descriptor *jack = |
1665 | &config->jack_ins[config->jack_in++]; |
1666 | int id = ++config->jack_id; |
1667 | int err; |
1668 | |
1669 | jack->bLength = 0x06; |
1670 | jack->bDescriptorType = USB_DT_CS_INTERFACE; |
1671 | jack->bDescriptorSubtype = USB_MS_MIDI_IN_JACK; |
1672 | jack->bJackType = type; |
1673 | jack->bJackID = id; |
1674 | /* use the corresponding block name as jack name */ |
1675 | if (map->ep) |
1676 | jack->iJack = map->ep->blks[map->block].string_id; |
1677 | |
1678 | err = append_config(config, d: jack); |
1679 | if (err < 0) |
1680 | return err; |
1681 | return id; |
1682 | } |
1683 | |
1684 | static int append_midi1_out_jack(struct f_midi2 *midi2, |
1685 | struct f_midi2_usb_config *config, |
1686 | struct midi1_cable_mapping *map, |
1687 | unsigned int type, unsigned int source) |
1688 | { |
1689 | struct usb_midi_out_jack_descriptor_1 *jack = |
1690 | &config->jack_outs[config->jack_out++]; |
1691 | int id = ++config->jack_id; |
1692 | int err; |
1693 | |
1694 | jack->bLength = 0x09; |
1695 | jack->bDescriptorType = USB_DT_CS_INTERFACE; |
1696 | jack->bDescriptorSubtype = USB_MS_MIDI_OUT_JACK; |
1697 | jack->bJackType = type; |
1698 | jack->bJackID = id; |
1699 | jack->bNrInputPins = 1; |
1700 | jack->pins[0].baSourceID = source; |
1701 | jack->pins[0].baSourcePin = 0x01; |
1702 | /* use the corresponding block name as jack name */ |
1703 | if (map->ep) |
1704 | jack->iJack = map->ep->blks[map->block].string_id; |
1705 | |
1706 | err = append_config(config, d: jack); |
1707 | if (err < 0) |
1708 | return err; |
1709 | return id; |
1710 | } |
1711 | |
1712 | static int f_midi2_create_usb_configs(struct f_midi2 *midi2, |
1713 | struct f_midi2_usb_config *config, |
1714 | int speed) |
1715 | { |
1716 | void **midi1_in_eps, **midi1_out_eps; |
1717 | int i, jack, total; |
1718 | int err; |
1719 | |
1720 | switch (speed) { |
1721 | default: |
1722 | case USB_SPEED_HIGH: |
1723 | midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(512); |
1724 | midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(512); |
1725 | for (i = 0; i < midi2->num_eps; i++) |
1726 | midi2_midi2_ep_out_desc[i].wMaxPacketSize = |
1727 | cpu_to_le16(512); |
1728 | fallthrough; |
1729 | case USB_SPEED_FULL: |
1730 | midi1_in_eps = midi2_midi1_ep_in_descs; |
1731 | midi1_out_eps = midi2_midi1_ep_out_descs; |
1732 | break; |
1733 | case USB_SPEED_SUPER: |
1734 | midi2_midi1_ep_out_desc.wMaxPacketSize = cpu_to_le16(1024); |
1735 | midi2_midi1_ep_in_desc.wMaxPacketSize = cpu_to_le16(1024); |
1736 | for (i = 0; i < midi2->num_eps; i++) |
1737 | midi2_midi2_ep_out_desc[i].wMaxPacketSize = |
1738 | cpu_to_le16(1024); |
1739 | midi1_in_eps = midi2_midi1_ep_in_ss_descs; |
1740 | midi1_out_eps = midi2_midi1_ep_out_ss_descs; |
1741 | break; |
1742 | } |
1743 | |
1744 | err = append_configs(config, d: midi2_audio_descs); |
1745 | if (err < 0) |
1746 | return err; |
1747 | |
1748 | if (midi2->num_midi1_in && midi2->num_midi1_out) |
1749 | midi2_midi1_if_desc.bNumEndpoints = 2; |
1750 | else |
1751 | midi2_midi1_if_desc.bNumEndpoints = 1; |
1752 | |
1753 | err = append_configs(config, d: midi2_midi1_descs); |
1754 | if (err < 0) |
1755 | return err; |
1756 | |
1757 | total = USB_DT_MS_HEADER_SIZE; |
1758 | if (midi2->num_midi1_out) { |
1759 | midi2_midi1_ep_out_class_desc.bLength = |
1760 | USB_DT_MS_ENDPOINT_SIZE(midi2->num_midi1_out); |
1761 | total += midi2_midi1_ep_out_class_desc.bLength; |
1762 | midi2_midi1_ep_out_class_desc.bNumEmbMIDIJack = |
1763 | midi2->num_midi1_out; |
1764 | total += midi2->num_midi1_out * |
1765 | (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1)); |
1766 | for (i = 0; i < midi2->num_midi1_out; i++) { |
1767 | jack = append_midi1_in_jack(midi2, config, |
1768 | map: &midi2->in_cable_mapping[i], |
1769 | USB_MS_EMBEDDED); |
1770 | if (jack < 0) |
1771 | return jack; |
1772 | midi2_midi1_ep_out_class_desc.baAssocJackID[i] = jack; |
1773 | jack = append_midi1_out_jack(midi2, config, |
1774 | map: &midi2->in_cable_mapping[i], |
1775 | USB_MS_EXTERNAL, source: jack); |
1776 | if (jack < 0) |
1777 | return jack; |
1778 | } |
1779 | } |
1780 | |
1781 | if (midi2->num_midi1_in) { |
1782 | midi2_midi1_ep_in_class_desc.bLength = |
1783 | USB_DT_MS_ENDPOINT_SIZE(midi2->num_midi1_in); |
1784 | total += midi2_midi1_ep_in_class_desc.bLength; |
1785 | midi2_midi1_ep_in_class_desc.bNumEmbMIDIJack = |
1786 | midi2->num_midi1_in; |
1787 | total += midi2->num_midi1_in * |
1788 | (USB_DT_MIDI_IN_SIZE + USB_DT_MIDI_OUT_SIZE(1)); |
1789 | for (i = 0; i < midi2->num_midi1_in; i++) { |
1790 | jack = append_midi1_in_jack(midi2, config, |
1791 | map: &midi2->out_cable_mapping[i], |
1792 | USB_MS_EXTERNAL); |
1793 | if (jack < 0) |
1794 | return jack; |
1795 | jack = append_midi1_out_jack(midi2, config, |
1796 | map: &midi2->out_cable_mapping[i], |
1797 | USB_MS_EMBEDDED, source: jack); |
1798 | if (jack < 0) |
1799 | return jack; |
1800 | midi2_midi1_ep_in_class_desc.baAssocJackID[i] = jack; |
1801 | } |
1802 | } |
1803 | |
1804 | midi2_midi1_class_desc.wTotalLength = cpu_to_le16(total); |
1805 | |
1806 | if (midi2->num_midi1_out) { |
1807 | err = append_configs(config, d: midi1_out_eps); |
1808 | if (err < 0) |
1809 | return err; |
1810 | } |
1811 | if (midi2->num_midi1_in) { |
1812 | err = append_configs(config, d: midi1_in_eps); |
1813 | if (err < 0) |
1814 | return err; |
1815 | } |
1816 | |
1817 | err = append_configs(config, d: midi2_midi2_descs); |
1818 | if (err < 0) |
1819 | return err; |
1820 | |
1821 | for (i = 0; i < midi2->num_eps; i++) { |
1822 | err = append_config(config, d: &midi2_midi2_ep_out_desc[i]); |
1823 | if (err < 0) |
1824 | return err; |
1825 | if (speed == USB_SPEED_SUPER || speed == USB_SPEED_SUPER_PLUS) { |
1826 | err = append_config(config, d: &midi2_midi2_ep_out_ss_comp_desc); |
1827 | if (err < 0) |
1828 | return err; |
1829 | } |
1830 | err = append_config(config, d: &midi2_midi2_ep_out_class_desc[i]); |
1831 | if (err < 0) |
1832 | return err; |
1833 | err = append_config(config, d: &midi2_midi2_ep_in_desc[i]); |
1834 | if (err < 0) |
1835 | return err; |
1836 | if (speed == USB_SPEED_SUPER || speed == USB_SPEED_SUPER_PLUS) { |
1837 | err = append_config(config, d: &midi2_midi2_ep_in_ss_comp_desc); |
1838 | if (err < 0) |
1839 | return err; |
1840 | } |
1841 | err = append_config(config, d: &midi2_midi2_ep_in_class_desc[i]); |
1842 | if (err < 0) |
1843 | return err; |
1844 | } |
1845 | |
1846 | return 0; |
1847 | } |
1848 | |
1849 | static void f_midi2_free_usb_configs(struct f_midi2_usb_config *config) |
1850 | { |
1851 | kfree(objp: config->list); |
1852 | memset(config, 0, sizeof(*config)); |
1853 | } |
1854 | |
1855 | /* as we use the static descriptors for simplicity, serialize bind call */ |
1856 | static DEFINE_MUTEX(f_midi2_desc_mutex); |
1857 | |
1858 | /* fill MIDI2 EP class-specific descriptor */ |
1859 | static void fill_midi2_class_desc(struct f_midi2_ep *ep, |
1860 | struct usb_ms20_endpoint_descriptor_32 *cdesc) |
1861 | { |
1862 | int blk; |
1863 | |
1864 | cdesc->bLength = USB_DT_MS20_ENDPOINT_SIZE(ep->num_blks); |
1865 | cdesc->bDescriptorType = USB_DT_CS_ENDPOINT; |
1866 | cdesc->bDescriptorSubtype = USB_MS_GENERAL_2_0; |
1867 | cdesc->bNumGrpTrmBlock = ep->num_blks; |
1868 | for (blk = 0; blk < ep->num_blks; blk++) |
1869 | cdesc->baAssoGrpTrmBlkID[blk] = ep->blks[blk].gtb_id; |
1870 | } |
1871 | |
1872 | /* initialize MIDI2 EP-in */ |
1873 | static int f_midi2_init_midi2_ep_in(struct f_midi2 *midi2, int index) |
1874 | { |
1875 | struct f_midi2_ep *ep = &midi2->midi2_eps[index]; |
1876 | struct usb_endpoint_descriptor *desc = &midi2_midi2_ep_in_desc[index]; |
1877 | |
1878 | desc->bLength = USB_DT_ENDPOINT_SIZE; |
1879 | desc->bDescriptorType = USB_DT_ENDPOINT; |
1880 | desc->bEndpointAddress = USB_DIR_IN; |
1881 | desc->bmAttributes = USB_ENDPOINT_XFER_INT; |
1882 | desc->wMaxPacketSize = cpu_to_le16(EP_MAX_PACKET_INT); |
1883 | desc->bInterval = 1; |
1884 | |
1885 | fill_midi2_class_desc(ep, cdesc: &midi2_midi2_ep_in_class_desc[index]); |
1886 | |
1887 | return f_midi2_init_ep(midi2, ep, usb_ep: &ep->ep_in, desc, |
1888 | complete: f_midi2_ep_in_complete); |
1889 | } |
1890 | |
1891 | /* initialize MIDI2 EP-out */ |
1892 | static int f_midi2_init_midi2_ep_out(struct f_midi2 *midi2, int index) |
1893 | { |
1894 | struct f_midi2_ep *ep = &midi2->midi2_eps[index]; |
1895 | struct usb_endpoint_descriptor *desc = &midi2_midi2_ep_out_desc[index]; |
1896 | |
1897 | desc->bLength = USB_DT_ENDPOINT_SIZE; |
1898 | desc->bDescriptorType = USB_DT_ENDPOINT; |
1899 | desc->bEndpointAddress = USB_DIR_OUT; |
1900 | desc->bmAttributes = USB_ENDPOINT_XFER_BULK; |
1901 | |
1902 | fill_midi2_class_desc(ep, cdesc: &midi2_midi2_ep_out_class_desc[index]); |
1903 | |
1904 | return f_midi2_init_ep(midi2, ep, usb_ep: &ep->ep_out, desc, |
1905 | complete: f_midi2_ep_out_complete); |
1906 | } |
1907 | |
1908 | /* gadget function bind callback */ |
1909 | static int f_midi2_bind(struct usb_configuration *c, struct usb_function *f) |
1910 | { |
1911 | struct usb_composite_dev *cdev = c->cdev; |
1912 | struct f_midi2 *midi2 = func_to_midi2(f); |
1913 | struct f_midi2_ep *ep; |
1914 | struct f_midi2_usb_config config = {}; |
1915 | struct usb_gadget_strings string_fn = { |
1916 | .language = 0x0409, /* en-us */ |
1917 | .strings = midi2->string_defs, |
1918 | }; |
1919 | struct usb_gadget_strings *strings[] = { |
1920 | &string_fn, |
1921 | NULL, |
1922 | }; |
1923 | int i, blk, status; |
1924 | |
1925 | midi2->gadget = cdev->gadget; |
1926 | midi2->operation_mode = MIDI_OP_MODE_UNSET; |
1927 | |
1928 | status = f_midi2_create_card(midi2); |
1929 | if (status < 0) |
1930 | goto fail_register; |
1931 | |
1932 | /* maybe allocate device-global string ID */ |
1933 | midi2->strings = usb_gstrings_attach(cdev: c->cdev, sp: strings, |
1934 | n_strings: midi2->total_blocks + 1); |
1935 | if (IS_ERR(ptr: midi2->strings)) { |
1936 | status = PTR_ERR(ptr: midi2->strings); |
1937 | goto fail_string; |
1938 | } |
1939 | |
1940 | mutex_lock(&f_midi2_desc_mutex); |
1941 | midi2_midi1_if_desc.iInterface = midi2->strings[STR_IFACE].id; |
1942 | midi2_midi2_if_desc.iInterface = midi2->strings[STR_IFACE].id; |
1943 | for (i = 0; i < midi2->num_eps; i++) { |
1944 | ep = &midi2->midi2_eps[i]; |
1945 | for (blk = 0; blk < ep->num_blks; blk++) |
1946 | ep->blks[blk].string_id = |
1947 | midi2->strings[gtb_to_str_id(ep->blks[blk].gtb_id)].id; |
1948 | } |
1949 | |
1950 | midi2_midi2_if_desc.bNumEndpoints = midi2->num_eps * 2; |
1951 | |
1952 | /* audio interface */ |
1953 | status = usb_interface_id(c, f); |
1954 | if (status < 0) |
1955 | goto fail; |
1956 | midi2_audio_if_desc.bInterfaceNumber = status; |
1957 | |
1958 | /* MIDI streaming */ |
1959 | status = usb_interface_id(c, f); |
1960 | if (status < 0) |
1961 | goto fail; |
1962 | midi2->midi_if = status; |
1963 | midi2_midi1_if_desc.bInterfaceNumber = status; |
1964 | midi2_midi2_if_desc.bInterfaceNumber = status; |
1965 | midi2_audio_class_desc.baInterfaceNr[0] = status; |
1966 | |
1967 | /* allocate instance-specific endpoints */ |
1968 | if (midi2->midi2_eps[0].blks[0].info.direction != SNDRV_UMP_DIR_OUTPUT) { |
1969 | status = f_midi2_init_ep(midi2, NULL, usb_ep: &midi2->midi1_ep_in, |
1970 | desc: &midi2_midi1_ep_in_desc, |
1971 | complete: f_midi2_midi1_ep_in_complete); |
1972 | if (status) |
1973 | goto fail; |
1974 | } |
1975 | |
1976 | if (midi2->midi2_eps[0].blks[0].info.direction != SNDRV_UMP_DIR_INPUT) { |
1977 | status = f_midi2_init_ep(midi2, NULL, usb_ep: &midi2->midi1_ep_out, |
1978 | desc: &midi2_midi1_ep_out_desc, |
1979 | complete: f_midi2_midi1_ep_out_complete); |
1980 | if (status) |
1981 | goto fail; |
1982 | } |
1983 | |
1984 | for (i = 0; i < midi2->num_eps; i++) { |
1985 | status = f_midi2_init_midi2_ep_in(midi2, index: i); |
1986 | if (status) |
1987 | goto fail; |
1988 | status = f_midi2_init_midi2_ep_out(midi2, index: i); |
1989 | if (status) |
1990 | goto fail; |
1991 | } |
1992 | |
1993 | status = f_midi2_create_usb_configs(midi2, config: &config, speed: USB_SPEED_FULL); |
1994 | if (status < 0) |
1995 | goto fail; |
1996 | f->fs_descriptors = usb_copy_descriptors(config.list); |
1997 | if (!f->fs_descriptors) { |
1998 | status = -ENOMEM; |
1999 | goto fail; |
2000 | } |
2001 | f_midi2_free_usb_configs(config: &config); |
2002 | |
2003 | status = f_midi2_create_usb_configs(midi2, config: &config, speed: USB_SPEED_HIGH); |
2004 | if (status < 0) |
2005 | goto fail; |
2006 | f->hs_descriptors = usb_copy_descriptors(config.list); |
2007 | if (!f->hs_descriptors) { |
2008 | status = -ENOMEM; |
2009 | goto fail; |
2010 | } |
2011 | f_midi2_free_usb_configs(config: &config); |
2012 | |
2013 | status = f_midi2_create_usb_configs(midi2, config: &config, speed: USB_SPEED_SUPER); |
2014 | if (status < 0) |
2015 | goto fail; |
2016 | f->ss_descriptors = usb_copy_descriptors(config.list); |
2017 | if (!f->ss_descriptors) { |
2018 | status = -ENOMEM; |
2019 | goto fail; |
2020 | } |
2021 | f_midi2_free_usb_configs(config: &config); |
2022 | |
2023 | mutex_unlock(lock: &f_midi2_desc_mutex); |
2024 | return 0; |
2025 | |
2026 | fail: |
2027 | f_midi2_free_usb_configs(config: &config); |
2028 | mutex_unlock(lock: &f_midi2_desc_mutex); |
2029 | usb_free_all_descriptors(f); |
2030 | fail_string: |
2031 | f_midi2_free_card(midi2); |
2032 | fail_register: |
2033 | ERROR(midi2, "%s: can't bind, err %d\n" , f->name, status); |
2034 | return status; |
2035 | } |
2036 | |
2037 | /* gadget function unbind callback */ |
2038 | static void f_midi2_unbind(struct usb_configuration *c, struct usb_function *f) |
2039 | { |
2040 | struct f_midi2 *midi2 = func_to_midi2(f); |
2041 | int i; |
2042 | |
2043 | f_midi2_free_card(midi2); |
2044 | |
2045 | f_midi2_free_ep(usb_ep: &midi2->midi1_ep_in); |
2046 | f_midi2_free_ep(usb_ep: &midi2->midi1_ep_out); |
2047 | for (i = 0; i < midi2->num_eps; i++) { |
2048 | f_midi2_free_ep(usb_ep: &midi2->midi2_eps[i].ep_in); |
2049 | f_midi2_free_ep(usb_ep: &midi2->midi2_eps[i].ep_out); |
2050 | } |
2051 | |
2052 | usb_free_all_descriptors(f); |
2053 | } |
2054 | |
2055 | /* |
2056 | * ConfigFS interface |
2057 | */ |
2058 | |
2059 | /* type conversion helpers */ |
2060 | static inline struct f_midi2_opts *to_f_midi2_opts(struct config_item *item) |
2061 | { |
2062 | return container_of(to_config_group(item), struct f_midi2_opts, |
2063 | func_inst.group); |
2064 | } |
2065 | |
2066 | static inline struct f_midi2_ep_opts * |
2067 | to_f_midi2_ep_opts(struct config_item *item) |
2068 | { |
2069 | return container_of(to_config_group(item), struct f_midi2_ep_opts, |
2070 | group); |
2071 | } |
2072 | |
2073 | static inline struct f_midi2_block_opts * |
2074 | to_f_midi2_block_opts(struct config_item *item) |
2075 | { |
2076 | return container_of(to_config_group(item), struct f_midi2_block_opts, |
2077 | group); |
2078 | } |
2079 | |
2080 | /* trim the string to be usable for EP and FB name strings */ |
2081 | static void make_name_string(char *s) |
2082 | { |
2083 | char *p; |
2084 | |
2085 | p = strchr(s, '\n'); |
2086 | if (p) |
2087 | *p = 0; |
2088 | |
2089 | p = s + strlen(s); |
2090 | for (; p > s && isspace(*p); p--) |
2091 | *p = 0; |
2092 | } |
2093 | |
2094 | /* configfs helpers: generic show/store for unisnged int */ |
2095 | static ssize_t f_midi2_opts_uint_show(struct f_midi2_opts *opts, |
2096 | u32 val, const char *format, char *page) |
2097 | { |
2098 | int result; |
2099 | |
2100 | mutex_lock(&opts->lock); |
2101 | result = sprintf(buf: page, fmt: format, val); |
2102 | mutex_unlock(lock: &opts->lock); |
2103 | return result; |
2104 | } |
2105 | |
2106 | static ssize_t f_midi2_opts_uint_store(struct f_midi2_opts *opts, |
2107 | u32 *valp, u32 minval, u32 maxval, |
2108 | const char *page, size_t len) |
2109 | { |
2110 | int ret; |
2111 | u32 val; |
2112 | |
2113 | mutex_lock(&opts->lock); |
2114 | if (opts->refcnt) { |
2115 | ret = -EBUSY; |
2116 | goto end; |
2117 | } |
2118 | |
2119 | ret = kstrtou32(s: page, base: 0, res: &val); |
2120 | if (ret) |
2121 | goto end; |
2122 | if (val < minval || val > maxval) { |
2123 | ret = -EINVAL; |
2124 | goto end; |
2125 | } |
2126 | |
2127 | *valp = val; |
2128 | ret = len; |
2129 | |
2130 | end: |
2131 | mutex_unlock(lock: &opts->lock); |
2132 | return ret; |
2133 | } |
2134 | |
2135 | /* generic store for bool */ |
2136 | static ssize_t f_midi2_opts_bool_store(struct f_midi2_opts *opts, |
2137 | bool *valp, const char *page, size_t len) |
2138 | { |
2139 | int ret; |
2140 | bool val; |
2141 | |
2142 | mutex_lock(&opts->lock); |
2143 | if (opts->refcnt) { |
2144 | ret = -EBUSY; |
2145 | goto end; |
2146 | } |
2147 | |
2148 | ret = kstrtobool(s: page, res: &val); |
2149 | if (ret) |
2150 | goto end; |
2151 | *valp = val; |
2152 | ret = len; |
2153 | |
2154 | end: |
2155 | mutex_unlock(lock: &opts->lock); |
2156 | return ret; |
2157 | } |
2158 | |
2159 | /* generic show/store for string */ |
2160 | static ssize_t f_midi2_opts_str_show(struct f_midi2_opts *opts, |
2161 | const char *str, char *page) |
2162 | { |
2163 | int result = 0; |
2164 | |
2165 | mutex_lock(&opts->lock); |
2166 | if (str) |
2167 | result = scnprintf(buf: page, PAGE_SIZE, fmt: "%s\n" , str); |
2168 | mutex_unlock(lock: &opts->lock); |
2169 | return result; |
2170 | } |
2171 | |
2172 | static ssize_t f_midi2_opts_str_store(struct f_midi2_opts *opts, |
2173 | const char **strp, size_t maxlen, |
2174 | const char *page, size_t len) |
2175 | { |
2176 | char *c; |
2177 | int ret; |
2178 | |
2179 | mutex_lock(&opts->lock); |
2180 | if (opts->refcnt) { |
2181 | ret = -EBUSY; |
2182 | goto end; |
2183 | } |
2184 | |
2185 | c = kstrndup(s: page, min(len, maxlen), GFP_KERNEL); |
2186 | if (!c) { |
2187 | ret = -ENOMEM; |
2188 | goto end; |
2189 | } |
2190 | |
2191 | kfree(objp: *strp); |
2192 | make_name_string(s: c); |
2193 | *strp = c; |
2194 | ret = len; |
2195 | |
2196 | end: |
2197 | mutex_unlock(lock: &opts->lock); |
2198 | return ret; |
2199 | } |
2200 | |
2201 | /* |
2202 | * Definitions for UMP Block config |
2203 | */ |
2204 | |
2205 | /* define an uint option for block */ |
2206 | #define F_MIDI2_BLOCK_OPT(name, format, minval, maxval) \ |
2207 | static ssize_t f_midi2_block_opts_##name##_show(struct config_item *item,\ |
2208 | char *page) \ |
2209 | { \ |
2210 | struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item); \ |
2211 | return f_midi2_opts_uint_show(opts->ep->opts, opts->info.name, \ |
2212 | format "\n", page); \ |
2213 | } \ |
2214 | \ |
2215 | static ssize_t f_midi2_block_opts_##name##_store(struct config_item *item,\ |
2216 | const char *page, size_t len) \ |
2217 | { \ |
2218 | struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item); \ |
2219 | return f_midi2_opts_uint_store(opts->ep->opts, &opts->info.name,\ |
2220 | minval, maxval, page, len); \ |
2221 | } \ |
2222 | \ |
2223 | CONFIGFS_ATTR(f_midi2_block_opts_, name) |
2224 | |
2225 | /* define a boolean option for block */ |
2226 | #define F_MIDI2_BLOCK_BOOL_OPT(name) \ |
2227 | static ssize_t f_midi2_block_opts_##name##_show(struct config_item *item,\ |
2228 | char *page) \ |
2229 | { \ |
2230 | struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item); \ |
2231 | return f_midi2_opts_uint_show(opts->ep->opts, opts->info.name, \ |
2232 | "%u\n", page); \ |
2233 | } \ |
2234 | \ |
2235 | static ssize_t f_midi2_block_opts_##name##_store(struct config_item *item,\ |
2236 | const char *page, size_t len) \ |
2237 | { \ |
2238 | struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item); \ |
2239 | return f_midi2_opts_bool_store(opts->ep->opts, &opts->info.name,\ |
2240 | page, len); \ |
2241 | } \ |
2242 | \ |
2243 | CONFIGFS_ATTR(f_midi2_block_opts_, name) |
2244 | |
2245 | F_MIDI2_BLOCK_OPT(direction, "0x%x" , 1, 3); |
2246 | F_MIDI2_BLOCK_OPT(first_group, "0x%x" , 0, 15); |
2247 | F_MIDI2_BLOCK_OPT(num_groups, "0x%x" , 1, 16); |
2248 | F_MIDI2_BLOCK_OPT(midi1_first_group, "0x%x" , 0, 15); |
2249 | F_MIDI2_BLOCK_OPT(midi1_num_groups, "0x%x" , 0, 16); |
2250 | F_MIDI2_BLOCK_OPT(ui_hint, "0x%x" , 0, 3); |
2251 | F_MIDI2_BLOCK_OPT(midi_ci_version, "%u" , 0, 1); |
2252 | F_MIDI2_BLOCK_OPT(sysex8_streams, "%u" , 0, 255); |
2253 | F_MIDI2_BLOCK_OPT(is_midi1, "%u" , 0, 2); |
2254 | F_MIDI2_BLOCK_BOOL_OPT(active); |
2255 | |
2256 | static ssize_t f_midi2_block_opts_name_show(struct config_item *item, |
2257 | char *page) |
2258 | { |
2259 | struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item); |
2260 | |
2261 | return f_midi2_opts_str_show(opts: opts->ep->opts, str: opts->info.name, page); |
2262 | } |
2263 | |
2264 | static ssize_t f_midi2_block_opts_name_store(struct config_item *item, |
2265 | const char *page, size_t len) |
2266 | { |
2267 | struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item); |
2268 | |
2269 | return f_midi2_opts_str_store(opts: opts->ep->opts, strp: &opts->info.name, maxlen: 128, |
2270 | page, len); |
2271 | } |
2272 | |
2273 | CONFIGFS_ATTR(f_midi2_block_opts_, name); |
2274 | |
2275 | static struct configfs_attribute *f_midi2_block_attrs[] = { |
2276 | &f_midi2_block_opts_attr_direction, |
2277 | &f_midi2_block_opts_attr_first_group, |
2278 | &f_midi2_block_opts_attr_num_groups, |
2279 | &f_midi2_block_opts_attr_midi1_first_group, |
2280 | &f_midi2_block_opts_attr_midi1_num_groups, |
2281 | &f_midi2_block_opts_attr_ui_hint, |
2282 | &f_midi2_block_opts_attr_midi_ci_version, |
2283 | &f_midi2_block_opts_attr_sysex8_streams, |
2284 | &f_midi2_block_opts_attr_is_midi1, |
2285 | &f_midi2_block_opts_attr_active, |
2286 | &f_midi2_block_opts_attr_name, |
2287 | NULL, |
2288 | }; |
2289 | |
2290 | static void f_midi2_block_opts_release(struct config_item *item) |
2291 | { |
2292 | struct f_midi2_block_opts *opts = to_f_midi2_block_opts(item); |
2293 | |
2294 | kfree(objp: opts->info.name); |
2295 | kfree(objp: opts); |
2296 | } |
2297 | |
2298 | static struct configfs_item_operations f_midi2_block_item_ops = { |
2299 | .release = f_midi2_block_opts_release, |
2300 | }; |
2301 | |
2302 | static const struct config_item_type f_midi2_block_type = { |
2303 | .ct_item_ops = &f_midi2_block_item_ops, |
2304 | .ct_attrs = f_midi2_block_attrs, |
2305 | .ct_owner = THIS_MODULE, |
2306 | }; |
2307 | |
2308 | /* create a f_midi2_block_opts instance for the given block number */ |
2309 | static int f_midi2_block_opts_create(struct f_midi2_ep_opts *ep_opts, |
2310 | unsigned int blk, |
2311 | struct f_midi2_block_opts **block_p) |
2312 | { |
2313 | struct f_midi2_block_opts *block_opts; |
2314 | int ret = 0; |
2315 | |
2316 | mutex_lock(&ep_opts->opts->lock); |
2317 | if (ep_opts->opts->refcnt || ep_opts->blks[blk]) { |
2318 | ret = -EBUSY; |
2319 | goto out; |
2320 | } |
2321 | |
2322 | block_opts = kzalloc(size: sizeof(*block_opts), GFP_KERNEL); |
2323 | if (!block_opts) { |
2324 | ret = -ENOMEM; |
2325 | goto out; |
2326 | } |
2327 | |
2328 | block_opts->ep = ep_opts; |
2329 | block_opts->id = blk; |
2330 | |
2331 | /* set up the default values */ |
2332 | block_opts->info.direction = SNDRV_UMP_DIR_BIDIRECTION; |
2333 | block_opts->info.first_group = 0; |
2334 | block_opts->info.num_groups = 1; |
2335 | block_opts->info.ui_hint = SNDRV_UMP_BLOCK_UI_HINT_BOTH; |
2336 | block_opts->info.active = 1; |
2337 | |
2338 | ep_opts->blks[blk] = block_opts; |
2339 | *block_p = block_opts; |
2340 | |
2341 | out: |
2342 | mutex_unlock(lock: &ep_opts->opts->lock); |
2343 | return ret; |
2344 | } |
2345 | |
2346 | /* make_group callback for a block */ |
2347 | static struct config_group * |
2348 | f_midi2_opts_block_make(struct config_group *group, const char *name) |
2349 | { |
2350 | struct f_midi2_ep_opts *ep_opts; |
2351 | struct f_midi2_block_opts *block_opts; |
2352 | unsigned int blk; |
2353 | int ret; |
2354 | |
2355 | if (strncmp(name, "block." , 6)) |
2356 | return ERR_PTR(error: -EINVAL); |
2357 | ret = kstrtouint(s: name + 6, base: 10, res: &blk); |
2358 | if (ret) |
2359 | return ERR_PTR(error: ret); |
2360 | |
2361 | ep_opts = to_f_midi2_ep_opts(item: &group->cg_item); |
2362 | |
2363 | if (blk >= SNDRV_UMP_MAX_BLOCKS) |
2364 | return ERR_PTR(error: -EINVAL); |
2365 | if (ep_opts->blks[blk]) |
2366 | return ERR_PTR(error: -EBUSY); |
2367 | ret = f_midi2_block_opts_create(ep_opts, blk, block_p: &block_opts); |
2368 | if (ret) |
2369 | return ERR_PTR(error: ret); |
2370 | |
2371 | config_group_init_type_name(group: &block_opts->group, name, |
2372 | type: &f_midi2_block_type); |
2373 | return &block_opts->group; |
2374 | } |
2375 | |
2376 | /* drop_item callback for a block */ |
2377 | static void |
2378 | f_midi2_opts_block_drop(struct config_group *group, struct config_item *item) |
2379 | { |
2380 | struct f_midi2_block_opts *block_opts = to_f_midi2_block_opts(item); |
2381 | |
2382 | mutex_lock(&block_opts->ep->opts->lock); |
2383 | block_opts->ep->blks[block_opts->id] = NULL; |
2384 | mutex_unlock(lock: &block_opts->ep->opts->lock); |
2385 | config_item_put(item); |
2386 | } |
2387 | |
2388 | /* |
2389 | * Definitions for UMP Endpoint config |
2390 | */ |
2391 | |
2392 | /* define an uint option for EP */ |
2393 | #define F_MIDI2_EP_OPT(name, format, minval, maxval) \ |
2394 | static ssize_t f_midi2_ep_opts_##name##_show(struct config_item *item, \ |
2395 | char *page) \ |
2396 | { \ |
2397 | struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item); \ |
2398 | return f_midi2_opts_uint_show(opts->opts, opts->info.name, \ |
2399 | format "\n", page); \ |
2400 | } \ |
2401 | \ |
2402 | static ssize_t f_midi2_ep_opts_##name##_store(struct config_item *item, \ |
2403 | const char *page, size_t len)\ |
2404 | { \ |
2405 | struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item); \ |
2406 | return f_midi2_opts_uint_store(opts->opts, &opts->info.name, \ |
2407 | minval, maxval, page, len); \ |
2408 | } \ |
2409 | \ |
2410 | CONFIGFS_ATTR(f_midi2_ep_opts_, name) |
2411 | |
2412 | /* define a string option for EP */ |
2413 | #define F_MIDI2_EP_STR_OPT(name, maxlen) \ |
2414 | static ssize_t f_midi2_ep_opts_##name##_show(struct config_item *item, \ |
2415 | char *page) \ |
2416 | { \ |
2417 | struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item); \ |
2418 | return f_midi2_opts_str_show(opts->opts, opts->info.name, page);\ |
2419 | } \ |
2420 | \ |
2421 | static ssize_t f_midi2_ep_opts_##name##_store(struct config_item *item, \ |
2422 | const char *page, size_t len) \ |
2423 | { \ |
2424 | struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item); \ |
2425 | return f_midi2_opts_str_store(opts->opts, &opts->info.name, maxlen,\ |
2426 | page, len); \ |
2427 | } \ |
2428 | \ |
2429 | CONFIGFS_ATTR(f_midi2_ep_opts_, name) |
2430 | |
2431 | F_MIDI2_EP_OPT(protocol, "0x%x" , 1, 2); |
2432 | F_MIDI2_EP_OPT(protocol_caps, "0x%x" , 1, 3); |
2433 | F_MIDI2_EP_OPT(manufacturer, "0x%x" , 0, 0xffffff); |
2434 | F_MIDI2_EP_OPT(family, "0x%x" , 0, 0xffff); |
2435 | F_MIDI2_EP_OPT(model, "0x%x" , 0, 0xffff); |
2436 | F_MIDI2_EP_OPT(sw_revision, "0x%x" , 0, 0xffffffff); |
2437 | F_MIDI2_EP_STR_OPT(ep_name, 128); |
2438 | F_MIDI2_EP_STR_OPT(product_id, 128); |
2439 | |
2440 | static struct configfs_attribute *f_midi2_ep_attrs[] = { |
2441 | &f_midi2_ep_opts_attr_protocol, |
2442 | &f_midi2_ep_opts_attr_protocol_caps, |
2443 | &f_midi2_ep_opts_attr_ep_name, |
2444 | &f_midi2_ep_opts_attr_product_id, |
2445 | &f_midi2_ep_opts_attr_manufacturer, |
2446 | &f_midi2_ep_opts_attr_family, |
2447 | &f_midi2_ep_opts_attr_model, |
2448 | &f_midi2_ep_opts_attr_sw_revision, |
2449 | NULL, |
2450 | }; |
2451 | |
2452 | static void f_midi2_ep_opts_release(struct config_item *item) |
2453 | { |
2454 | struct f_midi2_ep_opts *opts = to_f_midi2_ep_opts(item); |
2455 | |
2456 | kfree(objp: opts->info.ep_name); |
2457 | kfree(objp: opts->info.product_id); |
2458 | kfree(objp: opts); |
2459 | } |
2460 | |
2461 | static struct configfs_item_operations f_midi2_ep_item_ops = { |
2462 | .release = f_midi2_ep_opts_release, |
2463 | }; |
2464 | |
2465 | static struct configfs_group_operations f_midi2_ep_group_ops = { |
2466 | .make_group = f_midi2_opts_block_make, |
2467 | .drop_item = f_midi2_opts_block_drop, |
2468 | }; |
2469 | |
2470 | static const struct config_item_type f_midi2_ep_type = { |
2471 | .ct_item_ops = &f_midi2_ep_item_ops, |
2472 | .ct_group_ops = &f_midi2_ep_group_ops, |
2473 | .ct_attrs = f_midi2_ep_attrs, |
2474 | .ct_owner = THIS_MODULE, |
2475 | }; |
2476 | |
2477 | /* create a f_midi2_ep_opts instance */ |
2478 | static int f_midi2_ep_opts_create(struct f_midi2_opts *opts, |
2479 | unsigned int index, |
2480 | struct f_midi2_ep_opts **ep_p) |
2481 | { |
2482 | struct f_midi2_ep_opts *ep_opts; |
2483 | |
2484 | ep_opts = kzalloc(size: sizeof(*ep_opts), GFP_KERNEL); |
2485 | if (!ep_opts) |
2486 | return -ENOMEM; |
2487 | |
2488 | ep_opts->opts = opts; |
2489 | ep_opts->index = index; |
2490 | |
2491 | /* set up the default values */ |
2492 | ep_opts->info.protocol = 2; |
2493 | ep_opts->info.protocol_caps = 3; |
2494 | |
2495 | opts->eps[index] = ep_opts; |
2496 | *ep_p = ep_opts; |
2497 | return 0; |
2498 | } |
2499 | |
2500 | /* make_group callback for an EP */ |
2501 | static struct config_group * |
2502 | f_midi2_opts_ep_make(struct config_group *group, const char *name) |
2503 | { |
2504 | struct f_midi2_opts *opts; |
2505 | struct f_midi2_ep_opts *ep_opts; |
2506 | unsigned int index; |
2507 | int ret; |
2508 | |
2509 | if (strncmp(name, "ep." , 3)) |
2510 | return ERR_PTR(error: -EINVAL); |
2511 | ret = kstrtouint(s: name + 3, base: 10, res: &index); |
2512 | if (ret) |
2513 | return ERR_PTR(error: ret); |
2514 | |
2515 | opts = to_f_midi2_opts(item: &group->cg_item); |
2516 | if (index >= MAX_UMP_EPS) |
2517 | return ERR_PTR(error: -EINVAL); |
2518 | if (opts->eps[index]) |
2519 | return ERR_PTR(error: -EBUSY); |
2520 | ret = f_midi2_ep_opts_create(opts, index, ep_p: &ep_opts); |
2521 | if (ret) |
2522 | return ERR_PTR(error: ret); |
2523 | |
2524 | config_group_init_type_name(group: &ep_opts->group, name, type: &f_midi2_ep_type); |
2525 | return &ep_opts->group; |
2526 | } |
2527 | |
2528 | /* drop_item callback for an EP */ |
2529 | static void |
2530 | f_midi2_opts_ep_drop(struct config_group *group, struct config_item *item) |
2531 | { |
2532 | struct f_midi2_ep_opts *ep_opts = to_f_midi2_ep_opts(item); |
2533 | |
2534 | mutex_lock(&ep_opts->opts->lock); |
2535 | ep_opts->opts->eps[ep_opts->index] = NULL; |
2536 | mutex_unlock(lock: &ep_opts->opts->lock); |
2537 | config_item_put(item); |
2538 | } |
2539 | |
2540 | /* |
2541 | * Definitions for card config |
2542 | */ |
2543 | |
2544 | /* define a bool option for card */ |
2545 | #define F_MIDI2_BOOL_OPT(name) \ |
2546 | static ssize_t f_midi2_opts_##name##_show(struct config_item *item, \ |
2547 | char *page) \ |
2548 | { \ |
2549 | struct f_midi2_opts *opts = to_f_midi2_opts(item); \ |
2550 | return f_midi2_opts_uint_show(opts, opts->info.name, \ |
2551 | "%u\n", page); \ |
2552 | } \ |
2553 | \ |
2554 | static ssize_t f_midi2_opts_##name##_store(struct config_item *item, \ |
2555 | const char *page, size_t len) \ |
2556 | { \ |
2557 | struct f_midi2_opts *opts = to_f_midi2_opts(item); \ |
2558 | return f_midi2_opts_bool_store(opts, &opts->info.name, \ |
2559 | page, len); \ |
2560 | } \ |
2561 | \ |
2562 | CONFIGFS_ATTR(f_midi2_opts_, name) |
2563 | |
2564 | F_MIDI2_BOOL_OPT(process_ump); |
2565 | F_MIDI2_BOOL_OPT(static_block); |
2566 | |
2567 | static ssize_t f_midi2_opts_iface_name_show(struct config_item *item, |
2568 | char *page) |
2569 | { |
2570 | struct f_midi2_opts *opts = to_f_midi2_opts(item); |
2571 | |
2572 | return f_midi2_opts_str_show(opts, str: opts->info.iface_name, page); |
2573 | } |
2574 | |
2575 | static ssize_t f_midi2_opts_iface_name_store(struct config_item *item, |
2576 | const char *page, size_t len) |
2577 | { |
2578 | struct f_midi2_opts *opts = to_f_midi2_opts(item); |
2579 | |
2580 | return f_midi2_opts_str_store(opts, strp: &opts->info.iface_name, maxlen: 128, |
2581 | page, len); |
2582 | } |
2583 | |
2584 | CONFIGFS_ATTR(f_midi2_opts_, iface_name); |
2585 | |
2586 | static struct configfs_attribute *f_midi2_attrs[] = { |
2587 | &f_midi2_opts_attr_process_ump, |
2588 | &f_midi2_opts_attr_static_block, |
2589 | &f_midi2_opts_attr_iface_name, |
2590 | NULL |
2591 | }; |
2592 | |
2593 | static void f_midi2_opts_release(struct config_item *item) |
2594 | { |
2595 | struct f_midi2_opts *opts = to_f_midi2_opts(item); |
2596 | |
2597 | usb_put_function_instance(fi: &opts->func_inst); |
2598 | } |
2599 | |
2600 | static struct configfs_item_operations f_midi2_item_ops = { |
2601 | .release = f_midi2_opts_release, |
2602 | }; |
2603 | |
2604 | static struct configfs_group_operations f_midi2_group_ops = { |
2605 | .make_group = f_midi2_opts_ep_make, |
2606 | .drop_item = f_midi2_opts_ep_drop, |
2607 | }; |
2608 | |
2609 | static const struct config_item_type f_midi2_func_type = { |
2610 | .ct_item_ops = &f_midi2_item_ops, |
2611 | .ct_group_ops = &f_midi2_group_ops, |
2612 | .ct_attrs = f_midi2_attrs, |
2613 | .ct_owner = THIS_MODULE, |
2614 | }; |
2615 | |
2616 | static void f_midi2_free_inst(struct usb_function_instance *f) |
2617 | { |
2618 | struct f_midi2_opts *opts; |
2619 | |
2620 | opts = container_of(f, struct f_midi2_opts, func_inst); |
2621 | |
2622 | kfree(objp: opts->info.iface_name); |
2623 | kfree(objp: opts); |
2624 | } |
2625 | |
2626 | /* gadget alloc_inst */ |
2627 | static struct usb_function_instance *f_midi2_alloc_inst(void) |
2628 | { |
2629 | struct f_midi2_opts *opts; |
2630 | struct f_midi2_ep_opts *ep_opts; |
2631 | struct f_midi2_block_opts *block_opts; |
2632 | int ret; |
2633 | |
2634 | opts = kzalloc(size: sizeof(*opts), GFP_KERNEL); |
2635 | if (!opts) |
2636 | return ERR_PTR(error: -ENOMEM); |
2637 | |
2638 | mutex_init(&opts->lock); |
2639 | opts->func_inst.free_func_inst = f_midi2_free_inst; |
2640 | opts->info.process_ump = true; |
2641 | opts->info.static_block = true; |
2642 | opts->info.num_reqs = 32; |
2643 | opts->info.req_buf_size = 512; |
2644 | |
2645 | /* create the default ep */ |
2646 | ret = f_midi2_ep_opts_create(opts, index: 0, ep_p: &ep_opts); |
2647 | if (ret) { |
2648 | kfree(objp: opts); |
2649 | return ERR_PTR(error: ret); |
2650 | } |
2651 | |
2652 | /* create the default block */ |
2653 | ret = f_midi2_block_opts_create(ep_opts, blk: 0, block_p: &block_opts); |
2654 | if (ret) { |
2655 | kfree(objp: ep_opts); |
2656 | kfree(objp: opts); |
2657 | return ERR_PTR(error: ret); |
2658 | } |
2659 | |
2660 | /* set up the default MIDI1 (that is mandatory) */ |
2661 | block_opts->info.midi1_num_groups = 1; |
2662 | |
2663 | config_group_init_type_name(group: &opts->func_inst.group, name: "" , |
2664 | type: &f_midi2_func_type); |
2665 | |
2666 | config_group_init_type_name(group: &ep_opts->group, name: "ep.0" , |
2667 | type: &f_midi2_ep_type); |
2668 | configfs_add_default_group(new_group: &ep_opts->group, group: &opts->func_inst.group); |
2669 | |
2670 | config_group_init_type_name(group: &block_opts->group, name: "block.0" , |
2671 | type: &f_midi2_block_type); |
2672 | configfs_add_default_group(new_group: &block_opts->group, group: &ep_opts->group); |
2673 | |
2674 | return &opts->func_inst; |
2675 | } |
2676 | |
2677 | static void do_f_midi2_free(struct f_midi2 *midi2, struct f_midi2_opts *opts) |
2678 | { |
2679 | mutex_lock(&opts->lock); |
2680 | --opts->refcnt; |
2681 | mutex_unlock(lock: &opts->lock); |
2682 | kfree(objp: midi2->string_defs); |
2683 | kfree(objp: midi2); |
2684 | } |
2685 | |
2686 | static void f_midi2_free(struct usb_function *f) |
2687 | { |
2688 | do_f_midi2_free(func_to_midi2(f), |
2689 | container_of(f->fi, struct f_midi2_opts, func_inst)); |
2690 | } |
2691 | |
2692 | /* verify the parameters set up via configfs; |
2693 | * return the number of EPs or a negative error |
2694 | */ |
2695 | static int verify_parameters(struct f_midi2_opts *opts) |
2696 | { |
2697 | int i, j, num_eps, num_blks; |
2698 | struct f_midi2_ep_info *ep; |
2699 | struct f_midi2_block_info *bp; |
2700 | |
2701 | for (num_eps = 0; num_eps < MAX_UMP_EPS && opts->eps[num_eps]; |
2702 | num_eps++) |
2703 | ; |
2704 | if (!num_eps) { |
2705 | pr_err("f_midi2: No EP is defined\n" ); |
2706 | return -EINVAL; |
2707 | } |
2708 | |
2709 | num_blks = 0; |
2710 | for (i = 0; i < num_eps; i++) { |
2711 | ep = &opts->eps[i]->info; |
2712 | if (!(ep->protocol_caps & ep->protocol)) { |
2713 | pr_err("f_midi2: Invalid protocol 0x%x (caps 0x%x) for EP %d\n" , |
2714 | ep->protocol, ep->protocol_caps, i); |
2715 | return -EINVAL; |
2716 | } |
2717 | |
2718 | for (j = 0; j < SNDRV_UMP_MAX_BLOCKS && opts->eps[i]->blks[j]; |
2719 | j++, num_blks++) { |
2720 | bp = &opts->eps[i]->blks[j]->info; |
2721 | if (bp->first_group + bp->num_groups > SNDRV_UMP_MAX_GROUPS) { |
2722 | pr_err("f_midi2: Invalid group definitions for block %d:%d\n" , |
2723 | i, j); |
2724 | return -EINVAL; |
2725 | } |
2726 | |
2727 | if (bp->midi1_num_groups) { |
2728 | if (bp->midi1_first_group < bp->first_group || |
2729 | bp->midi1_first_group + bp->midi1_num_groups > |
2730 | bp->first_group + bp->num_groups) { |
2731 | pr_err("f_midi2: Invalid MIDI1 group definitions for block %d:%d\n" , |
2732 | i, j); |
2733 | return -EINVAL; |
2734 | } |
2735 | } |
2736 | } |
2737 | } |
2738 | if (!num_blks) { |
2739 | pr_err("f_midi2: No block is defined\n" ); |
2740 | return -EINVAL; |
2741 | } |
2742 | |
2743 | return num_eps; |
2744 | } |
2745 | |
2746 | /* fill mapping between MIDI 1.0 cable and UMP EP/group */ |
2747 | static void fill_midi1_cable_mapping(struct f_midi2 *midi2, |
2748 | struct f_midi2_ep *ep, |
2749 | int blk) |
2750 | { |
2751 | const struct f_midi2_block_info *binfo = &ep->blks[blk].info; |
2752 | struct midi1_cable_mapping *map; |
2753 | int i, group; |
2754 | |
2755 | if (!binfo->midi1_num_groups) |
2756 | return; |
2757 | if (binfo->direction != SNDRV_UMP_DIR_OUTPUT) { |
2758 | group = binfo->midi1_first_group; |
2759 | map = midi2->in_cable_mapping + midi2->num_midi1_in; |
2760 | for (i = 0; i < binfo->midi1_num_groups; i++, group++, map++) { |
2761 | if (midi2->num_midi1_in >= MAX_CABLES) |
2762 | break; |
2763 | map->ep = ep; |
2764 | map->block = blk; |
2765 | map->group = group; |
2766 | midi2->num_midi1_in++; |
2767 | /* store 1-based cable number */ |
2768 | ep->in_group_to_cable[group] = midi2->num_midi1_in; |
2769 | } |
2770 | } |
2771 | |
2772 | if (binfo->direction != SNDRV_UMP_DIR_INPUT) { |
2773 | group = binfo->midi1_first_group; |
2774 | map = midi2->out_cable_mapping + midi2->num_midi1_out; |
2775 | for (i = 0; i < binfo->midi1_num_groups; i++, group++, map++) { |
2776 | if (midi2->num_midi1_out >= MAX_CABLES) |
2777 | break; |
2778 | map->ep = ep; |
2779 | map->block = blk; |
2780 | map->group = group; |
2781 | midi2->num_midi1_out++; |
2782 | } |
2783 | } |
2784 | } |
2785 | |
2786 | /* gadget alloc callback */ |
2787 | static struct usb_function *f_midi2_alloc(struct usb_function_instance *fi) |
2788 | { |
2789 | struct f_midi2 *midi2; |
2790 | struct f_midi2_opts *opts; |
2791 | struct f_midi2_ep *ep; |
2792 | struct f_midi2_block *bp; |
2793 | int i, num_eps, blk; |
2794 | |
2795 | midi2 = kzalloc(size: sizeof(*midi2), GFP_KERNEL); |
2796 | if (!midi2) |
2797 | return ERR_PTR(error: -ENOMEM); |
2798 | |
2799 | opts = container_of(fi, struct f_midi2_opts, func_inst); |
2800 | mutex_lock(&opts->lock); |
2801 | num_eps = verify_parameters(opts); |
2802 | if (num_eps < 0) { |
2803 | mutex_unlock(lock: &opts->lock); |
2804 | kfree(objp: midi2); |
2805 | return ERR_PTR(error: num_eps); |
2806 | } |
2807 | ++opts->refcnt; |
2808 | mutex_unlock(lock: &opts->lock); |
2809 | |
2810 | spin_lock_init(&midi2->queue_lock); |
2811 | |
2812 | midi2->func.name = "midi2_func" ; |
2813 | midi2->func.bind = f_midi2_bind; |
2814 | midi2->func.unbind = f_midi2_unbind; |
2815 | midi2->func.get_alt = f_midi2_get_alt; |
2816 | midi2->func.set_alt = f_midi2_set_alt; |
2817 | midi2->func.setup = f_midi2_setup; |
2818 | midi2->func.disable = f_midi2_disable; |
2819 | midi2->func.free_func = f_midi2_free; |
2820 | |
2821 | midi2->info = opts->info; |
2822 | midi2->num_eps = num_eps; |
2823 | |
2824 | for (i = 0; i < num_eps; i++) { |
2825 | ep = &midi2->midi2_eps[i]; |
2826 | ep->info = opts->eps[i]->info; |
2827 | ep->card = midi2; |
2828 | for (blk = 0; blk < SNDRV_UMP_MAX_BLOCKS && |
2829 | opts->eps[i]->blks[blk]; blk++) { |
2830 | bp = &ep->blks[blk]; |
2831 | ep->num_blks++; |
2832 | bp->info = opts->eps[i]->blks[blk]->info; |
2833 | bp->gtb_id = ++midi2->total_blocks; |
2834 | } |
2835 | } |
2836 | |
2837 | midi2->string_defs = kcalloc(n: midi2->total_blocks + 1, |
2838 | size: sizeof(*midi2->string_defs), GFP_KERNEL); |
2839 | if (!midi2->string_defs) { |
2840 | do_f_midi2_free(midi2, opts); |
2841 | return ERR_PTR(error: -ENOMEM); |
2842 | } |
2843 | |
2844 | if (opts->info.iface_name && *opts->info.iface_name) |
2845 | midi2->string_defs[STR_IFACE].s = opts->info.iface_name; |
2846 | else |
2847 | midi2->string_defs[STR_IFACE].s = ump_ep_name(ep: &midi2->midi2_eps[0]); |
2848 | |
2849 | for (i = 0; i < midi2->num_eps; i++) { |
2850 | ep = &midi2->midi2_eps[i]; |
2851 | for (blk = 0; blk < ep->num_blks; blk++) { |
2852 | bp = &ep->blks[blk]; |
2853 | midi2->string_defs[gtb_to_str_id(bp->gtb_id)].s = |
2854 | ump_fb_name(info: &bp->info); |
2855 | |
2856 | fill_midi1_cable_mapping(midi2, ep, blk); |
2857 | } |
2858 | } |
2859 | |
2860 | if (!midi2->num_midi1_in && !midi2->num_midi1_out) { |
2861 | pr_err("f_midi2: MIDI1 definition is missing\n" ); |
2862 | do_f_midi2_free(midi2, opts); |
2863 | return ERR_PTR(error: -EINVAL); |
2864 | } |
2865 | |
2866 | return &midi2->func; |
2867 | } |
2868 | |
2869 | DECLARE_USB_FUNCTION_INIT(midi2, f_midi2_alloc_inst, f_midi2_alloc); |
2870 | |
2871 | MODULE_LICENSE("GPL" ); |
2872 | |