OLD | NEW |
1 /* Driver for Realtek RTS51xx USB card reader | 1 /* Driver for Realtek RTS51xx USB card reader |
2 * | 2 * |
3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. | 3 * Copyright(c) 2009 Realtek Semiconductor Corp. All rights reserved. |
4 * | 4 * |
5 * This program is free software; you can redistribute it and/or modify it | 5 * This program is free software; you can redistribute it and/or modify it |
6 * under the terms of the GNU General Public License as published by the | 6 * under the terms of the GNU General Public License as published by the |
7 * Free Software Foundation; either version 2, or (at your option) any | 7 * Free Software Foundation; either version 2, or (at your option) any |
8 * later version. | 8 * later version. |
9 * | 9 * |
10 * This program is distributed in the hope that it will be useful, but | 10 * This program is distributed in the hope that it will be useful, but |
(...skipping 26 matching lines...) Expand all Loading... |
37 #include <linux/usb_usual.h> | 37 #include <linux/usb_usual.h> |
38 | 38 |
39 #include "usb.h" | 39 #include "usb.h" |
40 #include "transport.h" | 40 #include "transport.h" |
41 #include "protocol.h" | 41 #include "protocol.h" |
42 #include "debug.h" | 42 #include "debug.h" |
43 | 43 |
44 MODULE_DESCRIPTION("Driver for Realtek USB Card Reader"); | 44 MODULE_DESCRIPTION("Driver for Realtek USB Card Reader"); |
45 MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>"); | 45 MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>"); |
46 MODULE_LICENSE("GPL"); | 46 MODULE_LICENSE("GPL"); |
| 47 MODULE_VERSION("1.02"); |
47 | 48 |
48 static int ss_en = 1; | 49 static int ss_en = 1; |
49 module_param(ss_en, int, S_IRUGO | S_IWUSR); | 50 module_param(ss_en, int, S_IRUGO | S_IWUSR); |
50 MODULE_PARM_DESC(ss_en, "enable selective suspend"); | 51 MODULE_PARM_DESC(ss_en, "enable selective suspend"); |
51 | 52 |
52 static int ss_delay = 20; | 53 static int ss_delay = 50; |
53 module_param(ss_delay, int, S_IRUGO | S_IWUSR); | 54 module_param(ss_delay, int, S_IRUGO | S_IWUSR); |
54 MODULE_PARM_DESC(ss_delay, "seconds to delay before entering selective suspend")
; | 55 MODULE_PARM_DESC(ss_delay, "seconds to delay before entering selective suspend")
; |
55 | 56 |
56 static int needs_remote_wakeup = 0; | 57 static int needs_remote_wakeup = 0; |
57 module_param(needs_remote_wakeup, int, S_IRUGO | S_IWUSR); | 58 module_param(needs_remote_wakeup, int, S_IRUGO | S_IWUSR); |
58 MODULE_PARM_DESC(needs_remote_wakeup, "ss state needs remote wakeup supported"); | 59 MODULE_PARM_DESC(needs_remote_wakeup, "ss state needs remote wakeup supported"); |
59 | 60 |
60 static int auto_delink_en = 1; | 61 static int auto_delink_en = 1; |
61 module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); | 62 module_param(auto_delink_en, int, S_IRUGO | S_IWUSR); |
62 MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); | 63 MODULE_PARM_DESC(auto_delink_en, "enable auto delink"); |
63 | 64 |
64 enum CHIP_STAT» {STAT_INIT, STAT_IDLE, STAT_RUN, STAT_SS_PRE, STAT_SS}; | 65 enum CHIP_STAT» {STAT_INIT, STAT_IDLE, STAT_RUN, STAT_SS_PRE, STAT_SS, STAT_SUSP
END}; |
65 | 66 |
66 struct rts51x_status { | 67 struct rts51x_status { |
67 u16 vid; | 68 u16 vid; |
68 u16 pid; | 69 u16 pid; |
69 u8 cur_lun; | 70 u8 cur_lun; |
70 u8 card_type; | 71 u8 card_type; |
71 u8 total_lun; | 72 u8 total_lun; |
72 u16 fw_ver; | 73 u16 fw_ver; |
73 u8 phy_exist; | 74 u8 phy_exist; |
74 u8 multi_flag; | 75 u8 multi_flag; |
75 u8 multi_card; | 76 u8 multi_card; |
76 u8 log_exist; | 77 u8 log_exist; |
77 union { | 78 union { |
78 u8 detailed_type1; | 79 u8 detailed_type1; |
79 u8 detailed_type2; | 80 u8 detailed_type2; |
80 } detailed_type; | 81 } detailed_type; |
81 u8 function[2]; | 82 u8 function[2]; |
82 }; | 83 }; |
83 | 84 |
84 struct rts51x_chip { | 85 struct rts51x_chip { |
85 u16 vendor_id; | 86 u16 vendor_id; |
86 u16 product_id; | 87 u16 product_id; |
87 char max_lun; | 88 char max_lun; |
88 | 89 |
89 int ss_counter; | 90 int ss_counter; |
90 int idle_counter; | 91 int idle_counter; |
91 enum CHIP_STAT chip_stat; | 92 enum CHIP_STAT chip_stat; |
92 | 93 |
| 94 int resume_from_scsi; |
| 95 |
93 struct rts51x_status *status; | 96 struct rts51x_status *status; |
94 int status_len; | 97 int status_len; |
95 u8 lun_ready; | 98 u8 lun_ready; |
96 | 99 |
97 u32 flag; | 100 u32 flag; |
98 | 101 |
99 struct task_struct *polling_thread; /* the polling thread */ | 102 struct task_struct *polling_thread; /* the polling thread */ |
100 }; | 103 }; |
101 | 104 |
102 // flag definition | 105 // flag definition |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 { | 418 { |
416 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); | 419 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); |
417 int retval; | 420 int retval; |
418 u8 buf[16]; | 421 u8 buf[16]; |
419 | 422 |
420 retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len)); | 423 retval = rts51x_read_status(us, lun, buf, 16, &(chip->status_len)); |
421 if (retval < 0) { | 424 if (retval < 0) { |
422 return -EIO; | 425 return -EIO; |
423 } | 426 } |
424 | 427 |
| 428 US_DEBUGP("chip->status_len = %d\n", chip->status_len); |
| 429 |
425 chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1]; | 430 chip->status[lun].vid = ((u16)buf[0] << 8) | buf[1]; |
426 chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3]; | 431 chip->status[lun].pid = ((u16)buf[2] << 8) | buf[3]; |
427 chip->status[lun].cur_lun = buf[4]; | 432 chip->status[lun].cur_lun = buf[4]; |
428 chip->status[lun].card_type = buf[5]; | 433 chip->status[lun].card_type = buf[5]; |
429 chip->status[lun].total_lun = buf[6]; | 434 chip->status[lun].total_lun = buf[6]; |
430 chip->status[lun].fw_ver = ((u16)buf[7] << 8) | buf[8]; | 435 chip->status[lun].fw_ver = ((u16)buf[7] << 8) | buf[8]; |
431 chip->status[lun].phy_exist = buf[9]; | 436 chip->status[lun].phy_exist = buf[9]; |
432 chip->status[lun].multi_flag = buf[10]; | 437 chip->status[lun].multi_flag = buf[10]; |
433 chip->status[lun].multi_card = buf[11]; | 438 chip->status[lun].multi_card = buf[11]; |
434 chip->status[lun].log_exist = buf[12]; | 439 chip->status[lun].log_exist = buf[12]; |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
648 } | 653 } |
649 } | 654 } |
650 } | 655 } |
651 | 656 |
652 return 0; | 657 return 0; |
653 } | 658 } |
654 | 659 |
655 static void rts51x_polling_func(struct us_data *us) | 660 static void rts51x_polling_func(struct us_data *us) |
656 { | 661 { |
657 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); | 662 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); |
| 663 |
| 664 /* lock the device pointers */ |
| 665 mutex_lock(&(us->dev_mutex)); |
658 | 666 |
659 if (RTS51X_CHK_STAT(chip, STAT_SS) || RTS51X_CHK_STAT(chip, STAT_SS_PRE)
) { | 667 if (RTS51X_CHK_STAT(chip, STAT_SS) || RTS51X_CHK_STAT(chip, STAT_SS_PRE)
) { |
| 668 /* unlock the device pointers */ |
| 669 mutex_unlock(&(us->dev_mutex)); |
660 return; | 670 return; |
661 } | 671 } |
662 | 672 |
663 #ifdef CONFIG_PM | 673 #ifdef CONFIG_PM |
664 if (ss_en) { | 674 if (ss_en) { |
665 if (RTS51X_CHK_STAT(chip, STAT_IDLE)) { | 675 if (RTS51X_CHK_STAT(chip, STAT_IDLE)) { |
666 if (chip->ss_counter < (ss_delay * 1000 / POLLING_INTERV
AL)) { | 676 if (chip->ss_counter < (ss_delay * 1000 / POLLING_INTERV
AL)) { |
667 chip->ss_counter ++; | 677 chip->ss_counter ++; |
668 } else { | 678 } else { |
669 US_DEBUGP("Ready to enter SS state\n"); | 679 US_DEBUGP("Ready to enter SS state\n"); |
670 RTS51X_SET_STAT(chip, STAT_SS_PRE); // Prepare
SS state | 680 RTS51X_SET_STAT(chip, STAT_SS_PRE); // Prepare
SS state |
| 681 |
| 682 /* unlock the device pointers */ |
| 683 mutex_unlock(&(us->dev_mutex)); |
671 usb_autopm_enable(us->pusb_intf); | 684 usb_autopm_enable(us->pusb_intf); |
672 return; | 685 return; |
673 } | 686 } |
674 } else { | 687 } else { |
675 chip->ss_counter = 0; | 688 chip->ss_counter = 0; |
676 } | 689 } |
677 } | 690 } |
678 #endif | 691 #endif |
679 | 692 |
680 if (chip->idle_counter < IDLE_MAX_COUNT) { | 693 if (chip->idle_counter < IDLE_MAX_COUNT) { |
681 chip->idle_counter ++; | 694 chip->idle_counter ++; |
682 } else { | 695 } else { |
683 if (!RTS51X_CHK_STAT(chip, STAT_IDLE)) { | 696 if (!RTS51X_CHK_STAT(chip, STAT_IDLE)) { |
684 US_DEBUGP("Idle state\n"); | 697 US_DEBUGP("Idle state\n"); |
685 RTS51X_SET_STAT(chip, STAT_IDLE); | 698 RTS51X_SET_STAT(chip, STAT_IDLE); |
686 } | 699 } |
687 } | 700 } |
688 | 701 |
689 » switch (RTS51X_GET_STAT(chip)) { | 702 » /* unlock the device pointers */ |
690 » case STAT_RUN: | 703 » mutex_unlock(&(us->dev_mutex)); |
691 » » break; | |
692 | |
693 » case STAT_IDLE: | |
694 » » break; | |
695 | |
696 » default: | |
697 » » break; | |
698 » } | |
699 } | 704 } |
700 | 705 |
701 static int rts51x_polling_thread(void * __us) | 706 static int rts51x_polling_thread(void * __us) |
702 { | 707 { |
703 struct us_data *us = (struct us_data *)__us; | 708 struct us_data *us = (struct us_data *)__us; |
704 | 709 |
705 // Wait until SCSI scan finished | 710 // Wait until SCSI scan finished |
706 wait_timeout(10 * HZ); | 711 wait_timeout(10 * HZ); |
707 | 712 |
708 for(;;) { | 713 for(;;) { |
709 wait_timeout(POLLING_INTERVAL); | 714 wait_timeout(POLLING_INTERVAL); |
710 | 715 |
711 /* if the device has disconnected, we are free to exit */ | 716 /* if the device has disconnected, we are free to exit */ |
712 if (kthread_should_stop()) { | 717 if (kthread_should_stop()) { |
713 printk(KERN_INFO "Stop polling thread!\n"); | 718 printk(KERN_INFO "Stop polling thread!\n"); |
714 break; | 719 break; |
715 } | 720 } |
716 | 721 |
717 /* lock the device pointers */ | |
718 mutex_lock(&(us->dev_mutex)); | |
719 | |
720 rts51x_polling_func(us); | 722 rts51x_polling_func(us); |
721 » » | 723 |
722 » » /* unlock the device pointers */ | |
723 » » mutex_unlock(&(us->dev_mutex)); | |
724 } /* for (;;) */ | 724 } /* for (;;) */ |
725 | 725 |
726 __set_current_state(TASK_RUNNING); | 726 __set_current_state(TASK_RUNNING); |
727 return 0; | 727 return 0; |
728 } | 728 } |
729 | 729 |
730 #ifdef CONFIG_PM | 730 #ifdef CONFIG_PM |
731 static void rts51x_handle_pm(struct us_data *us, int pwr_state) | 731 int realtek_cr_suspend(struct usb_interface *iface, pm_message_t message) |
732 { | 732 { |
| 733 struct us_data *us = usb_get_intfdata(iface); |
733 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); | 734 struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); |
| 735 |
| 736 US_DEBUGP("%s, message.event = 0x%x\n", __func__, message.event); |
734 | 737 |
735 » US_DEBUGP("Handle pm state: %s\n", pwr_state ? "resume" : "suspend"); | 738 » /* Wait until no command is running */ |
| 739 » mutex_lock(&us->dev_mutex); |
| 740 » |
| 741 » if (message.event == PM_EVENT_AUTO_SUSPEND) { |
| 742 » » US_DEBUGP("Enter SS state"); |
| 743 » » chip->resume_from_scsi = 0; |
| 744 » » RTS51X_SET_STAT(chip, STAT_SS); |
| 745 » } else { |
| 746 » » US_DEBUGP("Enter SUSPEND state"); |
| 747 » » RTS51X_SET_STAT(chip, STAT_SUSPEND); |
| 748 » } |
| 749 » (void)config_autodelink_before_power_down(us); |
736 | 750 |
737 » if (pwr_state == US_RESUME) { | 751 » /* When runtime PM is working, we'll set a flag to indicate |
| 752 » * whether we should autoresume when a SCSI request arrives. */ |
| 753 |
| 754 » mutex_unlock(&us->dev_mutex); |
| 755 |
| 756 » return 0; |
| 757 } |
| 758 |
| 759 int realtek_cr_resume(struct usb_interface *iface) |
| 760 { |
| 761 » struct us_data *us = usb_get_intfdata(iface); |
| 762 » struct rts51x_chip *chip = (struct rts51x_chip *)(us->extra); |
| 763 |
| 764 » US_DEBUGP("%s\n", __func__); |
| 765 » |
| 766 » if (!RTS51X_CHK_STAT(chip, STAT_SS) || !chip->resume_from_scsi) { |
| 767 » » mutex_lock(&us->dev_mutex); |
| 768 |
738 if (GET_PM_USAGE_CNT(us) <= 0) { | 769 if (GET_PM_USAGE_CNT(us) <= 0) { |
739 // Remote wake up, increase pm_usage_cnt | 770 // Remote wake up, increase pm_usage_cnt |
740 US_DEBUGP("Incr pm_usage_cnt\n"); | 771 US_DEBUGP("Incr pm_usage_cnt\n"); |
741 SET_PM_USAGE_CNT(us, 1); | 772 SET_PM_USAGE_CNT(us, 1); |
742 RTS51X_SET_STAT(chip, STAT_RUN); | |
743 } | 773 } |
744 » » | 774 |
745 (void)config_autodelink_after_power_on(us); | 775 (void)config_autodelink_after_power_on(us); |
746 » } else { | 776 |
747 » » if (RTS51X_CHK_STAT(chip, STAT_SS_PRE)) { | 777 » » RTS51X_SET_STAT(chip, STAT_RUN); |
748 » » » US_DEBUGP("Enter SS state"); | 778 » |
749 » » » RTS51X_SET_STAT(chip, STAT_SS); | 779 » » mutex_unlock(&us->dev_mutex); |
750 » » } | |
751 » » | |
752 » » (void)config_autodelink_before_power_down(us); | |
753 } | 780 } |
754 | 781 |
755 » US_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(us)); | 782 » return 0; |
756 } | 783 } |
757 #endif | 784 #endif |
758 | 785 |
759 static void realtek_cr_destructor(void *extra) | 786 static void realtek_cr_destructor(void *extra) |
760 { | 787 { |
761 struct rts51x_chip *chip = (struct rts51x_chip *)extra; | 788 struct rts51x_chip *chip = (struct rts51x_chip *)extra; |
762 | 789 |
763 if (!chip) | 790 if (!chip) |
764 return; | 791 return; |
765 | 792 |
(...skipping 13 matching lines...) Expand all Loading... |
779 int size, i, retval; | 806 int size, i, retval; |
780 struct task_struct *th; | 807 struct task_struct *th; |
781 | 808 |
782 chip = kzalloc(sizeof(struct rts51x_chip), GFP_KERNEL); | 809 chip = kzalloc(sizeof(struct rts51x_chip), GFP_KERNEL); |
783 if (!chip) | 810 if (!chip) |
784 return -ENOMEM; | 811 return -ENOMEM; |
785 | 812 |
786 us->extra = chip; | 813 us->extra = chip; |
787 us->extra_destructor = realtek_cr_destructor; | 814 us->extra_destructor = realtek_cr_destructor; |
788 | 815 |
789 #ifdef CONFIG_PM | |
790 us->suspend_resume_hook = rts51x_handle_pm; | |
791 #endif | |
792 | |
793 us->max_lun = chip->max_lun = rts51x_get_max_lun(us); | 816 us->max_lun = chip->max_lun = rts51x_get_max_lun(us); |
794 | 817 |
795 US_DEBUGP("chip->max_lun = %d\n", chip->max_lun); | 818 US_DEBUGP("chip->max_lun = %d\n", chip->max_lun); |
796 | 819 |
797 size = (chip->max_lun + 1) * sizeof(struct rts51x_status); | 820 size = (chip->max_lun + 1) * sizeof(struct rts51x_status); |
798 chip->status = (struct rts51x_status *)kzalloc(size, GFP_KERNEL); | 821 chip->status = (struct rts51x_status *)kzalloc(size, GFP_KERNEL); |
799 if (!chip->status) { | 822 if (!chip->status) { |
800 goto INIT_FAIL; | 823 goto INIT_FAIL; |
801 } | 824 } |
802 | 825 |
803 for (i = 0; i <= (int)(chip->max_lun); i++) { | 826 for (i = 0; i <= (int)(chip->max_lun); i++) { |
804 retval = rts51x_check_status(us, (u8)i); | 827 retval = rts51x_check_status(us, (u8)i); |
805 if (retval < 0) { | 828 if (retval < 0) { |
806 goto INIT_FAIL; | 829 goto INIT_FAIL; |
807 } | 830 } |
808 } | 831 } |
809 | 832 |
810 if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) || | 833 if (CHECK_FW_VER(chip, 0x5888) || CHECK_FW_VER(chip, 0x5889) || |
811 CHECK_FW_VER(chip, 0x5901)) { | 834 CHECK_FW_VER(chip, 0x5901)) { |
812 SET_AUTO_DELINK(chip); | 835 SET_AUTO_DELINK(chip); |
813 } | 836 } |
814 if (STATUS_LEN(chip) == 16) { | 837 if (STATUS_LEN(chip) == 16) { |
815 if (SUPPORT_AUTO_DELINK(chip)) { | 838 if (SUPPORT_AUTO_DELINK(chip)) { |
816 SET_AUTO_DELINK(chip); | 839 SET_AUTO_DELINK(chip); |
817 } | 840 } |
818 } | 841 } |
819 | 842 |
| 843 US_DEBUGP("chip->flag = 0x%x\n", chip->flag); |
| 844 |
820 (void)config_autodelink_after_power_on(us); | 845 (void)config_autodelink_after_power_on(us); |
821 | 846 |
822 #ifdef CONFIG_PM | 847 #ifdef CONFIG_PM |
823 if (ss_en) { | 848 if (ss_en) { |
824 us->pusb_intf->needs_remote_wakeup = needs_remote_wakeup; | 849 us->pusb_intf->needs_remote_wakeup = needs_remote_wakeup; |
825 SET_PM_USAGE_CNT(us, 1); | 850 SET_PM_USAGE_CNT(us, 1); |
826 US_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(us)); | 851 US_DEBUGP("pm_usage_cnt = %d\n", GET_PM_USAGE_CNT(us)); |
827 | 852 |
828 // Enable autosuspend | 853 // Enable autosuspend |
829 us->pusb_dev->autosuspend_disabled = 0; | 854 us->pusb_dev->autosuspend_disabled = 0; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
888 } else { | 913 } else { |
889 result = USB_STOR_TRANSPORT_GOOD; | 914 result = USB_STOR_TRANSPORT_GOOD; |
890 } | 915 } |
891 | 916 |
892 goto FINISH; | 917 goto FINISH; |
893 } | 918 } |
894 } else { | 919 } else { |
895 if (RTS51X_CHK_STAT(chip, STAT_SS)) { | 920 if (RTS51X_CHK_STAT(chip, STAT_SS)) { |
896 // Wake up device | 921 // Wake up device |
897 US_DEBUGP("Try to wake up device\n"); | 922 US_DEBUGP("Try to wake up device\n"); |
898 » » » » mutex_unlock(&(us->dev_mutex)); | 923 » » » » chip->resume_from_scsi = 1; |
899 usb_autopm_disable(us->pusb_intf); | 924 usb_autopm_disable(us->pusb_intf); |
900 wait_timeout(3000); | 925 wait_timeout(3000); |
901 » » » » mutex_lock(&(us->dev_mutex)); | 926 » » » » |
| 927 » » » » (void)config_autodelink_after_power_on(us); |
902 rts51x_reset_card(us, lun); | 928 rts51x_reset_card(us, lun); |
903 } | 929 } |
904 RTS51X_SET_STAT(chip, STAT_RUN); | 930 RTS51X_SET_STAT(chip, STAT_RUN); |
905 } | 931 } |
906 } | 932 } |
907 else | 933 else |
908 #endif | 934 #endif |
909 { | 935 { |
910 RTS51X_SET_STAT(chip, STAT_RUN); | 936 RTS51X_SET_STAT(chip, STAT_RUN); |
911 } | 937 } |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
943 us->max_lun = 0; | 969 us->max_lun = 0; |
944 | 970 |
945 result = usb_stor_probe2(us); | 971 result = usb_stor_probe2(us); |
946 return result; | 972 return result; |
947 } | 973 } |
948 | 974 |
949 static struct usb_driver realtek_cr_driver = { | 975 static struct usb_driver realtek_cr_driver = { |
950 .name = "ums-realtek", | 976 .name = "ums-realtek", |
951 .probe = realtek_cr_probe, | 977 .probe = realtek_cr_probe, |
952 .disconnect = usb_stor_disconnect, | 978 .disconnect = usb_stor_disconnect, |
953 » .suspend =» usb_stor_suspend, | 979 » .suspend =» realtek_cr_suspend, |
954 » .resume =» usb_stor_resume, | 980 » .resume =» realtek_cr_resume, |
955 .reset_resume = usb_stor_reset_resume, | 981 .reset_resume = usb_stor_reset_resume, |
956 .pre_reset = usb_stor_pre_reset, | 982 .pre_reset = usb_stor_pre_reset, |
957 .post_reset = usb_stor_post_reset, | 983 .post_reset = usb_stor_post_reset, |
958 .id_table = realtek_cr_ids, | 984 .id_table = realtek_cr_ids, |
959 .soft_unbind = 1, | 985 .soft_unbind = 1, |
960 }; | 986 }; |
961 | 987 |
962 static int __init realtek_cr_init(void) | 988 static int __init realtek_cr_init(void) |
963 { | 989 { |
964 return usb_register(&realtek_cr_driver); | 990 return usb_register(&realtek_cr_driver); |
965 } | 991 } |
966 | 992 |
967 static void __exit realtek_cr_exit(void) | 993 static void __exit realtek_cr_exit(void) |
968 { | 994 { |
969 usb_deregister(&realtek_cr_driver); | 995 usb_deregister(&realtek_cr_driver); |
970 } | 996 } |
971 | 997 |
972 module_init(realtek_cr_init); | 998 module_init(realtek_cr_init); |
973 module_exit(realtek_cr_exit); | 999 module_exit(realtek_cr_exit); |
974 | 1000 |
OLD | NEW |