1/***************************************************************************
2 ***
3 ***    Copyright 2005  Hon Hai Precision Ind. Co. Ltd.
4 ***    All Rights Reserved.
5 ***    No portions of this material shall be reproduced in any form without the
6 ***    written permission of Hon Hai Precision Ind. Co. Ltd.
7 ***
8 ***    All information contained in this document is Hon Hai Precision Ind.
9 ***    Co. Ltd. company private, proprietary, and trade secret property and
10 ***    are protected by international intellectual property laws and treaties.
11 ***
12 ****************************************************************************
13 ***
14 ***  Filename: hotplug_usb.c
15 ***
16 ***  Description:
17 ***    USB automount function
18 ***
19 ***  HISTORY:
20 ***       - Created Date: 04/24/2009, Water, @USB spec1.7 implement on WNR3500L
21 *******************************************************************************/
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <errno.h>
28#include <dirent.h>
29#include <sys/stat.h>
30#include <sys/mount.h>
31#include <sys/wait.h>
32#include "bcmconfig.h"
33#include "shutils.h"
34#include "bcmnvram.h"
35
36//#define USB_HOTPLUG_DBG//@debug
37#define MNT_DETACH 0x00000002 /* Foxconn add , Jenny Zhao, 04/22/2009 @usb dir */
38
39/***********************************************************************************************************************
40* Environment of hotplug for USB:
41* DEVICE=bus_num, dev_num
42*
43* PRODUCT=Vendor, Product, bcdDevice
44*
45* TYPE= DeviceClass, DeviceSubClass, DeviceProtocol
46*
47* if DeviceClass == 0
48*  -> INTERFACE=interface [0].altsetting [alt].bInterfaceClass, interface [0].altsetting [alt].bInterfaceSubClass,
49*               interface [0].altsetting [alt].bInterfaceProtocol
50*
51***********************************************************************************************************************/
52
53/* Foxconn added start pling 07/13/2009 */
54#include <sys/types.h>
55#include <sys/ipc.h>
56#include <sys/sem.h>
57
58#define LOCK           -1
59#define UNLOCK          1
60#define USB_SEM_KEY     0x5553424B     // "USBK"
61
62int usb_sem_init(void)
63{
64    struct sembuf lockop = { 0, 0, SEM_UNDO } /* sem operation */ ;
65    int semid;
66
67    /* create/init sem */
68    if ((semid = semget (USB_SEM_KEY, 1, IPC_CREAT | IPC_EXCL | 0666)) >= 0)
69    {
70        /* initialize the sem vaule to 1 */
71        if (semctl (semid, 0, SETVAL, 1) < 0)
72        {
73            perror("usb_sem_init");
74            return -1;
75        }
76        return 0;
77    }
78    return -1;
79}
80
81/* static */ int usb_sem_lock(int op)
82{
83    struct sembuf lockop = { 0, 0, SEM_UNDO } /* sem operation */ ;
84    int semid;
85
86    /* sem already created. get the semid */
87    if ((semid = semget (USB_SEM_KEY, 1, 0666)) < 0)
88    {
89        perror("usb_sem_lock");
90        return -1;
91    }
92
93    lockop.sem_op = op;
94    if (semop (semid, &lockop, 1) < 0)
95        return -1;
96
97    return 0;
98}
99
100#define USB_LOCK()      usb_sem_lock(LOCK)
101#define USB_UNLOCK()    usb_sem_lock(UNLOCK)
102/* Foxconn added end pling 07/13/2009 */
103
104/* Foxconn add start pling 02/05/2010*/
105/* USB LED on / off */
106#ifdef INCLUDE_USB_LED
107#include "wps_led.h"
108#include <sys/stat.h>
109#include <fcntl.h>
110
111/* Foxconn added start, Wins, 04/11/2011 */
112#if defined(R6300v2) || defined(R7000)
113#define MAX_BUF_LEN     512
114#define USB_MNT_TABLE   "/tmp/usb_mnt_table"
115#define USB_MNT_TABLE2  "/tmp/usb_mnt_table2"
116#define USB_MNT_PATTERN "PORT=%s,DEVICE=%s,PART=%s"
117
118int get_usb_port(char *pDevPath, char *pUsbPort)
119{
120    int rtn_val = 0;
121    char buf[256];
122    char *strPos1 = NULL, *strPos2 = NULL;
123
124#if defined(R6300v2)
125    if ((strPos1 = strstr(pDevPath, "/usb")) != NULL)
126    {
127        sscanf(strPos1, "/usb%s", buf);
128#elif defined(R7000)
129    if ((strstr(pDevPath, "/usb1/1-") != NULL) || (strstr(pDevPath, "/usb3/3-") != NULL))
130    {
131
132        if((strPos1 = strstr(pDevPath, "/usb1/1-")) != NULL)
133            sscanf(strPos1, "/usb1/1-%s", buf);
134        else if((strPos1 = strstr(pDevPath, "/usb3/3-")) != NULL)
135            sscanf(strPos1, "/usb3/3-%s", buf);
136#else
137    if ((strPos1 = strstr(pDevPath, "/host")) != NULL)
138    {
139        sscanf(strPos1, "/host%s", buf);
140#endif
141        if ((strPos2 = strchr(buf, '/')) != NULL)
142        {
143
144            memcpy(pUsbPort, buf, (strPos2 - buf));
145            rtn_val = 1;
146        }
147    }
148
149    return rtn_val;
150} /* get_usb_port() */
151
152int parse_target_path(char *pTarget, int *pDevice, int *pPart)
153{
154    int rtn_val = 0;
155    char usb_device[4], usb_part[4];
156    char buf[128];
157    char *strPos1 = NULL, *strPos2 = NULL;
158
159    /* Get USB device & part */
160    memset(usb_device, 0x0, sizeof(usb_device));
161    memset(usb_part, 0x0, sizeof(usb_part));
162    if ((strPos1 = strstr(pTarget, "/tmp/mnt/usb")) != NULL) {
163        sscanf(strPos1, "/tmp/mnt/usb%s", buf);
164        if ((strPos2 = strchr(buf, '/')) != NULL) {
165            memcpy(usb_device, buf, (strPos2-buf));
166            *pDevice = atoi(usb_device);
167            strPos2 = NULL;
168            if ((strPos2 = strstr(buf, "/part")) != NULL) {
169                sscanf(strPos2, "/part%s", usb_part);
170                *pPart = atoi(usb_part);
171                rtn_val = 1;
172            }
173        }
174    }
175
176    return rtn_val;
177} /* parse_target_path() */
178
179int add_into_mnt_file(char *pUsbPort, char *pDevice, char *pPart)
180{
181    FILE *fp = NULL;
182    int rtn_val = 0;
183    char buf[128];
184
185    /* Foxconn added start, Wins, 06/30/2011 */
186    if ((fp = fopen(USB_MNT_TABLE, "r")) != NULL)
187    {
188        int rec_found = 0;
189        char patt[128];
190        /* Check if record of USB device exists. */
191        while(fgets(buf, sizeof(buf), fp) != NULL)
192        {
193            memset(patt, 0x0, sizeof(patt));
194            sprintf(patt, USB_MNT_PATTERN, pUsbPort, pDevice, pPart);
195            strcat(patt, "\n");
196            if (!strcmp(buf, patt))
197            {
198                rec_found = 1;
199                break;  /* Record exists. */
200            }
201        }
202        fclose(fp);
203        if (rec_found)
204            return 1;   /* Not need to add a duplicated record. */
205    }
206    fp = NULL;
207    /* Foxconn added end, Wins, 06/30/2011 */
208
209    if ((fp = fopen(USB_MNT_TABLE, "a+")) != NULL)
210    {
211        fseek(fp, 0, SEEK_END);
212        sprintf(buf, USB_MNT_PATTERN, pUsbPort, pDevice, pPart);
213        strcat(buf, "\n");
214        fputs(buf, fp);
215        fclose(fp);
216        rtn_val = 1;
217    }
218
219    return rtn_val;
220} /* add_into_mnt_file() */
221
222int remove_from_mnt_file(char *pUsbPort, char *pDevice, char *pPart)
223{
224    FILE *fp = NULL, *fp2 = NULL;
225    int rtn_val = 0;
226    char usb_device[4], usb_part[4];
227    char buf[128];
228    char *strPos1 = NULL, *strPos2 = NULL;
229
230    if ((fp = fopen(USB_MNT_TABLE, "r+")) != NULL)
231    {
232        char buf[128];
233        sprintf(buf, "cp -f %s %s", USB_MNT_TABLE, USB_MNT_TABLE2);
234        system(buf);
235        fclose(fp);
236    }
237
238    fp = NULL; fp2 = NULL;
239    if ((fp2 = fopen(USB_MNT_TABLE2, "r+")) != NULL)
240    {
241        char buf[MAX_BUF_LEN];
242        char patt[MAX_BUF_LEN];
243        sprintf(patt, USB_MNT_PATTERN, pUsbPort, pDevice, pPart);
244        if ((fp = fopen(USB_MNT_TABLE, "w+")) != NULL)
245        {
246            while (fgets(buf, MAX_BUF_LEN, fp2) != NULL)
247            {
248                if ((strPos1 = strstr(buf, patt)) != NULL) {
249                    continue;
250                }
251                else {
252                    fputs(buf, fp);
253                }
254            }
255            fclose(fp);
256            rtn_val = 1;
257        }
258        fclose(fp2);
259
260        sprintf(buf, "rm -f %s", USB_MNT_TABLE2);
261        system(buf);
262    }
263
264    return rtn_val;
265} /* remove_from_mnt_file() */
266
267int usb1_led(void)
268{
269    int rtn_val = 0;
270    int has_usb1_dev = 0;
271    int fd;
272    FILE *fp = NULL;
273    char line[250] = "";
274
275    if ((fp = fopen(USB_MNT_TABLE, "r")) != NULL)
276    {
277        rtn_val = 1;
278        while (fgets(line, 200, fp) != NULL) {
279            if ( (strstr(line, "PORT=1") != NULL) || (strstr(line, "PORT=3") != NULL))
280            {
281                has_usb1_dev = 1;
282                rtn_val = 2;
283                break;
284            }
285        }
286        fclose(fp);
287    }
288    /* foxconn wklin modified start, 01/19/2011 @ USB LED for WNDR4000 */
289#if (defined GPIO_EXT_CTRL) /* WNDR4000 */
290    if (has_usb1_dev)
291        system("gpio usbled 1");
292    else
293        system("gpio usbled 0");
294#else
295    fd = open("/dev/wps_led", O_RDWR);
296    if (fd >= 0) {
297        rtn_val = 3;
298        if (has_usb1_dev)
299        {
300            ioctl(fd, USB_LED_STATE_ON, 1);
301            rtn_val = 4;
302        }
303        else
304        {
305            ioctl(fd, USB_LED_STATE_OFF, 1);
306            rtn_val = 5;
307        }
308        close(fd);
309    }
310#endif /* GPIO_EXT_CTRL */
311    /* foxconn wklin modified end ,01/19/2011 */
312    return rtn_val;
313} /* usb1_led() */
314
315int usb2_led(void)
316{
317    int rtn_val = 0;
318    int has_usb2_dev = 0;
319    int fd;
320    FILE *fp = NULL;
321    char line[250] = "";
322
323    if ((fp = fopen(USB_MNT_TABLE, "r")) != NULL)
324    {
325        rtn_val = 1;
326        while (fgets(line, 200, fp) != NULL) {
327            if (strstr(line, "PORT=2") != NULL) {
328                has_usb2_dev = 1;
329                rtn_val = 2;
330                break;
331            }
332        }
333        fclose(fp);
334    }
335    /* foxconn wklin modified start, 01/19/2011 @ USB LED for WNDR4000 */
336#if (defined GPIO_EXT_CTRL) /* WNDR4000 */
337    if (has_usb2_dev)
338        system("gpio usbled 1");
339    else
340        system("gpio usbled 0");
341#else
342    fd = open("/dev/wps_led", O_RDWR);
343    if (fd >= 0) {
344        rtn_val = 3;
345        if (has_usb2_dev)
346        {
347            ioctl(fd, USB2_LED_STATE_ON, 1);
348            rtn_val = 4;
349        }
350        else
351        {
352            ioctl(fd, USB2_LED_STATE_OFF, 1);
353            rtn_val = 5;
354        }
355        close(fd);
356    }
357#endif /* GPIO_EXT_CTRL */
358    /* foxconn wklin modified end ,01/19/2011 */
359    return rtn_val;
360} /* usb2_led() */
361
362int usb_dual_led(void)
363{
364    int rtn_val = 0;
365
366    usb1_led();
367#if (!defined R6700)    /* No USB2 LED for R6700 */
368    usb2_led();
369#endif
370
371    return rtn_val;
372} /* usb_dual_led() */
373#else /* R6300v2 */
374
375int usb_led(void)
376{
377    int has_usb_dev = 0;
378    int fd;
379    FILE *fp = NULL;
380    char line[250] = "";
381
382    fp = fopen("/proc/mounts", "r");
383    if (fp != NULL) {
384        while (fgets(line, 200, fp) != NULL) {
385            if (strstr(line, "/tmp/mnt/usb") != NULL) {
386                has_usb_dev = 1;
387                break;
388            }
389        }
390        fclose(fp);
391    }
392    /* foxconn wklin modified start, 01/19/2011 @ USB LED for WNDR4000 */
393#if (defined GPIO_EXT_CTRL) /* WNDR4000 */
394#if 0   /* Foxconn removed pling 12/26/2011, not needed for WNDR4000AC */
395    if (has_usb_dev)
396        system("gpio usbled 1");
397    else
398        system("gpio usbled 0");
399#endif
400#else
401    fd = open("/dev/wps_led", O_RDWR);
402    if (fd >= 0) {
403        if (has_usb_dev)
404            ioctl(fd, USB_LED_STATE_ON, 1);
405        else
406            ioctl(fd, USB_LED_STATE_OFF, 1);
407        close(fd);
408    }
409#endif /* GPIO_EXT_CTRL */
410    /* foxconn wklin modified end ,01/19/2011 */
411    return 0;
412}
413#endif /* R6300v2 */
414/* Foxconn added end, Wins, 04/11/2011 */
415#endif
416/* Foxconn add end pling 02/05/2010*/
417
418int usb_mount(void)
419{
420    char source[128];
421    char target[128];
422    char buf[128];
423    int i;
424    int rval;
425
426    /*foxconn add start, @mount approved devices, water, 05/11/2009*/
427    int index = 0;
428    FILE *fp = NULL;
429    char line[150] = "";
430    char *ptmp = NULL;
431    char vendor[32] = "";
432    char model[32] = "";
433    int  scsi_host_num = -1;
434    int usb_dev_approved[26] = {0};
435    char approved_usb[20][80] = {0};
436    int not_approved_index;
437
438    /* Foxconn added start pling 09/16/2009 */
439    int last_scsi_host_num = -1;
440    /* Foxconn added end pling 09/16/2009 */
441
442    sleep(3);   /* pling added 06/04/2009, add this delay seems to make mount more robust. */
443
444    if (nvram_match("enable_any_usb_dev", "0") )
445    {
446        for (i=0; i<20; i++)
447        {
448            sprintf(line, "approved_usb_%d", i);
449            strcpy(buf, nvram_safe_get(line));
450            if (strlen (buf) != 0)
451            {
452                sscanf(buf, "%*[^+]+%[^+]+%*[^+]", approved_usb[i]);
453            }
454        }
455
456        fp = fopen("/proc/scsi/scsi", "r");
457        if (fp != NULL)
458        {
459            while (fgets(line, 150, fp) != NULL)
460            {
461                if (strncmp(line, "Host: scsi", strlen("Host: scsi")) == 0)
462                {
463                    sscanf(line, "Host: scsi%d %*s", &scsi_host_num);
464
465                    /* Foxconn added start pling 09/16/2009 */
466                    /* Handle multi-lun devices */
467                    if (scsi_host_num == last_scsi_host_num)
468                    {
469                        /* Keep the same "approved"/"not-approved" status
470                         * as the previous LUN
471                         */
472                        usb_dev_approved[index] = usb_dev_approved[index-1];
473                        index++;
474                        continue;
475                    }
476                    /* Foxconn added end pling 09/16/2009 */
477
478                    if ((fgets(line, 150, fp) == NULL))
479                        break;
480
481                    ptmp=strstr(line, "Vendor:");
482                    if ( ptmp != NULL )
483                    {
484                        sscanf(ptmp, "Vendor: %s %*s", vendor);
485                        if (0 == strcmp(vendor, "Model:") )
486                            strcpy(vendor, "");
487                    }
488                    ptmp=strstr(line, "Model:");
489                    if ( ptmp != NULL )
490                    {
491                        sscanf(ptmp, "Model: %s %*s", model);
492                        if (0 == strcmp(vendor, "Rev:") )
493                            strcpy(vendor, "");
494                    }
495                    sprintf(buf, "%s %s", vendor, model);
496
497                    for (i=0; i<20; i++)
498                    {
499                        if (strlen(approved_usb[i]) == 0 )
500                            continue;
501                        if (0 == strcmp(approved_usb[i], buf) )
502                        {/*this usb device was approved*/
503                            /* Foxconn modified start pling 09/16/2009 */
504                            /* Use 'index' to help check multi-LUN device */
505                            //usb_dev_approved[scsi_host_num] = 1;
506                            usb_dev_approved[index] = 1;
507                            /* Foxconn modified end pling 09/16/2009 */
508                            break;
509                        }
510                    }
511                    /* Foxconn added start pling 09/16/2009 */
512                    /* Multi-LUN devices */
513                    index++;
514                    last_scsi_host_num = scsi_host_num;
515                    /* Foxconn added end pling 09/16/2009 */
516                }
517            }
518            fclose(fp);
519        }
520    }
521    else
522    {
523        for (i=0; i<26; i++)
524            usb_dev_approved[i] = 1;
525    }
526    not_approved_index = 0;
527    /*foxconn add end, water, 05/11/2009*/
528
529    index = 0;      // pling added 09/16/2009, reset index for later use
530
531//------------------------------------------------------
532// action: add
533// 1. mount dev with vfat
534// 2. if mount ok, save data to nvram
535// 3. restart smb
536//------------------------------------------------------
537//fixme: no good. zzz@
538/* Foxconn modified start, Jenny Zhao, 04/13/2009 @usb dir */
539    char diskName;
540    int j = 0;
541    int max_partition = atoi(nvram_safe_get("usb_disk_max_part"));
542    for (diskName='a'; diskName<='z'; diskName++)   // try to mount sda->sdz
543    {
544        /*foxconn add start, @mount approved devices, water, 05/11/2009*/
545        if (usb_dev_approved[index++] == 1)/*this device was approved...*/
546            scsi_host_num = 1;
547        else
548            scsi_host_num = 0;
549        /*foxconn add end, water, 05/11/2009*/
550        for (i=0; i<=max_partition; i++)            // try to mount sdx or sdx1, ..., sdx5
551        {
552            //------------------------
553            //set up source
554            //------------------------
555            if (!i)
556                snprintf(source, 128, "/dev/sd%c", diskName);
557            else
558                snprintf(source, 128, "/dev/sd%c%d", diskName,i);
559
560            //------------------------
561            //set up target
562            //------------------------
563            /*foxconn modified start, water, 05/12/2009*/
564            /*some usb device not in approved device list, but the approved device page
565                need to show its info, so it need mount too. */
566            //snprintf(target, 128, "/tmp/mnt/usb%d/part%d", j, i);
567            if (scsi_host_num == 1)
568                snprintf(target, 128, "/tmp/mnt/usb%d/part%d", j, i);
569            else
570                snprintf(target, 128, "/tmp/mnt/not_approved%d", not_approved_index++);
571            /*foxconn modified end, water, 05/12/2009*/
572
573            //------------------------
574            //start mount with sync
575            //------------------------
576            //rval = mount(source, target, "vfat",  0, NULL);
577            rval = mount(source, target, "vfat",0, "iocharset=utf8"); //stanley add,09/14/2009
578            /* pling added start 05/07/2009 */
579            /* Use mlabel to read VFAT volume label after successful mount */
580            if (rval == 0)
581            {
582                /* Foxconn, add-start by MJ., for downsizing WNDR3400v2,
583                 * 2011.02.11. */
584#if (defined WNDR3400v2) || (defined R6300v2)
585                snprintf(buf, 128, "/lib/udev/vol_id %s", source);
586                /* Foxconn added start pling 12/26/2011, for WNDR4000AC */
587#elif (defined WNDR4000AC)
588                get_vol_id(source);
589                memset(buf, 0, sizeof(buf));
590                /* Foxconn added end pling 12/26/2011, for WNDR4000AC */
591#else
592                /* Foxconn, add-end by MJ., for downsizing WNDR3400v2,
593                 * 2011.02.11. */
594                snprintf(buf, 128, "/usr/bin/mlabel -i %s -s ::", source);
595#endif
596                system(buf);
597            }
598            /* pling added end 05/07/2009 */
599
600#ifdef USB_HOTPLUG_DBG//debug
601            snprintf(buf, 128, "echo \"mount %s %s with vfat, rval:%d, errno=%d\">>/tmp/usberr.log",
602                               source, target, rval, errno);
603            system(buf);
604#endif
605
606            /* pling added start 08/24/2009 */
607            /* To speed up mounting:
608             *  if sda is mounted, then don't bother about sda1, sda2...
609             */
610            if (rval == 0 && i == 0)
611                break;
612            /* pling added end 08/24/2009 */
613
614            if (rval<0 && errno == EINVAL)
615            {
616                int ret;
617                /* Use NTFS-3g driver to provide NTFS r/w function */
618                snprintf(buf, 128, "/bin/ntfs-3g -o large_read %s %s 2> /dev/null", source, target);
619                ret = system(buf);
620
621#ifdef USB_HOTPLUG_DBG//debug
622                snprintf(buf, 128, "echo \"try to mount %s @ %s with ntfs-3g\">>/tmp/usberr.log", source, target);
623                system(buf);
624#endif
625
626                /* Foxconn added pling 08/24/2009 */
627                /* To speed up mounting:
628                 *  if sda is mounted, then don't bother about sda1, sda2...
629                 */
630                if (WIFEXITED(ret))
631                {
632                    int status = WEXITSTATUS(ret);
633                    if (status == 0 && i == 0)
634                        break;
635                }
636                /* Foxconn added pling 08/24/2009 */
637            }
638        } //end of for
639        j++;
640    }//end of for(diskName = 'a';diskName < 'd';diskName++)
641    /* Foxconn modified end, Jenny Zhao, 04/13/2009 */
642    //nvram_set("usb_dev_no_change", "0");
643    /* send signal to httpd ,create link ,2009/05/07, jenny*/
644    //nvram_set("usb_mount_signal", "1");
645    system("killall -SIGUSR2 httpd");
646    /* USB LED on / off */
647#ifdef INCLUDE_USB_LED
648    /* Foxconn modified start, Wins, 04/11/2011 */
649#if defined(R6300v2) || defined(R7000)
650    usb_dual_led();
651#else /* R6300v2 */
652    usb_led();
653#endif /* R6300v2 */
654    /* Foxconn modified end, Wins, 04/11/2011 */
655#endif
656
657    //sleep(5);   // Foxconn added pling 07/13/2009, wait for httpd to complete mount/umount processes
658    //nvram_set("usb_mount_signal", "0");
659    //acosNvramConfig_save();
660    return 0;
661}
662
663int usb_umount(void)
664{
665    int i, j;
666    int rval;
667    char path[128];
668    char buf[128];
669    //------------------------------------------------------
670    // action: remove
671    // remount devices
672    //------------------------------------------------------
673    //fixme: no good. zzz@
674    /* Foxconn modify start, Jenny Zhao, 04/13/2009 @usb dir */
675    char diskName;
676
677    /*foxconn add start, water, 05/12/2009*/
678    /*some usb device not in approved device list, but the approved device
679     page need to show its info, so it need mount too. */
680    for (j=0; j<20; j++)
681    {
682        snprintf(path, 128, "/tmp/mnt/not_approved%d", j);
683        umount2(path, MNT_DETACH);
684    }
685    /*foxconn add end, water, 05/12/2009*/
686
687    for (diskName='a', i=0; diskName<='z'; diskName++,i++)
688    {
689        snprintf(path, 128, "/tmp/mnt/usb%d/part0", i);
690
691        rval = umount2(path, MNT_DETACH);
692
693        for (j=0; j<16; j++)
694        {
695            snprintf(path, 128, "/tmp/mnt/usb%d/part%d", i, j);
696
697            rval = umount2(path, MNT_DETACH);
698            /* pling added start 05/07/2009 */
699            /* remove volume name file under /tmp after a successful umount */
700            if (rval == 0)
701            {
702                char filename[64];
703                if (j == 0)
704                    sprintf(filename, "/tmp/usb_vol_name/sd%c", diskName);
705                else
706                    sprintf(filename, "/tmp/usb_vol_name/sd%c%d", diskName, j);
707                unlink(filename);
708            }
709            /* pling added end 05/07/2009 */
710
711#ifdef USB_HOTPLUG_DBG//debug
712            snprintf(buf, 128, "echo \"umount %s, rval:%d \">>/tmp/usberr.log", path, rval);
713            system(buf);
714#endif
715        }
716    }
717    /* Foxconn modify end, Jenny Zhao, 04/13/2009 */
718    nvram_set("usb_dev_no_change", "0");
719    //acosNvramConfig_save();
720
721    usb_mount();
722    return 0;
723}
724int usb_hotplug(void)
725{
726    char *device, *interface;
727    char *action, *product;
728    char *type, *devfs;
729    int class, subclass, protocol;
730    char cmd[512];
731
732    /*foxconn add start, water, 05/11/2009*/
733    if (nvram_match("restart_usb", "1") )
734    {
735        usb_umount();
736        nvram_unset("restart_usb");
737        //eval("/usr/bin/setsmbftpconf");
738    }
739    /*foxconn add end, water, 05/11/2009*/
740
741    if (!(action = getenv("ACTION")) ||
742        !(type = getenv("TYPE")) ||
743        !(device = getenv("DEVICE")) ||
744        !(devfs = getenv("DEVFS")) ||
745        !(interface = getenv("INTERFACE")) ||
746        !(product = getenv("PRODUCT")))
747    {
748#ifdef USB_HOTPLUG_DBG//debug
749        sprintf(cmd, "echo \"return EINVAL;\" >> /tmp/hotAct\n");
750        system(cmd);
751#endif
752        return EINVAL;
753    }
754
755#ifdef USB_HOTPLUG_DBG//debug
756        sprintf(cmd, "echo \"ACTION=%s, TYPE=%s, DEVICE=%s, DEVFS=%s, INTERFACE=%s, PRODUCT=%s\" >> /tmp/hotAct\n",
757                action, type, device, devfs, interface, product);
758        system(cmd);
759#endif
760
761    sscanf(type, "%d/%d/%d", &class, &subclass, &protocol);
762    if (class == 0)
763    {
764        sscanf(interface, "%d/%d/%d", &class, &subclass, &protocol);
765    }
766    //set LED
767    //set_usb_led();/*No usb led in WNR3500U board, need further check.*/
768
769    //check Mass Storage for add action
770    /* Foxconn modified start pling 11/11/2009 */
771    /* We should mount all subclasses of Mass Storage class (8),
772     *  not just subclass 6 (Transparent SCSI).
773     */
774    //if (class == 8 && subclass == 6  && !strcmp(action, "add"))
775    if (class == 8 && !strcmp(action, "add"))
776    /* Foxconn modified end pling 11/11/2009 */
777    {
778        /*
779        sometimes usb_umount() not execute when unplug usb.
780        so before mount, we do umount firstly.
781        not sure, I think it need further test.
782        */
783        //usb_mount();
784        USB_LOCK();     // Foxconn added pling 07/13/2009
785        usb_umount();/*water, 11/06/2008*/
786        USB_UNLOCK();   // Foxconn added pling 07/13/2009
787    }
788    //check Mass Storage for remove action
789    /* Foxconn modified start pling 11/11/2009 */
790    /* We should un-mount all subclasses of Mass Storage class (8),
791     *  not just subclass 6 (Transparent SCSI).
792     */
793    //else if (class == 8 && subclass == 6  && !strcmp(action, "remove"))
794    else if (class == 8 && !strcmp(action, "remove"))
795    /* Foxconn modified end pling 11/11/2009 */
796    {
797        USB_LOCK();     // Foxconn added pling 07/13/2009
798        usb_umount();
799        USB_UNLOCK();   // Foxconn added pling 07/13/2009
800    }
801
802    //eval("/usr/bin/setsmbftpconf");
803#ifdef USB_HOTPLUG_DBG//debug
804    system("echo \"/usr/bin/setsmbftpconf\">>/tmp/usberr.log");
805#endif
806    return 0;
807}
808