12 #include <arpa/inet.h>
17 #include <sys/mount.h>
23 /* Adjust bdflush parameters.
24 * Do this here, because Tomato doesn't have the sysctl command.
25 * With these values, a disk block should be written to disk within 2 seconds.
28 void tune_bdflush(void)
30 f_write_string("/proc/sys/vm/dirty_expire_centisecs", "200", 0, 0);
31 f_write_string("/proc/sys/vm/dirty_writeback_centisecs", "200", 0, 0);
34 #include <sys/kdaemon.h>
35 #define SET_PARM(n) (n * 2 | 1)
36 void tune_bdflush(void)
38 bdflush(SET_PARM(5), 100);
39 bdflush(SET_PARM(6), 100);
40 bdflush(SET_PARM(8), 0);
44 #define USBCORE_MOD "usbcore"
45 #define USB20_MOD "ehci-hcd"
46 #define USBSTORAGE_MOD "usb-storage"
47 #define SCSI_MOD "scsi_mod"
48 #define SD_MOD "sd_mod"
50 #define USBOHCI_MOD "ohci-hcd"
51 #define USBUHCI_MOD "uhci-hcd"
52 #define USBPRINTER_MOD "usblp"
53 #define SCSI_WAIT_MOD "scsi_wait_scan"
56 #define USBOHCI_MOD "usb-ohci"
57 #define USBUHCI_MOD "usb-uhci"
58 #define USBPRINTER_MOD "printer"
59 #define USBFS "usbdevfs"
62 static int p9100d_sig(int sig
)
64 const char p910pid
[] = "/var/run/p9100d.pid";
68 if (f_read_string(p910pid
, s
, sizeof(s
)) > 0) {
69 if ((pid
= atoi(s
)) > 1) {
70 if (kill(pid
, sig
) == 0) {
87 if (nvram_match("boardtype", "0x052b")) { // Netgear WNR3500L v2 - initialize USB port
88 xstart("gpio", "enable", "20");
90 if (nvram_match("boardtype", "0x0617") && nvram_match("boardrev", "0x1102")) { //DIR-865L enable USB
91 xstart("gpio", "enable", "7");
94 _dprintf("%s\n", __FUNCTION__
);
97 if (nvram_get_int("usb_enable")) {
98 modprobe(USBCORE_MOD
);
100 /* mount usb device filesystem */
101 mount(USBFS
, "/proc/bus/usb", USBFS
, MS_MGC_VAL
, NULL
);
104 i
= do_led(LED_USB
, LED_PROBE
);
106 modprobe("ledtrig-usbdev");
107 modprobe("leds-usb");
108 sprintf(param
, "%d", i
);
109 f_write_string("/proc/leds-usb/gpio_pin", param
, 0, 0);
114 /* From Asus QTD cache params */
122 /* Save QTD cache params in nvram */
123 sprintf(arg1
, "log2_irq_thresh=%d", nvram_get_int("ehciirqt"));
124 sprintf(arg2
, "qtdc_pid=%d", nvram_get_int("qtdc_pid"));
125 sprintf(arg3
, "qtdc_vid=%d", nvram_get_int("qtdc_vid"));
126 sprintf(arg4
, "qtdc0_ep=%d", nvram_get_int("qtdc0_ep"));
127 sprintf(arg5
, "qtdc0_sz=%d", nvram_get_int("qtdc0_sz"));
128 sprintf(arg6
, "qtdc1_ep=%d", nvram_get_int("qtdc1_ep"));
129 sprintf(arg7
, "qtdc1_sz=%d", nvram_get_int("qtdc1_sz"));
131 modprobe("ehci-hcd", arg1
, arg2
, arg3
, arg4
, arg5
, arg6
, arg7
);
133 sprintf(instance
, "instance_base=1");
134 modprobe("wl_high", instance
);
137 if (nvram_get_int("usb_storage")) {
138 /* insert scsi and storage modules before usb drivers */
141 modprobe(SCSI_WAIT_MOD
);
144 modprobe(USBSTORAGE_MOD
);
146 if (nvram_get_int("usb_fs_ext3")) {
148 modprobe("mbcache"); // used by ext2/ext3
150 /* insert ext3 first so that lazy mount tries ext3 before ext2 */
156 if (nvram_get_int("usb_fs_fat")) {
162 if (nvram_get_int("usb_fs_ntfs")) {
168 if (nvram_get_int("usb_fs_hfs")) {
174 #if defined(LINUX26) && defined(TCONFIG_MICROSD)
175 if (nvram_get_int("usb_mmc") == 1) {
176 /* insert SD/MMC modules if present */
177 modprobe("mmc_core");
178 modprobe("mmc_block");
184 /* if enabled, force USB2 before USB1.1 */
185 if (nvram_get_int("usb_usb2") == 1) {
186 i
= nvram_get_int("usb_irq_thresh");
187 if ((i
< 0) || (i
> 6))
189 sprintf(param
, "log2_irq_thresh=%d", i
);
190 modprobe(USB20_MOD
, param
);
193 if (nvram_get_int("usb_uhci") == 1) {
194 modprobe(USBUHCI_MOD
);
197 if (nvram_get_int("usb_ohci") == 1) {
198 modprobe(USBOHCI_MOD
);
201 if (nvram_get_int("usb_printer")) {
202 symlink("/dev/usb", "/dev/printers");
203 modprobe(USBPRINTER_MOD
);
205 /* start printer server only if not already running */
206 if (p9100d_sig(0) != 0) {
208 nvram_get_int("usb_printer_bidirect") ? "-b" : "", //bidirectional
209 "-f", "/dev/usb/lp0", // device
215 if (nvram_get_int("idle_enable") == 1) {
225 //enable eth2 after detect new iface by wl_high module
227 xstart("service", "wireless", "restart");
231 // If we want restore backup of webmon from USB device,
232 // we have to wait for mount USB devices by hotplug
233 // and then reboot firewall service (webmon iptables rules) one more time.
234 if( nvram_match( "log_wm", "1" ) && nvram_match( "webmon_bkp", "1" ) )
235 xstart( "service", "firewall", "restart" );
242 int disabled
= !nvram_get_int("usb_enable");
244 // only find and kill the printer server we started (port 0)
246 modprobe_r(USBPRINTER_MOD
);
248 // only stop storage services if disabled
249 if (disabled
|| !nvram_get_int("usb_storage")) {
250 // Unmount all partitions
251 remove_storage_main(0);
253 // Stop storage services
258 modprobe_r("mbcache");
268 modprobe_r("hfsplus");
272 #ifdef TCONFIG_SAMBASRV
273 modprobe_r("nls_cp437");
274 modprobe_r("nls_cp850");
275 modprobe_r("nls_cp852");
276 modprobe_r("nls_cp866");
278 modprobe_r("nls_cp932");
279 modprobe_r("nls_cp936");
280 modprobe_r("nls_cp949");
281 modprobe_r("nls_cp950");
284 modprobe_r(USBSTORAGE_MOD
);
287 modprobe_r(SCSI_WAIT_MOD
);
289 modprobe_r(SCSI_MOD
);
292 #if defined(LINUX26) && defined(TCONFIG_MICROSD)
293 if (disabled
|| !nvram_get_int("usb_storage") || nvram_get_int("usb_mmc") != 1) {
295 modprobe_r("mmc_block");
296 modprobe_r("mmc_core");
300 if (disabled
|| nvram_get_int("usb_ohci") != 1) modprobe_r(USBOHCI_MOD
);
301 if (disabled
|| nvram_get_int("usb_uhci") != 1) modprobe_r(USBUHCI_MOD
);
302 if (disabled
|| nvram_get_int("usb_usb2") != 1) modprobe_r(USB20_MOD
);
305 modprobe_r("leds-usb");
306 modprobe_r("ledtrig-usbdev");
307 led(LED_USB
, LED_OFF
);
310 // only unload core modules if usb is disabled
312 umount("/proc/bus/usb"); // unmount usb device filesystem
313 modprobe_r(USBOHCI_MOD
);
314 modprobe_r(USBUHCI_MOD
);
315 modprobe_r(USB20_MOD
);
316 modprobe_r(USBCORE_MOD
);
320 if (nvram_get_int("idle_enable") == 0) {
321 killall("sd-idle", SIGTERM
);
328 if (nvram_match("3g_usb", "0") ) {
329 if (nvram_match("3g_module", "sierra") ) {
330 modprobe_r("sierra");
331 modprobe_r("usbserial");
334 if (nvram_match("3g_module", "option") ) {
335 modprobe_r("option");
336 modprobe_r("usbserial");
340 // when modem use usbserial module and we will try remove module, module will crash
341 // the only solution at the moment is reboot router
343 if (nvram_match("3g_module", "usbserial") ) {
344 modprobe_r("usbserial");
348 if (nvram_match("boardtype", "0x052b")) { // Netgear WNR3500L v2 - disable USB port
349 xstart("gpio", "disable", "20");
352 if (nvram_match("boardtype", "0x0617") && nvram_match("boardrev", "0x1102")) { //DIR-865L disable USB
353 xstart("gpio", "disable", "7");
362 #define MOUNT_VAL_FAIL 0
363 #define MOUNT_VAL_RONLY 1
364 #define MOUNT_VAL_RW 2
365 #define MOUNT_VAL_EXIST 3
367 int mount_r(char *mnt_dev
, char *mnt_dir
, char *type
)
375 if ((mnt
= findmntents(mnt_dev
, 0, NULL
, 0))) {
376 syslog(LOG_INFO
, "USB partition at %s already mounted on %s",
377 mnt_dev
, mnt
->mnt_dir
);
378 return MOUNT_VAL_EXIST
;
384 unsigned long flags
= MS_NOATIME
| MS_NODEV
;
386 if (strcmp(type
, "swap") == 0 || strcmp(type
, "mbr") == 0) {
387 /* not a mountable partition */
390 else if (strcmp(type
, "ext2") == 0 || strcmp(type
, "ext3") == 0) {
391 if (nvram_invmatch("usb_ext_opt", ""))
392 sprintf(options
, nvram_safe_get("usb_ext_opt"));
394 else if (strcmp(type
, "vfat") == 0) {
395 if (nvram_invmatch("smbd_cset", ""))
396 sprintf(options
, "iocharset=%s%s",
397 isdigit(nvram_get("smbd_cset")[0]) ? "cp" : "",
398 nvram_get("smbd_cset"));
399 if (nvram_invmatch("smbd_cpage", "")) {
400 char *cp
= nvram_safe_get("smbd_cpage");
401 sprintf(options
+ strlen(options
), ",codepage=%s" + (options
[0] ? 0 : 1), cp
);
402 sprintf(flagfn
, "nls_cp%s", cp
);
404 cp
= nvram_get("smbd_nlsmod");
405 if ((cp
) && (*cp
!= 0) && (strcmp(cp
, flagfn
) != 0))
409 nvram_set("smbd_nlsmod", flagfn
);
411 sprintf(options
+ strlen(options
), ",shortname=winnt" + (options
[0] ? 0 : 1));
413 sprintf(options
+ strlen(options
), ",flush" + (options
[0] ? 0 : 1));
415 if (nvram_invmatch("usb_fat_opt", ""))
416 sprintf(options
+ strlen(options
), "%s%s", options
[0] ? "," : "", nvram_safe_get("usb_fat_opt"));
418 else if (strncmp(type
, "ntfs", 4) == 0) {
419 if (nvram_invmatch("smbd_cset", ""))
420 sprintf(options
, "iocharset=%s%s",
421 isdigit(nvram_get("smbd_cset")[0]) ? "cp" : "",
422 nvram_get("smbd_cset"));
423 if (nvram_invmatch("usb_ntfs_opt", ""))
424 sprintf(options
+ strlen(options
), "%s%s", options
[0] ? "," : "", nvram_safe_get("usb_ntfs_opt"));
428 if ((dir_made
= mkdir_if_none(mnt_dir
))) {
429 /* Create the flag file for remove the directory on dismount. */
430 sprintf(flagfn
, "%s/.autocreated-dir", mnt_dir
);
431 f_write(flagfn
, NULL
, 0, 0, 0);
434 ret
= mount(mnt_dev
, mnt_dir
, type
, flags
, options
[0] ? options
: "");
437 /* try ntfs-3g in case it's installed */
438 if (ret
!= 0 && strncmp(type
, "ntfs", 4) == 0) {
439 sprintf(options
+ strlen(options
), ",noatime,nodev" + (options
[0] ? 0 : 1));
440 if (nvram_get_int("usb_fs_ntfs"))
442 ret
= eval("mount", "-t", "ufsd", "-o", options
, "-o", "force", mnt_dev
, mnt_dir
);
444 ret
= eval("ntfs-3g", "-o", options
, mnt_dev
, mnt_dir
);
450 if (ret
!= 0 && strncmp(type
, "hfs", "") == 0) {
451 ret
= eval("mount", "-o", "noatime,nodev", mnt_dev
, mnt_dir
);
454 if (ret
!= 0 && strncmp(type
, "hfsplus", "") == 0) {
455 ret
= eval("mount", "-o", "noatime,nodev", mnt_dev
, mnt_dir
);
459 if (ret
!= 0) /* give it another try - guess fs */
460 ret
= eval("mount", "-o", "noatime,nodev", mnt_dev
, mnt_dir
);
463 syslog(LOG_INFO
, "USB %s%s fs at %s mounted on %s",
464 type
, (flags
& MS_RDONLY
) ? " (ro)" : "", mnt_dev
, mnt_dir
);
465 return (flags
& MS_RDONLY
) ? MOUNT_VAL_RONLY
: MOUNT_VAL_RW
;
474 return MOUNT_VAL_FAIL
;
478 struct mntent
*mount_fstab(char *dev_name
, char *type
, char *label
, char *uuid
)
480 struct mntent
*mnt
= NULL
;
482 if (eval("mount", "-a") == 0)
483 mnt
= findmntents(dev_name
, 0, NULL
, 0);
485 char spec
[PATH_MAX
+1];
487 if (label
&& *label
) {
488 sprintf(spec
, "LABEL=%s", label
);
489 if (eval("mount", spec
) == 0)
490 mnt
= findmntents(dev_name
, 0, NULL
, 0);
493 if (!mnt
&& uuid
&& *uuid
) {
494 sprintf(spec
, "UUID=%s", uuid
);
495 if (eval("mount", spec
) == 0)
496 mnt
= findmntents(dev_name
, 0, NULL
, 0);
500 if (eval("mount", dev_name
) == 0)
501 mnt
= findmntents(dev_name
, 0, NULL
, 0);
505 /* Still did not find what we are looking for, try absolute path */
506 if (realpath(dev_name
, spec
)) {
507 if (eval("mount", spec
) == 0)
508 mnt
= findmntents(dev_name
, 0, NULL
, 0);
514 syslog(LOG_INFO
, "USB %s fs at %s mounted on %s", type
, dev_name
, mnt
->mnt_dir
);
519 /* Check if the UFD is still connected because the links created in /dev/discs
520 * are not removed when the UFD is unplugged.
521 * The file to read is: /proc/scsi/usb-storage-#/#, where # is the host no.
522 * We are looking for "Attached: Yes".
524 static int usb_ufd_connected(int host_no
)
532 sprintf(proc_file
, "%s/%s-%d/%d", PROC_SCSI_ROOT
, USB_STORAGE
, host_no
, host_no
);
533 fp
= fopen(proc_file
, "r");
536 /* try the way it's implemented in newer kernels: /proc/scsi/usb-storage/[host] */
537 sprintf(proc_file
, "%s/%s/%d", PROC_SCSI_ROOT
, USB_STORAGE
, host_no
);
538 fp
= fopen(proc_file
, "r");
546 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
547 if (strstr(line
, "Attached: Yes")) {
561 #define MNT_DETACH 0x00000002 /* from linux/fs.h - just detach from the tree */
563 int umount_mountpoint(struct mntent
*mnt
, uint flags
);
564 int uswap_mountpoint(struct mntent
*mnt
, uint flags
);
566 /* Unmount this partition from all its mountpoints. Note that it may
567 * actually be mounted several times, either with different names or
568 * with "-o bind" flag.
569 * If the special flagfile is now revealed, delete it and [attempt to] delete
572 int umount_partition(char *dev_name
, int host_num
, char *dsc_name
, char *pt_name
, uint flags
)
574 sync(); /* This won't matter if the device is unplugged, though. */
576 if (flags
& EFH_HUNKNOWN
) {
577 /* EFH_HUNKNOWN flag is passed if the host was unknown.
578 * Only unmount disconnected drives in this case.
580 if (usb_ufd_connected(host_num
))
584 /* Find all the active swaps that are on this device and stop them. */
585 findmntents(dev_name
, 1, uswap_mountpoint
, flags
);
587 /* Find all the mountpoints that are for this device and unmount them. */
588 findmntents(dev_name
, 0, umount_mountpoint
, flags
);
592 int uswap_mountpoint(struct mntent
*mnt
, uint flags
)
594 swapoff(mnt
->mnt_fsname
);
598 int umount_mountpoint(struct mntent
*mnt
, uint flags
)
603 sprintf(flagfn
, "%s/.autocreated-dir", mnt
->mnt_dir
);
605 /* Run user pre-unmount scripts if any. It might be too late if
606 * the drive has been disconnected, but we'll try it anyway.
608 if (nvram_get_int("usb_automount"))
609 run_nvscript("script_usbumount", mnt
->mnt_dir
, 3);
610 /* Run *.autostop scripts located in the root of the partition being unmounted if any. */
611 run_userfile(mnt
->mnt_dir
, ".autostop", mnt
->mnt_dir
, 5);
612 run_nvscript("script_autostop", mnt
->mnt_dir
, 5);
615 while ((ret
= umount(mnt
->mnt_dir
)) && (count
< 2)) {
617 /* If we could not unmount the drive on the 1st try,
618 * kill all NAS applications so they are not keeping the device busy -
619 * unless it's an unmount request from the Web GUI.
621 if ((count
== 1) && ((flags
& EFH_USER
) == 0))
622 restart_nas_services(1, 0);
627 syslog(LOG_INFO
, "USB partition unmounted from %s", mnt
->mnt_dir
);
629 if (ret
&& ((flags
& EFH_SHUTDN
) != 0)) {
630 /* If system is stopping (not restarting), and we couldn't unmount the
631 * partition, try to remount it as read-only. Ignore the return code -
632 * we can still try to do a lazy unmount.
634 eval("mount", "-o", "remount,ro", mnt
->mnt_dir
);
637 if (ret
&& ((flags
& EFH_USER
) == 0)) {
638 /* Make one more try to do a lazy unmount unless it's an unmount
639 * request from the Web GUI.
640 * MNT_DETACH will expose the underlying mountpoint directory to all
641 * except whatever has cd'ed to the mountpoint (thereby making it busy).
642 * So the unmount can't actually fail. It disappears from the ken of
643 * everyone else immediately, and from the ken of whomever is keeping it
644 * busy when they move away from it. And then it disappears for real.
646 ret
= umount2(mnt
->mnt_dir
, MNT_DETACH
);
647 syslog(LOG_INFO
, "USB partition busy - will unmount ASAP from %s", mnt
->mnt_dir
);
651 if ((unlink(flagfn
) == 0)) {
652 // Only delete the directory if it was auto-created
660 /* Mount this partition on this disc.
661 * If the device is already mounted on any mountpoint, don't mount it again.
662 * If this is a swap partition, try swapon -a.
663 * If this is a regular partition, try mount -a.
665 * Before we mount any partitions:
666 * If the type is swap and /etc/fstab exists, do "swapon -a"
667 * If /etc/fstab exists, try mounting using fstab.
668 * We delay invoking mount because mount will probe all the partitions
669 * to read the labels, and we don't want it to do that early on.
670 * We don't invoke swapon until we actually find a swap partition.
672 * If the mount succeeds, execute the *.autorun scripts in the top
673 * directory of the newly mounted partition.
674 * Returns NZ for success, 0 if we did not mount anything.
676 int mount_partition(char *dev_name
, int host_num
, char *dsc_name
, char *pt_name
, uint flags
)
678 char the_label
[128], mountpoint
[128], uuid
[40];
681 static char *swp_argv
[] = { "swapon", "-a", NULL
};
684 if ((type
= find_label_or_uuid(dev_name
, the_label
, uuid
)) == NULL
)
687 if (f_exists("/etc/fstab")) {
688 if (strcmp(type
, "swap") == 0) {
689 _eval(swp_argv
, NULL
, 0, NULL
);
693 if (mount_r(dev_name
, NULL
, NULL
) == MOUNT_VAL_EXIST
)
696 if ((mnt
= mount_fstab(dev_name
, type
, the_label
, uuid
))) {
697 strcpy(mountpoint
, mnt
->mnt_dir
);
703 if (*the_label
!= 0) {
704 for (p
= the_label
; *p
; p
++) {
705 if (!isalnum(*p
) && !strchr("+-&.@", *p
))
708 sprintf(mountpoint
, "%s/%s", MOUNT_ROOT
, the_label
);
709 if ((ret
= mount_r(dev_name
, mountpoint
, type
)))
713 /* Can't mount to /mnt/LABEL, so try mounting to /mnt/discDN_PN */
714 sprintf(mountpoint
, "%s/%s", MOUNT_ROOT
, pt_name
);
715 ret
= mount_r(dev_name
, mountpoint
, type
);
717 if (ret
== MOUNT_VAL_RONLY
|| ret
== MOUNT_VAL_RW
)
719 /* Run user *.autorun and post-mount scripts if any. */
720 run_userfile(mountpoint
, ".autorun", mountpoint
, 3);
721 if (nvram_get_int("usb_automount"))
722 run_nvscript("script_usbmount", mountpoint
, 3);
724 return (ret
== MOUNT_VAL_RONLY
|| ret
== MOUNT_VAL_RW
);
731 * Finds SCSI Host number. Returns the host number >=0 if found, or (-1) otherwise.
732 * The name and host number of scsi block device in kernel 2.6 (for attached devices) can be found as
733 * /sys($DEVPATH)/host<host_no>/target<*>/<id>/block:[sda|sdb|...]
734 * where $DEVPATH is passed to hotplug events, and looks like
735 * /devices/pci0000:00/0000:00:04.1/usb1/1-1/1-1:1.2
737 * For printers this function finds a minor assigned to a printer
738 * /sys($DEVPATH)/usb:lp[0|1|2|...]
740 int find_dev_host(const char *devpath
)
745 int host
= -1; /* Scsi Host */
747 sprintf(buf
, "/sys%s", devpath
);
748 if ((usb_devpath
= opendir(buf
))) {
749 while ((dp
= readdir(usb_devpath
))) {
751 if (strncmp(dp
->d_name
, "host", 4) == 0) {
752 host
= strtol(dp
->d_name
+ 4, (char **)NULL
, 10);
758 else if (strncmp(dp
->d_name
, "usb:lp", 6) == 0) {
759 host
= strtol(dp
->d_name
+ 6, (char **)NULL
, 10);
768 closedir(usb_devpath
);
775 int dir_is_mountpoint(const char *root
, const char *dir
)
781 snprintf(path
, sizeof(path
), "%s%s%s", root
? : "", root
? "/" : "", dir
);
783 /* Check if this is a directory */
784 sb
.st_mode
= S_IFDIR
; /* failsafe */
787 if (S_ISDIR(sb
.st_mode
)) {
789 /* If this dir & its parent dir are on the same device, it is not a mountpoint */
794 ++sb
.st_dev
; /* failsafe */
797 return (thisdev
!= sb
.st_dev
);
803 /* Mount or unmount all partitions on this controller.
804 * Parameter: action_add:
806 * >0 = mount only if automount config option is enabled.
807 * <0 = mount regardless of config option.
809 void hotplug_usb_storage_device(int host_no
, int action_add
, uint flags
)
811 if (!nvram_get_int("usb_enable"))
813 _dprintf("%s: host %d action: %d\n", __FUNCTION__
, host_no
, action_add
);
816 if (nvram_get_int("usb_storage") && (nvram_get_int("usb_automount") || action_add
< 0)) {
817 /* Do not probe the device here. It's either initiated by user,
818 * or hotplug_usb() already did.
820 if (exec_for_host(host_no
, 0x00, flags
, mount_partition
)) {
821 restart_nas_services(0, 1); // restart all NAS applications
826 if (nvram_get_int("usb_storage") || ((flags
& EFH_USER
) == 0)) {
827 /* When unplugged, unmount the device even if
828 * usb storage is disabled in the GUI.
830 exec_for_host(host_no
, (flags
& EFH_USER
) ? 0x00 : 0x02, flags
, umount_partition
);
831 /* Restart NAS applications (they could be killed by umount_mountpoint),
832 * or just re-read the configuration.
834 restart_nas_services(0, 1);
840 /* This gets called at reboot or upgrade. The system is stopping. */
841 void remove_storage_main(int shutdn
)
844 restart_nas_services(1, 0);
845 /* Unmount all partitions */
846 exec_for_host(-1, 0x02, shutdn
? EFH_SHUTDN
: 0, umount_partition
);
851 * All the complex locking & checking code was removed when the kernel USB-storage
853 * The crash bug was with overlapped I/O to different USB drives, not specifically
854 * with mount processing.
856 * And for USB devices that are slow to come up. The kernel now waits until the
857 * USB drive has settled, and it correctly reads the partition table before calling
860 * The kernel patch was cleaning up data structures on an unplug. It
861 * needs to wait until the disk is unmounted. We have 20 seconds to do
866 static inline void usbled_proc(char *device
, int add
)
871 if (do_led(LED_USB
, LED_PROBE
) != 255) {
872 strncpy(param
, device
, sizeof(param
));
873 if ((p
= strchr(param
, ':')) != NULL
)
876 /* verify if we need to ignore this device (i.e. an internal SD/MMC slot ) */
877 p
= nvram_safe_get("usb_noled");
878 if (strcmp(p
, param
) == 0)
881 f_write_string(add
? "/proc/leds-usb/add" : "/proc/leds-usb/remove", param
, 0, 0);
886 /* Plugging or removing usb device
888 * On an occurrance, multiple hotplug events may be fired off.
889 * For example, if a hub is plugged or unplugged, an event
890 * will be generated for everything downstream of it, plus one for
891 * the hub itself. These are fired off simultaneously, not serially.
892 * This means that many many hotplug processes will be running at
895 * The hotplug event generated by the kernel gives us several pieces
897 * PRODUCT is vendorid/productid/rev#.
898 * DEVICE is /proc/bus/usb/bus#/dev#
899 * ACTION is add or remove
900 * SCSI_HOST is the host (controller) number (this relies on the custom kernel patch)
902 * Note that when we get a hotplug add event, the USB susbsystem may
903 * or may not have yet tried to read the partition table of the
904 * device. For a new controller that has never been seen before,
905 * generally yes. For a re-plug of a controller that has been seen
906 * before, generally no.
908 * On a remove, the partition info has not yet been expunged. The
909 * partitions show up as /dev/discs/disc#/part#, and /proc/partitions.
910 * It appears that doing a "stat" for a non-existant partition will
911 * causes the kernel to re-validate the device and update the
912 * partition table info. However, it won't re-validate if the disc is
913 * mounted--you'll get a "Device busy for revalidation (usage=%d)" in
916 * The $INTERFACE is "class/subclass/protocol"
917 * Some interesting classes:
920 * 3 = HID. 3/1/2 = mouse.
921 * 6 = still image (6/1/1 = Digital camera Camera)
923 * 255 = scanner (255/255/255)
926 * Hub seems to have no INTERFACE (null), and TYPE of "9/0/0"
927 * Flash disk seems to have INTERFACE of "8/6/80", and TYPE of "0/0/0"
929 * When a hub is unplugged, a hotplug event is generated for it and everything
930 * downstream from it. You cannot depend on getting these events in any
931 * particular order, since there will be many hotplug programs all fired off
932 * at almost the same time.
933 * On a remove, don't try to access the downstream devices right away, give the
934 * kernel time to finish cleaning up all the data structures, which will be
935 * in the process of being torn down.
937 * On the initial plugin, the first time the kernel usb-storage subsystem sees
938 * the host (identified by GUID), it automatically reads the partition table.
939 * On subsequent plugins, it does not.
941 * Special values for Web Administration to unmount or remount
942 * all partitions of the host:
943 * INTERFACE=TOMATO/...
945 * SCSI_HOST=<host_no>
946 * If host_no is negative, we unmount all partions of *all* hosts.
948 void hotplug_usb(void)
952 char *interface
= getenv("INTERFACE");
953 char *action
= getenv("ACTION");
954 char *product
= getenv("PRODUCT");
956 char *device
= getenv("DEVICENAME");
957 int is_block
= strcmp(getenv("SUBSYSTEM") ? : "", "block") == 0;
959 char *device
= getenv("DEVICE");
961 char *scsi_host
= getenv("SCSI_HOST");
963 _dprintf("%s hotplug INTERFACE=%s ACTION=%s PRODUCT=%s HOST=%s DEVICE=%s\n",
964 getenv("SUBSYSTEM") ? : "USB", interface
, action
, product
, scsi_host
, device
);
966 if (!nvram_get_int("usb_enable")) return;
968 if (!action
|| ((!interface
|| !product
) && !is_block
))
970 if (!interface
|| !action
|| !product
) /* Hubs bail out here. */
975 host
= atoi(scsi_host
);
977 if (!wait_action_idle(10)) return;
979 add
= (strcmp(action
, "add") == 0);
980 if (add
&& (strncmp(interface
? : "", "TOMATO/", 7) != 0)) {
982 if (!is_block
&& device
)
984 syslog(LOG_DEBUG
, "Attached USB device %s [INTERFACE=%s PRODUCT=%s]",
985 device
, interface
, product
);
987 /* To allow automount to be blocked on startup.
988 * In kernel 2.6 we still need to serialize mount/umount calls -
989 * so the lock is down below in the "block" hotplug processing.
991 file_unlock(file_lock("usb"));
995 if (strncmp(interface
? : "", "TOMATO/", 7) == 0) { /* web admin */
996 if (scsi_host
== NULL
)
997 host
= atoi(product
); // for backward compatibility
998 /* If host is negative, unmount all partitions of *all* hosts.
999 * If host == -1, execute "soft" unmount (do not kill NAS apps, no "lazy" umount).
1000 * If host == -2, run "hard" unmount, as if the drive is unplugged.
1001 * This feature can be used in custom scripts as following:
1003 * # INTERFACE=TOMATO/1 ACTION=remove PRODUCT=-1 SCSI_HOST=-1 hotplug usb
1005 * PRODUCT is required to pass the env variables verification.
1007 /* Unmount or remount all partitions of the host. */
1008 hotplug_usb_storage_device(host
< 0 ? -1 : host
, add
? -1 : 0,
1009 host
== -2 ? 0 : EFH_USER
);
1012 else if (is_block
&& strcmp(getenv("MAJOR") ? : "", "8") == 0 && strcmp(getenv("PHYSDEVBUS") ? : "", "scsi") == 0) {
1013 /* scsi partition */
1017 sprintf(devname
, "/dev/%s", device
);
1018 lock
= file_lock("usb");
1020 if (nvram_get_int("usb_storage") && nvram_get_int("usb_automount")) {
1021 int minor
= atoi(getenv("MINOR") ? : "0");
1022 if ((minor
% 16) == 0 && !is_no_partition(device
)) {
1023 /* This is a disc, and not a "no-partition" device,
1024 * like APPLE iPOD shuffle. We can't mount it.
1028 if (mount_partition(devname
, host
, NULL
, device
, EFH_HP_ADD
)) {
1029 restart_nas_services(0, 1); // restart all NAS applications
1034 /* When unplugged, unmount the device even if usb storage is disabled in the GUI */
1035 umount_partition(devname
, host
, NULL
, device
, EFH_HP_REMOVE
);
1036 /* Restart NAS applications (they could be killed by umount_mountpoint),
1037 * or just re-read the configuration.
1039 restart_nas_services(0, 1);
1044 else if (strncmp(interface
? : "", "8/", 2) == 0) { /* usb storage */
1046 usbled_proc(device
, add
);
1048 run_nvscript("script_usbhotplug", NULL
, 2);
1050 hotplug_usb_storage_device(host
, add
, (add
? EFH_HP_ADD
: EFH_HP_REMOVE
) | (host
< 0 ? EFH_HUNKNOWN
: 0));
1053 else { /* It's some other type of USB device, not storage. */
1055 if (is_block
) return;
1058 if (strncmp(interface
? : "", "7/", 2) == 0) /* printer */
1059 usbled_proc(device
, add
);
1061 /* Do nothing. The user's hotplug script must do it all. */
1062 run_nvscript("script_usbhotplug", NULL
, 2);