1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * f_acm.c -- USB CDC serial (ACM) function driver |
4 | * |
5 | * Copyright (C) 2003 Al Borchers (alborchers@steinerpoint.com) |
6 | * Copyright (C) 2008 by David Brownell |
7 | * Copyright (C) 2008 by Nokia Corporation |
8 | * Copyright (C) 2009 by Samsung Electronics |
9 | * Author: Michal Nazarewicz (mina86@mina86.com) |
10 | */ |
11 | |
12 | /* #define VERBOSE_DEBUG */ |
13 | |
14 | #include <linux/slab.h> |
15 | #include <linux/kernel.h> |
16 | #include <linux/module.h> |
17 | #include <linux/device.h> |
18 | #include <linux/err.h> |
19 | |
20 | #include "u_serial.h" |
21 | |
22 | |
23 | /* |
24 | * This CDC ACM function support just wraps control functions and |
25 | * notifications around the generic serial-over-usb code. |
26 | * |
27 | * Because CDC ACM is standardized by the USB-IF, many host operating |
28 | * systems have drivers for it. Accordingly, ACM is the preferred |
29 | * interop solution for serial-port type connections. The control |
30 | * models are often not necessary, and in any case don't do much in |
31 | * this bare-bones implementation. |
32 | * |
33 | * Note that even MS-Windows has some support for ACM. However, that |
34 | * support is somewhat broken because when you use ACM in a composite |
35 | * device, having multiple interfaces confuses the poor OS. It doesn't |
36 | * seem to understand CDC Union descriptors. The new "association" |
37 | * descriptors (roughly equivalent to CDC Unions) may sometimes help. |
38 | */ |
39 | |
40 | struct f_acm { |
41 | struct gserial port; |
42 | u8 ctrl_id, data_id; |
43 | u8 port_num; |
44 | |
45 | u8 pending; |
46 | |
47 | /* lock is mostly for pending and notify_req ... they get accessed |
48 | * by callbacks both from tty (open/close/break) under its spinlock, |
49 | * and notify_req.complete() which can't use that lock. |
50 | */ |
51 | spinlock_t lock; |
52 | |
53 | struct usb_ep *notify; |
54 | struct usb_request *notify_req; |
55 | |
56 | struct usb_cdc_line_coding port_line_coding; /* 8-N-1 etc */ |
57 | |
58 | /* SetControlLineState request -- CDC 1.1 section 6.2.14 (INPUT) */ |
59 | u16 port_handshake_bits; |
60 | /* SerialState notification -- CDC 1.1 section 6.3.5 (OUTPUT) */ |
61 | u16 serial_state; |
62 | }; |
63 | |
64 | static inline struct f_acm *func_to_acm(struct usb_function *f) |
65 | { |
66 | return container_of(f, struct f_acm, port.func); |
67 | } |
68 | |
69 | static inline struct f_acm *port_to_acm(struct gserial *p) |
70 | { |
71 | return container_of(p, struct f_acm, port); |
72 | } |
73 | |
74 | /*-------------------------------------------------------------------------*/ |
75 | |
76 | /* notification endpoint uses smallish and infrequent fixed-size messages */ |
77 | |
78 | #define GS_NOTIFY_INTERVAL_MS 32 |
79 | #define GS_NOTIFY_MAXPACKET 10 /* notification + 2 bytes */ |
80 | |
81 | /* interface and class descriptors: */ |
82 | |
83 | static struct usb_interface_assoc_descriptor |
84 | acm_iad_descriptor = { |
85 | .bLength = sizeof acm_iad_descriptor, |
86 | .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, |
87 | |
88 | /* .bFirstInterface = DYNAMIC, */ |
89 | .bInterfaceCount = 2, // control + data |
90 | .bFunctionClass = USB_CLASS_COMM, |
91 | .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, |
92 | .bFunctionProtocol = USB_CDC_ACM_PROTO_AT_V25TER, |
93 | /* .iFunction = DYNAMIC */ |
94 | }; |
95 | |
96 | |
97 | static struct usb_interface_descriptor acm_control_interface_desc = { |
98 | .bLength = USB_DT_INTERFACE_SIZE, |
99 | .bDescriptorType = USB_DT_INTERFACE, |
100 | /* .bInterfaceNumber = DYNAMIC */ |
101 | .bNumEndpoints = 1, |
102 | .bInterfaceClass = USB_CLASS_COMM, |
103 | .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, |
104 | .bInterfaceProtocol = USB_CDC_ACM_PROTO_AT_V25TER, |
105 | /* .iInterface = DYNAMIC */ |
106 | }; |
107 | |
108 | static struct usb_interface_descriptor acm_data_interface_desc = { |
109 | .bLength = USB_DT_INTERFACE_SIZE, |
110 | .bDescriptorType = USB_DT_INTERFACE, |
111 | /* .bInterfaceNumber = DYNAMIC */ |
112 | .bNumEndpoints = 2, |
113 | .bInterfaceClass = USB_CLASS_CDC_DATA, |
114 | .bInterfaceSubClass = 0, |
115 | .bInterfaceProtocol = 0, |
116 | /* .iInterface = DYNAMIC */ |
117 | }; |
118 | |
119 | static struct usb_cdc_header_desc = { |
120 | .bLength = sizeof(acm_header_desc), |
121 | .bDescriptorType = USB_DT_CS_INTERFACE, |
122 | .bDescriptorSubType = USB_CDC_HEADER_TYPE, |
123 | .bcdCDC = cpu_to_le16(0x0110), |
124 | }; |
125 | |
126 | static struct usb_cdc_call_mgmt_descriptor |
127 | acm_call_mgmt_descriptor = { |
128 | .bLength = sizeof(acm_call_mgmt_descriptor), |
129 | .bDescriptorType = USB_DT_CS_INTERFACE, |
130 | .bDescriptorSubType = USB_CDC_CALL_MANAGEMENT_TYPE, |
131 | .bmCapabilities = 0, |
132 | /* .bDataInterface = DYNAMIC */ |
133 | }; |
134 | |
135 | static struct usb_cdc_acm_descriptor acm_descriptor = { |
136 | .bLength = sizeof(acm_descriptor), |
137 | .bDescriptorType = USB_DT_CS_INTERFACE, |
138 | .bDescriptorSubType = USB_CDC_ACM_TYPE, |
139 | .bmCapabilities = USB_CDC_CAP_LINE, |
140 | }; |
141 | |
142 | static struct usb_cdc_union_desc acm_union_desc = { |
143 | .bLength = sizeof(acm_union_desc), |
144 | .bDescriptorType = USB_DT_CS_INTERFACE, |
145 | .bDescriptorSubType = USB_CDC_UNION_TYPE, |
146 | /* .bMasterInterface0 = DYNAMIC */ |
147 | /* .bSlaveInterface0 = DYNAMIC */ |
148 | }; |
149 | |
150 | /* full speed support: */ |
151 | |
152 | static struct usb_endpoint_descriptor acm_fs_notify_desc = { |
153 | .bLength = USB_DT_ENDPOINT_SIZE, |
154 | .bDescriptorType = USB_DT_ENDPOINT, |
155 | .bEndpointAddress = USB_DIR_IN, |
156 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
157 | .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), |
158 | .bInterval = GS_NOTIFY_INTERVAL_MS, |
159 | }; |
160 | |
161 | static struct usb_endpoint_descriptor acm_fs_in_desc = { |
162 | .bLength = USB_DT_ENDPOINT_SIZE, |
163 | .bDescriptorType = USB_DT_ENDPOINT, |
164 | .bEndpointAddress = USB_DIR_IN, |
165 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
166 | }; |
167 | |
168 | static struct usb_endpoint_descriptor acm_fs_out_desc = { |
169 | .bLength = USB_DT_ENDPOINT_SIZE, |
170 | .bDescriptorType = USB_DT_ENDPOINT, |
171 | .bEndpointAddress = USB_DIR_OUT, |
172 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
173 | }; |
174 | |
175 | static struct usb_descriptor_header *acm_fs_function[] = { |
176 | (struct usb_descriptor_header *) &acm_iad_descriptor, |
177 | (struct usb_descriptor_header *) &acm_control_interface_desc, |
178 | (struct usb_descriptor_header *) &acm_header_desc, |
179 | (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, |
180 | (struct usb_descriptor_header *) &acm_descriptor, |
181 | (struct usb_descriptor_header *) &acm_union_desc, |
182 | (struct usb_descriptor_header *) &acm_fs_notify_desc, |
183 | (struct usb_descriptor_header *) &acm_data_interface_desc, |
184 | (struct usb_descriptor_header *) &acm_fs_in_desc, |
185 | (struct usb_descriptor_header *) &acm_fs_out_desc, |
186 | NULL, |
187 | }; |
188 | |
189 | /* high speed support: */ |
190 | static struct usb_endpoint_descriptor acm_hs_notify_desc = { |
191 | .bLength = USB_DT_ENDPOINT_SIZE, |
192 | .bDescriptorType = USB_DT_ENDPOINT, |
193 | .bEndpointAddress = USB_DIR_IN, |
194 | .bmAttributes = USB_ENDPOINT_XFER_INT, |
195 | .wMaxPacketSize = cpu_to_le16(GS_NOTIFY_MAXPACKET), |
196 | .bInterval = USB_MS_TO_HS_INTERVAL(GS_NOTIFY_INTERVAL_MS), |
197 | }; |
198 | |
199 | static struct usb_endpoint_descriptor acm_hs_in_desc = { |
200 | .bLength = USB_DT_ENDPOINT_SIZE, |
201 | .bDescriptorType = USB_DT_ENDPOINT, |
202 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
203 | .wMaxPacketSize = cpu_to_le16(512), |
204 | }; |
205 | |
206 | static struct usb_endpoint_descriptor acm_hs_out_desc = { |
207 | .bLength = USB_DT_ENDPOINT_SIZE, |
208 | .bDescriptorType = USB_DT_ENDPOINT, |
209 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
210 | .wMaxPacketSize = cpu_to_le16(512), |
211 | }; |
212 | |
213 | static struct usb_descriptor_header *acm_hs_function[] = { |
214 | (struct usb_descriptor_header *) &acm_iad_descriptor, |
215 | (struct usb_descriptor_header *) &acm_control_interface_desc, |
216 | (struct usb_descriptor_header *) &acm_header_desc, |
217 | (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, |
218 | (struct usb_descriptor_header *) &acm_descriptor, |
219 | (struct usb_descriptor_header *) &acm_union_desc, |
220 | (struct usb_descriptor_header *) &acm_hs_notify_desc, |
221 | (struct usb_descriptor_header *) &acm_data_interface_desc, |
222 | (struct usb_descriptor_header *) &acm_hs_in_desc, |
223 | (struct usb_descriptor_header *) &acm_hs_out_desc, |
224 | NULL, |
225 | }; |
226 | |
227 | static struct usb_endpoint_descriptor acm_ss_in_desc = { |
228 | .bLength = USB_DT_ENDPOINT_SIZE, |
229 | .bDescriptorType = USB_DT_ENDPOINT, |
230 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
231 | .wMaxPacketSize = cpu_to_le16(1024), |
232 | }; |
233 | |
234 | static struct usb_endpoint_descriptor acm_ss_out_desc = { |
235 | .bLength = USB_DT_ENDPOINT_SIZE, |
236 | .bDescriptorType = USB_DT_ENDPOINT, |
237 | .bmAttributes = USB_ENDPOINT_XFER_BULK, |
238 | .wMaxPacketSize = cpu_to_le16(1024), |
239 | }; |
240 | |
241 | static struct usb_ss_ep_comp_descriptor acm_ss_bulk_comp_desc = { |
242 | .bLength = sizeof acm_ss_bulk_comp_desc, |
243 | .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, |
244 | }; |
245 | |
246 | static struct usb_descriptor_header *acm_ss_function[] = { |
247 | (struct usb_descriptor_header *) &acm_iad_descriptor, |
248 | (struct usb_descriptor_header *) &acm_control_interface_desc, |
249 | (struct usb_descriptor_header *) &acm_header_desc, |
250 | (struct usb_descriptor_header *) &acm_call_mgmt_descriptor, |
251 | (struct usb_descriptor_header *) &acm_descriptor, |
252 | (struct usb_descriptor_header *) &acm_union_desc, |
253 | (struct usb_descriptor_header *) &acm_hs_notify_desc, |
254 | (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, |
255 | (struct usb_descriptor_header *) &acm_data_interface_desc, |
256 | (struct usb_descriptor_header *) &acm_ss_in_desc, |
257 | (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, |
258 | (struct usb_descriptor_header *) &acm_ss_out_desc, |
259 | (struct usb_descriptor_header *) &acm_ss_bulk_comp_desc, |
260 | NULL, |
261 | }; |
262 | |
263 | /* string descriptors: */ |
264 | |
265 | #define ACM_CTRL_IDX 0 |
266 | #define ACM_DATA_IDX 1 |
267 | #define ACM_IAD_IDX 2 |
268 | |
269 | /* static strings, in UTF-8 */ |
270 | static struct usb_string acm_string_defs[] = { |
271 | [ACM_CTRL_IDX].s = "CDC Abstract Control Model (ACM)" , |
272 | [ACM_DATA_IDX].s = "CDC ACM Data" , |
273 | [ACM_IAD_IDX ].s = "CDC Serial" , |
274 | { } /* end of list */ |
275 | }; |
276 | |
277 | static struct usb_gadget_strings acm_string_table = { |
278 | .language = 0x0409, /* en-us */ |
279 | .strings = acm_string_defs, |
280 | }; |
281 | |
282 | static struct usb_gadget_strings *acm_strings[] = { |
283 | &acm_string_table, |
284 | NULL, |
285 | }; |
286 | |
287 | /*-------------------------------------------------------------------------*/ |
288 | |
289 | /* ACM control ... data handling is delegated to tty library code. |
290 | * The main task of this function is to activate and deactivate |
291 | * that code based on device state; track parameters like line |
292 | * speed, handshake state, and so on; and issue notifications. |
293 | */ |
294 | |
295 | static void acm_complete_set_line_coding(struct usb_ep *ep, |
296 | struct usb_request *req) |
297 | { |
298 | struct f_acm *acm = ep->driver_data; |
299 | struct usb_composite_dev *cdev = acm->port.func.config->cdev; |
300 | |
301 | if (req->status != 0) { |
302 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d completion, err %d\n" , |
303 | acm->port_num, req->status); |
304 | return; |
305 | } |
306 | |
307 | /* normal completion */ |
308 | if (req->actual != sizeof(acm->port_line_coding)) { |
309 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d short resp, len %d\n" , |
310 | acm->port_num, req->actual); |
311 | usb_ep_set_halt(ep); |
312 | } else { |
313 | struct usb_cdc_line_coding *value = req->buf; |
314 | |
315 | /* REVISIT: we currently just remember this data. |
316 | * If we change that, (a) validate it first, then |
317 | * (b) update whatever hardware needs updating, |
318 | * (c) worry about locking. This is information on |
319 | * the order of 9600-8-N-1 ... most of which means |
320 | * nothing unless we control a real RS232 line. |
321 | */ |
322 | acm->port_line_coding = *value; |
323 | } |
324 | } |
325 | |
326 | static int acm_send_break(struct gserial *port, int duration); |
327 | |
328 | static int acm_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) |
329 | { |
330 | struct f_acm *acm = func_to_acm(f); |
331 | struct usb_composite_dev *cdev = f->config->cdev; |
332 | struct usb_request *req = cdev->req; |
333 | int value = -EOPNOTSUPP; |
334 | u16 w_index = le16_to_cpu(ctrl->wIndex); |
335 | u16 w_value = le16_to_cpu(ctrl->wValue); |
336 | u16 w_length = le16_to_cpu(ctrl->wLength); |
337 | |
338 | /* composite driver infrastructure handles everything except |
339 | * CDC class messages; interface activation uses set_alt(). |
340 | * |
341 | * Note CDC spec table 4 lists the ACM request profile. It requires |
342 | * encapsulated command support ... we don't handle any, and respond |
343 | * to them by stalling. Options include get/set/clear comm features |
344 | * (not that useful) and SEND_BREAK. |
345 | */ |
346 | switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { |
347 | |
348 | /* SET_LINE_CODING ... just read and save what the host sends */ |
349 | case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) |
350 | | USB_CDC_REQ_SET_LINE_CODING: |
351 | if (w_length != sizeof(struct usb_cdc_line_coding) |
352 | || w_index != acm->ctrl_id) |
353 | goto invalid; |
354 | |
355 | value = w_length; |
356 | cdev->gadget->ep0->driver_data = acm; |
357 | req->complete = acm_complete_set_line_coding; |
358 | break; |
359 | |
360 | /* GET_LINE_CODING ... return what host sent, or initial value */ |
361 | case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) |
362 | | USB_CDC_REQ_GET_LINE_CODING: |
363 | if (w_index != acm->ctrl_id) |
364 | goto invalid; |
365 | |
366 | value = min_t(unsigned, w_length, |
367 | sizeof(struct usb_cdc_line_coding)); |
368 | memcpy(req->buf, &acm->port_line_coding, value); |
369 | break; |
370 | |
371 | /* SET_CONTROL_LINE_STATE ... save what the host sent */ |
372 | case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) |
373 | | USB_CDC_REQ_SET_CONTROL_LINE_STATE: |
374 | if (w_index != acm->ctrl_id) |
375 | goto invalid; |
376 | |
377 | value = 0; |
378 | |
379 | /* FIXME we should not allow data to flow until the |
380 | * host sets the USB_CDC_CTRL_DTR bit; and when it clears |
381 | * that bit, we should return to that no-flow state. |
382 | */ |
383 | acm->port_handshake_bits = w_value; |
384 | break; |
385 | |
386 | case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8) |
387 | | USB_CDC_REQ_SEND_BREAK: |
388 | if (w_index != acm->ctrl_id) |
389 | goto invalid; |
390 | |
391 | acm_send_break(port: &acm->port, duration: w_value); |
392 | break; |
393 | |
394 | default: |
395 | invalid: |
396 | dev_vdbg(&cdev->gadget->dev, |
397 | "invalid control req%02x.%02x v%04x i%04x l%d\n" , |
398 | ctrl->bRequestType, ctrl->bRequest, |
399 | w_value, w_index, w_length); |
400 | } |
401 | |
402 | /* respond with data transfer or status phase? */ |
403 | if (value >= 0) { |
404 | dev_dbg(&cdev->gadget->dev, |
405 | "acm ttyGS%d req%02x.%02x v%04x i%04x l%d\n" , |
406 | acm->port_num, ctrl->bRequestType, ctrl->bRequest, |
407 | w_value, w_index, w_length); |
408 | req->zero = 0; |
409 | req->length = value; |
410 | value = usb_ep_queue(ep: cdev->gadget->ep0, req, GFP_ATOMIC); |
411 | if (value < 0) |
412 | ERROR(cdev, "acm response on ttyGS%d, err %d\n" , |
413 | acm->port_num, value); |
414 | } |
415 | |
416 | /* device either stalls (value < 0) or reports success */ |
417 | return value; |
418 | } |
419 | |
420 | static int acm_set_alt(struct usb_function *f, unsigned intf, unsigned alt) |
421 | { |
422 | struct f_acm *acm = func_to_acm(f); |
423 | struct usb_composite_dev *cdev = f->config->cdev; |
424 | |
425 | /* we know alt == 0, so this is an activation or a reset */ |
426 | |
427 | if (intf == acm->ctrl_id) { |
428 | if (acm->notify->enabled) { |
429 | dev_vdbg(&cdev->gadget->dev, |
430 | "reset acm control interface %d\n" , intf); |
431 | usb_ep_disable(ep: acm->notify); |
432 | } |
433 | |
434 | if (!acm->notify->desc) |
435 | if (config_ep_by_speed(g: cdev->gadget, f, ep: acm->notify)) |
436 | return -EINVAL; |
437 | |
438 | usb_ep_enable(ep: acm->notify); |
439 | |
440 | } else if (intf == acm->data_id) { |
441 | if (acm->notify->enabled) { |
442 | dev_dbg(&cdev->gadget->dev, |
443 | "reset acm ttyGS%d\n" , acm->port_num); |
444 | gserial_disconnect(&acm->port); |
445 | } |
446 | if (!acm->port.in->desc || !acm->port.out->desc) { |
447 | dev_dbg(&cdev->gadget->dev, |
448 | "activate acm ttyGS%d\n" , acm->port_num); |
449 | if (config_ep_by_speed(g: cdev->gadget, f, |
450 | ep: acm->port.in) || |
451 | config_ep_by_speed(g: cdev->gadget, f, |
452 | ep: acm->port.out)) { |
453 | acm->port.in->desc = NULL; |
454 | acm->port.out->desc = NULL; |
455 | return -EINVAL; |
456 | } |
457 | } |
458 | gserial_connect(&acm->port, port_num: acm->port_num); |
459 | |
460 | } else |
461 | return -EINVAL; |
462 | |
463 | return 0; |
464 | } |
465 | |
466 | static void acm_disable(struct usb_function *f) |
467 | { |
468 | struct f_acm *acm = func_to_acm(f); |
469 | struct usb_composite_dev *cdev = f->config->cdev; |
470 | |
471 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d deactivated\n" , acm->port_num); |
472 | gserial_disconnect(&acm->port); |
473 | usb_ep_disable(ep: acm->notify); |
474 | } |
475 | |
476 | /*-------------------------------------------------------------------------*/ |
477 | |
478 | /** |
479 | * acm_cdc_notify - issue CDC notification to host |
480 | * @acm: wraps host to be notified |
481 | * @type: notification type |
482 | * @value: Refer to cdc specs, wValue field. |
483 | * @data: data to be sent |
484 | * @length: size of data |
485 | * Context: irqs blocked, acm->lock held, acm_notify_req non-null |
486 | * |
487 | * Returns zero on success or a negative errno. |
488 | * |
489 | * See section 6.3.5 of the CDC 1.1 specification for information |
490 | * about the only notification we issue: SerialState change. |
491 | */ |
492 | static int acm_cdc_notify(struct f_acm *acm, u8 type, u16 value, |
493 | void *data, unsigned length) |
494 | { |
495 | struct usb_ep *ep = acm->notify; |
496 | struct usb_request *req; |
497 | struct usb_cdc_notification *notify; |
498 | const unsigned len = sizeof(*notify) + length; |
499 | void *buf; |
500 | int status; |
501 | |
502 | req = acm->notify_req; |
503 | acm->notify_req = NULL; |
504 | acm->pending = false; |
505 | |
506 | req->length = len; |
507 | notify = req->buf; |
508 | buf = notify + 1; |
509 | |
510 | notify->bmRequestType = USB_DIR_IN | USB_TYPE_CLASS |
511 | | USB_RECIP_INTERFACE; |
512 | notify->bNotificationType = type; |
513 | notify->wValue = cpu_to_le16(value); |
514 | notify->wIndex = cpu_to_le16(acm->ctrl_id); |
515 | notify->wLength = cpu_to_le16(length); |
516 | memcpy(buf, data, length); |
517 | |
518 | /* ep_queue() can complete immediately if it fills the fifo... */ |
519 | spin_unlock(lock: &acm->lock); |
520 | status = usb_ep_queue(ep, req, GFP_ATOMIC); |
521 | spin_lock(lock: &acm->lock); |
522 | |
523 | if (status < 0) { |
524 | ERROR(acm->port.func.config->cdev, |
525 | "acm ttyGS%d can't notify serial state, %d\n" , |
526 | acm->port_num, status); |
527 | acm->notify_req = req; |
528 | } |
529 | |
530 | return status; |
531 | } |
532 | |
533 | static int acm_notify_serial_state(struct f_acm *acm) |
534 | { |
535 | struct usb_composite_dev *cdev = acm->port.func.config->cdev; |
536 | int status; |
537 | __le16 serial_state; |
538 | |
539 | spin_lock(lock: &acm->lock); |
540 | if (acm->notify_req) { |
541 | dev_dbg(&cdev->gadget->dev, "acm ttyGS%d serial state %04x\n" , |
542 | acm->port_num, acm->serial_state); |
543 | serial_state = cpu_to_le16(acm->serial_state); |
544 | status = acm_cdc_notify(acm, USB_CDC_NOTIFY_SERIAL_STATE, |
545 | value: 0, data: &serial_state, length: sizeof(acm->serial_state)); |
546 | } else { |
547 | acm->pending = true; |
548 | status = 0; |
549 | } |
550 | spin_unlock(lock: &acm->lock); |
551 | return status; |
552 | } |
553 | |
554 | static void acm_cdc_notify_complete(struct usb_ep *ep, struct usb_request *req) |
555 | { |
556 | struct f_acm *acm = req->context; |
557 | u8 doit = false; |
558 | |
559 | /* on this call path we do NOT hold the port spinlock, |
560 | * which is why ACM needs its own spinlock |
561 | */ |
562 | spin_lock(lock: &acm->lock); |
563 | if (req->status != -ESHUTDOWN) |
564 | doit = acm->pending; |
565 | acm->notify_req = req; |
566 | spin_unlock(lock: &acm->lock); |
567 | |
568 | if (doit) |
569 | acm_notify_serial_state(acm); |
570 | } |
571 | |
572 | /* connect == the TTY link is open */ |
573 | |
574 | static void acm_connect(struct gserial *port) |
575 | { |
576 | struct f_acm *acm = port_to_acm(p: port); |
577 | |
578 | acm->serial_state |= USB_CDC_SERIAL_STATE_DSR | USB_CDC_SERIAL_STATE_DCD; |
579 | acm_notify_serial_state(acm); |
580 | } |
581 | |
582 | static void acm_disconnect(struct gserial *port) |
583 | { |
584 | struct f_acm *acm = port_to_acm(p: port); |
585 | |
586 | acm->serial_state &= ~(USB_CDC_SERIAL_STATE_DSR | USB_CDC_SERIAL_STATE_DCD); |
587 | acm_notify_serial_state(acm); |
588 | } |
589 | |
590 | static int acm_send_break(struct gserial *port, int duration) |
591 | { |
592 | struct f_acm *acm = port_to_acm(p: port); |
593 | u16 state; |
594 | |
595 | state = acm->serial_state; |
596 | state &= ~USB_CDC_SERIAL_STATE_BREAK; |
597 | if (duration) |
598 | state |= USB_CDC_SERIAL_STATE_BREAK; |
599 | |
600 | acm->serial_state = state; |
601 | return acm_notify_serial_state(acm); |
602 | } |
603 | |
604 | /*-------------------------------------------------------------------------*/ |
605 | |
606 | /* ACM function driver setup/binding */ |
607 | static int |
608 | acm_bind(struct usb_configuration *c, struct usb_function *f) |
609 | { |
610 | struct usb_composite_dev *cdev = c->cdev; |
611 | struct f_acm *acm = func_to_acm(f); |
612 | struct usb_string *us; |
613 | int status; |
614 | struct usb_ep *ep; |
615 | |
616 | /* REVISIT might want instance-specific strings to help |
617 | * distinguish instances ... |
618 | */ |
619 | |
620 | /* maybe allocate device-global string IDs, and patch descriptors */ |
621 | us = usb_gstrings_attach(cdev, sp: acm_strings, |
622 | ARRAY_SIZE(acm_string_defs)); |
623 | if (IS_ERR(ptr: us)) |
624 | return PTR_ERR(ptr: us); |
625 | acm_control_interface_desc.iInterface = us[ACM_CTRL_IDX].id; |
626 | acm_data_interface_desc.iInterface = us[ACM_DATA_IDX].id; |
627 | acm_iad_descriptor.iFunction = us[ACM_IAD_IDX].id; |
628 | |
629 | /* allocate instance-specific interface IDs, and patch descriptors */ |
630 | status = usb_interface_id(c, f); |
631 | if (status < 0) |
632 | goto fail; |
633 | acm->ctrl_id = status; |
634 | acm_iad_descriptor.bFirstInterface = status; |
635 | |
636 | acm_control_interface_desc.bInterfaceNumber = status; |
637 | acm_union_desc .bMasterInterface0 = status; |
638 | |
639 | status = usb_interface_id(c, f); |
640 | if (status < 0) |
641 | goto fail; |
642 | acm->data_id = status; |
643 | |
644 | acm_data_interface_desc.bInterfaceNumber = status; |
645 | acm_union_desc.bSlaveInterface0 = status; |
646 | acm_call_mgmt_descriptor.bDataInterface = status; |
647 | |
648 | status = -ENODEV; |
649 | |
650 | /* allocate instance-specific endpoints */ |
651 | ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_in_desc); |
652 | if (!ep) |
653 | goto fail; |
654 | acm->port.in = ep; |
655 | |
656 | ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_out_desc); |
657 | if (!ep) |
658 | goto fail; |
659 | acm->port.out = ep; |
660 | |
661 | ep = usb_ep_autoconfig(cdev->gadget, &acm_fs_notify_desc); |
662 | if (!ep) |
663 | goto fail; |
664 | acm->notify = ep; |
665 | |
666 | /* allocate notification */ |
667 | acm->notify_req = gs_alloc_req(ep, |
668 | len: sizeof(struct usb_cdc_notification) + 2, |
669 | GFP_KERNEL); |
670 | if (!acm->notify_req) |
671 | goto fail; |
672 | |
673 | acm->notify_req->complete = acm_cdc_notify_complete; |
674 | acm->notify_req->context = acm; |
675 | |
676 | /* support all relevant hardware speeds... we expect that when |
677 | * hardware is dual speed, all bulk-capable endpoints work at |
678 | * both speeds |
679 | */ |
680 | acm_hs_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; |
681 | acm_hs_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; |
682 | acm_hs_notify_desc.bEndpointAddress = |
683 | acm_fs_notify_desc.bEndpointAddress; |
684 | |
685 | acm_ss_in_desc.bEndpointAddress = acm_fs_in_desc.bEndpointAddress; |
686 | acm_ss_out_desc.bEndpointAddress = acm_fs_out_desc.bEndpointAddress; |
687 | |
688 | status = usb_assign_descriptors(f, fs: acm_fs_function, hs: acm_hs_function, |
689 | ss: acm_ss_function, ssp: acm_ss_function); |
690 | if (status) |
691 | goto fail; |
692 | |
693 | dev_dbg(&cdev->gadget->dev, |
694 | "acm ttyGS%d: IN/%s OUT/%s NOTIFY/%s\n" , |
695 | acm->port_num, |
696 | acm->port.in->name, acm->port.out->name, |
697 | acm->notify->name); |
698 | return 0; |
699 | |
700 | fail: |
701 | if (acm->notify_req) |
702 | gs_free_req(acm->notify, req: acm->notify_req); |
703 | |
704 | ERROR(cdev, "%s/%p: can't bind, err %d\n" , f->name, f, status); |
705 | |
706 | return status; |
707 | } |
708 | |
709 | static void acm_unbind(struct usb_configuration *c, struct usb_function *f) |
710 | { |
711 | struct f_acm *acm = func_to_acm(f); |
712 | |
713 | acm_string_defs[0].id = 0; |
714 | usb_free_all_descriptors(f); |
715 | if (acm->notify_req) |
716 | gs_free_req(acm->notify, req: acm->notify_req); |
717 | } |
718 | |
719 | static void acm_free_func(struct usb_function *f) |
720 | { |
721 | struct f_acm *acm = func_to_acm(f); |
722 | |
723 | kfree(objp: acm); |
724 | } |
725 | |
726 | static void acm_resume(struct usb_function *f) |
727 | { |
728 | struct f_acm *acm = func_to_acm(f); |
729 | |
730 | gserial_resume(p: &acm->port); |
731 | } |
732 | |
733 | static void acm_suspend(struct usb_function *f) |
734 | { |
735 | struct f_acm *acm = func_to_acm(f); |
736 | |
737 | gserial_suspend(p: &acm->port); |
738 | } |
739 | |
740 | static struct usb_function *acm_alloc_func(struct usb_function_instance *fi) |
741 | { |
742 | struct f_serial_opts *opts; |
743 | struct f_acm *acm; |
744 | |
745 | acm = kzalloc(size: sizeof(*acm), GFP_KERNEL); |
746 | if (!acm) |
747 | return ERR_PTR(error: -ENOMEM); |
748 | |
749 | spin_lock_init(&acm->lock); |
750 | |
751 | acm->port.connect = acm_connect; |
752 | acm->port.disconnect = acm_disconnect; |
753 | acm->port.send_break = acm_send_break; |
754 | |
755 | acm->port.func.name = "acm" ; |
756 | acm->port.func.strings = acm_strings; |
757 | /* descriptors are per-instance copies */ |
758 | acm->port.func.bind = acm_bind; |
759 | acm->port.func.set_alt = acm_set_alt; |
760 | acm->port.func.setup = acm_setup; |
761 | acm->port.func.disable = acm_disable; |
762 | |
763 | opts = container_of(fi, struct f_serial_opts, func_inst); |
764 | acm->port_num = opts->port_num; |
765 | acm->port.func.unbind = acm_unbind; |
766 | acm->port.func.free_func = acm_free_func; |
767 | acm->port.func.resume = acm_resume; |
768 | acm->port.func.suspend = acm_suspend; |
769 | |
770 | return &acm->port.func; |
771 | } |
772 | |
773 | static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item) |
774 | { |
775 | return container_of(to_config_group(item), struct f_serial_opts, |
776 | func_inst.group); |
777 | } |
778 | |
779 | static void acm_attr_release(struct config_item *item) |
780 | { |
781 | struct f_serial_opts *opts = to_f_serial_opts(item); |
782 | |
783 | usb_put_function_instance(fi: &opts->func_inst); |
784 | } |
785 | |
786 | static struct configfs_item_operations acm_item_ops = { |
787 | .release = acm_attr_release, |
788 | }; |
789 | |
790 | #ifdef CONFIG_U_SERIAL_CONSOLE |
791 | |
792 | static ssize_t f_acm_console_store(struct config_item *item, |
793 | const char *page, size_t count) |
794 | { |
795 | return gserial_set_console(port_num: to_f_serial_opts(item)->port_num, |
796 | page, count); |
797 | } |
798 | |
799 | static ssize_t f_acm_console_show(struct config_item *item, char *page) |
800 | { |
801 | return gserial_get_console(port_num: to_f_serial_opts(item)->port_num, page); |
802 | } |
803 | |
804 | CONFIGFS_ATTR(f_acm_, console); |
805 | |
806 | #endif /* CONFIG_U_SERIAL_CONSOLE */ |
807 | |
808 | static ssize_t f_acm_port_num_show(struct config_item *item, char *page) |
809 | { |
810 | return sprintf(buf: page, fmt: "%u\n" , to_f_serial_opts(item)->port_num); |
811 | } |
812 | |
813 | CONFIGFS_ATTR_RO(f_acm_, port_num); |
814 | |
815 | static struct configfs_attribute *acm_attrs[] = { |
816 | #ifdef CONFIG_U_SERIAL_CONSOLE |
817 | &f_acm_attr_console, |
818 | #endif |
819 | &f_acm_attr_port_num, |
820 | NULL, |
821 | }; |
822 | |
823 | static const struct config_item_type acm_func_type = { |
824 | .ct_item_ops = &acm_item_ops, |
825 | .ct_attrs = acm_attrs, |
826 | .ct_owner = THIS_MODULE, |
827 | }; |
828 | |
829 | static void acm_free_instance(struct usb_function_instance *fi) |
830 | { |
831 | struct f_serial_opts *opts; |
832 | |
833 | opts = container_of(fi, struct f_serial_opts, func_inst); |
834 | gserial_free_line(port_line: opts->port_num); |
835 | kfree(objp: opts); |
836 | } |
837 | |
838 | static struct usb_function_instance *acm_alloc_instance(void) |
839 | { |
840 | struct f_serial_opts *opts; |
841 | int ret; |
842 | |
843 | opts = kzalloc(size: sizeof(*opts), GFP_KERNEL); |
844 | if (!opts) |
845 | return ERR_PTR(error: -ENOMEM); |
846 | opts->func_inst.free_func_inst = acm_free_instance; |
847 | ret = gserial_alloc_line(port_line: &opts->port_num); |
848 | if (ret) { |
849 | kfree(objp: opts); |
850 | return ERR_PTR(error: ret); |
851 | } |
852 | config_group_init_type_name(group: &opts->func_inst.group, name: "" , |
853 | type: &acm_func_type); |
854 | return &opts->func_inst; |
855 | } |
856 | DECLARE_USB_FUNCTION_INIT(acm, acm_alloc_instance, acm_alloc_func); |
857 | MODULE_LICENSE("GPL" ); |
858 | |