[PATCH] Fix missing sysfs vendor/model entries for some devices
Brought to you by:
aeb,
bencollins
From: Adam G. <ad...@po...> - 2023-11-26 10:56:47
|
Hi, When the Sony DVMC-DA1 is connected, /sys/bus/firewire/devices/fw1/ has a vendor entry, but is missing vendor_name, model, and model_name. This is the DVMC-DA1's config ROM: 00000000: fbe7 1e04 3439 3331 0040 64e0 0346 0008 ....4931.@d..F.. 00000010: 3c19 1400 81b6 0600 4600 0803 c083 000c <.......F....... 00000020: 0a00 008d 0300 00d1 0500 00c3 0a00 0081 ................ 00000030: bfcd 0200 2da0 0012 0000 0113 fe0c 0200 ....-........... 00000040: 0000 fa17 0800 0081 6ec6 0200 0346 0008 ........n....F.. 00000050: 3c19 1400 269e 0300 0000 0000 0000 0000 <...&........... 00000060: 796e 6f53 1d00 0500 0000 0000 0000 0000 ynoS............ 00000070: 434d 5644 3141 442d 0000 0000 CMVD1AD-.... Note that the root directory contains two entries for vendor. The first is a Vendor_ID immediate value, and the second is a Vendor_Info directory. The descriptor for vendor_name is after the Vendor_Info entry. However, search_leaf compares the directory entry high byte against the desired key_id without masking off the type bits, so it doesn't recognize the Vendor_Info entry. Also, the model and model_name are not in the root directory, but instead are in the vendor directory. search_leaf and show_immediate don't see these, because they only search the root directory. The following patch fixes the above problems. The new behavior is conformant with Annex A of 1394TA Document 1999027, Configuration ROM for AV/C Devices 1.0: "Some legacy devices may have their Model_IDs and textual descriptors in minimal ASCII subset in their vendor directories. It is recommended for a controller to read the Model_ID and its descriptor in the vendor directory of a target only if the Model_ID and its descriptor are not present in the root directory of the target." In addition to the DVMC-DA1, other devices are also affected. This patch also fixes the missing sysfs entries for the Sony DCR-TRV120 and Panasonic AG-DV1DC. The Sony DCR-TRV310 has been reported to have the same problem and should be fixed by the patch, but I don't have one for testing. --- core-device.c.orig 2023-09-23 02:11:13.000000000 -0700 +++ core-device.c 2023-11-25 20:58:02.000000000 -0800 @@ -54,13 +54,19 @@ fw_csr_iterator_init(&ci, directory); while (fw_csr_iterator_next(&ci, &key, &value)) { - if (last_key == search_key && + if ((last_key & 0x3f) == search_key && key == (CSR_DESCRIPTOR | CSR_LEAF)) return ci.p - 1 + value; last_key = key; } + /* Not in root directory, check vendor directory if present */ + fw_csr_iterator_init(&ci, directory); + while (fw_csr_iterator_next(&ci, &key, &value)) + if (key == (CSR_VENDOR | CSR_DIRECTORY)) + return search_leaf(ci.p - 1 + value, search_key); + return NULL; } @@ -245,14 +251,32 @@ u32 key; }; +static int search_immediate(const u32 *directory, int search_key) +{ + struct fw_csr_iterator ci; + int key, value; + + fw_csr_iterator_init(&ci, directory); + while (fw_csr_iterator_next(&ci, &key, &value)) + if (key == search_key) + return value; + + /* Not in root directory, check vendor directory if present */ + fw_csr_iterator_init(&ci, directory); + while (fw_csr_iterator_next(&ci, &key, &value)) + if (key == (CSR_VENDOR | CSR_DIRECTORY)) + return search_immediate(ci.p - 1 + value, search_key); + + return -1; +} + static ssize_t show_immediate(struct device *dev, struct device_attribute *dattr, char *buf) { struct config_rom_attribute *attr = container_of(dattr, struct config_rom_attribute, attr); - struct fw_csr_iterator ci; const u32 *dir; - int key, value, ret = -ENOENT; + int value, ret = -ENOENT; down_read(&fw_device_rwsem); @@ -261,13 +285,9 @@ else dir = fw_device(dev)->config_rom + 5; - fw_csr_iterator_init(&ci, dir); - while (fw_csr_iterator_next(&ci, &key, &value)) - if (attr->key == key) { - ret = snprintf(buf, buf ? PAGE_SIZE : 0, - "0x%06x\n", value); - break; - } + value = search_immediate(dir, attr->key); + if (value != -1) + ret = snprintf(buf, buf ? PAGE_SIZE : 0, "0x%06x\n", value); up_read(&fw_device_rwsem); |