aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/dvb-usb/af9015.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/dvb-usb/af9015.c')
-rw-r--r--drivers/media/dvb/dvb-usb/af9015.c363
1 files changed, 197 insertions, 166 deletions
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
index cf042b309b46..74d94e45324d 100644
--- a/drivers/media/dvb/dvb-usb/af9015.c
+++ b/drivers/media/dvb/dvb-usb/af9015.c
@@ -21,6 +21,9 @@
21 * 21 *
22 */ 22 */
23 23
24#include <linux/hash.h>
25#include <linux/slab.h>
26
24#include "af9015.h" 27#include "af9015.h"
25#include "af9013.h" 28#include "af9013.h"
26#include "mt2060.h" 29#include "mt2060.h"
@@ -553,26 +556,45 @@ exit:
553 return ret; 556 return ret;
554} 557}
555 558
556/* dump eeprom */ 559/* hash (and dump) eeprom */
557static int af9015_eeprom_dump(struct dvb_usb_device *d) 560static int af9015_eeprom_hash(struct usb_device *udev)
558{ 561{
559 u8 reg, val; 562 static const unsigned int eeprom_size = 256;
563 unsigned int reg;
564 int ret;
565 u8 val, *eeprom;
566 struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
560 567
561 for (reg = 0; ; reg++) { 568 eeprom = kmalloc(eeprom_size, GFP_KERNEL);
562 if (reg % 16 == 0) { 569 if (eeprom == NULL)
563 if (reg) 570 return -ENOMEM;
564 deb_info(KERN_CONT "\n"); 571
565 deb_info(KERN_DEBUG "%02x:", reg); 572 for (reg = 0; reg < eeprom_size; reg++) {
566 } 573 req.addr = reg;
567 if (af9015_read_reg_i2c(d, AF9015_I2C_EEPROM, reg, &val) == 0) 574 ret = af9015_rw_udev(udev, &req);
568 deb_info(KERN_CONT " %02x", val); 575 if (ret)
569 else 576 goto free;
570 deb_info(KERN_CONT " --"); 577 eeprom[reg] = val;
571 if (reg == 0xff)
572 break;
573 } 578 }
574 deb_info(KERN_CONT "\n"); 579
575 return 0; 580 if (dvb_usb_af9015_debug & 0x01)
581 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom,
582 eeprom_size);
583
584 BUG_ON(eeprom_size % 4);
585
586 af9015_config.eeprom_sum = 0;
587 for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) {
588 af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32;
589 af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]);
590 }
591
592 deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum);
593
594 ret = 0;
595free:
596 kfree(eeprom);
597 return ret;
576} 598}
577 599
578static int af9015_download_ir_table(struct dvb_usb_device *d) 600static int af9015_download_ir_table(struct dvb_usb_device *d)
@@ -711,12 +733,132 @@ error:
711 return ret; 733 return ret;
712} 734}
713 735
736struct af9015_setup {
737 unsigned int id;
738 struct dvb_usb_rc_key *rc_key_map;
739 unsigned int rc_key_map_size;
740 u8 *ir_table;
741 unsigned int ir_table_size;
742};
743
744static const struct af9015_setup *af9015_setup_match(unsigned int id,
745 const struct af9015_setup *table)
746{
747 for (; table->rc_key_map; table++)
748 if (table->id == id)
749 return table;
750 return NULL;
751}
752
753static const struct af9015_setup af9015_setup_modparam[] = {
754 { AF9015_REMOTE_A_LINK_DTU_M,
755 af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
756 af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
757 { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
758 af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
759 af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
760 { AF9015_REMOTE_MYGICTV_U718,
761 af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
762 af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
763 { AF9015_REMOTE_DIGITTRADE_DVB_T,
764 af9015_rc_keys_digittrade, ARRAY_SIZE(af9015_rc_keys_digittrade),
765 af9015_ir_table_digittrade, ARRAY_SIZE(af9015_ir_table_digittrade) },
766 { AF9015_REMOTE_AVERMEDIA_KS,
767 af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
768 af9015_ir_table_avermedia_ks, ARRAY_SIZE(af9015_ir_table_avermedia_ks) },
769 { }
770};
771
772/* don't add new entries here anymore, use hashes instead */
773static const struct af9015_setup af9015_setup_usbids[] = {
774 { USB_VID_LEADTEK,
775 af9015_rc_keys_leadtek, ARRAY_SIZE(af9015_rc_keys_leadtek),
776 af9015_ir_table_leadtek, ARRAY_SIZE(af9015_ir_table_leadtek) },
777 { USB_VID_VISIONPLUS,
778 af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
779 af9015_ir_table_twinhan, ARRAY_SIZE(af9015_ir_table_twinhan) },
780 { USB_VID_KWORLD_2, /* TODO: use correct rc keys */
781 af9015_rc_keys_twinhan, ARRAY_SIZE(af9015_rc_keys_twinhan),
782 af9015_ir_table_kworld, ARRAY_SIZE(af9015_ir_table_kworld) },
783 { USB_VID_AVERMEDIA,
784 af9015_rc_keys_avermedia, ARRAY_SIZE(af9015_rc_keys_avermedia),
785 af9015_ir_table_avermedia, ARRAY_SIZE(af9015_ir_table_avermedia) },
786 { USB_VID_MSI_2,
787 af9015_rc_keys_msi_digivox_iii, ARRAY_SIZE(af9015_rc_keys_msi_digivox_iii),
788 af9015_ir_table_msi_digivox_iii, ARRAY_SIZE(af9015_ir_table_msi_digivox_iii) },
789 { }
790};
791
792static const struct af9015_setup af9015_setup_hashes[] = {
793 { 0xb8feb708,
794 af9015_rc_keys_msi, ARRAY_SIZE(af9015_rc_keys_msi),
795 af9015_ir_table_msi, ARRAY_SIZE(af9015_ir_table_msi) },
796 { 0xa3703d00,
797 af9015_rc_keys_a_link, ARRAY_SIZE(af9015_rc_keys_a_link),
798 af9015_ir_table_a_link, ARRAY_SIZE(af9015_ir_table_a_link) },
799 { 0x9b7dc64e,
800 af9015_rc_keys_mygictv, ARRAY_SIZE(af9015_rc_keys_mygictv),
801 af9015_ir_table_mygictv, ARRAY_SIZE(af9015_ir_table_mygictv) },
802 { }
803};
804
805static void af9015_set_remote_config(struct usb_device *udev,
806 struct dvb_usb_device_properties *props)
807{
808 const struct af9015_setup *table = NULL;
809
810 if (dvb_usb_af9015_remote) {
811 /* load remote defined as module param */
812 table = af9015_setup_match(dvb_usb_af9015_remote,
813 af9015_setup_modparam);
814 } else {
815 u16 vendor = le16_to_cpu(udev->descriptor.idVendor);
816
817 table = af9015_setup_match(af9015_config.eeprom_sum,
818 af9015_setup_hashes);
819
820 if (!table && vendor == USB_VID_AFATECH) {
821 /* Check USB manufacturer and product strings and try
822 to determine correct remote in case of chip vendor
823 reference IDs are used.
824 DO NOT ADD ANYTHING NEW HERE. Use hashes instead.
825 */
826 char manufacturer[10];
827 memset(manufacturer, 0, sizeof(manufacturer));
828 usb_string(udev, udev->descriptor.iManufacturer,
829 manufacturer, sizeof(manufacturer));
830 if (!strcmp("MSI", manufacturer)) {
831 /* iManufacturer 1 MSI
832 iProduct 2 MSI K-VOX */
833 table = af9015_setup_match(
834 AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
835 af9015_setup_modparam);
836 } else if (udev->descriptor.idProduct ==
837 cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
838 table = &(const struct af9015_setup){ 0,
839 af9015_rc_keys_trekstor,
840 ARRAY_SIZE(af9015_rc_keys_trekstor),
841 af9015_ir_table_trekstor,
842 ARRAY_SIZE(af9015_ir_table_trekstor)
843 };
844 }
845 } else if (!table)
846 table = af9015_setup_match(vendor, af9015_setup_usbids);
847 }
848
849 if (table) {
850 props->rc_key_map = table->rc_key_map;
851 props->rc_key_map_size = table->rc_key_map_size;
852 af9015_config.ir_table = table->ir_table;
853 af9015_config.ir_table_size = table->ir_table_size;
854 }
855}
856
714static int af9015_read_config(struct usb_device *udev) 857static int af9015_read_config(struct usb_device *udev)
715{ 858{
716 int ret; 859 int ret;
717 u8 val, i, offset = 0; 860 u8 val, i, offset = 0;
718 struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val}; 861 struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
719 char manufacturer[10];
720 862
721 /* IR remote controller */ 863 /* IR remote controller */
722 req.addr = AF9015_EEPROM_IR_MODE; 864 req.addr = AF9015_EEPROM_IR_MODE;
@@ -728,148 +870,18 @@ static int af9015_read_config(struct usb_device *udev)
728 } 870 }
729 if (ret) 871 if (ret)
730 goto error; 872 goto error;
873
874 ret = af9015_eeprom_hash(udev);
875 if (ret)
876 goto error;
877
731 deb_info("%s: IR mode:%d\n", __func__, val); 878 deb_info("%s: IR mode:%d\n", __func__, val);
732 for (i = 0; i < af9015_properties_count; i++) { 879 for (i = 0; i < af9015_properties_count; i++) {
733 if (val == AF9015_IR_MODE_DISABLED || val == 0x04) { 880 if (val == AF9015_IR_MODE_DISABLED) {
734 af9015_properties[i].rc_key_map = NULL; 881 af9015_properties[i].rc_key_map = NULL;
735 af9015_properties[i].rc_key_map_size = 0; 882 af9015_properties[i].rc_key_map_size = 0;
736 } else if (dvb_usb_af9015_remote) { 883 } else
737 /* load remote defined as module param */ 884 af9015_set_remote_config(udev, &af9015_properties[i]);
738 switch (dvb_usb_af9015_remote) {
739 case AF9015_REMOTE_A_LINK_DTU_M:
740 af9015_properties[i].rc_key_map =
741 af9015_rc_keys_a_link;
742 af9015_properties[i].rc_key_map_size =
743 ARRAY_SIZE(af9015_rc_keys_a_link);
744 af9015_config.ir_table = af9015_ir_table_a_link;
745 af9015_config.ir_table_size =
746 ARRAY_SIZE(af9015_ir_table_a_link);
747 break;
748 case AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3:
749 af9015_properties[i].rc_key_map =
750 af9015_rc_keys_msi;
751 af9015_properties[i].rc_key_map_size =
752 ARRAY_SIZE(af9015_rc_keys_msi);
753 af9015_config.ir_table = af9015_ir_table_msi;
754 af9015_config.ir_table_size =
755 ARRAY_SIZE(af9015_ir_table_msi);
756 break;
757 case AF9015_REMOTE_MYGICTV_U718:
758 af9015_properties[i].rc_key_map =
759 af9015_rc_keys_mygictv;
760 af9015_properties[i].rc_key_map_size =
761 ARRAY_SIZE(af9015_rc_keys_mygictv);
762 af9015_config.ir_table =
763 af9015_ir_table_mygictv;
764 af9015_config.ir_table_size =
765 ARRAY_SIZE(af9015_ir_table_mygictv);
766 break;
767 case AF9015_REMOTE_DIGITTRADE_DVB_T:
768 af9015_properties[i].rc_key_map =
769 af9015_rc_keys_digittrade;
770 af9015_properties[i].rc_key_map_size =
771 ARRAY_SIZE(af9015_rc_keys_digittrade);
772 af9015_config.ir_table =
773 af9015_ir_table_digittrade;
774 af9015_config.ir_table_size =
775 ARRAY_SIZE(af9015_ir_table_digittrade);
776 break;
777 case AF9015_REMOTE_AVERMEDIA_KS:
778 af9015_properties[i].rc_key_map =
779 af9015_rc_keys_avermedia;
780 af9015_properties[i].rc_key_map_size =
781 ARRAY_SIZE(af9015_rc_keys_avermedia);
782 af9015_config.ir_table =
783 af9015_ir_table_avermedia_ks;
784 af9015_config.ir_table_size =
785 ARRAY_SIZE(af9015_ir_table_avermedia_ks);
786 break;
787 }
788 } else {
789 switch (le16_to_cpu(udev->descriptor.idVendor)) {
790 case USB_VID_LEADTEK:
791 af9015_properties[i].rc_key_map =
792 af9015_rc_keys_leadtek;
793 af9015_properties[i].rc_key_map_size =
794 ARRAY_SIZE(af9015_rc_keys_leadtek);
795 af9015_config.ir_table =
796 af9015_ir_table_leadtek;
797 af9015_config.ir_table_size =
798 ARRAY_SIZE(af9015_ir_table_leadtek);
799 break;
800 case USB_VID_VISIONPLUS:
801 af9015_properties[i].rc_key_map =
802 af9015_rc_keys_twinhan;
803 af9015_properties[i].rc_key_map_size =
804 ARRAY_SIZE(af9015_rc_keys_twinhan);
805 af9015_config.ir_table =
806 af9015_ir_table_twinhan;
807 af9015_config.ir_table_size =
808 ARRAY_SIZE(af9015_ir_table_twinhan);
809 break;
810 case USB_VID_KWORLD_2:
811 /* TODO: use correct rc keys */
812 af9015_properties[i].rc_key_map =
813 af9015_rc_keys_twinhan;
814 af9015_properties[i].rc_key_map_size =
815 ARRAY_SIZE(af9015_rc_keys_twinhan);
816 af9015_config.ir_table = af9015_ir_table_kworld;
817 af9015_config.ir_table_size =
818 ARRAY_SIZE(af9015_ir_table_kworld);
819 break;
820 /* Check USB manufacturer and product strings and try
821 to determine correct remote in case of chip vendor
822 reference IDs are used. */
823 case USB_VID_AFATECH:
824 memset(manufacturer, 0, sizeof(manufacturer));
825 usb_string(udev, udev->descriptor.iManufacturer,
826 manufacturer, sizeof(manufacturer));
827 if (!strcmp("Geniatech", manufacturer)) {
828 /* iManufacturer 1 Geniatech
829 iProduct 2 AF9015 */
830 af9015_properties[i].rc_key_map =
831 af9015_rc_keys_mygictv;
832 af9015_properties[i].rc_key_map_size =
833 ARRAY_SIZE(af9015_rc_keys_mygictv);
834 af9015_config.ir_table =
835 af9015_ir_table_mygictv;
836 af9015_config.ir_table_size =
837 ARRAY_SIZE(af9015_ir_table_mygictv);
838 } else if (!strcmp("MSI", manufacturer)) {
839 /* iManufacturer 1 MSI
840 iProduct 2 MSI K-VOX */
841 af9015_properties[i].rc_key_map =
842 af9015_rc_keys_msi;
843 af9015_properties[i].rc_key_map_size =
844 ARRAY_SIZE(af9015_rc_keys_msi);
845 af9015_config.ir_table =
846 af9015_ir_table_msi;
847 af9015_config.ir_table_size =
848 ARRAY_SIZE(af9015_ir_table_msi);
849 } else if (udev->descriptor.idProduct ==
850 cpu_to_le16(USB_PID_TREKSTOR_DVBT)) {
851 af9015_properties[i].rc_key_map =
852 af9015_rc_keys_trekstor;
853 af9015_properties[i].rc_key_map_size =
854 ARRAY_SIZE(af9015_rc_keys_trekstor);
855 af9015_config.ir_table =
856 af9015_ir_table_trekstor;
857 af9015_config.ir_table_size =
858 ARRAY_SIZE(af9015_ir_table_trekstor);
859 }
860 break;
861 case USB_VID_AVERMEDIA:
862 af9015_properties[i].rc_key_map =
863 af9015_rc_keys_avermedia;
864 af9015_properties[i].rc_key_map_size =
865 ARRAY_SIZE(af9015_rc_keys_avermedia);
866 af9015_config.ir_table =
867 af9015_ir_table_avermedia;
868 af9015_config.ir_table_size =
869 ARRAY_SIZE(af9015_ir_table_avermedia);
870 break;
871 }
872 }
873 } 885 }
874 886
875 /* TS mode - one or two receivers */ 887 /* TS mode - one or two receivers */
@@ -991,6 +1003,9 @@ static int af9015_read_config(struct usb_device *udev)
991 af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO; 1003 af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
992 af9015_af9013_config[i].rf_spec_inv = 1; 1004 af9015_af9013_config[i].rf_spec_inv = 1;
993 break; 1005 break;
1006 case AF9013_TUNER_TDA18218:
1007 warn("tuner NXP TDA18218 not supported yet");
1008 return -ENODEV;
994 default: 1009 default:
995 warn("tuner id:%d not supported, please report!", val); 1010 warn("tuner id:%d not supported, please report!", val);
996 return -ENODEV; 1011 return -ENODEV;
@@ -1115,11 +1130,6 @@ static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
1115 1130
1116 deb_info("%s: init I2C\n", __func__); 1131 deb_info("%s: init I2C\n", __func__);
1117 ret = af9015_i2c_init(adap->dev); 1132 ret = af9015_i2c_init(adap->dev);
1118
1119 /* dump eeprom (debug) */
1120 ret = af9015_eeprom_dump(adap->dev);
1121 if (ret)
1122 return ret;
1123 } else { 1133 } else {
1124 /* select I2C adapter */ 1134 /* select I2C adapter */
1125 i2c_adap = &state->i2c_adap; 1135 i2c_adap = &state->i2c_adap;
@@ -1283,6 +1293,10 @@ static struct usb_device_id af9015_usb_table[] = {
1283 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)}, 1293 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
1284 {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)}, 1294 {USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
1285/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)}, 1295/* 25 */{USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
1296 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
1297 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
1298 {USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
1299 {USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
1286 {0}, 1300 {0},
1287}; 1301};
1288MODULE_DEVICE_TABLE(usb, af9015_usb_table); 1302MODULE_DEVICE_TABLE(usb, af9015_usb_table);
@@ -1296,7 +1310,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1296 .firmware = "dvb-usb-af9015.fw", 1310 .firmware = "dvb-usb-af9015.fw",
1297 .no_reconnect = 1, 1311 .no_reconnect = 1,
1298 1312
1299 .size_of_priv = sizeof(struct af9015_state), \ 1313 .size_of_priv = sizeof(struct af9015_state),
1300 1314
1301 .num_adapters = 2, 1315 .num_adapters = 2,
1302 .adapter = { 1316 .adapter = {
@@ -1369,7 +1383,8 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1369 }, 1383 },
1370 { 1384 {
1371 .name = "DigitalNow TinyTwin DVB-T Receiver", 1385 .name = "DigitalNow TinyTwin DVB-T Receiver",
1372 .cold_ids = {&af9015_usb_table[5], NULL}, 1386 .cold_ids = {&af9015_usb_table[5],
1387 &af9015_usb_table[28], NULL},
1373 .warm_ids = {NULL}, 1388 .warm_ids = {NULL},
1374 }, 1389 },
1375 { 1390 {
@@ -1402,7 +1417,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1402 .firmware = "dvb-usb-af9015.fw", 1417 .firmware = "dvb-usb-af9015.fw",
1403 .no_reconnect = 1, 1418 .no_reconnect = 1,
1404 1419
1405 .size_of_priv = sizeof(struct af9015_state), \ 1420 .size_of_priv = sizeof(struct af9015_state),
1406 1421
1407 .num_adapters = 2, 1422 .num_adapters = 2,
1408 .adapter = { 1423 .adapter = {
@@ -1508,7 +1523,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1508 .firmware = "dvb-usb-af9015.fw", 1523 .firmware = "dvb-usb-af9015.fw",
1509 .no_reconnect = 1, 1524 .no_reconnect = 1,
1510 1525
1511 .size_of_priv = sizeof(struct af9015_state), \ 1526 .size_of_priv = sizeof(struct af9015_state),
1512 1527
1513 .num_adapters = 2, 1528 .num_adapters = 2,
1514 .adapter = { 1529 .adapter = {
@@ -1554,7 +1569,7 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1554 1569
1555 .i2c_algo = &af9015_i2c_algo, 1570 .i2c_algo = &af9015_i2c_algo,
1556 1571
1557 .num_device_descs = 4, /* max 9 */ 1572 .num_device_descs = 7, /* max 9 */
1558 .devices = { 1573 .devices = {
1559 { 1574 {
1560 .name = "AverMedia AVerTV Volar GPS 805 (A805)", 1575 .name = "AverMedia AVerTV Volar GPS 805 (A805)",
@@ -1577,6 +1592,22 @@ static struct dvb_usb_device_properties af9015_properties[] = {
1577 .cold_ids = {&af9015_usb_table[24], NULL}, 1592 .cold_ids = {&af9015_usb_table[24], NULL},
1578 .warm_ids = {NULL}, 1593 .warm_ids = {NULL},
1579 }, 1594 },
1595 {
1596 .name = "KWorld PlusTV DVB-T PCI Pro Card " \
1597 "(DVB-T PC160-T)",
1598 .cold_ids = {&af9015_usb_table[26], NULL},
1599 .warm_ids = {NULL},
1600 },
1601 {
1602 .name = "Sveon STV20 Tuner USB DVB-T HDTV",
1603 .cold_ids = {&af9015_usb_table[27], NULL},
1604 .warm_ids = {NULL},
1605 },
1606 {
1607 .name = "Leadtek WinFast DTV2000DS",
1608 .cold_ids = {&af9015_usb_table[29], NULL},
1609 .warm_ids = {NULL},
1610 },
1580 } 1611 }
1581 }, 1612 },
1582}; 1613};