]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blob - src/hwinfo/src/hd/usb.c
Kleiner netter neuer Versuch.
[people/pmueller/ipfire-2.x.git] / src / hwinfo / src / hd / usb.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <unistd.h>
5 #include <fcntl.h>
6 #include <errno.h>
7 #include <sys/stat.h>
8 #include <sys/types.h>
9 #include <sys/ioctl.h>
10
11 #include "hd.h"
12 #include "hd_int.h"
13 #include "hddb.h"
14 #include "usb.h"
15
16 /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
17 * usb
18 *
19 * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
20 */
21
22 #define IOCNR_GET_DEVICE_ID 1
23 #define IOCNR_GET_BUS_ADDRESS 5
24 #define IOCNR_GET_VID_PID 6
25
26 /* Get device_id string: */
27 #define LPIOC_GET_DEVICE_ID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_DEVICE_ID, len)
28 /* Get two-int array: [0]=bus number, [1]=device address: */
29 #define LPIOC_GET_BUS_ADDRESS(len) _IOC(_IOC_READ, 'P', IOCNR_GET_BUS_ADDRESS, len)
30 /* Get two-int array: [0]=vendor ID, [1]=product ID: */
31 #define LPIOC_GET_VID_PID(len) _IOC(_IOC_READ, 'P', IOCNR_GET_VID_PID, len)
32
33
34 static void get_usb_devs(hd_data_t *hd_data);
35 static void set_class_entries(hd_data_t *hd_data, hd_t *hd, usb_t *usb);
36 static void get_input_devs(hd_data_t *hd_data);
37 static void get_printer_devs(hd_data_t *hd_data);
38 static void read_usb_lp(hd_data_t *hd_data, hd_t *hd);
39 static void get_serial_devs(hd_data_t *hd_data);
40
41 void hd_scan_sysfs_usb(hd_data_t *hd_data)
42 {
43 if(!hd_probe_feature(hd_data, pr_usb)) return;
44
45 hd_data->module = mod_usb;
46
47 /* some clean-up */
48 remove_hd_entries(hd_data);
49 hd_data->proc_usb = free_str_list(hd_data->proc_usb);
50 hd_data->usb = NULL;
51
52 PROGRESS(1, 0, "sysfs drivers");
53
54 hd_sysfs_driver_list(hd_data);
55
56 PROGRESS(2, 0, "usb");
57
58 get_usb_devs(hd_data);
59
60 PROGRESS(3, 1, "joydev mod");
61 load_module(hd_data, "joydev");
62
63 PROGRESS(3, 2, "evdev mod");
64 load_module(hd_data, "evdev");
65
66 PROGRESS(3, 3, "input");
67 get_input_devs(hd_data);
68
69 PROGRESS(3, 4, "lp");
70 get_printer_devs(hd_data);
71
72 PROGRESS(3, 5, "serial");
73 get_serial_devs(hd_data);
74
75 }
76
77
78 void get_usb_devs(hd_data_t *hd_data)
79 {
80 uint64_t ul0;
81 unsigned u1, u2, u3;
82 hd_t *hd, *hd1;
83 usb_t *usb;
84 str_list_t *sl, *usb_devs = NULL;
85 char *s, *s1, *t;
86 hd_res_t *res;
87 size_t l;
88
89 struct sysfs_bus *sf_bus;
90 struct dlist *sf_dev_list;
91 struct sysfs_device *sf_dev;
92 struct sysfs_device *sf_dev_2;
93
94 sf_bus = sysfs_open_bus("usb");
95
96 if(!sf_bus) {
97 ADD2LOG("sysfs: no such bus: usb\n");
98 return;
99 }
100
101 sf_dev_list = sysfs_get_bus_devices(sf_bus);
102
103 if(sf_dev_list) dlist_for_each_data(sf_dev_list, sf_dev, struct sysfs_device) {
104 if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bNumInterfaces"), &ul0, 0)) {
105 add_str_list(&usb_devs, sf_dev->path);
106 ADD2LOG(" usb dev: %s\n", hd_sysfs_id(sf_dev->path));
107 }
108 }
109
110 if(sf_dev_list) dlist_for_each_data(sf_dev_list, sf_dev, struct sysfs_device) {
111 ADD2LOG(
112 " usb device: name = %s, bus_id = %s, bus = %s\n path = %s\n",
113 sf_dev->name,
114 sf_dev->bus_id,
115 sf_dev->bus,
116 hd_sysfs_id(sf_dev->path)
117 );
118
119 if(
120 hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceNumber"), &ul0, 16)
121 ) {
122 hd = add_hd_entry(hd_data, __LINE__, 0);
123
124 hd->detail = new_mem(sizeof *hd->detail);
125 hd->detail->type = hd_detail_usb;
126 hd->detail->usb.data = usb = new_mem(sizeof *usb);
127
128 hd->sysfs_id = new_str(hd_sysfs_id(sf_dev->path));
129 hd->sysfs_bus_id = new_str(sf_dev->bus_id);
130
131 hd->bus.id = bus_usb;
132 hd->func = ul0;
133
134 usb->ifdescr = ul0;
135
136 ADD2LOG(" bInterfaceNumber = %u\n", hd->func);
137
138 if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceClass"), &ul0, 16)) {
139 usb->i_cls = ul0;
140 ADD2LOG(" bInterfaceClass = %u\n", usb->i_cls);
141 }
142
143 if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceSubClass"), &ul0, 16)) {
144 usb->i_sub = ul0;
145 ADD2LOG(" bInterfaceSubClass = %u\n", usb->i_sub);
146 }
147
148 if(hd_attr_uint(sysfs_get_device_attr(sf_dev, "bInterfaceProtocol"), &ul0, 16)) {
149 usb->i_prot = ul0;
150 ADD2LOG(" bInterfaceProtocol = %u\n", usb->i_prot);
151 }
152
153 /* device has longest matching sysfs id */
154 u2 = strlen(sf_dev->path);
155 s = NULL;
156 for(u3 = 0, sl = usb_devs; sl; sl = sl->next) {
157 u1 = strlen(sl->str);
158 if(u1 > u3 && u1 <= u2 && !strncmp(sf_dev->path, sl->str, u1)) {
159 u3 = u1;
160 s = sl->str;
161 }
162 }
163
164 if(s) {
165 ADD2LOG(" if: %s @ %s\n", hd->sysfs_bus_id, hd_sysfs_id(s));
166 sf_dev_2 = sysfs_open_device_path(s);
167 if(sf_dev_2) {
168
169 if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bDeviceClass"), &ul0, 16)) {
170 usb->d_cls = ul0;
171 ADD2LOG(" bDeviceClass = %u\n", usb->d_cls);
172 }
173
174 if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bDeviceSubClass"), &ul0, 16)) {
175 usb->d_sub = ul0;
176 ADD2LOG(" bDeviceSubClass = %u\n", usb->d_sub);
177 }
178
179 if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bDeviceProtocol"), &ul0, 16)) {
180 usb->d_prot = ul0;
181 ADD2LOG(" bDeviceProtocol = %u\n", usb->d_prot);
182 }
183
184 if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "idVendor"), &ul0, 16)) {
185 usb->vendor = ul0;
186 ADD2LOG(" idVendor = 0x%04x\n", usb->vendor);
187 }
188
189 if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "idProduct"), &ul0, 16)) {
190 usb->device = ul0;
191 ADD2LOG(" idProduct = 0x%04x\n", usb->device);
192 }
193
194 if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "manufacturer")))) {
195 usb->manufact = canon_str(s, strlen(s));
196 ADD2LOG(" manufacturer = \"%s\"\n", usb->manufact);
197 }
198
199 if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "product")))) {
200 usb->product = canon_str(s, strlen(s));
201 ADD2LOG(" product = \"%s\"\n", usb->product);
202 }
203
204 if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "serial")))) {
205 usb->serial = canon_str(s, strlen(s));
206 ADD2LOG(" serial = \"%s\"\n", usb->serial);
207 }
208
209 if(hd_attr_uint(sysfs_get_device_attr(sf_dev_2, "bcdDevice"), &ul0, 16)) {
210 usb->rev = ul0;
211 ADD2LOG(" bcdDevice = %04x\n", usb->rev);
212 }
213
214 if((s = hd_attr_str(sysfs_get_device_attr(sf_dev_2, "speed")))) {
215 s = canon_str(s, strlen(s));
216 if(strcmp(s, "1.5")) usb->speed = 15*100000;
217 else if(strcmp(s, "12")) usb->speed = 12*1000000;
218 else if(strcmp(s, "240")) usb->speed = 240*1000000;
219 ADD2LOG(" speed = \"%s\"\n", s);
220 s = free_mem(s);
221 }
222
223 sysfs_close_device(sf_dev_2);
224 }
225 }
226
227 if(usb->vendor || usb->device) {
228 hd->vendor.id = MAKE_ID(TAG_USB, usb->vendor);
229 hd->device.id = MAKE_ID(TAG_USB, usb->device);
230 }
231
232 if(usb->manufact) hd->vendor.name = new_str(usb->manufact);
233 if(usb->product) hd->device.name = new_str(usb->product);
234 if(usb->serial) hd->serial = new_str(usb->serial);
235
236 if(usb->rev) str_printf(&hd->revision.name, 0, "%x.%02x", usb->rev >> 8, usb->rev & 0xff);
237
238 if(usb->speed) {
239 res = add_res_entry(&hd->res, new_mem(sizeof *res));
240 res->baud.type = res_baud;
241 res->baud.speed = usb->speed;
242 }
243
244 s = hd_sysfs_find_driver(hd_data, hd->sysfs_id, 1);
245 if(s) add_str_list(&hd->drivers, s);
246
247 set_class_entries(hd_data, hd, usb);
248
249 if(!hd_data->scanner_db) {
250 hd_data->scanner_db = hd_module_list(hd_data, 1);
251 }
252
253 if(
254 hd->drivers &&
255 search_str_list(hd_data->scanner_db, hd->drivers->str)
256 ) {
257 hd->base_class.id = bc_scanner;
258 }
259
260 // ###### FIXME
261 if(hd->base_class.id == bc_modem) {
262 hd->unix_dev_name = new_str("/dev/ttyACM0");
263 }
264
265 }
266 }
267
268 sysfs_close_bus(sf_bus);
269
270 /* connect usb devices to each other */
271 for(hd = hd_data->hd; hd; hd = hd->next) {
272 if(hd->module == hd_data->module && hd->sysfs_id) {
273
274 s = new_str(hd->sysfs_id);
275 t = strrchr(s, '/');
276 if(t) *t = 0;
277
278 /* parent has longest matching sysfs id */
279 u2 = strlen(s);
280 for(u3 = 0, hd1 = hd_data->hd; hd1; hd1 = hd1->next) {
281 if(hd1->sysfs_id) {
282 s1 = new_str(hd1->sysfs_id);
283
284 if(hd1->module == hd_data->module) {
285 t = strrchr(s1, ':');
286 if(t) *t = 0;
287 l = strlen(s1);
288 if(l > 2 && s1[l-2] == '-' && s1[l-1] == '0') {
289 /* root hub */
290 s1[l-2] = 0 ;
291 }
292 }
293
294 u1 = strlen(s1);
295 if(u1 > u3 && u1 <= u2 && !strncmp(s, s1, u1)) {
296 u3 = u1;
297 hd->attached_to = hd1->idx;
298 }
299
300 s1 = free_mem(s1);
301 }
302 }
303
304 s = free_mem(s);
305 }
306 }
307
308 /* remove some entries */
309 for(hd = hd_data->hd; hd; hd = hd->next) {
310 if(
311 hd->module == hd_data->module &&
312 hd->sysfs_id &&
313 !hd->tag.remove
314 ) {
315
316 s = new_str(hd->sysfs_id);
317 t = strrchr(s, ':');
318 if(t) *t = 0;
319
320 for(hd1 = hd_data->hd; hd1; hd1 = hd1->next) {
321 if(
322 hd1 != hd &&
323 hd1->module == hd_data->module &&
324 hd1->sysfs_id &&
325 !hd1->tag.remove &&
326 hd1->base_class.id == hd->base_class.id
327 ) {
328
329 s1 = new_str(hd1->sysfs_id);
330 t = strrchr(s1, ':');
331 if(t) *t = 0;
332
333 /* same usb device */
334 if(!strcmp(s, s1)) {
335 hd1->tag.remove = 1;
336 ADD2LOG("removed: %s\n", hd1->sysfs_id);
337 }
338
339 s1 = free_mem(s1);
340 }
341 }
342
343 s = free_mem(s);
344 }
345 }
346
347 remove_tagged_hd_entries(hd_data);
348
349
350 }
351
352
353 void set_class_entries(hd_data_t *hd_data, hd_t *hd, usb_t *usb)
354 {
355 int cls, sub, prot;
356 unsigned u;
357
358 if(usb->d_cls) {
359 cls = usb->d_cls; sub = usb->d_sub; prot = usb->d_prot;
360 }
361 else {
362 cls = usb->i_cls; sub = usb->i_sub; prot = usb->i_prot;
363 }
364
365 switch(cls) {
366 case 2:
367 if(usb->i_sub == 6 && usb->i_prot == 0) {
368 hd->base_class.id = bc_network;
369 hd->sub_class.id = 0x91;
370 }
371 else if(usb->i_sub == 2 && usb->i_prot >= 1 && usb->i_prot <= 6) {
372 hd->base_class.id = bc_modem;
373 }
374 break;
375
376 case 3:
377 if(sub == 1 && prot == 1) {
378 hd->base_class.id = bc_keyboard;
379 hd->sub_class.id = sc_keyboard_kbd;
380 break;
381 }
382 if(sub == 1 && prot == 2) {
383 if(!(
384 (usb->vendor == 0x056a && usb->device == 0x0022) /* Wacom Tablet */
385 // || (usb->vendor == 0x08ca && usb->device == 0x0020) /* AIPTEK APT-6000U tablet */
386 )) {
387 hd->base_class.id = bc_mouse;
388 hd->sub_class.id = sc_mou_usb;
389 hd->compat_vendor.id = MAKE_ID(TAG_SPECIAL, 0x0200);
390 hd->compat_device.id = MAKE_ID(TAG_SPECIAL, 0x001);
391 }
392 break;
393 }
394 break;
395
396 case 6:
397 if(sub == 1 && prot == 1) { /* PTP camera */
398 hd->base_class.id = bc_camera;
399 hd->sub_class.id = sc_camera_digital;
400 break;
401 }
402 break;
403
404 case 7:
405 hd->base_class.id = bc_printer;
406 break;
407
408 case 8:
409 hd->base_class.id = bc_storage_device;
410 switch(sub) {
411 case 1: /* flash devices & removable media */
412 case 5:
413 case 6:
414 hd->sub_class.id = sc_sdev_disk;
415 break;
416 case 2:
417 hd->sub_class.id = sc_sdev_cdrom;
418 break;
419 case 3:
420 hd->sub_class.id = sc_sdev_tape;
421 break;
422 case 4:
423 hd->sub_class.id = sc_sdev_floppy;
424 break;
425 default:
426 hd->sub_class.id = sc_sdev_other;
427 }
428 break;
429
430 case 9:
431 hd->base_class.id = bc_hub;
432 break;
433
434 case 0xe0:
435 if(sub == 1 && prot == 1) {
436 hd->base_class.id = bc_bluetooth;
437 hd->sub_class.id = 0;
438 }
439 break;
440
441 case 0xff:
442 /* hp psc 2100, 2200, 2150, officejet 6100 */
443 if(
444 sub == 0xcc &&
445 (
446 usb->vendor == 0x03f0 &&
447 (
448 usb->device == 0x2811 ||
449 usb->device == 0x2911 ||
450 usb->device == 0x2a11 ||
451 usb->device == 0x2d11
452 )
453 )
454 ) {
455 hd->base_class.id = bc_scanner;
456 hd->sub_class.id = 1;
457 }
458 break;
459 }
460
461 if((u = device_class(hd_data, hd->vendor.id, hd->device.id))) {
462 hd->base_class.id = u >> 8;
463 hd->sub_class.id = u & 0xff;
464 }
465
466 /* FIXME: hack for bt isdn box */
467 if(
468 hd->vendor.id == MAKE_ID(TAG_USB, 0x057c) &&
469 hd->device.id == MAKE_ID(TAG_USB, 0x2200)
470 ) {
471 hd_set_hw_class(hd, hw_bluetooth);
472 }
473
474 }
475
476
477 void get_input_devs(hd_data_t *hd_data)
478 {
479 hd_t *hd;
480 char *s, *t;
481 hd_dev_num_t dev_num;
482 unsigned u1, u2;
483
484 struct sysfs_class *sf_class;
485 struct sysfs_class_device *sf_cdev;
486 struct sysfs_device *sf_dev;
487 struct dlist *sf_cdev_list;
488
489 sf_class = sysfs_open_class("input");
490
491 if(!sf_class) {
492 ADD2LOG("sysfs: no such class: input\n");
493 return;
494 }
495
496 sf_cdev_list = sysfs_get_class_devices(sf_class);
497 if(sf_cdev_list) dlist_for_each_data(sf_cdev_list, sf_cdev, struct sysfs_class_device) {
498 ADD2LOG(
499 " input: name = %s, path = %s\n",
500 sf_cdev->name,
501 hd_sysfs_id(sf_cdev->path)
502 );
503
504 if((s = hd_attr_str(sysfs_get_classdev_attr(sf_cdev, "dev")))) {
505 if(sscanf(s, "%u:%u", &u1, &u2) == 2) {
506 dev_num.type = 'c';
507 dev_num.major = u1;
508 dev_num.minor = u2;
509 dev_num.range = 1;
510 }
511 ADD2LOG(" dev = %u:%u\n", u1, u2);
512 }
513
514 sf_dev = sysfs_get_classdev_device(sf_cdev);
515 if(sf_dev) {
516 s = hd_sysfs_id(sf_dev->path);
517
518 ADD2LOG(
519 " input device: bus = %s, bus_id = %s driver = %s\n path = %s\n",
520 sf_dev->bus,
521 sf_dev->bus_id,
522 sf_dev->driver_name,
523 s
524 );
525
526 for(hd = hd_data->hd; hd; hd = hd->next) {
527 if(
528 hd->module == hd_data->module &&
529 hd->sysfs_id &&
530 s &&
531 !strcmp(s, hd->sysfs_id)
532 ) {
533 t = NULL;
534 str_printf(&t, 0, "/dev/input/%s", sf_cdev->name);
535
536 if(strncmp(sf_cdev->name, "mouse", sizeof "mouse" - 1)) {
537 hd->unix_dev_name = t;
538 hd->unix_dev_num = dev_num;
539 }
540 else {
541 hd->unix_dev_name2 = t;
542 hd->unix_dev_num2 = dev_num;
543
544 dev_num.major = 13;
545 dev_num.minor = 63;
546 hd->unix_dev_name = new_str(DEV_MICE);
547 hd->unix_dev_num = dev_num;
548 }
549 }
550 }
551 }
552 }
553
554 sysfs_close_class(sf_class);
555 }
556
557
558 void get_printer_devs(hd_data_t *hd_data)
559 {
560 hd_t *hd;
561 char *s, *t;
562 hd_dev_num_t dev_num;
563 unsigned u1, u2;
564
565 struct sysfs_class *sf_class;
566 struct sysfs_class_device *sf_cdev;
567 struct sysfs_device *sf_dev;
568 struct dlist *sf_cdev_list;
569
570 sf_class = sysfs_open_class("usb");
571
572 if(!sf_class) {
573 ADD2LOG("sysfs: no such class: usb\n");
574 return;
575 }
576
577 sf_cdev_list = sysfs_get_class_devices(sf_class);
578 if(sf_cdev_list) dlist_for_each_data(sf_cdev_list, sf_cdev, struct sysfs_class_device) {
579 if(strncmp(sf_cdev->name, "lp", 2)) continue;
580
581 ADD2LOG(
582 " usb: name = %s, path = %s\n",
583 sf_cdev->name,
584 hd_sysfs_id(sf_cdev->path)
585 );
586
587 if((s = hd_attr_str(sysfs_get_classdev_attr(sf_cdev, "dev")))) {
588 if(sscanf(s, "%u:%u", &u1, &u2) == 2) {
589 dev_num.type = 'c';
590 dev_num.major = u1;
591 dev_num.minor = u2;
592 dev_num.range = 1;
593 }
594 ADD2LOG(" dev = %u:%u\n", u1, u2);
595 }
596
597 sf_dev = sysfs_get_classdev_device(sf_cdev);
598 if(sf_dev) {
599 s = hd_sysfs_id(sf_dev->path);
600
601 ADD2LOG(
602 " usb device: bus = %s, bus_id = %s driver = %s\n path = %s\n",
603 sf_dev->bus,
604 sf_dev->bus_id,
605 sf_dev->driver_name,
606 s
607 );
608
609 for(hd = hd_data->hd; hd; hd = hd->next) {
610 if(
611 hd->module == hd_data->module &&
612 hd->sysfs_id &&
613 s &&
614 !strcmp(s, hd->sysfs_id)
615 ) {
616 t = NULL;
617 str_printf(&t, 0, "/dev/usb/%s", sf_cdev->name);
618
619 hd->unix_dev_name = t;
620 hd->unix_dev_num = dev_num;
621
622 read_usb_lp(hd_data, hd);
623 }
624 }
625 }
626 }
627
628 sysfs_close_class(sf_class);
629 }
630
631
632 #define MATCH_FIELD(field, var) \
633 if(!strncasecmp(sl->str, field, sizeof field - 1)) var = sl->str + sizeof field - 1
634
635 /*
636 * assign /dev/usb/lp* to usb printers.
637 */
638 void read_usb_lp(hd_data_t *hd_data, hd_t *hd)
639 {
640 char *s;
641 char buf[1024];
642 int fd, two_ints[2];
643 unsigned bus;
644 str_list_t *sl0, *sl;
645 char *vend, *prod, *serial, *descr;
646
647 if((fd = open(hd->unix_dev_name, O_RDWR)) < 0) return;
648
649 if(ioctl(fd, LPIOC_GET_BUS_ADDRESS(sizeof two_ints), two_ints) == -1) {
650 close(fd);
651 return;
652 }
653
654 ADD2LOG(" usb/lp: bus = %d, dev_nr = %d\n", two_ints[0], two_ints[1]);
655 bus = ((two_ints[0] & 0xff) << 8) + (two_ints[1] & 0xff);
656
657 if(ioctl(fd, LPIOC_GET_VID_PID(sizeof two_ints), two_ints) != -1) {
658 /* just for the record */
659 ADD2LOG(" usb/lp: vend = 0x%04x, prod = 0x%04x\n", two_ints[0], two_ints[1]);
660 }
661
662 memset(buf, 0, sizeof buf);
663 if(!ioctl(fd, LPIOC_GET_DEVICE_ID(sizeof buf), buf)) {
664 buf[sizeof buf - 1] = 0;
665 s = canon_str(buf + 2, sizeof buf - 3);
666 ADD2LOG(" usb/lp: \"%s\"\n", s);
667 sl0 = hd_split(';', s);
668 free_mem(s);
669 vend = prod = serial = descr = NULL;
670 for(sl = sl0; sl; sl = sl->next) {
671 MATCH_FIELD("MFG:", vend);
672 MATCH_FIELD("MANUFACTURER:", vend);
673 MATCH_FIELD("MDL:", prod);
674 MATCH_FIELD("MODEL:", prod);
675 MATCH_FIELD("DES:", descr);
676 MATCH_FIELD("DESCRIPTION:", descr);
677 MATCH_FIELD("SERN:", serial);
678 MATCH_FIELD("SERIALNUMBER:", serial);
679 }
680 ADD2LOG(
681 " usb/lp: vend = %s, prod = %s, descr = %s, serial = %s\n",
682 vend ?: "", prod ?: "", descr ?: "", serial ?: ""
683 );
684 if(descr) {
685 str_printf(&hd->model, 0, "%s", descr);
686 }
687 if(vend && prod) {
688 str_printf(&hd->sub_vendor.name, 0, "%s", vend);
689 str_printf(&hd->sub_device.name, 0, "%s", prod);
690 }
691 if(serial && !hd->serial) {
692 hd->serial = new_str(serial);
693 }
694
695 free_str_list(sl0);
696 }
697
698 close(fd);
699 }
700 #undef MATCH_FIELD
701
702
703 void get_serial_devs(hd_data_t *hd_data)
704 {
705 hd_t *hd;
706 char *s, *t;
707 hd_dev_num_t dev_num;
708 unsigned u1, u2;
709
710 struct sysfs_class *sf_class;
711 struct sysfs_class_device *sf_cdev;
712 struct sysfs_device *sf_dev;
713 struct dlist *sf_cdev_list;
714
715 sf_class = sysfs_open_class("tty");
716
717 if(!sf_class) {
718 ADD2LOG("sysfs: no such class: tty\n");
719 return;
720 }
721
722 sf_cdev_list = sysfs_get_class_devices(sf_class);
723 if(sf_cdev_list) dlist_for_each_data(sf_cdev_list, sf_cdev, struct sysfs_class_device) {
724 if(strncmp(sf_cdev->name, "ttyUSB", 6)) continue;
725
726 ADD2LOG(
727 " usb: name = %s, path = %s\n",
728 sf_cdev->name,
729 hd_sysfs_id(sf_cdev->path)
730 );
731
732 if((s = hd_attr_str(sysfs_get_classdev_attr(sf_cdev, "dev")))) {
733 if(sscanf(s, "%u:%u", &u1, &u2) == 2) {
734 dev_num.type = 'c';
735 dev_num.major = u1;
736 dev_num.minor = u2;
737 dev_num.range = 1;
738 }
739 ADD2LOG(" dev = %u:%u\n", u1, u2);
740 }
741
742 sf_dev = sysfs_get_classdev_device(sf_cdev);
743 if(sf_dev) {
744 s = hd_sysfs_id(sf_dev->path);
745
746 if((t = strrchr(s, '/')) && !strncmp(t + 1, "ttyUSB", sizeof "ttyUSB" - 1)) *t =0;
747
748 ADD2LOG(
749 " usb device: bus = %s, bus_id = %s driver = %s\n path = %s\n",
750 sf_dev->bus,
751 sf_dev->bus_id,
752 sf_dev->driver_name,
753 s
754 );
755
756 for(hd = hd_data->hd; hd; hd = hd->next) {
757 if(
758 hd->module == hd_data->module &&
759 hd->sysfs_id &&
760 s &&
761 !strcmp(s, hd->sysfs_id)
762 ) {
763 t = NULL;
764 str_printf(&t, 0, "/dev/%s", sf_cdev->name);
765
766 hd->unix_dev_name = t;
767 hd->unix_dev_num = dev_num;
768
769 hd->base_class.id = bc_comm;
770 hd->sub_class.id = sc_com_ser;
771 hd->prog_if.id = 0x80;
772 }
773 }
774 }
775 }
776
777 sysfs_close_class(sf_class);
778 }
779
780