[uslcom][patch] Add GPIO support

JD Louw jdl.ntq at gmail.com
Fri Nov 11 21:37:37 UTC 2011


This patch adds custom IOCTLs to read and write the 4 GPIO pins on the
cp2103 usb-to-serial chip. Time from IOCTL to actual pin change is
pretty slow though.
-------------- next part --------------
Index: serial/uslcom.c
===================================================================
--- serial/uslcom.c	(revision 227453)
+++ serial/uslcom.c	(working copy)
@@ -42,6 +42,7 @@
 #include <dev/usb/usbdi.h>
 #include <dev/usb/usbdi_util.h>
 #include "usbdevs.h"
+#include <dev/usb/usb_ioctl.h>
 
 #define	USB_DEBUG_VAR uslcom_debug
 #include <dev/usb/usb_debug.h>
@@ -75,6 +76,7 @@
 #define	USLCOM_CTRL		0x07
 #define	USLCOM_RCTRL            0x08
 #define	USLCOM_SET_FLOWCTRL     0x13
+#define	USLCOM_VENDOR_SPECIFIC	0xff
 
 /* USLCOM_UART values */
 #define	USLCOM_UART_DISABLE	0x00
@@ -113,6 +115,10 @@
 #define	USLCOM_FLOW_RTS_ON      0x00000040 /* RTS static active */
 #define	USLCOM_FLOW_RTS_HS      0x00000080 /* RTS handshake */
 
+/* USLCOM_VENDOR_SPECIFIC values */
+#define	USLCOM_WRITE_LATCH	0x37E1
+#define	USLCOM_READ_LATCH	0x00C2
+
 enum {
 	USLCOM_BULK_DT_WR,
 	USLCOM_BULK_DT_RD,
@@ -145,6 +151,8 @@
 static void uslcom_set_dtr(struct ucom_softc *, uint8_t);
 static void uslcom_set_rts(struct ucom_softc *, uint8_t);
 static void uslcom_set_break(struct ucom_softc *, uint8_t);
+static int uslcom_ioctl(struct ucom_softc *, uint32_t, caddr_t, int,
+		struct thread *);
 static int uslcom_pre_param(struct ucom_softc *, struct termios *);
 static void uslcom_param(struct ucom_softc *, struct termios *);
 static void uslcom_get_status(struct ucom_softc *, uint8_t *, uint8_t *);
@@ -192,6 +200,7 @@
 	.ucom_cfg_set_dtr = &uslcom_set_dtr,
 	.ucom_cfg_set_rts = &uslcom_set_rts,
 	.ucom_cfg_set_break = &uslcom_set_break,
+	.ucom_ioctl = &uslcom_ioctl,
 	.ucom_cfg_param = &uslcom_param,
 	.ucom_pre_param = &uslcom_pre_param,
 	.ucom_start_read = &uslcom_start_read,
@@ -591,6 +600,57 @@
 	}
 }
 
+static int
+uslcom_ioctl(struct ucom_softc *ucom, uint32_t cmd, caddr_t data,
+    int flag, struct thread *td)
+{
+	struct uslcom_softc *sc = ucom->sc_parent;
+	struct usb_device_request req;
+	int error = 0;
+	uint8_t latch;
+
+	DPRINTF("cmd=0x%08x\n", cmd);
+
+	switch (cmd) {
+
+	case USB_GET_GPIO:
+		req.bmRequestType = USLCOM_READ;
+		req.bRequest = USLCOM_VENDOR_SPECIFIC;
+		USETW(req.wValue, USLCOM_READ_LATCH);
+		USETW(req.wIndex, 0);
+		USETW(req.wLength, sizeof(latch));
+
+        	if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
+		    &req, &latch, 0, 1000)) {
+			DPRINTF("Get LATCH failed\n");
+			error = EIO;
+		}
+		*(uint8_t *)data = latch;
+		break;
+
+	case USB_SET_GPIO:
+		req.bmRequestType = USLCOM_WRITE;
+		req.bRequest = USLCOM_VENDOR_SPECIFIC;
+		USETW(req.wValue, USLCOM_WRITE_LATCH);
+		USETW(req.wIndex, (*(uint16_t *)data));
+		USETW(req.wLength, 0);
+		
+        	if (ucom_cfg_do_request(sc->sc_udev, &sc->sc_ucom, 
+		    &req, NULL, 0, 1000)) {
+			DPRINTF("Set LATCH failed\n");
+			error = EIO;
+		}
+		break;
+
+	default:
+		DPRINTF("unknown\n");
+		error = ENOIOCTL;
+		break;
+	}
+
+	return (error);
+}
+
 static void
 uslcom_write_callback(struct usb_xfer *xfer, usb_error_t error)
 {
Index: usb_ioctl.h
===================================================================
--- usb_ioctl.h	(revision 227453)
+++ usb_ioctl.h	(working copy)
@@ -289,6 +289,10 @@
 #define	USB_GET_CM_OVER_DATA	_IOR ('U', 180, int)
 #define	USB_SET_CM_OVER_DATA	_IOW ('U', 181, int)
 
+/* GPIO control */
+#define	USB_GET_GPIO		_IOR ('U', 182, int)
+#define	USB_SET_GPIO		_IOW ('U', 183, int)
+
 /* USB file system interface */
 #define	USB_FS_START		_IOW ('U', 192, struct usb_fs_start)
 #define	USB_FS_STOP		_IOW ('U', 193, struct usb_fs_stop)


More information about the freebsd-usb mailing list