1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * storage_common.c -- Common definitions for mass storage functionality 4 * 5 * Copyright (C) 2003-2008 Alan Stern 6 * Copyeight (C) 2009 Samsung Electronics 7 * Author: Michal Nazarewicz (mina86@mina86.com) 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 */ 14 15 /* 16 * This file requires the following identifiers used in USB strings to 17 * be defined (each of type pointer to char): 18 * - fsg_string_interface -- name of the interface 19 */ 20 21 /* 22 * When USB_GADGET_DEBUG_FILES is defined the module param num_buffers 23 * sets the number of pipeline buffers (length of the fsg_buffhd array). 24 * The valid range of num_buffers is: num >= 2 && num <= 4. 25 */ 26 27 #include <linux/module.h> 28 #include <linux/blkdev.h> 29 #include <linux/file.h> 30 #include <linux/fs.h> 31 #include <linux/usb/composite.h> 32 33 #include "storage_common.h" 34 35 /* There is only one interface. */ 36 37 struct usb_interface_descriptor fsg_intf_desc = { 38 .bLength = sizeof fsg_intf_desc, 39 .bDescriptorType = USB_DT_INTERFACE, 40 41 .bNumEndpoints = 2, /* Adjusted during fsg_bind() */ 42 .bInterfaceClass = USB_CLASS_MASS_STORAGE, 43 .bInterfaceSubClass = USB_SC_SCSI, /* Adjusted during fsg_bind() */ 44 .bInterfaceProtocol = USB_PR_BULK, /* Adjusted during fsg_bind() */ 45 .iInterface = FSG_STRING_INTERFACE, 46 }; 47 EXPORT_SYMBOL_GPL(fsg_intf_desc); 48 49 /* 50 * Three full-speed endpoint descriptors: bulk-in, bulk-out, and 51 * interrupt-in. 52 */ 53 54 struct usb_endpoint_descriptor fsg_fs_bulk_in_desc = { 55 .bLength = USB_DT_ENDPOINT_SIZE, 56 .bDescriptorType = USB_DT_ENDPOINT, 57 58 .bEndpointAddress = USB_DIR_IN, 59 .bmAttributes = USB_ENDPOINT_XFER_BULK, 60 /* wMaxPacketSize set by autoconfiguration */ 61 }; 62 EXPORT_SYMBOL_GPL(fsg_fs_bulk_in_desc); 63 64 struct usb_endpoint_descriptor fsg_fs_bulk_out_desc = { 65 .bLength = USB_DT_ENDPOINT_SIZE, 66 .bDescriptorType = USB_DT_ENDPOINT, 67 68 .bEndpointAddress = USB_DIR_OUT, 69 .bmAttributes = USB_ENDPOINT_XFER_BULK, 70 /* wMaxPacketSize set by autoconfiguration */ 71 }; 72 EXPORT_SYMBOL_GPL(fsg_fs_bulk_out_desc); 73 74 struct usb_descriptor_header *fsg_fs_function[] = { 75 (struct usb_descriptor_header *) &fsg_intf_desc, 76 (struct usb_descriptor_header *) &fsg_fs_bulk_in_desc, 77 (struct usb_descriptor_header *) &fsg_fs_bulk_out_desc, 78 NULL, 79 }; 80 EXPORT_SYMBOL_GPL(fsg_fs_function); 81 82 83 /* 84 * USB 2.0 devices need to expose both high speed and full speed 85 * descriptors, unless they only run at full speed. 86 * 87 * That means alternate endpoint descriptors (bigger packets). 88 */ 89 struct usb_endpoint_descriptor fsg_hs_bulk_in_desc = { 90 .bLength = USB_DT_ENDPOINT_SIZE, 91 .bDescriptorType = USB_DT_ENDPOINT, 92 93 /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ 94 .bmAttributes = USB_ENDPOINT_XFER_BULK, 95 .wMaxPacketSize = cpu_to_le16(512), 96 }; 97 EXPORT_SYMBOL_GPL(fsg_hs_bulk_in_desc); 98 99 struct usb_endpoint_descriptor fsg_hs_bulk_out_desc = { 100 .bLength = USB_DT_ENDPOINT_SIZE, 101 .bDescriptorType = USB_DT_ENDPOINT, 102 103 /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ 104 .bmAttributes = USB_ENDPOINT_XFER_BULK, 105 .wMaxPacketSize = cpu_to_le16(512), 106 .bInterval = 1, /* NAK every 1 uframe */ 107 }; 108 EXPORT_SYMBOL_GPL(fsg_hs_bulk_out_desc); 109 110 111 struct usb_descriptor_header *fsg_hs_function[] = { 112 (struct usb_descriptor_header *) &fsg_intf_desc, 113 (struct usb_descriptor_header *) &fsg_hs_bulk_in_desc, 114 (struct usb_descriptor_header *) &fsg_hs_bulk_out_desc, 115 NULL, 116 }; 117 EXPORT_SYMBOL_GPL(fsg_hs_function); 118 119 struct usb_endpoint_descriptor fsg_ss_bulk_in_desc = { 120 .bLength = USB_DT_ENDPOINT_SIZE, 121 .bDescriptorType = USB_DT_ENDPOINT, 122 123 /* bEndpointAddress copied from fs_bulk_in_desc during fsg_bind() */ 124 .bmAttributes = USB_ENDPOINT_XFER_BULK, 125 .wMaxPacketSize = cpu_to_le16(1024), 126 }; 127 EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_desc); 128 129 struct usb_ss_ep_comp_descriptor fsg_ss_bulk_in_comp_desc = { 130 .bLength = sizeof(fsg_ss_bulk_in_comp_desc), 131 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 132 133 /*.bMaxBurst = DYNAMIC, */ 134 }; 135 EXPORT_SYMBOL_GPL(fsg_ss_bulk_in_comp_desc); 136 137 struct usb_endpoint_descriptor fsg_ss_bulk_out_desc = { 138 .bLength = USB_DT_ENDPOINT_SIZE, 139 .bDescriptorType = USB_DT_ENDPOINT, 140 141 /* bEndpointAddress copied from fs_bulk_out_desc during fsg_bind() */ 142 .bmAttributes = USB_ENDPOINT_XFER_BULK, 143 .wMaxPacketSize = cpu_to_le16(1024), 144 }; 145 EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_desc); 146 147 struct usb_ss_ep_comp_descriptor fsg_ss_bulk_out_comp_desc = { 148 .bLength = sizeof(fsg_ss_bulk_in_comp_desc), 149 .bDescriptorType = USB_DT_SS_ENDPOINT_COMP, 150 151 /*.bMaxBurst = DYNAMIC, */ 152 }; 153 EXPORT_SYMBOL_GPL(fsg_ss_bulk_out_comp_desc); 154 155 struct usb_descriptor_header *fsg_ss_function[] = { 156 (struct usb_descriptor_header *) &fsg_intf_desc, 157 (struct usb_descriptor_header *) &fsg_ss_bulk_in_desc, 158 (struct usb_descriptor_header *) &fsg_ss_bulk_in_comp_desc, 159 (struct usb_descriptor_header *) &fsg_ss_bulk_out_desc, 160 (struct usb_descriptor_header *) &fsg_ss_bulk_out_comp_desc, 161 NULL, 162 }; 163 EXPORT_SYMBOL_GPL(fsg_ss_function); 164 165 166 /*-------------------------------------------------------------------------*/ 167 168 /* 169 * If the next two routines are called while the gadget is registered, 170 * the caller must own fsg->filesem for writing. 171 */ 172 173 void fsg_lun_close(struct fsg_lun *curlun) 174 { 175 if (curlun->filp) { 176 LDBG(curlun, "close backing file\n"); 177 fput(curlun->filp); 178 curlun->filp = NULL; 179 } 180 } 181 EXPORT_SYMBOL_GPL(fsg_lun_close); 182 183 int fsg_lun_open(struct fsg_lun *curlun, const char *filename) 184 { 185 int ro; 186 struct file *filp = NULL; 187 int rc = -EINVAL; 188 struct inode *inode = NULL; 189 loff_t size; 190 loff_t num_sectors; 191 loff_t min_sectors; 192 unsigned int blkbits; 193 unsigned int blksize; 194 195 /* R/W if we can, R/O if we must */ 196 ro = curlun->initially_ro; 197 if (!ro) { 198 filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); 199 if (PTR_ERR(filp) == -EROFS || PTR_ERR(filp) == -EACCES) 200 ro = 1; 201 } 202 if (ro) 203 filp = filp_open(filename, O_RDONLY | O_LARGEFILE, 0); 204 if (IS_ERR(filp)) { 205 LINFO(curlun, "unable to open backing file: %s\n", filename); 206 return PTR_ERR(filp); 207 } 208 209 if (!(filp->f_mode & FMODE_WRITE)) 210 ro = 1; 211 212 inode = file_inode(filp); 213 if ((!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode))) { 214 LINFO(curlun, "invalid file type: %s\n", filename); 215 goto out; 216 } 217 218 /* 219 * If we can't read the file, it's no good. 220 * If we can't write the file, use it read-only. 221 */ 222 if (!(filp->f_mode & FMODE_CAN_READ)) { 223 LINFO(curlun, "file not readable: %s\n", filename); 224 goto out; 225 } 226 if (!(filp->f_mode & FMODE_CAN_WRITE)) 227 ro = 1; 228 229 size = i_size_read(inode->i_mapping->host); 230 if (size < 0) { 231 LINFO(curlun, "unable to find file size: %s\n", filename); 232 rc = (int) size; 233 goto out; 234 } 235 236 if (curlun->cdrom) { 237 blksize = 2048; 238 blkbits = 11; 239 } else if (inode->i_bdev) { 240 blksize = bdev_logical_block_size(inode->i_bdev); 241 blkbits = blksize_bits(blksize); 242 } else { 243 blksize = 512; 244 blkbits = 9; 245 } 246 247 num_sectors = size >> blkbits; /* File size in logic-block-size blocks */ 248 min_sectors = 1; 249 if (curlun->cdrom) { 250 min_sectors = 300; /* Smallest track is 300 frames */ 251 if (num_sectors >= 256*60*75) { 252 num_sectors = 256*60*75 - 1; 253 LINFO(curlun, "file too big: %s\n", filename); 254 LINFO(curlun, "using only first %d blocks\n", 255 (int) num_sectors); 256 } 257 } 258 if (num_sectors < min_sectors) { 259 LINFO(curlun, "file too small: %s\n", filename); 260 rc = -ETOOSMALL; 261 goto out; 262 } 263 264 if (fsg_lun_is_open(curlun)) 265 fsg_lun_close(curlun); 266 267 curlun->blksize = blksize; 268 curlun->blkbits = blkbits; 269 curlun->ro = ro; 270 curlun->filp = filp; 271 curlun->file_length = size; 272 curlun->num_sectors = num_sectors; 273 LDBG(curlun, "open backing file: %s\n", filename); 274 return 0; 275 276 out: 277 fput(filp); 278 return rc; 279 } 280 EXPORT_SYMBOL_GPL(fsg_lun_open); 281 282 283 /*-------------------------------------------------------------------------*/ 284 285 /* 286 * Sync the file data, don't bother with the metadata. 287 * This code was copied from fs/buffer.c:sys_fdatasync(). 288 */ 289 int fsg_lun_fsync_sub(struct fsg_lun *curlun) 290 { 291 struct file *filp = curlun->filp; 292 293 if (curlun->ro || !filp) 294 return 0; 295 return vfs_fsync(filp, 1); 296 } 297 EXPORT_SYMBOL_GPL(fsg_lun_fsync_sub); 298 299 void store_cdrom_address(u8 *dest, int msf, u32 addr) 300 { 301 if (msf) { 302 /* Convert to Minutes-Seconds-Frames */ 303 addr >>= 2; /* Convert to 2048-byte frames */ 304 addr += 2*75; /* Lead-in occupies 2 seconds */ 305 dest[3] = addr % 75; /* Frames */ 306 addr /= 75; 307 dest[2] = addr % 60; /* Seconds */ 308 addr /= 60; 309 dest[1] = addr; /* Minutes */ 310 dest[0] = 0; /* Reserved */ 311 } else { 312 /* Absolute sector */ 313 put_unaligned_be32(addr, dest); 314 } 315 } 316 EXPORT_SYMBOL_GPL(store_cdrom_address); 317 318 /*-------------------------------------------------------------------------*/ 319 320 321 ssize_t fsg_show_ro(struct fsg_lun *curlun, char *buf) 322 { 323 return sprintf(buf, "%d\n", fsg_lun_is_open(curlun) 324 ? curlun->ro 325 : curlun->initially_ro); 326 } 327 EXPORT_SYMBOL_GPL(fsg_show_ro); 328 329 ssize_t fsg_show_nofua(struct fsg_lun *curlun, char *buf) 330 { 331 return sprintf(buf, "%u\n", curlun->nofua); 332 } 333 EXPORT_SYMBOL_GPL(fsg_show_nofua); 334 335 ssize_t fsg_show_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, 336 char *buf) 337 { 338 char *p; 339 ssize_t rc; 340 341 down_read(filesem); 342 if (fsg_lun_is_open(curlun)) { /* Get the complete pathname */ 343 p = file_path(curlun->filp, buf, PAGE_SIZE - 1); 344 if (IS_ERR(p)) 345 rc = PTR_ERR(p); 346 else { 347 rc = strlen(p); 348 memmove(buf, p, rc); 349 buf[rc] = '\n'; /* Add a newline */ 350 buf[++rc] = 0; 351 } 352 } else { /* No file, return 0 bytes */ 353 *buf = 0; 354 rc = 0; 355 } 356 up_read(filesem); 357 return rc; 358 } 359 EXPORT_SYMBOL_GPL(fsg_show_file); 360 361 ssize_t fsg_show_cdrom(struct fsg_lun *curlun, char *buf) 362 { 363 return sprintf(buf, "%u\n", curlun->cdrom); 364 } 365 EXPORT_SYMBOL_GPL(fsg_show_cdrom); 366 367 ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf) 368 { 369 return sprintf(buf, "%u\n", curlun->removable); 370 } 371 EXPORT_SYMBOL_GPL(fsg_show_removable); 372 373 ssize_t fsg_show_inquiry_string(struct fsg_lun *curlun, char *buf) 374 { 375 return sprintf(buf, "%s\n", curlun->inquiry_string); 376 } 377 EXPORT_SYMBOL_GPL(fsg_show_inquiry_string); 378 379 /* 380 * The caller must hold fsg->filesem for reading when calling this function. 381 */ 382 static ssize_t _fsg_store_ro(struct fsg_lun *curlun, bool ro) 383 { 384 if (fsg_lun_is_open(curlun)) { 385 LDBG(curlun, "read-only status change prevented\n"); 386 return -EBUSY; 387 } 388 389 curlun->ro = ro; 390 curlun->initially_ro = ro; 391 LDBG(curlun, "read-only status set to %d\n", curlun->ro); 392 393 return 0; 394 } 395 396 ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem, 397 const char *buf, size_t count) 398 { 399 ssize_t rc; 400 bool ro; 401 402 rc = strtobool(buf, &ro); 403 if (rc) 404 return rc; 405 406 /* 407 * Allow the write-enable status to change only while the 408 * backing file is closed. 409 */ 410 down_read(filesem); 411 rc = _fsg_store_ro(curlun, ro); 412 if (!rc) 413 rc = count; 414 up_read(filesem); 415 416 return rc; 417 } 418 EXPORT_SYMBOL_GPL(fsg_store_ro); 419 420 ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count) 421 { 422 bool nofua; 423 int ret; 424 425 ret = strtobool(buf, &nofua); 426 if (ret) 427 return ret; 428 429 /* Sync data when switching from async mode to sync */ 430 if (!nofua && curlun->nofua) 431 fsg_lun_fsync_sub(curlun); 432 433 curlun->nofua = nofua; 434 435 return count; 436 } 437 EXPORT_SYMBOL_GPL(fsg_store_nofua); 438 439 ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem, 440 const char *buf, size_t count) 441 { 442 int rc = 0; 443 444 if (curlun->prevent_medium_removal && fsg_lun_is_open(curlun)) { 445 LDBG(curlun, "eject attempt prevented\n"); 446 return -EBUSY; /* "Door is locked" */ 447 } 448 449 /* Remove a trailing newline */ 450 if (count > 0 && buf[count-1] == '\n') 451 ((char *) buf)[count-1] = 0; /* Ugh! */ 452 453 /* Load new medium */ 454 down_write(filesem); 455 if (count > 0 && buf[0]) { 456 /* fsg_lun_open() will close existing file if any. */ 457 rc = fsg_lun_open(curlun, buf); 458 if (rc == 0) 459 curlun->unit_attention_data = 460 SS_NOT_READY_TO_READY_TRANSITION; 461 } else if (fsg_lun_is_open(curlun)) { 462 fsg_lun_close(curlun); 463 curlun->unit_attention_data = SS_MEDIUM_NOT_PRESENT; 464 } 465 up_write(filesem); 466 return (rc < 0 ? rc : count); 467 } 468 EXPORT_SYMBOL_GPL(fsg_store_file); 469 470 ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem, 471 const char *buf, size_t count) 472 { 473 bool cdrom; 474 int ret; 475 476 ret = strtobool(buf, &cdrom); 477 if (ret) 478 return ret; 479 480 down_read(filesem); 481 ret = cdrom ? _fsg_store_ro(curlun, true) : 0; 482 483 if (!ret) { 484 curlun->cdrom = cdrom; 485 ret = count; 486 } 487 up_read(filesem); 488 489 return ret; 490 } 491 EXPORT_SYMBOL_GPL(fsg_store_cdrom); 492 493 ssize_t fsg_store_removable(struct fsg_lun *curlun, const char *buf, 494 size_t count) 495 { 496 bool removable; 497 int ret; 498 499 ret = strtobool(buf, &removable); 500 if (ret) 501 return ret; 502 503 curlun->removable = removable; 504 505 return count; 506 } 507 EXPORT_SYMBOL_GPL(fsg_store_removable); 508 509 ssize_t fsg_store_inquiry_string(struct fsg_lun *curlun, const char *buf, 510 size_t count) 511 { 512 const size_t len = min(count, sizeof(curlun->inquiry_string)); 513 514 if (len == 0 || buf[0] == '\n') { 515 curlun->inquiry_string[0] = 0; 516 } else { 517 snprintf(curlun->inquiry_string, 518 sizeof(curlun->inquiry_string), "%-28s", buf); 519 if (curlun->inquiry_string[len-1] == '\n') 520 curlun->inquiry_string[len-1] = ' '; 521 } 522 523 return count; 524 } 525 EXPORT_SYMBOL_GPL(fsg_store_inquiry_string); 526 527 MODULE_LICENSE("GPL"); 528