aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2006-10-05 04:40:55 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2006-10-17 17:46:31 -0400
commit6a4f1b41357d2bd65d39f7a5d44e92f69daaf04b (patch)
tree9cd7cb832e9c1435f16c6a1a11c949e3f23fd291 /drivers/usb
parentccf40d62c70128990cf2e8775853cc3287cd7ce3 (diff)
speedtch: "extended reach"
The speedtouch modem setup code was reverse engineered many years ago from a prehistoric windows driver. Less ancient windows drivers, even those from a few years ago, perform extra initialization steps which this patch adds to the linux driver. David Woodhouse observed that this initialization along with the firmware bin/sachu3/zzzlp2.eni from the driver at http://www.speedtouch.co.uk/downloads/330/301/UK3012%20Extended.zip improves line sync speeds by about 20%. He provided the original patch, which I've modified to use symbolic names (BMaxDSL, ModemMode, ModemOption) rather than magic numbers. These names may not seem like much of an improvement (after all, what is "ModemOption" exactly?), but they do have one big advantage: they are the names used in the windows registry. I've made them available as module parameters. Thanks are due to Aurelio Arroyo, who noticed the relationship between these magic numbers and the entries in Phonebook.ini. Signed-off-by: Duncan Sands <baldrick@free.fr> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/atm/speedtch.c93
1 files changed, 77 insertions, 16 deletions
diff --git a/drivers/usb/atm/speedtch.c b/drivers/usb/atm/speedtch.c
index 7c7b507af29d..c870c804470f 100644
--- a/drivers/usb/atm/speedtch.c
+++ b/drivers/usb/atm/speedtch.c
@@ -55,7 +55,6 @@ static const char speedtch_driver_name[] = "speedtch";
55#define OFFSET_d 9 /* size 4 */ 55#define OFFSET_d 9 /* size 4 */
56#define OFFSET_e 13 /* size 1 */ 56#define OFFSET_e 13 /* size 1 */
57#define OFFSET_f 14 /* size 1 */ 57#define OFFSET_f 14 /* size 1 */
58#define TOTAL 15
59 58
60#define SIZE_7 1 59#define SIZE_7 1
61#define SIZE_b 8 60#define SIZE_b 8
@@ -79,6 +78,18 @@ static int dl_512_first = DEFAULT_DL_512_FIRST;
79static int enable_isoc = DEFAULT_ENABLE_ISOC; 78static int enable_isoc = DEFAULT_ENABLE_ISOC;
80static int sw_buffering = DEFAULT_SW_BUFFERING; 79static int sw_buffering = DEFAULT_SW_BUFFERING;
81 80
81#define DEFAULT_B_MAX_DSL 8128
82#define DEFAULT_MODEM_MODE 11
83#define MODEM_OPTION_LENGTH 16
84static const unsigned char DEFAULT_MODEM_OPTION[MODEM_OPTION_LENGTH] = {
85 0x10, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
86};
87
88static unsigned int BMaxDSL = DEFAULT_B_MAX_DSL;
89static unsigned char ModemMode = DEFAULT_MODEM_MODE;
90static unsigned char ModemOption[MODEM_OPTION_LENGTH];
91static int num_ModemOption;
92
82module_param(altsetting, uint, S_IRUGO | S_IWUSR); 93module_param(altsetting, uint, S_IRUGO | S_IWUSR);
83MODULE_PARM_DESC(altsetting, 94MODULE_PARM_DESC(altsetting,
84 "Alternative setting for data interface (bulk_default: " 95 "Alternative setting for data interface (bulk_default: "
@@ -100,6 +111,17 @@ MODULE_PARM_DESC(sw_buffering,
100 "Enable software buffering (default: " 111 "Enable software buffering (default: "
101 __MODULE_STRING(DEFAULT_SW_BUFFERING) ")"); 112 __MODULE_STRING(DEFAULT_SW_BUFFERING) ")");
102 113
114module_param(BMaxDSL, uint, S_IRUGO | S_IWUSR);
115MODULE_PARM_DESC(BMaxDSL,
116 "default: " __MODULE_STRING(DEFAULT_B_MAX_DSL));
117
118module_param(ModemMode, byte, S_IRUGO | S_IWUSR);
119MODULE_PARM_DESC(ModemMode,
120 "default: " __MODULE_STRING(DEFAULT_MODEM_MODE));
121
122module_param_array(ModemOption, byte, &num_ModemOption, S_IRUGO);
123MODULE_PARM_DESC(ModemOption, "default: 0x10,0x00,0x00,0x00,0x20");
124
103#define INTERFACE_DATA 1 125#define INTERFACE_DATA 1
104#define ENDPOINT_INT 0x81 126#define ENDPOINT_INT 0x81
105#define ENDPOINT_BULK_DATA 0x07 127#define ENDPOINT_BULK_DATA 0x07
@@ -108,10 +130,17 @@ MODULE_PARM_DESC(sw_buffering,
108 130
109#define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) ) 131#define hex2int(c) ( (c >= '0') && (c <= '9') ? (c - '0') : ((c & 0xf) + 9) )
110 132
133struct speedtch_params {
134 unsigned int altsetting;
135 unsigned int BMaxDSL;
136 unsigned char ModemMode;
137 unsigned char ModemOption[MODEM_OPTION_LENGTH];
138};
139
111struct speedtch_instance_data { 140struct speedtch_instance_data {
112 struct usbatm_data *usbatm; 141 struct usbatm_data *usbatm;
113 142
114 unsigned int altsetting; 143 struct speedtch_params params; /* set in probe, constant afterwards */
115 144
116 struct work_struct status_checker; 145 struct work_struct status_checker;
117 146
@@ -123,7 +152,7 @@ struct speedtch_instance_data {
123 struct urb *int_urb; 152 struct urb *int_urb;
124 unsigned char int_data[16]; 153 unsigned char int_data[16];
125 154
126 unsigned char scratch_buffer[TOTAL]; 155 unsigned char scratch_buffer[16];
127}; 156};
128 157
129/*************** 158/***************
@@ -186,6 +215,34 @@ static void speedtch_test_sequence(struct speedtch_instance_data *instance)
186 0x01, 0x40, 0x04, 0x00, buf, 3, CTRL_TIMEOUT); 215 0x01, 0x40, 0x04, 0x00, buf, 3, CTRL_TIMEOUT);
187 if (ret < 0) 216 if (ret < 0)
188 usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret); 217 usb_warn(usbatm, "%s failed on URB150: %d\n", __func__, ret);
218
219 /* Extra initialisation in recent drivers - gives higher speeds */
220
221 /* URBext1 */
222 buf[0] = instance->params.ModemMode;
223 ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
224 0x01, 0x40, 0x11, 0x00, buf, 1, CTRL_TIMEOUT);
225 if (ret < 0)
226 usb_warn(usbatm, "%s failed on URBext1: %d\n", __func__, ret);
227
228 /* URBext2 */
229 /* This seems to be the one which actually triggers the higher sync
230 rate -- it does require the new firmware too, although it works OK
231 with older firmware */
232 ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
233 0x01, 0x40, 0x14, 0x00,
234 instance->params.ModemOption,
235 MODEM_OPTION_LENGTH, CTRL_TIMEOUT);
236 if (ret < 0)
237 usb_warn(usbatm, "%s failed on URBext2: %d\n", __func__, ret);
238
239 /* URBext3 */
240 buf[0] = instance->params.BMaxDSL & 0xff;
241 buf[1] = instance->params.BMaxDSL >> 8;
242 ret = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
243 0x01, 0x40, 0x12, 0x00, buf, 2, CTRL_TIMEOUT);
244 if (ret < 0)
245 usb_warn(usbatm, "%s failed on URBext3: %d\n", __func__, ret);
189} 246}
190 247
191static int speedtch_upload_firmware(struct speedtch_instance_data *instance, 248static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
@@ -285,8 +342,8 @@ static int speedtch_upload_firmware(struct speedtch_instance_data *instance,
285 because we're in our own kernel thread anyway. */ 342 because we're in our own kernel thread anyway. */
286 msleep_interruptible(1000); 343 msleep_interruptible(1000);
287 344
288 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { 345 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->params.altsetting)) < 0) {
289 usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->altsetting, ret); 346 usb_err(usbatm, "%s: setting interface to %d failed (%d)!\n", __func__, instance->params.altsetting, ret);
290 goto out_free; 347 goto out_free;
291 } 348 }
292 349
@@ -372,7 +429,7 @@ static int speedtch_read_status(struct speedtch_instance_data *instance)
372 unsigned char *buf = instance->scratch_buffer; 429 unsigned char *buf = instance->scratch_buffer;
373 int ret; 430 int ret;
374 431
375 memset(buf, 0, TOTAL); 432 memset(buf, 0, 16);
376 433
377 ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0), 434 ret = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
378 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7, 435 0x12, 0xc0, 0x07, 0x00, buf + OFFSET_7, SIZE_7,
@@ -746,17 +803,21 @@ static int speedtch_bind(struct usbatm_data *usbatm,
746 803
747 instance->usbatm = usbatm; 804 instance->usbatm = usbatm;
748 805
749 /* altsetting and enable_isoc may change at any moment, so take a snapshot */ 806 /* module parameters may change at any moment, so take a snapshot */
750 instance->altsetting = altsetting; 807 instance->params.altsetting = altsetting;
808 instance->params.BMaxDSL = BMaxDSL;
809 instance->params.ModemMode = ModemMode;
810 memcpy(instance->params.ModemOption, DEFAULT_MODEM_OPTION, MODEM_OPTION_LENGTH);
811 memcpy(instance->params.ModemOption, ModemOption, num_ModemOption);
751 use_isoc = enable_isoc; 812 use_isoc = enable_isoc;
752 813
753 if (instance->altsetting) 814 if (instance->params.altsetting)
754 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->altsetting)) < 0) { 815 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, instance->params.altsetting)) < 0) {
755 usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->altsetting, ret); 816 usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, instance->params.altsetting, ret);
756 instance->altsetting = 0; /* fall back to default */ 817 instance->params.altsetting = 0; /* fall back to default */
757 } 818 }
758 819
759 if (!instance->altsetting && use_isoc) 820 if (!instance->params.altsetting && use_isoc)
760 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) { 821 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_ISOC_ALTSETTING)) < 0) {
761 usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret); 822 usb_dbg(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_ISOC_ALTSETTING, ret);
762 use_isoc = 0; /* fall back to bulk */ 823 use_isoc = 0; /* fall back to bulk */
@@ -783,14 +844,14 @@ static int speedtch_bind(struct usbatm_data *usbatm,
783 usb_info(usbatm, "isochronous transfer not supported - using bulk\n"); 844 usb_info(usbatm, "isochronous transfer not supported - using bulk\n");
784 } 845 }
785 846
786 if (!use_isoc && !instance->altsetting) 847 if (!use_isoc && !instance->params.altsetting)
787 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) { 848 if ((ret = usb_set_interface(usb_dev, INTERFACE_DATA, DEFAULT_BULK_ALTSETTING)) < 0) {
788 usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret); 849 usb_err(usbatm, "%s: setting interface to %2d failed (%d)!\n", __func__, DEFAULT_BULK_ALTSETTING, ret);
789 goto fail_free; 850 goto fail_free;
790 } 851 }
791 852
792 if (!instance->altsetting) 853 if (!instance->params.altsetting)
793 instance->altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING; 854 instance->params.altsetting = use_isoc ? DEFAULT_ISOC_ALTSETTING : DEFAULT_BULK_ALTSETTING;
794 855
795 usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0); 856 usbatm->flags |= (use_isoc ? UDSL_USE_ISOC : 0);
796 857