#define CXACRU_EP_DATA         0x02    /* Bulk in/out */
 
 #define CMD_PACKET_SIZE                64      /* Should be maxpacket(ep)? */
+#define CMD_MAX_CONFIG         ((CMD_PACKET_SIZE / 4 - 1) / 2)
 
 /* Addresses */
 #define PLLFCLK_ADDR   0x00350068
 static DEVICE_ATTR(_name, S_IWUSR | S_IRUGO, \
        cxacru_sysfs_show_##_name, cxacru_sysfs_store_##_name)
 
+#define CXACRU_SET_INIT(_name) \
+static DEVICE_ATTR(_name, S_IWUSR, \
+       NULL, cxacru_sysfs_store_##_name)
+
 #define CXACRU_ATTR_INIT(_value, _type, _name) \
 static ssize_t cxacru_sysfs_show_##_name(struct device *dev, \
        struct device_attribute *attr, char *buf) \
 
 #define CXACRU_ATTR_CREATE(_v, _t, _name) CXACRU_DEVICE_CREATE_FILE(_name)
 #define CXACRU_CMD_CREATE(_name)          CXACRU_DEVICE_CREATE_FILE(_name)
+#define CXACRU_SET_CREATE(_name)          CXACRU_DEVICE_CREATE_FILE(_name)
 #define CXACRU__ATTR_CREATE(_name)        CXACRU_DEVICE_CREATE_FILE(_name)
 
 #define CXACRU_ATTR_REMOVE(_v, _t, _name) CXACRU_DEVICE_REMOVE_FILE(_name)
 #define CXACRU_CMD_REMOVE(_name)          CXACRU_DEVICE_REMOVE_FILE(_name)
+#define CXACRU_SET_REMOVE(_name)          CXACRU_DEVICE_REMOVE_FILE(_name)
 #define CXACRU__ATTR_REMOVE(_name)        CXACRU_DEVICE_REMOVE_FILE(_name)
 
 static ssize_t cxacru_sysfs_showattr_u32(u32 value, char *buf)
        return ret;
 }
 
+/* CM_REQUEST_CARD_DATA_GET times out, so no show attribute */
+
+static ssize_t cxacru_sysfs_store_adsl_config(struct device *dev,
+       struct device_attribute *attr, const char *buf, size_t count)
+{
+       struct cxacru_data *instance = to_usbatm_driver_data(
+                       to_usb_interface(dev));
+       int len = strlen(buf);
+       int ret, pos, num;
+       __le32 data[CMD_PACKET_SIZE / 4];
+
+       if (!capable(CAP_NET_ADMIN))
+               return -EACCES;
+
+       if (instance == NULL)
+               return -ENODEV;
+
+       pos = 0;
+       num = 0;
+       while (pos < len) {
+               int tmp;
+               u32 index;
+               u32 value;
+
+               ret = sscanf(buf + pos, "%x=%x%n", &index, &value, &tmp);
+               if (ret < 2)
+                       return -EINVAL;
+               if (index < 0 || index > 0x7f)
+                       return -EINVAL;
+               pos += tmp;
+
+               /* skip trailing newline */
+               if (buf[pos] == '\n' && pos == len-1)
+                       pos++;
+
+               data[num * 2 + 1] = cpu_to_le32(index);
+               data[num * 2 + 2] = cpu_to_le32(value);
+               num++;
+
+               /* send config values when data buffer is full
+                * or no more data
+                */
+               if (pos >= len || num >= CMD_MAX_CONFIG) {
+                       char log[CMD_MAX_CONFIG * 12 + 1]; /* %02x=%08x */
+
+                       data[0] = cpu_to_le32(num);
+                       ret = cxacru_cm(instance, CM_REQUEST_CARD_DATA_SET,
+                               (u8 *) data, 4 + num * 8, NULL, 0);
+                       if (ret < 0) {
+                               atm_err(instance->usbatm,
+                                       "set card data returned %d\n", ret);
+                               return -EIO;
+                       }
+
+                       for (tmp = 0; tmp < num; tmp++)
+                               snprintf(log + tmp*12, 13, " %02x=%08x",
+                                       le32_to_cpu(data[tmp * 2 + 1]),
+                                       le32_to_cpu(data[tmp * 2 + 2]));
+                       atm_info(instance->usbatm, "config%s\n", log);
+                       num = 0;
+               }
+       }
+
+       return len;
+}
+
 /*
  * All device attributes are included in CXACRU_ALL_FILES
  * so that the same list can be used multiple times:
 CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND,              u32,  adsl_headend); \
 CXACRU_ATTR_##_action(CXINF_ADSL_HEADEND_ENVIRONMENT,  u32,  adsl_headend_environment); \
 CXACRU_ATTR_##_action(CXINF_CONTROLLER_VERSION,        u32,  adsl_controller_version); \
-CXACRU_CMD_##_action(                                        adsl_state);
+CXACRU_CMD_##_action(                                        adsl_state); \
+CXACRU_SET_##_action(                                        adsl_config);
 
 CXACRU_ALL_FILES(INIT);