Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / httpd / usb.c
blob592a7252aa1d6b09a44937b20daf7fb6d61b123b
1 /*
3 Tomato Firmware
4 USB Support
6 */
8 #include "tomato.h"
10 #include <sys/ioctl.h>
11 #include <fcntl.h>
12 #include <dirent.h>
13 #include <sys/statfs.h>
14 #include <mntent.h>
16 #ifndef BLKGETSIZE
17 #define BLKGETSIZE _IO(0x12,96)
18 #endif
19 #ifndef BLKGETSIZE64
20 #define BLKGETSIZE64 _IOR(0x12,114,size_t)
21 #endif
23 static uint64_t get_psize(char *dev)
25 uint64_t bytes = 0;
26 unsigned long sectors;
27 int fd;
29 if ((fd = open(dev, O_RDONLY)) >= 0) {
30 if (ioctl(fd, BLKGETSIZE64, &bytes) < 0) {
31 bytes = 0;
32 /* Can't get bytes, try 512 byte sectors */
33 if (ioctl(fd, BLKGETSIZE, &sectors) >= 0)
34 bytes = (uint64_t)sectors << 9;
36 close(fd);
39 return bytes;
42 #define PROC_SCSI_ROOT "/proc/scsi"
43 #define USB_STORAGE "usb-storage"
45 int is_partition_mounted(char *dev_name, int host_num, char *dsc_name, char *pt_name, uint flags)
47 char the_label[128];
48 char *type, *js;
49 int is_mounted = 0;
50 struct mntent *mnt;
51 struct statfs sf;
52 uint64_t size, fsize;
54 type = find_label_or_uuid(dev_name, the_label, NULL);
55 if (*the_label == 0) {
56 strncpy(the_label, pt_name, sizeof(the_label));
59 if (flags & EFH_PRINT) {
60 if (flags & EFH_1ST_DISC) {
61 // [disc_name, [partitions array]],...
62 web_printf("]],['%s',[", dsc_name);
64 // [partition_name, is_mounted, mount_point, type, opts, size, free],...
65 js = js_string(the_label);
66 web_printf("%s['%s',", (flags & EFH_1ST_DISC) ? "" : ",", js ? : "");
67 free(js);
70 if ((mnt = findmntents(dev_name, 0, 0, 0))) {
71 is_mounted = 1;
72 if (flags & EFH_PRINT) {
73 if (statfs(mnt->mnt_dir, &sf) == 0) {
74 size = (uint64_t)sf.f_bsize * sf.f_blocks;
75 fsize = (uint64_t)sf.f_bsize * sf.f_bfree;
77 else {
78 size = get_psize(dev_name);
79 fsize = 0;
81 web_printf("1,'%s','%s','%s',%llu,%llu]",
82 mnt->mnt_dir, mnt->mnt_type, mnt->mnt_opts, size, fsize);
85 else if ((mnt = findmntents(dev_name, 1, 0, 0))) {
86 is_mounted = 1;
87 if (flags & EFH_PRINT) {
88 web_printf("2,'','swap','',%llu,0]",
89 (uint64_t)atoi(mnt->mnt_type) * 1024);
92 else {
93 if (flags & EFH_PRINT) {
94 web_printf("0,'','%s','',%llu,0]", type ? : "", get_psize(dev_name));
98 return is_mounted;
101 int is_host_mounted(int host_no, int print_parts)
103 if (print_parts) web_puts("[-1,[");
105 int mounted = exec_for_host(
106 host_no,
107 0x00,
108 print_parts ? EFH_PRINT : 0,
109 is_partition_mounted);
111 if (print_parts) web_puts("]]");
113 return mounted;
117 * The disc # doesn't correspond to the host#, since there may be more than
118 * one partition on a disk.
119 * Nor does either correspond to the scsi host number.
120 * And if the user plugs or unplugs a usb storage device after bringing up the
121 * NAS:USB support page, the numbers won't match anymore, since "part#"s
122 * may be added or deleted to the /dev/discs* or /dev/scsi**.
124 * But since we only need to support the devices list and mount/unmount
125 * functionality on the host level, the host# shoudl work ok. Just make sure
126 * to always pass and use the _host#_, and not the disc#.
128 void asp_usbdevices(int argc, char **argv)
130 DIR *usb_dir;
131 struct dirent *dp;
132 uint host_no;
133 int last_hn = -1;
134 char *p, *p1;
135 int i = 0, mounted;
136 FILE *fp;
137 char line[128];
138 char *tmp, *js_vend, *js_prod;
139 char g_usb_vendor[30], g_usb_product[30];
141 web_puts("\nusbdev = [");
143 if (!nvram_match("usb_enable", "1")) {
144 web_puts("];\n");
145 return;
148 /* find all attached USB storage devices */
149 #if 1 // NZ = Get the info from the SCSI subsystem.
150 fp = fopen(PROC_SCSI_ROOT"/scsi", "r");
151 if (fp) {
152 while (fgets(line, sizeof(line), fp) != NULL) {
153 p = strstr(line, "Host: scsi");
154 if (p) {
155 host_no = atoi(p + 10);
156 if (host_no == last_hn)
157 continue;
158 last_hn = host_no;
159 if (fgets(line, sizeof(line), fp) != NULL) {
160 memset(g_usb_vendor, 0, sizeof(g_usb_vendor));
161 memset(g_usb_product, 0, sizeof(g_usb_product));
162 p = strstr(line, " Vendor: ");
163 p1 = strstr(line + 10 + 8, " Model: ");
164 if (p && p1) {
165 strncpy(g_usb_vendor, p + 10, 8);
166 strncpy(g_usb_product, p1 + 8, 16);
167 js_vend = js_string(g_usb_vendor);
168 js_prod = js_string(g_usb_product);
169 web_printf("%s['Storage','%d','%s','%s','', [", i ? "," : "",
170 host_no, js_vend ? : "", js_prod ? : "");
171 free(js_vend);
172 free(js_prod);
173 mounted = is_host_mounted(host_no, 1);
174 web_printf("], %d]", mounted);
175 ++i;
180 fclose(fp);
182 #else // Get the info from the usb/storage subsystem.
183 DIR *scsi_dir;
184 struct dirent *scsi_dirent;
185 char *g_usb_serial[30];
186 int attached;
188 scsi_dir = opendir(PROC_SCSI_ROOT);
189 while (scsi_dir && (scsi_dirent = readdir(scsi_dir)))
191 if (!strncmp(USB_STORAGE, scsi_dirent->d_name, strlen(USB_STORAGE)))
193 sprintf(line, "%s/%s", PROC_SCSI_ROOT, scsi_dirent->d_name);
194 usb_dir = opendir(line);
195 while (usb_dir && (dp = readdir(usb_dir)))
197 if (!strcmp(dp->d_name, "..") || !strcmp(dp->d_name, "."))
198 continue;
199 sprintf(line, "%s/%s/%s", PROC_SCSI_ROOT, scsi_dirent->d_name, dp->d_name);
201 fp = fopen(line, "r");
202 if (fp) {
203 attached = 0;
204 g_usb_vendor[0] = 0;
205 g_usb_product[0] = 0;
206 g_usb_serial[0] = 0;
207 tmp = NULL;
209 while (fgets(line, sizeof(line), fp) != NULL) {
210 if (strstr(line, "Attached: Yes")) {
211 attached = 1;
213 else if (strstr(line, "Vendor")) {
214 tmp = strtok(line, " ");
215 tmp = strtok(NULL, "\n");
216 strncpy(g_usb_vendor, tmp, sizeof(g_usb_vendor) - 1);
217 tmp = NULL;
219 else if (strstr(line, "Product")) {
220 tmp = strtok(line, " ");
221 tmp = strtok(NULL, "\n");
222 strncpy(g_usb_product, tmp, sizeof(g_usb_product) - 1);
223 tmp = NULL;
225 else if (strstr(line, "Serial Number")) {
226 tmp = strtok(line, " ");
227 tmp = strtok(NULL, " ");
228 tmp = strtok(NULL, "\n");
229 strncpy(g_usb_serial, tmp, sizeof(g_usb_serial) - 1);
230 tmp = NULL;
233 fclose(fp);
234 #ifdef LINUX26
235 attached = (strlen(g_usb_product) > 0) || (strlen(g_usb_vendor) > 0);
236 #endif
237 if (attached) {
238 /* Host no. assigned by scsi driver for this UFD */
239 host_no = atoi(dp->d_name);
240 js_vend = js_string(g_usb_vendor);
241 js_prod = js_string(g_usb_product);
242 web_printf("%s['Storage','%d','%s','%s','%s', [", i ? "," : "",
243 host_no, js_vend ? : "", js_prod ? : "", g_usb_serial);
244 free(js_vend);
245 free(js_prod);
246 mounted = is_host_mounted(host_no, 1);
247 web_printf("], %d]", mounted);
248 ++i;
253 if (usb_dir)
254 closedir(usb_dir);
257 if (scsi_dir)
258 closedir(scsi_dir);
259 #endif
261 /* now look for printers */
262 usb_dir = opendir("/proc/usblp");
263 while (usb_dir && (dp = readdir(usb_dir)))
265 if (!strcmp(dp->d_name, "..") || !strcmp(dp->d_name, "."))
266 continue;
268 sprintf(line, "/proc/usblp/%s", dp->d_name);
269 if ((fp = fopen(line, "r"))) {
270 g_usb_vendor[0] = 0;
271 g_usb_product[0] = 0;
272 tmp = NULL;
274 while (fgets(line, sizeof(line), fp) != NULL) {
275 if (strstr(line, "Manufacturer")) {
276 tmp = strtok(line, "=");
277 tmp = strtok(NULL, "\n");
278 strncpy(g_usb_vendor, tmp, sizeof(g_usb_vendor) - 1);
279 tmp = NULL;
281 else if (strstr(line, "Model")) {
282 tmp = strtok(line, "=");
283 tmp = strtok(NULL, "\n");
284 strncpy(g_usb_product, tmp, sizeof(g_usb_product) - 1);
285 tmp = NULL;
288 if ((strlen(g_usb_product) > 0) || (strlen(g_usb_vendor) > 0)) {
289 js_vend = js_string(g_usb_vendor);
290 js_prod = js_string(g_usb_product);
291 web_printf("%s['Printer','%s','%s','%s','']", i ? "," : "",
292 dp->d_name, js_vend ? : "", js_prod ? : "");
293 free(js_vend);
294 free(js_prod);
295 ++i;
298 fclose(fp);
301 if (usb_dir)
302 closedir(usb_dir);
304 web_puts("];\n");
307 void wo_usbcommand(char *url)
309 char *p;
310 int add = 0;
312 web_puts("\nusb = [\n");
313 if ((p = webcgi_get("remove")) != NULL) {
314 add = 0;
316 else if ((p = webcgi_get("mount")) != NULL) {
317 add = 1;
319 if (p) {
320 add_remove_usbhost(p, add);
321 web_printf("%d", is_host_mounted(atoi(p), 0));
323 web_puts("];\n");