Bulk reads and writes now work (albeit with no flow control)
authorMichael Brown <mbrown@fensystems.co.uk>
Tue, 14 Mar 2006 15:48:59 +0000 (15:48 +0000)
committerMichael Brown <mbrown@fensystems.co.uk>
Tue, 14 Mar 2006 15:48:59 +0000 (15:48 +0000)
kernel/quickusb.c
kernel/quickusb.h

index 467e300..a7c5a32 100644 (file)
@@ -223,6 +223,48 @@ static ssize_t quickusb_hspio_write_command ( struct file *file,
        return len;
 }
 
+static ssize_t quickusb_hspio_read_data ( struct file *file,
+                                         char __user *user_data,
+                                         size_t len, loff_t *ppos ) {
+       struct quickusb_hspio *hspio = file->private_data;
+       unsigned char data[QUICKUSB_MAX_BULK_DATA_LEN];
+       int rc;
+
+       if ( len > sizeof ( data ) )
+               len = sizeof ( data );
+
+       if ( ( rc = quickusb_read_data ( hspio->quickusb->usb,
+                                        data, len ) ) != 0 )
+               return rc;
+
+       if ( ( rc = copy_to_user ( user_data, data, len ) ) != 0 )
+               return rc;
+
+       *ppos += len;
+       return len;
+}
+
+static ssize_t quickusb_hspio_write_data ( struct file *file,
+                                          const char __user *user_data,
+                                          size_t len, loff_t *ppos ) {
+       struct quickusb_hspio *hspio = file->private_data;
+       unsigned char data[QUICKUSB_MAX_BULK_DATA_LEN];
+       int rc;
+
+       if ( len > sizeof ( data ) )
+               len = sizeof ( data );
+
+       if ( ( rc = copy_from_user ( data, user_data, len ) ) != 0 )
+               return rc;
+
+       if ( ( rc = quickusb_write_data ( hspio->quickusb->usb,
+                                         data, len ) ) != 0 )
+               return rc;
+
+       *ppos += len;
+       return len;
+}
+
 static int quickusb_hspio_release ( struct inode *inode, struct file *file ) {
        struct quickusb_hspio *hspio = file->private_data;
        
@@ -237,6 +279,13 @@ static struct file_operations quickusb_hspio_command_fops = {
        .release        = quickusb_hspio_release,
 };
 
+static struct file_operations quickusb_hspio_data_fops = {
+       .owner          = THIS_MODULE,
+       .read           = quickusb_hspio_read_data,
+       .write          = quickusb_hspio_write_data,
+       .release        = quickusb_hspio_release,
+};
+
 /****************************************************************************
  *
  * Char device (subdev) operations
@@ -394,6 +443,12 @@ static int quickusb_register_devices ( struct quickusb_device *quickusb ) {
                                               "qu%dhc",
                                               quickusb->board ) ) != 0 )
                return rc;
+       if ( ( rc = quickusb_register_subdev ( quickusb, subdev_idx++,
+                                              &quickusb_hspio_data_fops,
+                                              &quickusb->hspio,
+                                              "qu%dhd",
+                                              quickusb->board ) ) != 0 )
+               return rc;
        
        return 0;
 }
index 5bddf7e..ca8e1c2 100644 (file)
@@ -8,11 +8,16 @@
 #define QUICKUSB_BREQUEST_SETTING      0xb0
 #define QUICKUSB_BREQUEST_HSPIO_COMMAND        0xb2
 #define QUICKUSB_BREQUEST_GPPIO                0xb3
+#define QUICKUSB_BREQUEST_HSPIO                0xb7
 
 #define QUICKUSB_BREQUESTTYPE_READ     0xc0
 #define QUICKUSB_BREQUESTTYPE_WRITE    0x40
 
-#define QUICKUSB_MAX_DATA_LEN 64
+#define QUICKUSB_BULK_OUT_EP           0x02
+#define QUICKUSB_BULK_IN_EP            0x86
+
+#define QUICKUSB_MAX_DATA_LEN          64
+#define QUICKUSB_MAX_BULK_DATA_LEN     512
 
 #define QUICKUSB_WINDEX_GPPIO_DIR 0
 #define QUICKUSB_WINDEX_GPPIO_DATA 1
@@ -34,15 +39,17 @@ static inline int quickusb_read_setting ( struct usb_device *usb,
        uint16_t setting_le;
        int ret;
 
-       ret =  usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_SETTING,
-                                QUICKUSB_BREQUESTTYPE_READ,
-                                0, address,
-                                &setting_le, sizeof ( setting_le ),
-                                QUICKUSB_TIMEOUT );
+       ret = usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_SETTING,
+                               QUICKUSB_BREQUESTTYPE_READ,
+                               0, address,
+                               &setting_le, sizeof ( setting_le ),
+                               QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
 
        *setting = le16_to_cpu ( setting_le );
-       return ( ret > 0 ) ? 0 : ret;
+       return 0;
 }
 
 /**
@@ -60,14 +67,16 @@ static inline int quickusb_write_setting ( struct usb_device *usb,
        uint16_t setting_le = cpu_to_le16 ( setting );
        int ret;
 
-       ret =  usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_SETTING,
-                                QUICKUSB_BREQUESTTYPE_WRITE,
-                                0, address,
-                                &setting_le, sizeof ( setting_le ),
-                                QUICKUSB_TIMEOUT );
+       ret = usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_SETTING,
+                               QUICKUSB_BREQUESTTYPE_WRITE,
+                               0, address,
+                               &setting_le, sizeof ( setting_le ),
+                               QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
 
-       return ( ret > 0 ) ? 0 : ret;
+       return 0;
 }
 
 /**
@@ -85,13 +94,15 @@ static inline int quickusb_read_command ( struct usb_device *usb,
                                          void *data, size_t len ) {
        int ret;
        
-       ret =  usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_HSPIO_COMMAND,
-                                QUICKUSB_BREQUESTTYPE_READ,
-                                len, address,
-                                data, len, QUICKUSB_TIMEOUT );
-
-       return ( ret > 0 ) ? 0 : ret;
+       ret = usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_HSPIO_COMMAND,
+                               QUICKUSB_BREQUESTTYPE_READ,
+                               len, address,
+                               data, len, QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
+
+       return 0;
 }
 
 /**
@@ -109,13 +120,71 @@ static inline int quickusb_write_command ( struct usb_device *usb,
                                           void *data, size_t len ) {
        int ret;
        
-       ret =  usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_HSPIO_COMMAND,
-                                QUICKUSB_BREQUESTTYPE_WRITE,
-                                len, address,
-                                data, len, QUICKUSB_TIMEOUT );
+       ret = usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_HSPIO_COMMAND,
+                               QUICKUSB_BREQUESTTYPE_WRITE,
+                               len, address,
+                               data, len, QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
+
+       return 0;
+}
+
+/**
+ * quickusb_read_data - read HSPIO port with a data cycle
+ *
+ * @usb: USB device
+ * @data: Data buffer
+ * @len: Length of data to read (max QUICKUSB_MAX_BULK_DATA_LEN)
+ *
+ * Returns 0 for success, or negative error number
+ */
+static inline int quickusb_read_data ( struct usb_device *usb,
+                                      void *data, size_t len ) {
+       uint32_t len_le = cpu_to_le32 ( len );
+       int actual_length;
+       int ret;
+       
+       ret = usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_HSPIO,
+                               QUICKUSB_BREQUESTTYPE_WRITE,
+                               0, 0,
+                               &len_le, sizeof ( len_le ),
+                               QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
+
+       ret = usb_bulk_msg ( usb,
+                            usb_rcvbulkpipe ( usb, QUICKUSB_BULK_IN_EP ),
+                            data, len, &actual_length, QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
+
+       return 0;
+}
+
+/**
+ * quickusb_write_data - write HSPIO port with a data cycle
+ *
+ * @usb: USB device
+ * @data: Data to be written
+ * @len: Length of data to write (max QUICKUSB_MAX_BULK_DATA_LEN)
+ *
+ * Returns 0 for success, or negative error number
+ */
+static inline int quickusb_write_data ( struct usb_device *usb,
+                                       void *data, size_t len ) {
+       int actual_length;
+       int ret;
+       
+       ret = usb_bulk_msg ( usb,
+                            usb_sndbulkpipe ( usb, QUICKUSB_BULK_OUT_EP ),
+                            data, len, &actual_length, QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
 
-       return ( ret > 0 ) ? 0 : ret;
+       return 0;
 }
 
 /**
@@ -132,14 +201,16 @@ static inline int quickusb_read_port_dir ( struct usb_device *usb,
                                           uint8_t *outputs ) {
        int ret;
        
-       ret =  usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_GPPIO,
-                                QUICKUSB_BREQUESTTYPE_READ,
-                                address, QUICKUSB_WINDEX_GPPIO_DIR,
-                                outputs, sizeof ( *outputs ),
-                                QUICKUSB_TIMEOUT );
-
-       return ( ret > 0 ) ? 0 : ret;
+       ret = usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_GPPIO,
+                               QUICKUSB_BREQUESTTYPE_READ,
+                               address, QUICKUSB_WINDEX_GPPIO_DIR,
+                               outputs, sizeof ( *outputs ),
+                               QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
+
+       return 0;
 }
 
 /**
@@ -156,18 +227,16 @@ static inline int quickusb_write_port_dir ( struct usb_device *usb,
                                            uint8_t outputs ) {
        int ret;
 
-       ret =  usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_GPPIO,
-                                QUICKUSB_BREQUESTTYPE_WRITE,
-                                address, QUICKUSB_WINDEX_GPPIO_DIR,
-                                &outputs, sizeof ( outputs ),
-                                QUICKUSB_TIMEOUT );
-
-       if ( ret > 0 ) {
-               ret = 0;
-       }
+       ret = usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_GPPIO,
+                               QUICKUSB_BREQUESTTYPE_WRITE,
+                               address, QUICKUSB_WINDEX_GPPIO_DIR,
+                               &outputs, sizeof ( outputs ),
+                               QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -185,13 +254,15 @@ static inline int quickusb_read_port ( struct usb_device *usb,
                                       void *data, size_t len ) {
        int ret;
        
-       ret =  usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_GPPIO,
-                                QUICKUSB_BREQUESTTYPE_READ,
-                                address, QUICKUSB_WINDEX_GPPIO_DATA,
-                                data, len, QUICKUSB_TIMEOUT );
-
-       return ( ret > 0 ) ? 0 : ret;
+       ret = usb_control_msg ( usb, usb_rcvctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_GPPIO,
+                               QUICKUSB_BREQUESTTYPE_READ,
+                               address, QUICKUSB_WINDEX_GPPIO_DATA,
+                               data, len, QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
+
+       return 0;
 }
 
 /**
@@ -209,13 +280,15 @@ static inline int quickusb_write_port ( struct usb_device *usb,
                                        void *data, size_t len ) {
        int ret;
 
-       ret =  usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
-                                QUICKUSB_BREQUEST_GPPIO,
-                                QUICKUSB_BREQUESTTYPE_WRITE,
-                                address, QUICKUSB_WINDEX_GPPIO_DATA,
-                                data, len, QUICKUSB_TIMEOUT );
-       
-       return ( ret > 0 ) ? 0 : ret;
+       ret = usb_control_msg ( usb, usb_sndctrlpipe ( usb, 0 ),
+                               QUICKUSB_BREQUEST_GPPIO,
+                               QUICKUSB_BREQUESTTYPE_WRITE,
+                               address, QUICKUSB_WINDEX_GPPIO_DATA,
+                               data, len, QUICKUSB_TIMEOUT );
+       if ( ret < 0 )
+               return ret;
+
+       return 0;
 }
 
 #endif /* __KERNEL__ */