f_obex.c (12593B)
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * f_obex.c -- USB CDC OBEX function driver 4 * 5 * Copyright (C) 2008 Nokia Corporation 6 * Contact: Felipe Balbi <felipe.balbi@nokia.com> 7 * 8 * Based on f_acm.c by Al Borchers and David Brownell. 9 */ 10 11/* #define VERBOSE_DEBUG */ 12 13#include <linux/slab.h> 14#include <linux/kernel.h> 15#include <linux/device.h> 16#include <linux/module.h> 17 18#include "u_serial.h" 19 20 21/* 22 * This CDC OBEX function support just packages a TTY-ish byte stream. 23 * A user mode server will put it into "raw" mode and handle all the 24 * relevant protocol details ... this is just a kernel passthrough. 25 * When possible, we prevent gadget enumeration until that server is 26 * ready to handle the commands. 27 */ 28 29struct f_obex { 30 struct gserial port; 31 u8 ctrl_id; 32 u8 data_id; 33 u8 cur_alt; 34 u8 port_num; 35}; 36 37static inline struct f_obex *func_to_obex(struct usb_function *f) 38{ 39 return container_of(f, struct f_obex, port.func); 40} 41 42static inline struct f_obex *port_to_obex(struct gserial *p) 43{ 44 return container_of(p, struct f_obex, port); 45} 46 47/*-------------------------------------------------------------------------*/ 48 49#define OBEX_CTRL_IDX 0 50#define OBEX_DATA_IDX 1 51 52static struct usb_string obex_string_defs[] = { 53 [OBEX_CTRL_IDX].s = "CDC Object Exchange (OBEX)", 54 [OBEX_DATA_IDX].s = "CDC OBEX Data", 55 { }, /* end of list */ 56}; 57 58static struct usb_gadget_strings obex_string_table = { 59 .language = 0x0409, /* en-US */ 60 .strings = obex_string_defs, 61}; 62 63static struct usb_gadget_strings *obex_strings[] = { 64 &obex_string_table, 65 NULL, 66}; 67 68/*-------------------------------------------------------------------------*/ 69 70static struct usb_interface_descriptor obex_control_intf = { 71 .bLength = sizeof(obex_control_intf), 72 .bDescriptorType = USB_DT_INTERFACE, 73 .bInterfaceNumber = 0, 74 75 .bAlternateSetting = 0, 76 .bNumEndpoints = 0, 77 .bInterfaceClass = USB_CLASS_COMM, 78 .bInterfaceSubClass = USB_CDC_SUBCLASS_OBEX, 79}; 80 81static struct usb_interface_descriptor obex_data_nop_intf = { 82 .bLength = sizeof(obex_data_nop_intf), 83 .bDescriptorType = USB_DT_INTERFACE, 84 .bInterfaceNumber = 1, 85 86 .bAlternateSetting = 0, 87 .bNumEndpoints = 0, 88 .bInterfaceClass = USB_CLASS_CDC_DATA, 89}; 90 91static struct usb_interface_descriptor obex_data_intf = { 92 .bLength = sizeof(obex_data_intf), 93 .bDescriptorType = USB_DT_INTERFACE, 94 .bInterfaceNumber = 2, 95 96 .bAlternateSetting = 1, 97 .bNumEndpoints = 2, 98 .bInterfaceClass = USB_CLASS_CDC_DATA, 99}; 100 101static struct usb_cdc_header_desc obex_cdc_header_desc = { 102 .bLength = sizeof(obex_cdc_header_desc), 103 .bDescriptorType = USB_DT_CS_INTERFACE, 104 .bDescriptorSubType = USB_CDC_HEADER_TYPE, 105 .bcdCDC = cpu_to_le16(0x0120), 106}; 107 108static struct usb_cdc_union_desc obex_cdc_union_desc = { 109 .bLength = sizeof(obex_cdc_union_desc), 110 .bDescriptorType = USB_DT_CS_INTERFACE, 111 .bDescriptorSubType = USB_CDC_UNION_TYPE, 112 .bMasterInterface0 = 1, 113 .bSlaveInterface0 = 2, 114}; 115 116static struct usb_cdc_obex_desc obex_desc = { 117 .bLength = sizeof(obex_desc), 118 .bDescriptorType = USB_DT_CS_INTERFACE, 119 .bDescriptorSubType = USB_CDC_OBEX_TYPE, 120 .bcdVersion = cpu_to_le16(0x0100), 121}; 122 123/* High-Speed Support */ 124 125static struct usb_endpoint_descriptor obex_hs_ep_out_desc = { 126 .bLength = USB_DT_ENDPOINT_SIZE, 127 .bDescriptorType = USB_DT_ENDPOINT, 128 129 .bEndpointAddress = USB_DIR_OUT, 130 .bmAttributes = USB_ENDPOINT_XFER_BULK, 131 .wMaxPacketSize = cpu_to_le16(512), 132}; 133 134static struct usb_endpoint_descriptor obex_hs_ep_in_desc = { 135 .bLength = USB_DT_ENDPOINT_SIZE, 136 .bDescriptorType = USB_DT_ENDPOINT, 137 138 .bEndpointAddress = USB_DIR_IN, 139 .bmAttributes = USB_ENDPOINT_XFER_BULK, 140 .wMaxPacketSize = cpu_to_le16(512), 141}; 142 143static struct usb_descriptor_header *hs_function[] = { 144 (struct usb_descriptor_header *) &obex_control_intf, 145 (struct usb_descriptor_header *) &obex_cdc_header_desc, 146 (struct usb_descriptor_header *) &obex_desc, 147 (struct usb_descriptor_header *) &obex_cdc_union_desc, 148 149 (struct usb_descriptor_header *) &obex_data_nop_intf, 150 (struct usb_descriptor_header *) &obex_data_intf, 151 (struct usb_descriptor_header *) &obex_hs_ep_in_desc, 152 (struct usb_descriptor_header *) &obex_hs_ep_out_desc, 153 NULL, 154}; 155 156/* Full-Speed Support */ 157 158static struct usb_endpoint_descriptor obex_fs_ep_in_desc = { 159 .bLength = USB_DT_ENDPOINT_SIZE, 160 .bDescriptorType = USB_DT_ENDPOINT, 161 162 .bEndpointAddress = USB_DIR_IN, 163 .bmAttributes = USB_ENDPOINT_XFER_BULK, 164}; 165 166static struct usb_endpoint_descriptor obex_fs_ep_out_desc = { 167 .bLength = USB_DT_ENDPOINT_SIZE, 168 .bDescriptorType = USB_DT_ENDPOINT, 169 170 .bEndpointAddress = USB_DIR_OUT, 171 .bmAttributes = USB_ENDPOINT_XFER_BULK, 172}; 173 174static struct usb_descriptor_header *fs_function[] = { 175 (struct usb_descriptor_header *) &obex_control_intf, 176 (struct usb_descriptor_header *) &obex_cdc_header_desc, 177 (struct usb_descriptor_header *) &obex_desc, 178 (struct usb_descriptor_header *) &obex_cdc_union_desc, 179 180 (struct usb_descriptor_header *) &obex_data_nop_intf, 181 (struct usb_descriptor_header *) &obex_data_intf, 182 (struct usb_descriptor_header *) &obex_fs_ep_in_desc, 183 (struct usb_descriptor_header *) &obex_fs_ep_out_desc, 184 NULL, 185}; 186 187/*-------------------------------------------------------------------------*/ 188 189static int obex_set_alt(struct usb_function *f, unsigned intf, unsigned alt) 190{ 191 struct f_obex *obex = func_to_obex(f); 192 struct usb_composite_dev *cdev = f->config->cdev; 193 194 if (intf == obex->ctrl_id) { 195 if (alt != 0) 196 goto fail; 197 /* NOP */ 198 dev_dbg(&cdev->gadget->dev, 199 "reset obex ttyGS%d control\n", obex->port_num); 200 201 } else if (intf == obex->data_id) { 202 if (alt > 1) 203 goto fail; 204 205 if (obex->port.in->enabled) { 206 dev_dbg(&cdev->gadget->dev, 207 "reset obex ttyGS%d\n", obex->port_num); 208 gserial_disconnect(&obex->port); 209 } 210 211 if (!obex->port.in->desc || !obex->port.out->desc) { 212 dev_dbg(&cdev->gadget->dev, 213 "init obex ttyGS%d\n", obex->port_num); 214 if (config_ep_by_speed(cdev->gadget, f, 215 obex->port.in) || 216 config_ep_by_speed(cdev->gadget, f, 217 obex->port.out)) { 218 obex->port.out->desc = NULL; 219 obex->port.in->desc = NULL; 220 goto fail; 221 } 222 } 223 224 if (alt == 1) { 225 dev_dbg(&cdev->gadget->dev, 226 "activate obex ttyGS%d\n", obex->port_num); 227 gserial_connect(&obex->port, obex->port_num); 228 } 229 230 } else 231 goto fail; 232 233 obex->cur_alt = alt; 234 235 return 0; 236 237fail: 238 return -EINVAL; 239} 240 241static int obex_get_alt(struct usb_function *f, unsigned intf) 242{ 243 struct f_obex *obex = func_to_obex(f); 244 245 return obex->cur_alt; 246} 247 248static void obex_disable(struct usb_function *f) 249{ 250 struct f_obex *obex = func_to_obex(f); 251 struct usb_composite_dev *cdev = f->config->cdev; 252 253 dev_dbg(&cdev->gadget->dev, "obex ttyGS%d disable\n", obex->port_num); 254 gserial_disconnect(&obex->port); 255} 256 257/*-------------------------------------------------------------------------*/ 258 259static void obex_connect(struct gserial *g) 260{ 261 struct f_obex *obex = port_to_obex(g); 262 struct usb_composite_dev *cdev = g->func.config->cdev; 263 int status; 264 265 status = usb_function_activate(&g->func); 266 if (status) 267 dev_dbg(&cdev->gadget->dev, 268 "obex ttyGS%d function activate --> %d\n", 269 obex->port_num, status); 270} 271 272static void obex_disconnect(struct gserial *g) 273{ 274 struct f_obex *obex = port_to_obex(g); 275 struct usb_composite_dev *cdev = g->func.config->cdev; 276 int status; 277 278 status = usb_function_deactivate(&g->func); 279 if (status) 280 dev_dbg(&cdev->gadget->dev, 281 "obex ttyGS%d function deactivate --> %d\n", 282 obex->port_num, status); 283} 284 285/*-------------------------------------------------------------------------*/ 286 287/* Some controllers can't support CDC OBEX ... */ 288static inline bool can_support_obex(struct usb_configuration *c) 289{ 290 /* Since the first interface is a NOP, we can ignore the 291 * issue of multi-interface support on most controllers. 292 * 293 * Altsettings are mandatory, however... 294 */ 295 if (!gadget_is_altset_supported(c->cdev->gadget)) 296 return false; 297 298 /* everything else is *probably* fine ... */ 299 return true; 300} 301 302static int obex_bind(struct usb_configuration *c, struct usb_function *f) 303{ 304 struct usb_composite_dev *cdev = c->cdev; 305 struct f_obex *obex = func_to_obex(f); 306 struct usb_string *us; 307 int status; 308 struct usb_ep *ep; 309 310 if (!can_support_obex(c)) 311 return -EINVAL; 312 313 us = usb_gstrings_attach(cdev, obex_strings, 314 ARRAY_SIZE(obex_string_defs)); 315 if (IS_ERR(us)) 316 return PTR_ERR(us); 317 obex_control_intf.iInterface = us[OBEX_CTRL_IDX].id; 318 obex_data_nop_intf.iInterface = us[OBEX_DATA_IDX].id; 319 obex_data_intf.iInterface = us[OBEX_DATA_IDX].id; 320 321 /* allocate instance-specific interface IDs, and patch descriptors */ 322 323 status = usb_interface_id(c, f); 324 if (status < 0) 325 goto fail; 326 obex->ctrl_id = status; 327 328 obex_control_intf.bInterfaceNumber = status; 329 obex_cdc_union_desc.bMasterInterface0 = status; 330 331 status = usb_interface_id(c, f); 332 if (status < 0) 333 goto fail; 334 obex->data_id = status; 335 336 obex_data_nop_intf.bInterfaceNumber = status; 337 obex_data_intf.bInterfaceNumber = status; 338 obex_cdc_union_desc.bSlaveInterface0 = status; 339 340 /* allocate instance-specific endpoints */ 341 342 status = -ENODEV; 343 ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_in_desc); 344 if (!ep) 345 goto fail; 346 obex->port.in = ep; 347 348 ep = usb_ep_autoconfig(cdev->gadget, &obex_fs_ep_out_desc); 349 if (!ep) 350 goto fail; 351 obex->port.out = ep; 352 353 /* support all relevant hardware speeds... we expect that when 354 * hardware is dual speed, all bulk-capable endpoints work at 355 * both speeds 356 */ 357 358 obex_hs_ep_in_desc.bEndpointAddress = 359 obex_fs_ep_in_desc.bEndpointAddress; 360 obex_hs_ep_out_desc.bEndpointAddress = 361 obex_fs_ep_out_desc.bEndpointAddress; 362 363 status = usb_assign_descriptors(f, fs_function, hs_function, NULL, 364 NULL); 365 if (status) 366 goto fail; 367 368 dev_dbg(&cdev->gadget->dev, "obex ttyGS%d: %s speed IN/%s OUT/%s\n", 369 obex->port_num, 370 gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", 371 obex->port.in->name, obex->port.out->name); 372 373 return 0; 374 375fail: 376 ERROR(cdev, "%s/%p: can't bind, err %d\n", f->name, f, status); 377 378 return status; 379} 380 381static inline struct f_serial_opts *to_f_serial_opts(struct config_item *item) 382{ 383 return container_of(to_config_group(item), struct f_serial_opts, 384 func_inst.group); 385} 386 387static void obex_attr_release(struct config_item *item) 388{ 389 struct f_serial_opts *opts = to_f_serial_opts(item); 390 391 usb_put_function_instance(&opts->func_inst); 392} 393 394static struct configfs_item_operations obex_item_ops = { 395 .release = obex_attr_release, 396}; 397 398static ssize_t f_obex_port_num_show(struct config_item *item, char *page) 399{ 400 return sprintf(page, "%u\n", to_f_serial_opts(item)->port_num); 401} 402 403CONFIGFS_ATTR_RO(f_obex_, port_num); 404 405static struct configfs_attribute *acm_attrs[] = { 406 &f_obex_attr_port_num, 407 NULL, 408}; 409 410static const struct config_item_type obex_func_type = { 411 .ct_item_ops = &obex_item_ops, 412 .ct_attrs = acm_attrs, 413 .ct_owner = THIS_MODULE, 414}; 415 416static void obex_free_inst(struct usb_function_instance *f) 417{ 418 struct f_serial_opts *opts; 419 420 opts = container_of(f, struct f_serial_opts, func_inst); 421 gserial_free_line(opts->port_num); 422 kfree(opts); 423} 424 425static struct usb_function_instance *obex_alloc_inst(void) 426{ 427 struct f_serial_opts *opts; 428 int ret; 429 430 opts = kzalloc(sizeof(*opts), GFP_KERNEL); 431 if (!opts) 432 return ERR_PTR(-ENOMEM); 433 434 opts->func_inst.free_func_inst = obex_free_inst; 435 ret = gserial_alloc_line_no_console(&opts->port_num); 436 if (ret) { 437 kfree(opts); 438 return ERR_PTR(ret); 439 } 440 config_group_init_type_name(&opts->func_inst.group, "", 441 &obex_func_type); 442 443 return &opts->func_inst; 444} 445 446static void obex_free(struct usb_function *f) 447{ 448 struct f_obex *obex; 449 450 obex = func_to_obex(f); 451 kfree(obex); 452} 453 454static void obex_unbind(struct usb_configuration *c, struct usb_function *f) 455{ 456 usb_free_all_descriptors(f); 457} 458 459static struct usb_function *obex_alloc(struct usb_function_instance *fi) 460{ 461 struct f_obex *obex; 462 struct f_serial_opts *opts; 463 464 /* allocate and initialize one new instance */ 465 obex = kzalloc(sizeof(*obex), GFP_KERNEL); 466 if (!obex) 467 return ERR_PTR(-ENOMEM); 468 469 opts = container_of(fi, struct f_serial_opts, func_inst); 470 471 obex->port_num = opts->port_num; 472 473 obex->port.connect = obex_connect; 474 obex->port.disconnect = obex_disconnect; 475 476 obex->port.func.name = "obex"; 477 /* descriptors are per-instance copies */ 478 obex->port.func.bind = obex_bind; 479 obex->port.func.unbind = obex_unbind; 480 obex->port.func.set_alt = obex_set_alt; 481 obex->port.func.get_alt = obex_get_alt; 482 obex->port.func.disable = obex_disable; 483 obex->port.func.free_func = obex_free; 484 obex->port.func.bind_deactivated = true; 485 486 return &obex->port.func; 487} 488 489DECLARE_USB_FUNCTION_INIT(obex, obex_alloc_inst, obex_alloc); 490MODULE_AUTHOR("Felipe Balbi"); 491MODULE_LICENSE("GPL");