diff options
author | Simon Arlott <simon@fire.lp0.eu> | 2009-11-21 10:14:01 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-03-02 17:53:01 -0500 |
commit | 4ac37208e9b30b36b615ed22a79b4ee787fdc9b5 (patch) | |
tree | 792b78405d06b00a0d0a5fa3a342ef359f1f5383 | |
parent | 885582c48e5fbf47ccc4273aaa5f2f56ad513253 (diff) |
USB: cxacru: add write-only sysfs attribute for modem configuration
The modem can be configured using CM_REQUEST_CARD_DATA_SET,
although CM_REQUEST_CARD_DATA_GET does not return any data.
Tested by setting the modulation (0x0a) option.
There is a list of parameters in the following archive,
but the meaning of many of them is not well documented:
http://sourceforge.net/project/shownotes.php?release_id=301825
This source also indicates that the highest parameter set
is 0x4a but this varies by model so an arbitrary limit of
0x7f has been used (the index is a 32-bit integer).
Signed-off-by: Simon Arlott <simon@fire.lp0.eu>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | Documentation/networking/cxacru.txt | 9 | ||||
-rw-r--r-- | drivers/usb/atm/cxacru.c | 76 |
2 files changed, 84 insertions, 1 deletions
diff --git a/Documentation/networking/cxacru.txt b/Documentation/networking/cxacru.txt index 3532ceecd2c3..f4fbf4cd592c 100644 --- a/Documentation/networking/cxacru.txt +++ b/Documentation/networking/cxacru.txt | |||
@@ -15,6 +15,15 @@ several sysfs attribute files for retrieving device statistics: | |||
15 | * adsl_headend_environment | 15 | * adsl_headend_environment |
16 | Information about the remote headend. | 16 | Information about the remote headend. |
17 | 17 | ||
18 | * adsl_config | ||
19 | Configuration writing interface. | ||
20 | Write parameters in hexadecimal format <index>=<value>, | ||
21 | separated by whitespace, e.g.: | ||
22 | "1=0 a=5" | ||
23 | Up to 7 parameters at a time will be sent and the modem will restart | ||
24 | the ADSL connection when any value is set. These are logged for future | ||
25 | reference. | ||
26 | |||
18 | * downstream_attenuation (dB) | 27 | * downstream_attenuation (dB) |
19 | * downstream_bits_per_frame | 28 | * downstream_bits_per_frame |
20 | * downstream_rate (kbps) | 29 | * downstream_rate (kbps) |
diff --git a/drivers/usb/atm/cxacru.c b/drivers/usb/atm/cxacru.c index 5e3d7b9a78a7..c2163d0826e3 100644 --- a/drivers/usb/atm/cxacru.c +++ b/drivers/usb/atm/cxacru.c | |||
@@ -52,6 +52,7 @@ static const char cxacru_driver_name[] = "cxacru"; | |||
52 | #define CXACRU_EP_DATA 0x02 /* Bulk in/out */ | 52 | #define CXACRU_EP_DATA 0x02 /* Bulk in/out */ |
53 | 53 | ||
54 | #define CMD_PACKET_SIZE 64 /* Should be maxpacket(ep)? */ | 54 | #define CMD_PACKET_SIZE 64 /* Should be maxpacket(ep)? */ |
55 | #define CMD_MAX_CONFIG ((CMD_PACKET_SIZE / 4 - 1) / 2) | ||
55 | 56 | ||
56 | /* Addresses */ | 57 | /* Addresses */ |
57 | #define PLLFCLK_ADDR 0x00350068 | 58 | #define PLLFCLK_ADDR 0x00350068 |
@@ -216,6 +217,10 @@ static DEVICE_ATTR(_name, S_IRUGO, cxacru_sysfs_show_##_name, NULL) | |||
216 | static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \ | 217 | static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \ |
217 | cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name) | 218 | cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name) |
218 | 219 | ||
220 | #define CXACRU_SET_INIT(_name) \ | ||
221 | static DEVICE_ATTR(_name, S_IWUSR, \ | ||
222 | NULL, cxacru_sysfs_store_##_name) | ||
223 | |||
219 | #define CXACRU_ATTR_INIT(_value, _type, _name) \ | 224 | #define CXACRU_ATTR_INIT(_value, _type, _name) \ |
220 | static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \ | 225 | static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \ |
221 | struct device_attribute *attr, char *buf) \ | 226 | struct device_attribute *attr, char *buf) \ |
@@ -232,10 +237,12 @@ CXACRU__ATTR_INIT(_name) | |||
232 | 237 | ||
233 | #define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name) | 238 | #define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name) |
234 | #define CXACRU_CMD_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name) | 239 | #define CXACRU_CMD_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name) |
240 | #define CXACRU_SET_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name) | ||
235 | #define CXACRU__ATTR_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name) | 241 | #define CXACRU__ATTR_CREATE(_name) CXACRU_DEVICE_CREATE_FILE(_name) |
236 | 242 | ||
237 | #define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name) | 243 | #define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name) |
238 | #define CXACRU_CMD_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name) | 244 | #define CXACRU_CMD_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name) |
245 | #define CXACRU_SET_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name) | ||
239 | #define CXACRU__ATTR_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name) | 246 | #define CXACRU__ATTR_REMOVE(_name) CXACRU_DEVICE_REMOVE_FILE(_name) |
240 | 247 | ||
241 | static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf) | 248 | static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf) |
@@ -438,6 +445,72 @@ static ssize_t cxacru_sysfs_store_adsl_state(struct device *dev, | |||
438 | return ret; | 445 | return ret; |
439 | } | 446 | } |
440 | 447 | ||
448 | /* CM_REQUEST_CARD_DATA_GET times out, so no show attribute */ | ||
449 | |||
450 | static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev, | ||
451 | struct device_attribute *attr, const char *buf, size_t count) | ||
452 | { | ||
453 | struct cxacru_data *instance = to_usbatm_driver_data( | ||
454 | to_usb_interface(dev)); | ||
455 | int len = strlen(buf); | ||
456 | int ret, pos, num; | ||
457 | __le32 data[CMD_PACKET_SIZE / 4]; | ||
458 | |||
459 | if (!capable(CAP_NET_ADMIN)) | ||
460 | return -EACCES; | ||
461 | |||
462 | if (instance == NULL) | ||
463 | return -ENODEV; | ||
464 | |||
465 | pos = 0; | ||
466 | num = 0; | ||
467 | while (pos < len) { | ||
468 | int tmp; | ||
469 | u32 index; | ||
470 | u32 value; | ||
471 | |||
472 | ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp); | ||
473 | if (ret < 2) | ||
474 | return -EINVAL; | ||
475 | if (index < 0 || index > 0x7f) | ||
476 | return -EINVAL; | ||
477 | pos += tmp; | ||
478 | |||
479 | /* skip trailing newline */ | ||
480 | if (buf[pos] == '\n' && pos == len-1) | ||
481 | pos++; | ||
482 | |||
483 | data[num * 2 + 1] = cpu_to_le32(index); | ||
484 | data[num * 2 + 2] = cpu_to_le32(value); | ||
485 | num++; | ||
486 | |||
487 | /* send config values when data buffer is full | ||
488 | * or no more data | ||
489 | */ | ||
490 | if (pos >= len || num >= CMD_MAX_CONFIG) { | ||
491 | char log[CMD_MAX_CONFIG * 12 + 1]; /* %02x=%08x */ | ||
492 | |||
493 | data[0] = cpu_to_le32(num); | ||
494 | ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET, | ||
495 | (u8 *) data, 4 + num * 8, NULL, 0); | ||
496 | if (ret < 0) { | ||
497 | atm_err(instance->usbatm, | ||
498 | "set card data returned %d\n", ret); | ||
499 | return -EIO; | ||
500 | } | ||
501 | |||
502 | for (tmp = 0; tmp < num; tmp++) | ||
503 | snprintf(log + tmp*12, 13, " %02x=%08x", | ||
504 | le32_to_cpu(data[tmp * 2 + 1]), | ||
505 | le32_to_cpu(data[tmp * 2 + 2])); | ||
506 | atm_info(instance->usbatm, "config%s\n", log); | ||
507 | num = 0; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | return len; | ||
512 | } | ||
513 | |||
441 | /* | 514 | /* |
442 | * All device attributes are included in CXACRU_ALL_FILES | 515 | * All device attributes are included in CXACRU_ALL_FILES |
443 | * so that the same list can be used multiple times: | 516 | * so that the same list can be used multiple times: |
@@ -473,7 +546,8 @@ CXACRU_ATTR_##_action(CXINF_MODULATION, MODU, modulation); \ | |||
473 | CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND, u32, adsl_headend); \ | 546 | CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND, u32, adsl_headend); \ |
474 | CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT, u32, adsl_headend_environment); \ | 547 | CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT, u32, adsl_headend_environment); \ |
475 | CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION, u32, adsl_controller_version); \ | 548 | CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION, u32, adsl_controller_version); \ |
476 | CXACRU_CMD_##_action( adsl_state); | 549 | CXACRU_CMD_##_action( adsl_state); \ |
550 | CXACRU_SET_##_action( adsl_config); | ||
477 | 551 | ||
478 | CXACRU_ALL_FILES(INIT); | 552 | CXACRU_ALL_FILES(INIT); |
479 | 553 | ||