0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029 #include <linux/module.h>
0030 #include <linux/kernel.h>
0031 #include <linux/slab.h>
0032 #include <linux/usb.h>
0033
0034 #define DRIVER_AUTHOR "Oliver Bock (bock@tfh-berlin.de)"
0035 #define DRIVER_DESC "Cypress CY7C63xxx USB driver"
0036
0037 #define CYPRESS_VENDOR_ID 0xa2c
0038 #define CYPRESS_PRODUCT_ID 0x8
0039
0040 #define CYPRESS_READ_PORT 0x4
0041 #define CYPRESS_WRITE_PORT 0x5
0042
0043 #define CYPRESS_READ_RAM 0x2
0044 #define CYPRESS_WRITE_RAM 0x3
0045 #define CYPRESS_READ_ROM 0x1
0046
0047 #define CYPRESS_READ_PORT_ID0 0
0048 #define CYPRESS_WRITE_PORT_ID0 0
0049 #define CYPRESS_READ_PORT_ID1 0x2
0050 #define CYPRESS_WRITE_PORT_ID1 1
0051
0052 #define CYPRESS_MAX_REQSIZE 8
0053
0054
0055
0056 static const struct usb_device_id cypress_table[] = {
0057 { USB_DEVICE(CYPRESS_VENDOR_ID, CYPRESS_PRODUCT_ID) },
0058 { }
0059 };
0060 MODULE_DEVICE_TABLE(usb, cypress_table);
0061
0062
0063 struct cypress {
0064 struct usb_device * udev;
0065 unsigned char port[2];
0066 };
0067
0068
0069 static int vendor_command(struct cypress *dev, unsigned char request,
0070 unsigned char address, unsigned char data)
0071 {
0072 int retval = 0;
0073 unsigned int pipe;
0074 unsigned char *iobuf;
0075
0076
0077 iobuf = kzalloc(CYPRESS_MAX_REQSIZE, GFP_KERNEL);
0078 if (!iobuf) {
0079 retval = -ENOMEM;
0080 goto error;
0081 }
0082
0083 dev_dbg(&dev->udev->dev, "Sending usb_control_msg (data: %d)\n", data);
0084
0085
0086 pipe = usb_rcvctrlpipe(dev->udev, 0);
0087 retval = usb_control_msg(dev->udev, pipe, request,
0088 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
0089 address, data, iobuf, CYPRESS_MAX_REQSIZE,
0090 USB_CTRL_GET_TIMEOUT);
0091
0092
0093 switch (request) {
0094 case CYPRESS_READ_PORT:
0095 if (address == CYPRESS_READ_PORT_ID0) {
0096 dev->port[0] = iobuf[1];
0097 dev_dbg(&dev->udev->dev,
0098 "READ_PORT0 returned: %d\n",
0099 dev->port[0]);
0100 }
0101 else if (address == CYPRESS_READ_PORT_ID1) {
0102 dev->port[1] = iobuf[1];
0103 dev_dbg(&dev->udev->dev,
0104 "READ_PORT1 returned: %d\n",
0105 dev->port[1]);
0106 }
0107 break;
0108 }
0109
0110 kfree(iobuf);
0111 error:
0112 return retval;
0113 }
0114
0115
0116 static ssize_t write_port(struct device *dev, struct device_attribute *attr,
0117 const char *buf, size_t count,
0118 int port_num, int write_id)
0119 {
0120 int value = -1;
0121 int result = 0;
0122
0123 struct usb_interface *intf = to_usb_interface(dev);
0124 struct cypress *cyp = usb_get_intfdata(intf);
0125
0126 dev_dbg(&cyp->udev->dev, "WRITE_PORT%d called\n", port_num);
0127
0128
0129 if (sscanf(buf, "%d", &value) < 1) {
0130 result = -EINVAL;
0131 goto error;
0132 }
0133 if (value < 0 || value > 255) {
0134 result = -EINVAL;
0135 goto error;
0136 }
0137
0138 result = vendor_command(cyp, CYPRESS_WRITE_PORT, write_id,
0139 (unsigned char)value);
0140
0141 dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
0142 error:
0143 return result < 0 ? result : count;
0144 }
0145
0146
0147 static ssize_t port0_store(struct device *dev,
0148 struct device_attribute *attr,
0149 const char *buf, size_t count)
0150 {
0151 return write_port(dev, attr, buf, count, 0, CYPRESS_WRITE_PORT_ID0);
0152 }
0153
0154
0155 static ssize_t port1_store(struct device *dev,
0156 struct device_attribute *attr,
0157 const char *buf, size_t count)
0158 {
0159 return write_port(dev, attr, buf, count, 1, CYPRESS_WRITE_PORT_ID1);
0160 }
0161
0162
0163 static ssize_t read_port(struct device *dev, struct device_attribute *attr,
0164 char *buf, int port_num, int read_id)
0165 {
0166 int result = 0;
0167
0168 struct usb_interface *intf = to_usb_interface(dev);
0169 struct cypress *cyp = usb_get_intfdata(intf);
0170
0171 dev_dbg(&cyp->udev->dev, "READ_PORT%d called\n", port_num);
0172
0173 result = vendor_command(cyp, CYPRESS_READ_PORT, read_id, 0);
0174
0175 dev_dbg(&cyp->udev->dev, "Result of vendor_command: %d\n\n", result);
0176
0177 return sprintf(buf, "%d", cyp->port[port_num]);
0178 }
0179
0180
0181 static ssize_t port0_show(struct device *dev,
0182 struct device_attribute *attr, char *buf)
0183 {
0184 return read_port(dev, attr, buf, 0, CYPRESS_READ_PORT_ID0);
0185 }
0186 static DEVICE_ATTR_RW(port0);
0187
0188
0189 static ssize_t port1_show(struct device *dev,
0190 struct device_attribute *attr, char *buf)
0191 {
0192 return read_port(dev, attr, buf, 1, CYPRESS_READ_PORT_ID1);
0193 }
0194 static DEVICE_ATTR_RW(port1);
0195
0196 static struct attribute *cypress_attrs[] = {
0197 &dev_attr_port0.attr,
0198 &dev_attr_port1.attr,
0199 NULL,
0200 };
0201 ATTRIBUTE_GROUPS(cypress);
0202
0203 static int cypress_probe(struct usb_interface *interface,
0204 const struct usb_device_id *id)
0205 {
0206 struct cypress *dev = NULL;
0207 int retval = -ENOMEM;
0208
0209
0210 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
0211 if (!dev)
0212 goto error_mem;
0213
0214 dev->udev = usb_get_dev(interface_to_usbdev(interface));
0215
0216
0217 usb_set_intfdata(interface, dev);
0218
0219
0220 dev_info(&interface->dev,
0221 "Cypress CY7C63xxx device now attached\n");
0222 return 0;
0223
0224 error_mem:
0225 return retval;
0226 }
0227
0228 static void cypress_disconnect(struct usb_interface *interface)
0229 {
0230 struct cypress *dev;
0231
0232 dev = usb_get_intfdata(interface);
0233
0234
0235
0236 usb_set_intfdata(interface, NULL);
0237
0238 usb_put_dev(dev->udev);
0239
0240 dev_info(&interface->dev,
0241 "Cypress CY7C63xxx device now disconnected\n");
0242
0243 kfree(dev);
0244 }
0245
0246 static struct usb_driver cypress_driver = {
0247 .name = "cypress_cy7c63",
0248 .probe = cypress_probe,
0249 .disconnect = cypress_disconnect,
0250 .id_table = cypress_table,
0251 .dev_groups = cypress_groups,
0252 };
0253
0254 module_usb_driver(cypress_driver);
0255
0256 MODULE_AUTHOR(DRIVER_AUTHOR);
0257 MODULE_DESCRIPTION(DRIVER_DESC);
0258
0259 MODULE_LICENSE("GPL");