diff options
author | Olivier Bornet <Olivier.Bornet@puck.ch> | 2009-08-18 15:05:55 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-09-23 09:46:35 -0400 |
commit | 20eda943cc55b2bfdb6b6e4a3da23c8f198910c8 (patch) | |
tree | ee73bea7000afb028fa8f3834af761209551fedc /drivers/usb | |
parent | 8844a32d54988ddf9eaf8f439085491547debcc8 (diff) |
USB: iuu_phoenix: add support for changing VCC
You can now set the IUU reader to 3.3V VCC instead of 5V VCC, using the sysfs
parameter vcc_mode. Valid values are 3 and 5.
Signed-off-by: Olivier Bornet <Olivier.Bornet@puck.ch>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/serial/iuu_phoenix.c | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 60a7d8dc0758..5f133429cd45 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
@@ -79,6 +79,7 @@ struct iuu_private { | |||
79 | u8 *buf; /* used for initialize speed */ | 79 | u8 *buf; /* used for initialize speed */ |
80 | u8 *dbgbuf; /* debug buffer */ | 80 | u8 *dbgbuf; /* debug buffer */ |
81 | u8 len; | 81 | u8 len; |
82 | int vcc; /* vcc (either 3 or 5 V) */ | ||
82 | }; | 83 | }; |
83 | 84 | ||
84 | 85 | ||
@@ -114,6 +115,7 @@ static int iuu_startup(struct usb_serial *serial) | |||
114 | kfree(priv); | 115 | kfree(priv); |
115 | return -ENOMEM; | 116 | return -ENOMEM; |
116 | } | 117 | } |
118 | priv->vcc = 5; /* 5 V for vcc by default */ | ||
117 | spin_lock_init(&priv->lock); | 119 | spin_lock_init(&priv->lock); |
118 | init_waitqueue_head(&priv->delta_msr_wait); | 120 | init_waitqueue_head(&priv->delta_msr_wait); |
119 | usb_set_serial_port_data(serial->port[0], priv); | 121 | usb_set_serial_port_data(serial->port[0], priv); |
@@ -1178,6 +1180,95 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1178 | return result; | 1180 | return result; |
1179 | } | 1181 | } |
1180 | 1182 | ||
1183 | /* how to change VCC */ | ||
1184 | static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc) | ||
1185 | { | ||
1186 | int status; | ||
1187 | u8 *buf; | ||
1188 | |||
1189 | buf = kmalloc(5, GFP_KERNEL); | ||
1190 | if (!buf) | ||
1191 | return -ENOMEM; | ||
1192 | |||
1193 | dbg("%s - enter", __func__); | ||
1194 | |||
1195 | buf[0] = IUU_SET_VCC; | ||
1196 | buf[1] = vcc & 0xFF; | ||
1197 | buf[2] = (vcc >> 8) & 0xFF; | ||
1198 | buf[3] = (vcc >> 16) & 0xFF; | ||
1199 | buf[4] = (vcc >> 24) & 0xFF; | ||
1200 | |||
1201 | status = bulk_immediate(port, buf, 5); | ||
1202 | kfree(buf); | ||
1203 | |||
1204 | if (status != IUU_OPERATION_OK) | ||
1205 | dbg("%s - vcc error status = %2x", __func__, status); | ||
1206 | else | ||
1207 | dbg("%s - vcc OK !", __func__); | ||
1208 | |||
1209 | return status; | ||
1210 | } | ||
1211 | |||
1212 | /* | ||
1213 | * Sysfs Attributes | ||
1214 | */ | ||
1215 | |||
1216 | static ssize_t show_vcc_mode(struct device *dev, | ||
1217 | struct device_attribute *attr, char *buf) | ||
1218 | { | ||
1219 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
1220 | struct iuu_private *priv = usb_get_serial_port_data(port); | ||
1221 | |||
1222 | return sprintf(buf, "%d\n", priv->vcc); | ||
1223 | } | ||
1224 | |||
1225 | static ssize_t store_vcc_mode(struct device *dev, | ||
1226 | struct device_attribute *attr, const char *buf, size_t count) | ||
1227 | { | ||
1228 | struct usb_serial_port *port = to_usb_serial_port(dev); | ||
1229 | struct iuu_private *priv = usb_get_serial_port_data(port); | ||
1230 | unsigned long v; | ||
1231 | |||
1232 | if (strict_strtoul(buf, 10, &v)) { | ||
1233 | dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n", | ||
1234 | __func__, buf); | ||
1235 | goto fail_store_vcc_mode; | ||
1236 | } | ||
1237 | |||
1238 | dbg("%s: setting vcc_mode = %ld", __func__, v); | ||
1239 | |||
1240 | if ((v != 3) && (v != 5)) { | ||
1241 | dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v); | ||
1242 | } else { | ||
1243 | iuu_vcc_set(port, v); | ||
1244 | priv->vcc = v; | ||
1245 | } | ||
1246 | fail_store_vcc_mode: | ||
1247 | return count; | ||
1248 | } | ||
1249 | |||
1250 | static DEVICE_ATTR(vcc_mode, S_IRUSR | S_IWUSR, show_vcc_mode, | ||
1251 | store_vcc_mode); | ||
1252 | |||
1253 | static int iuu_create_sysfs_attrs(struct usb_serial_port *port) | ||
1254 | { | ||
1255 | dbg("%s", __func__); | ||
1256 | |||
1257 | return device_create_file(&port->dev, &dev_attr_vcc_mode); | ||
1258 | } | ||
1259 | |||
1260 | static int iuu_remove_sysfs_attrs(struct usb_serial_port *port) | ||
1261 | { | ||
1262 | dbg("%s", __func__); | ||
1263 | |||
1264 | device_remove_file(&port->dev, &dev_attr_vcc_mode); | ||
1265 | return 0; | ||
1266 | } | ||
1267 | |||
1268 | /* | ||
1269 | * End Sysfs Attributes | ||
1270 | */ | ||
1271 | |||
1181 | static struct usb_serial_driver iuu_device = { | 1272 | static struct usb_serial_driver iuu_device = { |
1182 | .driver = { | 1273 | .driver = { |
1183 | .owner = THIS_MODULE, | 1274 | .owner = THIS_MODULE, |
@@ -1185,6 +1276,8 @@ static struct usb_serial_driver iuu_device = { | |||
1185 | }, | 1276 | }, |
1186 | .id_table = id_table, | 1277 | .id_table = id_table, |
1187 | .num_ports = 1, | 1278 | .num_ports = 1, |
1279 | .port_probe = iuu_create_sysfs_attrs, | ||
1280 | .port_remove = iuu_remove_sysfs_attrs, | ||
1188 | .open = iuu_open, | 1281 | .open = iuu_open, |
1189 | .close = iuu_close, | 1282 | .close = iuu_close, |
1190 | .write = iuu_uart_write, | 1283 | .write = iuu_uart_write, |