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 ***
21 ***  Modify Reason             Author          Date             Search Flag(Option)
22 ***--------------------------------------------------------------------------------------
23 ***  Created                   zZz            09/14/2007
24 **   Port to WNR3500U          Water          10/31/2008
25 *******************************************************************************/
26
27#include <stdio.h>
28#include <stdlib.h>
29#include <string.h>
30#include <errno.h>
31#include <dirent.h>
32#include <sys/stat.h>
33#include <sys/mount.h>
34#include "bcmconfig.h"
35
36//#define USB_HOTPLUG_DBG//@debug
37
38#if 0
39static set_usb_led()
40{
41    FILE *fp;
42    unsigned char line[256];
43    unsigned char port[2] = {0, 0};
44    char cmd[32];
45
46    fp = fopen("/proc/bus/usb/devices", "r");
47
48    if(fp == NULL)
49    {
50        fprintf(stderr, "open usb info failure\n");
51    }
52
53//------------------
54//reset flag
55//------------------
56    port[0] = 0;
57    port[1] = 0;
58
59//----------------------------
60//parse /proc/bus/usb/devices
61//----------------------------
62    while(1)
63    {
64        fgets(line, 256, fp);
65
66    //----------------------------
67    //parse Toplogy info
68    //----------------------------
69        if (strncmp(line, "T: ", 3) == 0)
70        {
71            char *subtoken;
72            char *saveptr1, *saveptr2;
73            char *token = strtok_r(line, " \t\n", &saveptr1);
74            int   tmpNum;
75
76            if (token)
77            {
78                while (1)
79                {
80                    token = strtok_r(NULL, " \t\n", &saveptr1);
81                    if (token == NULL)
82                    {
83                        break;
84                    }
85                    //fprintf(stderr, "%s \n", token);
86                    if (strncmp(token, "Prnt=", 5) == 0 )
87                    {
88                    //-----------------------------------------
89                    //Parent = 0x1 -> leaf of root hub -> a node
90                    //Then read Port: port 0 -> USB1
91                    //                port 1 -> USB2
92                    //-----------------------------------------
93                        //fprintf(stderr, "%s ", token);
94                        subtoken = strtok_r(token, "=", &saveptr2);
95                        //fprintf(stderr, "%s ", subtoken);
96                        subtoken = strtok_r(NULL, "=", &saveptr2);
97                        //fprintf(stderr, "%s ", subtoken);
98
99                        tmpNum = atoi(subtoken);
100                        if (tmpNum == 1)
101                        {
102                        //------------------
103                        //get port
104                        //------------------
105                            token = strtok_r(NULL, " \t\n", &saveptr1);
106                            //fprintf(stderr, "%s ", token);
107                            subtoken = strtok_r(token, "=", &saveptr2);
108                            //fprintf(stderr, "%s ", subtoken);
109                            subtoken = strtok_r(NULL, "=", &saveptr2);
110                            //fprintf(stderr, "%s ", subtoken);
111
112                        //------------------
113                        //set flag
114                        //------------------
115                            tmpNum = atoi(subtoken);
116                            if (tmpNum == 0)
117                            {
118                                port[0] = 1;
119                            }
120                            else if(tmpNum == 1)
121                            {
122                                port[1] = 1;
123                            }
124                            else
125                            {
126                                fprintf(stderr, "unexcepted port #\n");
127                            }
128                            break;
129                        } //parse port if parent is 1 (root)
130                    } //parset parent
131                } //while 1
132            } //if token
133        } //strcmp T:
134        if (feof(fp))
135        {
136            break;
137        }
138    } //while 1 -> read lines in files
139    fclose(fp);
140    //------------------
141    //set LED
142    //------------------
143    snprintf(cmd, 32, "/sbin/gpio 9 %d", (int)port[0]);
144    system(cmd);
145
146    snprintf(cmd, 32, "/sbin/gpio 10 %d", (int)port[1]);
147    system(cmd);
148}
149#endif/*No usb led in WNR3500U board, need further check.*/
150
151/***********************************************************************************************************************
152* Environment of hotplug for USB:
153* DEVICE=bus_num, dev_num
154*
155* PRODUCT=Vendor, Product, bcdDevice
156*
157* TYPE= DeviceClass, DeviceSubClass, DeviceProtocol
158*
159* if DeviceClass == 0
160*  -> INTERFACE=interface [0].altsetting [alt].bInterfaceClass, interface [0].altsetting [alt].bInterfaceSubClass,
161*               interface [0].altsetting [alt].bInterfaceProtocol
162*
163***********************************************************************************************************************/
164
165int usb_mount()
166{
167    char source[128];
168    char target[128];
169    char buf[128];
170    int i;
171    int rval;
172//------------------------------------------------------
173// action: add
174// 1. mount dev with vfat
175// 2. if mount ok, save data to nvram
176// 3. restart smb
177//------------------------------------------------------
178//fixme: no good. zzz@
179    for (i=1; i<16; i++ )
180    {
181#if 0
182        //------------------------
183        //set up source
184        //------------------------
185        snprintf(source, 128, "/dev/sda%d", i);
186
187        //------------------------
188        //set up target
189        //------------------------
190        snprintf(target, 128, "/tmp/mnt/usb%d", i);
191
192        //------------------------
193        //start mount with sync
194        //------------------------
195        rval = mount(source, target, "vfat", MS_SYNCHRONOUS, 0);
196
197#ifdef USB_HOTPLUG_DBG//debug
198        snprintf(buf, 128, "echo \"mount %s %s with vfat, rval:%d \">>/tmp/usberr.log", source, target, rval);
199        system(buf);
200#endif
201        if (rval)
202        {
203            rval = mount(source, target, "ntfs", MS_RDONLY, 0);
204#ifdef USB_HOTPLUG_DBG//debug
205            snprintf(buf, 128, "echo \"mount %s %s with ntfs, rval:%d \">>/tmp/usberr.log", source, target, rval);
206            system(buf);
207#endif
208        }
209        /*foxconn add start, water, 12/08/2008*/
210#endif/*if 0, removed water, 12/08/2008, @write throughput too low.*/
211        /*If we do mount by key in mount command in the console. the write throughput is ok.*/
212        /*I think there're some bugs in the above mount function. But the mount command build by busybox is ok.*/
213        /*So we use mount command here. It isn't a good solution. Just a "work around".*/
214        snprintf(buf, 128, "/bin/mount -t vfat /dev/sda%d /tmp/mnt/usb%d", i, i);
215        system(buf);
216
217        /*ntfs read only supported*/
218        snprintf(buf, 128, "/bin/mount -t ntfs /dev/sda%d /tmp/mnt/usb%d", i, i);
219        system(buf);
220        /*foxconn add end, water, 12/08/2008*/
221    } //end of for
222
223    return 0;
224}
225
226int usb_umount()
227{
228    int i, j;
229    int rval;
230    char path[128];
231    char buf[128];
232    //------------------------------------------------------
233    // action: remove
234    // remount devices
235    //------------------------------------------------------
236    //fixme: no good. zzz@
237
238    for (j=1; j<16; j++)
239    {
240        snprintf(path, 128, "/bin/umount /tmp/mnt/usb%d", j);
241
242        rval = system(path);
243#ifdef USB_HOTPLUG_DBG//debug
244        snprintf(buf, 128, "echo \"umount %s, rval:%d \">>/tmp/usberr.log", path, rval);
245        system(buf);
246#endif
247    }
248
249    usb_mount();
250    return 0;
251}
252int usb_hotplug(void)
253{
254    char *device, *interface;
255    char *action, *product;
256    char *type, *devfs;
257    int class, subclass, protocol;
258    char cmd[512];
259
260    if (!(action = getenv("ACTION")) ||
261        !(type = getenv("TYPE")) ||
262        !(device = getenv("DEVICE")) ||
263        !(devfs = getenv("DEVFS")) ||
264        !(interface = getenv("INTERFACE")) ||
265        !(product = getenv("PRODUCT")))
266    {
267#ifdef USB_HOTPLUG_DBG//debug
268        sprintf(cmd, "echo \"return EINVAL;\" >> /tmp/hotAct\n");
269        system(cmd);
270#endif
271        return EINVAL;
272    }
273
274#ifdef USB_HOTPLUG_DBG//debug
275        sprintf(cmd, "echo \"ACTION=%s, TYPE=%s, DEVICE=%s, DEVFS=%s, INTERFACE=%s, PRODUCT=%s\" >> /tmp/hotAct\n",
276                action, type, device, devfs, interface, product);
277        system(cmd);
278#endif
279
280    sscanf(type, "%d/%d/%d", &class, &subclass, &protocol);
281    if (class == 0)
282    {
283        sscanf(interface, "%d/%d/%d", &class, &subclass, &protocol);
284    }
285    //set LED
286    //set_usb_led();/*No usb led in WNR3500U board, need further check.*/
287
288    //check Mass Storage for add action
289    if (class == 8 && subclass == 6  && !strcmp(action, "add"))
290    {
291        /*
292        sometimes usb_umount() not execute when unplug usb.
293        so before mount, we do umount firstly.
294        not sure, I think it need further test.
295        */
296        //usb_mount();
297        usb_umount();/*water, 11/06/2008*/
298    }
299    //check Mass Storage for remove action
300    else if (class == 8 && subclass == 6  && !strcmp(action, "remove"))
301    {
302        usb_umount();
303    }
304
305    system("/usr/bin/setsmbftpconf");
306#ifdef USB_HOTPLUG_DBG//debug
307    system("echo \"/usr/bin/setsmbftpconf\">>/tmp/usberr.log");
308#endif
309    return 0;
310}
311