]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
UBUNTU: SAUCE: xr-usb-serial: interface for switching modes
authorDarren Wu <darren.wu@canonical.com>
Fri, 2 Dec 2016 09:11:03 +0000 (17:11 +0800)
committerTim Gardner <tim.gardner@canonical.com>
Mon, 20 Feb 2017 03:57:58 +0000 (20:57 -0700)
BugLink: https://launchpad.net/bugs/1645591
Add an interface for mode switching between RS232 and RS422/485.

Signed-off-by: Darren Wu <darren.wu@canonical.com>
Signed-off-by: Wen-chien Jesse Sung <jesse.sung@canonical.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
ubuntu/xr-usb-serial/xr_usb_serial_common.c
ubuntu/xr-usb-serial/xr_usb_serial_common.h
ubuntu/xr-usb-serial/xr_usb_serial_hal.c

index 0225dc704744710ffbe5f80ffe9d584b522c16a3..d16f072613b122456a42b5b05eb7d279682c6eb3 100644 (file)
@@ -249,6 +249,46 @@ static ssize_t show_country_rel_date
 }
 
 static DEVICE_ATTR(iCountryCodeRelDate, S_IRUGO, show_country_rel_date, NULL);
+
+static ssize_t set_rs485_422_en(struct device *dev,
+                               struct device_attribute *attr, const char *buf,
+                               size_t count)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf);
+       int error, value = 0;
+
+       error = kstrtoint(buf, 0, &value);
+       if (error)
+               return error;
+
+       if (value == 0) {
+               xr_usb_serial->rs485_422_en = false;
+       } else if (value == 1) {
+               // RS485,RS422 HD/FD mode
+               xr_usb_serial->rs485_422_en = true;
+       }
+
+       return count;
+}
+
+static ssize_t show_rs485_422_en(struct device *dev,
+                                struct device_attribute *attr, char *buf)
+{
+       struct usb_interface *intf = to_usb_interface(dev);
+       struct xr_usb_serial *xr_usb_serial = usb_get_intfdata(intf);
+
+       if (xr_usb_serial->rs485_422_en == false) {
+               return sprintf(buf, "0");
+       } else if (xr_usb_serial->rs485_422_en == true) {
+               // RS485,RS422 HD/FD mode
+               return sprintf(buf, "1");
+       }
+       return 0;
+}
+
+static DEVICE_ATTR(bRS485_422_en, 0644, show_rs485_422_en, set_rs485_422_en);
+
 /*
  * Interrupt handlers for various XR_USB_SERIAL device responses
  */
@@ -1384,10 +1424,15 @@ made_compressed_probe:
 
        usb_set_intfdata(intf, xr_usb_serial);
 
-       i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
+       xr_usb_serial->rs485_422_en = false;    //default enable rs232
+       i = device_create_file(&intf->dev, &dev_attr_bRS485_422_en);
        if (i < 0)
                goto alloc_fail7;
 
+       i = device_create_file(&intf->dev, &dev_attr_bmCapabilities);
+       if (i < 0)
+               goto alloc_fail8;
+
        if (cfd) { /* export the country data */
                xr_usb_serial->country_codes = kmalloc(cfd->bLength - 4, GFP_KERNEL);
                if (!xr_usb_serial->country_codes)
@@ -1446,12 +1491,12 @@ skip_countries:
                        &control_interface->dev);
        if (IS_ERR(tty_dev)) {
                rv = PTR_ERR(tty_dev);
-               goto alloc_fail8;
+               goto alloc_fail9;
        }
 #endif 
 
        return 0;
-alloc_fail8:
+alloc_fail9:
        if (xr_usb_serial->country_codes) {
                device_remove_file(&xr_usb_serial->control->dev,
                                &dev_attr_wCountryCodes);
@@ -1459,6 +1504,8 @@ alloc_fail8:
                                &dev_attr_iCountryCodeRelDate);
        }
        device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities);
+alloc_fail8:
+       device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en);
 alloc_fail7:
        usb_set_intfdata(intf, NULL);
        for (i = 0; i < XR_USB_SERIAL_NW; i++)
@@ -1516,6 +1563,7 @@ static void xr_usb_serial_disconnect(struct usb_interface *intf)
                                &dev_attr_iCountryCodeRelDate);
        }
        device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bmCapabilities);
+       device_remove_file(&xr_usb_serial->control->dev, &dev_attr_bRS485_422_en);
        usb_set_intfdata(xr_usb_serial->control, NULL);
        usb_set_intfdata(xr_usb_serial->data, NULL);
        mutex_unlock(&xr_usb_serial->mutex);
index 4ba22d947999b314d741409a65a36ec3de7013ff..fe3460c57adfe62925573fd2088c0cfce2a5e4d6 100644 (file)
@@ -147,6 +147,7 @@ struct xr_usb_serial {
        unsigned short DeviceVendor;
        unsigned short DeviceProduct;
        struct reg_addr_map reg_map;
+       bool rs485_422_en;
 };
 
 #define CDC_DATA_INTERFACE_TYPE        0x0a
index 0fcc580002bdbb06387c0e52f1ca015d907707b3..f44970995368071b19faf676ec1bc75f1fc36500 100644 (file)
@@ -479,8 +479,15 @@ int xr_usb_serial_set_line(struct xr_usb_serial *xr_usb_serial, struct usb_cdc_l
            flow      = UART_FLOW_MODE_NONE;
            gpio_mode = UART_GPIO_MODE_SEL_GPIO;
        }
-    xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow);
-    xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode);
+       // rs485,rs422 FD/HD mode
+       if (xr_usb_serial->rs485_422_en) {
+               xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, 0x00);
+               xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, 0x0B);
+       } else {
+               //rs232, default mode
+               xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_flow_addr, flow);
+               xr_usb_serial_set_reg(xr_usb_serial, xr_usb_serial->reg_map.uart_gpio_mode_addr, gpio_mode);
+       }
        return 0;